Compare commits

..
Author SHA1 Message Date
anthropic-code-agent[bot]andashaduri c673bd95bb Add unit tests for SelfTest adaptive ETA algorithm
Co-authored-by: ashaduri <2302268+ashaduri@users.noreply.github.com>
Agent-Logs-Url: https://github.com/ashaduri/gsmartcontrol/sessions/8b4b77f5-beb6-4c32-bf49-93d641714685
2026-03-22 17:04:36 +00:00
copilot-swe-agent[bot]andashaduri b2912e5b61 Remove redundant build/ from .gitignore (already covered by /build*)
Co-authored-by: ashaduri <2302268+ashaduri@users.noreply.github.com>
2026-03-07 15:35:28 +00:00
copilot-swe-agent[bot]andashaduri b1ccfd43e0 Fix narrowing conversion: use int instead of int8_t for remaining_segments
Co-authored-by: ashaduri <2302268+ashaduri@users.noreply.github.com>
2026-03-07 15:26:53 +00:00
copilot-swe-agent[bot]andashaduri dd0b9fe8ea Move gran to fallback path and fix adaptive ETA for NVMe drives
Co-authored-by: ashaduri <2302268+ashaduri@users.noreply.github.com>
2026-03-07 15:21:48 +00:00
anthropic-code-agent[bot]andashaduri d88090d6b6 Skip first segment in adaptive ETA to avoid skew from instant/partial progress
Co-authored-by: ashaduri <2302268+ashaduri@users.noreply.github.com>
2026-03-06 14:54:17 +00:00
anthropic-code-agent[bot]andashaduri 1c99ff8350 Implement adaptive ETA calculation based on observed segment durations
Co-authored-by: ashaduri <2302268+ashaduri@users.noreply.github.com>
2026-03-06 14:43:41 +00:00
copilot-swe-agent[bot]andashaduri 2ef695f8fb Fix misleading ETA: 0 sec during self-test when drive estimate is exceeded
Co-authored-by: ashaduri <2302268+ashaduri@users.noreply.github.com>
2026-03-04 22:05:23 +00:00
copilot-swe-agent[bot] d0a2852119 Initial plan 2026-03-04 21:54:35 +00:00
Alexander Shaduri 5343ba9dae Cleanups 2026-03-04 22:48:21 +01:00
Alexander Shaduri 3d1e962107 Agentic: Tweak instructions. 2026-03-04 22:37:05 +01:00
Alexander Shaduri c14d7a7791 Windows: Manually install nsis since it's no longer available by default in CI. 2026-03-04 22:33:57 +01:00
Alexander Shaduri 4f3745f8ec Add copilot helper files. 2026-03-04 22:06:57 +01:00
Alexander Shaduri dadfd60ed3 Fix gcc shadow warning. 2025-11-25 19:29:46 +01:00
copilot-swe-agent[bot] 6c8fea7309 Add new natural sort order tests. 2025-11-25 19:29:28 +01:00
copilot-swe-agent[bot] 9d9e3b1a4d Update .gitignore to exclude CodeQL build directory 2025-11-25 13:00:03 +01:00
copilot-swe-agent[bot]andashaduri 54425a306a Implement natural sort order for drive names
Co-authored-by: ashaduri <2302268+ashaduri@users.noreply.github.com>
2025-11-25 12:59:41 +01:00
Alexander Shaduri be601f514d Upgrade CodeQL actions to version 4
Updated CodeQL actions to version 4 in the workflow configuration.
2025-11-18 19:44:28 +01:00
Alexander Shaduri a7c7c8190c Update CodeQL SARIF upload action to v4 2025-11-18 19:43:57 +01:00
Alexander Shaduri 44948de7d0 Fixed typos and updated visible copyright years. 2025-06-11 09:43:36 +02:00
Alexander Shaduri e2efde2d1a Updated nlohmann json to version 3.12.0. 2025-05-16 17:48:32 +04:00
Alexander Shaduri 6630116ba1 Properly implemented persistence of manually added devices (#87). Added --forget-devices option to clear the list if any of the devices causes trouble. 2025-04-28 18:51:42 +04:00
Alexander Shaduri 1f7c2b6a92 Manually added devices can be persistent now. 2025-04-28 11:19:44 +00:00
Alexander Shaduri 10ad6b74eb Merge remote-tracking branch 'origin/main' 2025-04-25 12:22:38 +04:00
Alexander Shaduri f62de567df MSYS no longer supports 32-bit Windows, so disable it in CI. 2025-04-25 12:12:52 +04:00
Alexander Shaduri d96dc79943 Merge pull request #86 from checktext00/patch-1
Update 36535 to 65535 hours in selftest log tooltip.
2025-04-17 11:32:32 +04:00
Alexander Shaduri e35c301605 Update gsc_info_window.cpp
Looking at the smartmontools code, it should be 65535 I believe.
2025-04-17 11:31:13 +04:00
checktext00 7af8dba9f3 update 36535 to 65536 hours 2025-04-16 11:58:09 +00:00
Alexander Shaduri caa80a30d1 Merge pull request #83 from stanislav-brabec/main
Typo fix in Czech desktop translation.
2025-03-12 20:46:01 +04:00
Stanislav Brabec db4928e78f Typo fix in Czech desktop translation. 2025-03-12 16:43:39 +01:00
Alexander Shaduri af96fa2cda Merge pull request #82 from stanislav-brabec/main
Add desktop translations
2025-03-11 11:55:47 +04:00
Stanislav Brabec c08ef9070b Add desktop translations
Add desktop translations imported from the openSUSE
desktop-file-translations project.
https://l10n.opensuse.org/projects/desktop-file-translations/
2025-03-10 22:10:45 +01:00
Alexander Shaduri 6fe5b43bc1 Document Vista. 2025-03-02 19:13:32 +04:00
Alexander Shaduri b3056aedd0 Update download links for 2.0.2. 2025-02-24 16:50:08 +04:00
Alexander Shaduri b2912950c9 Fixed Windows CI packaging. 2025-02-24 16:08:36 +04:00
Alexander Shaduri af2e47308c Bumped version to 2.0.2. 2025-02-24 16:04:30 +04:00
Alexander Shaduri 37be3a413a Updated NEWS for 2.0.2 release. 2025-02-24 16:03:48 +04:00
Alexander Shaduri a7281b7b1e Document GCC 11 support. 2025-02-24 16:03:22 +04:00
Alexander Shaduri 23d06c4bc7 Cleanup. 2025-02-24 16:03:02 +04:00
Alexander Shaduri b5f522d8bc Fix OBS repository list. 2025-02-24 14:56:14 +04:00
Alexander Shaduri 283792715c Update CI to use GCC14. 2025-02-24 14:03:40 +04:00
Alexander Shaduri d7032eb351 Allow smartctl < 7.3 again, falling back to Text parser; this configuration is for compatibility only and not fully supported. 2025-02-24 13:52:04 +04:00
Alexander Shaduri 589c280bdc Support saving smartctl output to text (using old text format) instead of json (#76). 2025-02-15 13:22:47 +04:00
Alexander Shaduri 9f85d09736 Support standard (non-extended) self-test log in JSON ATA parser (#79). 2025-02-14 13:48:30 +04:00
Alexander Shaduri d45e5360cc Temperature: Fixed reporting unreasonably large values when raw value encodes min/max values as well (#78); support protocol-independent temperature reporting in JSON. 2025-02-14 13:28:43 +04:00
Alexander Shaduri 58d2a8b58f Windows: Use older librsvg in CI to support Windows 7 (#71). 2025-02-13 17:11:33 +04:00
Alexander Shaduri d51820476b Windows: Use older librsvg in CI to support Windows 7 (#71). 2025-02-13 16:35:55 +04:00
Alexander Shaduri bfce801cc5 Windows: Use older librsvg in CI to support Windows 7 (#71). 2025-02-13 16:30:36 +04:00
Alexander Shaduri 63f32e4d8b Windows: Use older librsvg in CI to support Windows 7 (#71). 2025-02-13 16:25:47 +04:00
Alexander Shaduri 0fc5d208bb Support Ubuntu 22.04 in CI. 2025-02-07 13:00:29 +04:00
Alexander Shaduri 8b3b500034 Support Ubuntu 22.04 in CI. 2025-02-07 11:51:13 +04:00
Alexander Shaduri a5fddf1bb2 Use {fmt} instead of <format> to support older compilers. 2025-02-07 11:44:50 +04:00
Alexander Shaduri f3dc0274c3 Added generic build instructions. 2025-02-07 10:41:04 +04:00
Alexander Shaduri 515bf11c3d Added self-test "lifetime hours" wrapping behavior to the column header tooltip. 2024-12-26 13:07:24 +04:00
Alexander Shaduri a254c17fcb Updated wikipedia links. 2024-12-10 18:26:40 +04:00
Alexander Shaduri 7e9959c455 Update wikipedia link. 2024-12-10 18:20:35 +04:00
Alexander Shaduri a57e543701 Windows: Avoid using non-integer font sizes. 2024-12-06 12:33:50 +04:00
Alexander Shaduri 43d4b86943 Add sha1sum of the source archive. 2024-11-26 15:44:54 +04:00
Alexander Shaduri 81cdd0db81 Reflect version 2.0.1. 2024-11-26 15:45:49 +04:00
Alexander Shaduri b76bb1002e Windows: Bundle missing dlls needed by CI GTK. 2024-11-26 14:59:00 +04:00
Alexander Shaduri dea940222e GitHub CI: Fixed invalid artifact names. 2024-11-26 14:57:21 +04:00
Alexander Shaduri 4a075cc187 Bumped version to 2.0.1. 2024-11-26 14:04:37 +04:00
Alexander Shaduri e17c10c965 Windows: Bundle glib schemas to avoid native file dialog crash. 2024-11-26 13:59:52 +04:00
Alexander Shaduri 8c96c02468 Add a note about DPI awareness limitations. 2024-11-26 13:43:45 +04:00
Alexander Shaduri 4260f94ce7 Minor style issue in documentation. 2024-11-21 16:17:50 +04:00
Alexander Shaduri 21f73e4eae Add a note about SCSI / SAS support. 2024-11-21 16:14:13 +04:00
Alexander Shaduri 743173df81 Merge remote-tracking branch 'origin/main' 2024-11-19 18:22:46 +04:00
Alexander Shaduri 17b6ea23b4 Clarify device support in documentation. 2024-11-19 18:21:34 +04:00
Alexander Shaduri 840398c073 Fix potential crash in attribute description database. 2024-11-19 12:58:45 +04:00
Alexander Shaduri 93384e4c37 Fix compiler warning. 2024-11-19 12:39:01 +04:00
Alexander Shaduri 566b11026e Fix "Show SMART capable only" checkbox not having effect. 2024-11-07 14:48:18 +04:00
Alexander Shaduri 8fd2986a92 Update SECURITY.md for 2.0.0. 2024-11-07 14:00:47 +04:00
Alexander Shaduri e7dd2cf434 Recommend a 64-bit installer on Windows due to more testing. 2024-11-07 13:57:27 +04:00
Alexander Shaduri cdfbf8795a Update the Downloads page for 2.0.0. 2024-11-07 13:51:46 +04:00
Alexander Shaduri d110ddad10 Update NEWS.txt and other files in preparation for 2.0.0. 2024-11-07 13:09:59 +04:00
Alexander Shaduri 36cecf3acc Bumped version to 2.0.0. 2024-11-06 14:55:23 +04:00
Alexander Shaduri 066eaec993 Windows: Use Adwaita theme by default, win32 theme has too many problems (with Classic theme and with fractional dpi scaling). 2024-11-06 14:11:08 +04:00
Alexander Shaduri 746ebf9b02 Windows: Re-enable dpi awareness and scale up the font in case of fractional scaling. 2024-11-06 13:57:59 +04:00
Alexander Shaduri 1deffe6a98 Don't require gettext - we don't need it yet. 2024-11-06 12:38:04 +04:00
Alexander Shaduri 7ac61f1cac Fix crash on startup in Windows. 2024-11-06 12:37:48 +04:00
Alexander Shaduri e386c86316 Merge remote-tracking branch 'origin/main' 2024-11-05 17:28:48 +04:00
Alexander Shaduri da84eb027f Disable LTO in mingw due to CI errors. 2024-11-05 17:28:25 +04:00
Alexander Shaduri 1d9f2a2744 Fix win32 toolchain files for release builds. 2024-11-05 16:52:26 +04:00
Alexander Shaduri c1d0f46366 Make sure NSIS installer works. 2024-11-05 15:33:33 +04:00
Alexander Shaduri 99bf00d27c Fixed running "Update smartctl database" on Windows; use argv on all platforms so it is more secure. 2024-11-05 14:53:19 +04:00
Alexander Shaduri 7fd43bba2c Info window: Don't use Gtk::Stock for icons. 2024-11-05 14:15:19 +04:00
Alexander Shaduri 48f14267e5 Hide too noisy clang-tidy warning. 2024-11-05 14:00:50 +04:00
Alexander Shaduri b785a4fbec Replace bundled icons with the ones from Oxygen project; bundle removable drive icon; update copyrights accordingly. 2024-11-05 14:00:33 +04:00
Alexander Shaduri 3aa5ddfc32 Test results are presented in a more obvious manner now. 2024-11-04 20:38:47 +04:00
Alexander Shaduri c2277edb56 Show smartctl database version in basic properties. 2024-11-04 17:07:20 +04:00
Alexander Shaduri d82ec219f6 Refactoring: Split out property description code for ATA Attribute and ATA Statistic into separate files.
Added descriptions and warnings to NVMe Attributes.
Storage Property: Rely less on reported name (not as useful with JSON parser), more on generic name.
2024-11-04 16:56:10 +04:00
Alexander Shaduri dc007c84ab Fix ATA testing with when JSON parser is used. 2024-11-04 13:11:19 +04:00
Alexander Shaduri ccd04b86d3 Page tweaks. 2024-10-31 19:09:43 +04:00
Alexander Shaduri 0531a37133 Update pages remote theme (the old one was deleted). 2024-10-31 19:02:11 +04:00
Alexander Shaduri 566cff8ded Update pages remote theme (the old one was deleted). 2024-10-31 18:57:24 +04:00
Alexander Shaduri 74c5e92d4b Do not remove NVMe devices namespaces if a device has more than one namespace. 2024-10-31 16:21:43 +04:00
Alexander Shaduri aaa374c8ed Fix self-test status execution returning error. 2024-10-31 16:21:15 +04:00
Alexander Shaduri 2a6902dbb5 Support self-tests on WD NVMe with smartctl < 7.5. 2024-10-31 16:05:07 +04:00
Alexander Shaduri 02206a8967 Minor code cleanups. 2024-10-31 15:56:23 +04:00
Alexander Shaduri af2a5a18b3 "Perform Tests" menu item is correctly disabled now if self-tests are not supported; if support is unknown, an appropriate message is shown after the Info window is displayed. 2024-10-31 15:47:42 +04:00
Alexander Shaduri 1d0e325813 JSON Basic Parser: Make sure the health property is in the health section (fixes GUI not displaying health after first scan). 2024-10-31 15:21:02 +04:00
Alexander Shaduri f4e22a5c96 Windows: Add a note about why hidpi is disabled. 2024-10-31 15:18:01 +04:00
Alexander Shaduri fb468f8594 Windows: Fixed auto-detection issues, minor refactoring of the detection code. 2024-10-31 14:26:20 +04:00
Alexander Shaduri 4ff0aaad9c Hide self-test tab if NVMe does not support self-tests. 2024-06-11 13:53:23 +04:00
Alexander Shaduri c0eb5e2087 Renamed bundled icon files. 2024-06-11 13:48:41 +04:00
Alexander Shaduri c795635469 Improve device type detection. 2024-06-11 13:47:11 +04:00
Alexander Shaduri e844b9949d Detection of NVMe self-test support. 2024-06-11 13:46:57 +04:00
Alexander Shaduri 5c807e1859 Fix missing include. 2024-06-11 13:29:35 +04:00
Alexander Shaduri b2edaf69c1 Fix data member naming convention. 2024-06-11 13:29:25 +04:00
Alexander Shaduri dfa6d043b3 Improve per-drive-type icon selection. 2024-06-11 13:16:24 +04:00
Alexander Shaduri 5e3f01f350 Fixed function naming convention. 2024-06-11 13:15:40 +04:00
Alexander Shaduri f9a098d67b Merge pull request #62 from skitt/package-name
Add the package name to the icons and ui paths
2024-06-11 12:22:18 +04:00
Stephen Kitt 3324e27dee Add the package name to the icons and ui paths
CMAKE_INSTALL_FULL_DATADIR gives the read-only
architecture-independent data root without the package name, so
BuildEnv::package_pkgdata_dir() only returns that ("/usr/share" or
equivalent). This adds the package name to the appropriate search
paths in app_init_and_loop().

Signed-off-by: Stephen Kitt <steve@sk2.org>
2024-06-05 16:01:47 +02:00
Alexander Shaduri 25f1c62d2c Support NVMe behind USB bridges. 2024-05-31 12:50:03 +04:00
Alexander Shaduri afd6ce0a1f Fix CI. 2024-05-29 13:36:00 +04:00
Alexander Shaduri fb62473b0b Fix CI. 2024-05-29 12:49:04 +04:00
Alexander Shaduri 9b1bc82353 Extract smartmontools before running cmake. 2024-05-29 12:23:51 +04:00
Alexander Shaduri d1f0b517e4 More debug messages. 2024-05-29 11:24:22 +04:00
Alexander Shaduri ec50159a15 Add listing of files for debugging. 2024-05-29 11:06:38 +04:00
Alexander Shaduri a7f513fd7c Fix CPack rules. 2024-05-28 14:07:20 +04:00
Alexander Shaduri 698024d47d Fix CPack rules. 2024-05-28 13:44:00 +04:00
Alexander Shaduri eb8d91470b Fix CPack rules. 2024-05-28 13:34:50 +04:00
Alexander Shaduri 780f22818e CPack improvements for Windows. 2024-05-28 11:59:49 +04:00
Alexander Shaduri fdcf9f7099 Fix security warning. 2024-05-28 11:25:59 +04:00
Alexander Shaduri ec0445ec54 Merge remote-tracking branch 'origin/main' 2024-05-28 11:21:13 +04:00
Alexander Shaduri 75f50cd5bb Update workflows with latest permissions. 2024-05-28 11:19:51 +04:00
Alexander Shaduri 4d1af3ce9c Merge pull request #61 from skitt/canonical-nlohmann-json
Use the canonical nlohmann json include path.
2024-05-28 10:53:52 +04:00
Stephen Kitt 7b6aa046f4 Use the canonical nlohmann json include path
As documented in https://github.com/nlohmann/json, the canonical
include path for json.hpp is nlohmann/json.hpp. Tihs updated the
vendored dependency to match, so that gsmartcontrol can more easily be
built using a system-installed copy of nlohmann json as well as the
vendored copy.

Signed-off-by: Stephen Kitt <steve@sk2.org>
2024-05-27 13:31:27 +02:00
Alexander Shaduri 844f6ed86f Add workflow for creating Windows Release packages. 2024-05-22 13:44:06 +04:00
Alexander Shaduri 7a8cbe202e Use llvm17 in FreeBSD. 2024-05-22 13:34:56 +04:00
Alexander Shaduri ec2a4648e1 Upgrade freebsd build to latest version of action. 2024-05-22 12:59:23 +04:00
Alexander Shaduri 186682b6d4 Updated NEWS.txt to include information about 1.1.4. 2024-05-22 12:01:55 +04:00
Alexander Shaduri db6811450e Remove local_glibmm.h workaround for broken libintl.h. 2024-05-22 11:51:41 +04:00
Alexander Shaduri 1c19b51fda Moved application GUI source files to gui subdirectory. 2024-05-22 11:46:02 +04:00
Alexander Shaduri 28cad446b7 Packaging fixes. 2024-05-21 20:33:04 +04:00
Alexander Shaduri 84867cc474 Create and use cmake toolchains for msys2. 2024-05-21 16:46:53 +04:00
Alexander Shaduri 13c644efdc List msys2 files for debugging. 2024-05-21 14:47:26 +04:00
Alexander Shaduri 5085c35269 List msys2 files for debugging. 2024-05-21 14:46:30 +04:00
Alexander Shaduri 7682f1285e Merge remote-tracking branch 'origin/main' 2024-05-20 17:41:41 +04:00
Alexander Shaduri 74a0cf012b Refactored so that executor options are given as a vector, not as a string; this improves reliability as the string does not have to be shell-parsed. 2024-05-20 17:41:29 +04:00
Alexander Shaduri d356e2e79f Add nvme as a type option in GUI. 2024-05-20 17:40:41 +04:00
Alexander Shaduri fe027b7fc7 Update windows packaging. 2024-05-17 17:09:22 +04:00
Alexander Shaduri 501134c2fd Use double-quoting of commands in Windows. 2024-05-17 16:56:44 +04:00
Alexander Shaduri debe2e63cb Github issue template tweaks. 2024-05-17 14:38:52 +04:00
Alexander Shaduri 4452ec50fb Updated OBS workflow repositories. 2024-05-17 14:38:21 +04:00
Alexander Shaduri f034f45b93 Packaging fixes. 2024-05-17 14:10:19 +04:00
Alexander Shaduri 5160486dcd Packaging fixes. 2024-05-17 14:04:24 +04:00
Alexander Shaduri 876c586620 Packaging fixes. 2024-05-17 13:59:47 +04:00
Alexander Shaduri 85ef6faf7d Packaging fixes. 2024-05-17 13:40:46 +04:00
Alexander Shaduri 6004a76884 Packaging fixes. 2024-05-17 13:39:54 +04:00
Alexander Shaduri 944829a6be Packaging fixes. 2024-05-17 13:34:29 +04:00
Alexander Shaduri 9b75a426c5 Packaging fixes. 2024-05-17 13:26:32 +04:00
Alexander Shaduri d6d63b7f88 Packaging fixes. 2024-05-17 13:14:01 +04:00
Alexander Shaduri d9adde161c Packaging fixes. 2024-05-17 13:12:03 +04:00
Alexander Shaduri 3d45bbe12a Packaging fixes. 2024-05-17 13:09:13 +04:00
Alexander Shaduri 90be761780 Updated packaging. 2024-05-17 12:49:47 +04:00
Alexander Shaduri 22c5cfdffd Updated packaging. 2024-05-17 12:46:06 +04:00
Alexander Shaduri 7834f61662 Updated packaging. 2024-05-17 12:43:04 +04:00
Alexander Shaduri cafb1ef28d Updated packaging. 2024-05-17 12:29:44 +04:00
Alexander Shaduri 4211374126 Updated documentation to indicate NVMe support. 2024-05-17 11:38:57 +04:00
Alexander Shaduri cfa50198ee Removed unused cmake file. 2024-05-17 11:37:35 +04:00
Alexander Shaduri f4c1cebfd0 Update cron script to use json. 2024-05-17 11:24:52 +04:00
Alexander Shaduri 7cef499e67 Use ubuntu-24.04 for Actions as ubuntu-latest does not have gcc13 as of now. 2024-05-16 17:04:37 +04:00
Alexander Shaduri e40da83827 Merge pull request #60 from ashaduri/stdregex
PCRE to std::regex port
2024-05-16 16:49:27 +04:00
Alexander Shaduri d916dc4a9d Removed mention of any pcre dependency. 2024-05-16 16:47:44 +04:00
Alexander Shaduri 791cc93f5f Fixed std::regex-based parsing. 2024-05-16 16:41:39 +04:00
Alexander Shaduri 1df72dc2e0 Initial port from pcre to std::regex (not working yet). 2024-05-16 16:27:18 +04:00
Alexander Shaduri cf3a9f6ae3 Partial port from pcre to std::regex. 2024-05-16 15:13:34 +04:00
Alexander Shaduri 946f4b4339 Fix test failure under Arm architecture. 2024-05-15 13:48:48 +04:00
Alexander Shaduri e88a0b5ca3 Limit the VM memory. 2024-05-15 13:42:50 +04:00
Alexander Shaduri 6d23e01a82 Fixed running tests under Arm. 2024-05-15 13:42:38 +04:00
Alexander Shaduri 0f8c6039ce Update GitHub actions. 2024-05-15 13:12:49 +04:00
Alexander Shaduri 2abae1c673 Update GitHub actions. 2024-05-15 13:07:05 +04:00
Alexander Shaduri 1e16d7b521 Update GitHub actions. 2024-05-15 12:26:40 +04:00
Alexander Shaduri 55dade8b51 Install clang. 2024-05-15 12:18:42 +04:00
Alexander Shaduri 2e53d3e4c9 Try AppleClang 16. 2024-05-15 12:09:52 +04:00
Alexander Shaduri 4a0ce23184 Compile with AppleClang 15. 2024-05-15 12:00:33 +04:00
Alexander Shaduri 02535eeeb2 Update GitHub actions. 2024-05-14 18:35:42 +04:00
Alexander Shaduri 6d49968a59 Fix make_format_args() calls. 2024-05-14 18:30:46 +04:00
Alexander Shaduri 84ae416c2c Removed AODC feature, it's been deprecated for a while. 2024-05-14 17:42:46 +04:00
Alexander Shaduri dd4fd4d187 Fixed loading text files as virtual devices (size parsing, ATA detection). 2024-05-14 17:26:51 +04:00
Alexander Shaduri ade001359b Implemented loading virtual drives from JSON. 2024-05-14 16:57:01 +04:00
Alexander Shaduri ac2d3d6b33 Implement proper SMART on/off switch support detection. 2024-05-14 15:55:12 +04:00
Alexander Shaduri 537ea258ca NVMe: Full support for self-testing. 2024-05-14 15:41:27 +04:00
Alexander Shaduri 32302c6a80 Info Window: Fixed refresh not working with treeviews. 2024-05-14 15:11:06 +04:00
Alexander Shaduri 5ba969c561 NVMe: Support self-test log and running self-tests (untested). 2024-05-14 14:27:24 +04:00
Alexander Shaduri 5a4e60f645 Format LBA in locale-aware way. 2024-05-14 14:26:37 +04:00
Alexander Shaduri 456feb645a NVMe: Show Error Log. 2024-05-14 11:50:27 +04:00
Alexander Shaduri 556a82e42b NVMe: Show attributes in Info window. 2024-05-13 18:11:06 +04:00
Alexander Shaduri 57f7b6d000 Make Info window display tabs only if properties with appropriate sections are available. 2024-05-13 17:17:24 +04:00
Alexander Shaduri 67a0b128f7 Display info properly for flash drives. 2024-05-13 16:49:07 +04:00
Alexander Shaduri f60f08327c Info Window: Adapt to ATA JSON parser. 2024-05-13 16:48:48 +04:00
Alexander Shaduri 72c01bebba NVMe: Parse error log. 2024-05-13 16:48:26 +04:00
Alexander Shaduri dede4695e9 ATA JSON parser is on par with Text parser now, feature-wise. 2024-05-13 16:48:01 +04:00
Alexander Shaduri 5efefd3576 Implemented NVMe self-test log parsing.
Refactoring AtaStorageProperty -> StorageProperty.
2024-05-07 19:36:40 +04:00
Alexander Shaduri 516eaa2086 Basic NVMe parser implemented. 2024-05-02 15:20:16 +04:00
Alexander Shaduri c3a6f0b624 Implemented detection of device type. 2024-05-02 14:38:31 +04:00
Alexander Shaduri 6594cddb65 Refactored drive data fetch and parsing, and drive types. 2024-05-02 13:47:20 +04:00
Alexander Shaduri bf2343015e Avoid unnecessary exceptions when reading config file. 2024-05-02 13:47:14 +04:00
Alexander Shaduri 228bcf5014 Fixed enum_helper.h errors. 2024-05-02 13:46:49 +04:00
Alexander Shaduri 589263e902 etc... -> etc. 2024-04-25 16:53:30 +04:00
Alexander Shaduri 02bdf755a3 Fixed crash on reload; tables still to be fixed. 2024-04-25 16:44:25 +04:00
Alexander Shaduri 61fe92e201 ATA JSON parser improvements. 2024-04-24 15:58:45 +04:00
Alexander Shaduri 1b7264793e ATA JSON parser improvements. 2024-04-24 15:51:01 +04:00
Alexander Shaduri 13fc56c24a Updated visible copyright years. 2024-04-23 17:18:08 +04:00
Alexander Shaduri 18a6628d0e Support parsing more of ATA output in JSON. 2024-04-23 17:03:52 +04:00
Alexander Shaduri 5746ab5ed9 GitHub actions: Fix conflicting artifact names. 2024-04-23 16:32:59 +04:00
Alexander Shaduri ac90991a27 GitHub actions: Support smartmontools 7.4 installer directory structure when extracting. 2024-04-23 14:11:31 +04:00
Alexander Shaduri 531d39d888 Smartmontools in Windows uses update-smart-drivedb.ps1 now, so use that. 2024-04-23 13:51:51 +04:00
Alexander Shaduri 68576e9a95 Use smartmontools 7.4 in CI. 2024-04-23 13:31:01 +04:00
Alexander Shaduri f7d9956665 Support parsing ATA Self-test Log in JSON.
UI fixes.
2024-04-23 12:55:23 +04:00
Alexander Shaduri aa0c2e520f Updated GitHub actions to use Node20 versions. 2024-04-22 22:19:14 +04:00
Alexander Shaduri 9ea48c7298 Fix win32 compilation. 2024-04-22 22:05:36 +04:00
Alexander Shaduri c065e55ca1 GH Actions: Use GCC 13, that is the minimum required now. 2024-04-22 18:08:34 +04:00
Alexander Shaduri 2c163503d9 GH Actions: Use GCC 12. 2024-04-22 17:48:34 +04:00
Alexander Shaduri 212b6bfe4f Fix compilation. 2024-04-22 17:22:14 +04:00
Alexander Shaduri ea6998dcad Support parsing ATA Directory Log in JSON. 2024-04-22 17:17:00 +04:00
Alexander Shaduri d6ec442945 Support parsing ATA Attributes in JSON. 2024-04-19 14:21:06 +04:00
Alexander Shaduri 6da27f7e86 Support parsing ATA Capabilities from JSON. 2024-04-19 11:47:48 +04:00
Alexander Shaduri 50d605b5b4 Updated .clang-tidy to ignore library headers. 2024-04-19 11:47:25 +04:00
Alexander Shaduri b147a3db3e Ported some more of string_algo.h to string_view. 2024-04-19 11:46:51 +04:00
Alexander Shaduri 6018f35598 Disable std::filesystem TR support, we require C++20 anyway. 2024-04-16 12:40:10 +04:00
Alexander Shaduri fccf448b3a Bundle and use tl::expected instead of std::expected to support C++20 compilers. 2024-04-16 12:39:22 +04:00
Alexander Shaduri 0cd846728c Fixed compiler warnings. 2024-04-15 17:15:00 +04:00
Alexander Shaduri 876e29973c Simplified AtaStorageProperty by mergin Section and SubSection. 2024-04-15 16:29:51 +04:00
Alexander Shaduri 351f5edaa9 Switched most of message-based error handling to std::expected.
Refactored enum class naming to use ThisCase.
Decorated most getters with [[nodiscard]].
2024-03-22 18:21:08 +04:00
Alexander Shaduri 6edcf19694 Implemented Basic Output JSON parser.
Switched all devices to JSON by default.
2024-03-20 23:11:50 +04:00
Alexander Shaduri 73463e5c23 Cleanup of output format / device type handling. 2024-03-20 20:57:16 +04:00
Alexander Shaduri 21267acb8c Separate out basic text parser from StorageDevice.
Store all properties in StoragePropertyRepository.
2024-03-20 20:29:19 +04:00
Alexander Shaduri 9889f8792f Initial work on JSON parser. 2024-03-19 16:16:36 +04:00
Alexander Shaduri ae5a327116 Initial work on JSON parser. 2024-03-15 17:33:24 +04:00
Alexander Shaduri 8b12bb45c3 Initial work on JSON parser. 2024-03-15 16:59:14 +04:00
Alexander Shaduri a32b9fb8a9 Initial work on JSON parser. 2024-03-14 16:06:16 +04:00
Alexander Shaduri eb44ed1bc5 Some code modernization. 2024-03-14 13:52:46 +04:00
Alexander Shaduri 5fe252934c Disabled false positive. 2024-03-11 15:25:38 +04:00
Alexander Shaduri 3c4a740759 Improved constness of local variables. 2024-03-11 15:25:14 +04:00
Alexander Shaduri 29555ed584 Ported away from deprecated u8path(). 2024-03-11 14:53:05 +04:00
Alexander Shaduri f454b9df2d Disabled noisy warnings. 2024-03-11 14:50:21 +04:00
Alexander Shaduri 6266ce3c6c Ported SmartctlParser to std::expected, added hz::ErrorContainer as a helper. 2024-03-11 14:50:08 +04:00
Alexander Shaduri d0cfd73fab Removed leaf, porting to std::expected. 2024-03-07 14:39:08 +04:00
Alexander Shaduri 985700c79d Moved to C++23, making the code compatible with it (u8string / u8path incompatibilities). 2024-03-07 14:38:44 +04:00
Alexander Shaduri e650fa4d8b Fixed a typo. 2024-02-29 18:28:35 +04:00
Alexander Shaduri 72b2173dfc Make sure to require Gtkmm. 2024-02-29 18:28:16 +04:00
Alexander Shaduri 7f688e0fa4 Initial work on JSON parser. 2023-03-06 19:18:48 +04:00
Alexander Shaduri c8f79c36b4 Minor cleanups. 2023-03-06 19:18:16 +04:00
Alexander Shaduri 396ea3daf3 Fixed some clang-tidy warnings. 2023-03-03 23:00:52 +04:00
Alexander Shaduri c4b2c1d760 Merge pull request #41 from ferdnyc/no-warn-printf
FindFilesystem: Eliminate Win32 warning
2023-01-16 13:32:31 +04:00
FeRD (Frank Dana) 0bf4ef711e FindFilesystem: Eliminate Win32 warning
Using `printf("%s")` with a `std::filesystem::path` on Win32 will
cause a compile warning, because `std::filesystem::path::value_type`
is technically `wchar_t`.

The warning is harmless, but by using iostream to print the value
on `std::cout` instead, the code compiles without warnings.
2023-01-15 12:54:17 -05:00
Alexander Shaduri affdd497ec Updated GitHub actions to use Node16 (try 2). 2023-01-09 18:18:29 +04:00
Alexander Shaduri 6b6bd2e369 GitHub action: Fix codeql. 2023-01-09 17:44:05 +04:00
Alexander Shaduri 466b4f9a0f GitHub action: Install pcre in msys2. 2023-01-09 17:43:02 +04:00
Alexander Shaduri e90aad5994 Updated GitHub actions to use Node16. 2023-01-09 17:41:21 +04:00
Alexander Shaduri 338c8a8eee Merge remote-tracking branch 'origin/main' 2023-01-09 17:28:04 +04:00
Alexander Shaduri a390c3daa6 Updated Catch2 to 2.13.10. 2023-01-09 17:27:52 +04:00
Alexander Shaduri 9e0dbe67e6 Ignore doxygen_doc in git. 2023-01-09 17:14:03 +04:00
Alexander Shaduri 6b02bf5df0 Update _config.yml 2022-09-14 12:38:20 +04:00
Alexander Shaduri 029f519005 Update SECURITY.md 2022-06-17 12:35:41 +04:00
Alexander Shaduri b6248459be Update issue templates 2022-06-17 12:34:08 +04:00
Alexander Shaduri 51e3b2a1f7 Update issue templates 2022-06-17 12:33:50 +04:00
Alexander Shaduri b2504e9477 Update issue templates 2022-06-17 12:32:35 +04:00
Alexander Shaduri ec6ddd1c5c Update SECURITY.md 2022-06-17 12:30:44 +04:00
Alexander Shaduri 60705fe93b Update issue templates 2022-06-17 12:29:37 +04:00
Alexander Shaduri cf407da41b Update issue templates 2022-06-17 12:27:01 +04:00
Alexander Shaduri 5435feb932 Windows: Make sure we consider non-fixed drives as well, when detecting "Drive letters" for a drive. 2022-05-20 13:04:26 +04:00
Alexander Shaduri 02e4f8e536 GitHub Actions: Use github.workspace instead of runner.workspace. 2022-03-15 14:12:30 +04:00
Alexander Shaduri db090f9164 Updated github pages: Document NSIS options. 2022-02-18 12:12:40 +04:00
Alexander Shaduri 70967beebf Implemented smartctl output format detection function, along with its test. 2022-02-16 17:33:05 +04:00
Alexander Shaduri 5b7c2f6dbb Added helper for testing leaf-created errors. 2022-02-16 17:32:20 +04:00
Alexander Shaduri 2d7a3a4dd9 Updated clang-tidy configuration to exclude noisy warnings. 2022-02-16 17:30:06 +04:00
Alexander Shaduri 01d699fc74 Make sure the third-party libraries are always included as "system". 2022-02-15 16:30:27 +04:00
Alexander Shaduri 6ed82f821f Added a Boost LEAF library copy. 2022-02-15 16:29:45 +04:00
Alexander Shaduri c59fa32efe Added a Boost LEAF library copy. 2022-02-15 16:22:41 +04:00
Alexander Shaduri dbdb0e4686 Fixed compilation. 2022-02-15 16:22:00 +04:00
Alexander Shaduri fc0df14992 Refactored smartctl output parser for better API, support for different formats. 2022-02-15 15:56:42 +04:00
Alexander Shaduri a5771f1af9 Updated OBS workflows. 2022-02-15 14:03:35 +04:00
Alexander Shaduri 4db097b0b0 Update cmake requirement to 3.14. 2022-02-15 14:03:24 +04:00
Alexander Shaduri 65e4c4f7ac Revert "Fixed test link errors on Debian 10."
This reverts commit 5009fbfbe4.
2022-02-15 14:01:51 +04:00
Alexander Shaduri d1df4b2fad Updated OBS workflows. 2022-02-15 13:44:01 +04:00
Alexander Shaduri 5009fbfbe4 Fixed test link errors on Debian 10. 2022-02-15 13:42:43 +04:00
Alexander Shaduri cbfcf2bb3c Updated OBS workflows. 2022-02-15 12:58:32 +04:00
Alexander Shaduri 63e16d0bac Updated OBS workflows. 2022-02-14 17:27:51 +04:00
Alexander Shaduri cd58c6ce90 Updated OBS workflows. 2022-02-14 15:29:41 +04:00
Alexander Shaduri 6787b3c1fe Updated OBS workflows. 2022-02-14 15:27:04 +04:00
Alexander Shaduri 980ff6f150 Updated OBS workflows. 2022-02-14 15:25:16 +04:00
Alexander Shaduri ef5f97ad88 Updated OBS workflows. 2022-02-14 15:20:21 +04:00
Alexander Shaduri 9ad97c8390 Added OBS workflow integration. 2022-02-14 14:33:12 +04:00
Alexander Shaduri 8256ea2115 Fixed CodeQL workflow. 2022-02-14 14:32:51 +04:00
Alexander Shaduri b6f97ba0a4 Updated github actions. 2022-02-14 13:46:42 +04:00
Alexander Shaduri 88a36c6f57 Changed internal property names to match smartctl's json paths. 2022-02-14 13:21:23 +04:00
Alexander Shaduri 8932460b8c Updated github pages. 2022-02-13 13:43:21 +04:00
Alexander Shaduri 7e570cea45 Refactored parse_byte_size out of SmartctlAtaTextParser. 2022-02-11 18:04:54 +04:00
Alexander Shaduri 1d781d3d54 Code cleanups. 2022-02-11 16:01:10 +04:00
Alexander Shaduri c1070e375f Added initial work for selecting smartctl parser type.
Refactored smartctl version parsing, added tests.
2022-02-11 16:00:21 +04:00
Alexander Shaduri 582d4ad5cd Converted hz string algorithms example into a test. 2022-02-11 14:08:57 +04:00
Alexander Shaduri 907c9ac423 Refactored example_string_num.cpp into a test.
Fixed underflow detection for unsigned types in hz::string_is_numeric().
2022-02-11 13:43:22 +04:00
Alexander Shaduri f9c805648a Converted hz unit formatting example into a test. 2022-02-10 17:17:06 +04:00
Alexander Shaduri 94e3e864bc Merge remote-tracking branch 'origin/main' into main 2022-02-10 16:45:45 +04:00
Alexander Shaduri 53acbd9594 libdebug: Removed C-style debug_print*() functions, ported everything to debug_out_*(). 2022-02-10 16:45:33 +04:00
Alexander Shaduri 085f066958 rconfig: A safer way to pass data to a C callback. 2022-02-10 16:44:08 +04:00
Alexander Shaduri 594f177160 Merge pull request #27 from skitt/lcall
Set LC_ALL to control the locale of other processes.
2022-02-10 12:18:23 +04:00
Stephen Kitt c53166f630 Set LC_ALL to control the locale
LANG specifies the default locale, LC_NUMERIC specifies the locale for
that particular category, but LC_ALL overrides all the locale
settings. Thus any user with LC_ALL set can still run into
locale-related problems.

Setting LC_ALL to C avoids any such issue.

See locale(7) for details.

Signed-off-by: Stephen Kitt <steve@sk2.org>
2022-02-10 08:26:34 +01:00
Alexander Shaduri 64f4a8077e Updated links to the new gsmartcontrol.shaduri.dev site. 2022-02-09 17:51:09 +04:00
Alexander Shaduri a4bfdcefa8 Updated github pages. 2022-02-09 17:33:20 +04:00
Alexander Shaduri e6b83c7473 Updated links to online documentation. 2022-02-08 19:21:45 +04:00
Alexander Shaduri 107292a328 Updated github pages. 2022-02-08 19:16:25 +04:00
Alexander Shaduri 9f31c845ee Updated github pages. 2022-02-08 18:39:26 +04:00
Alexander Shaduri 3acee26d05 Updated github pages. 2022-02-08 18:36:44 +04:00
Alexander Shaduri 1b260fd745 Updated github pages. 2022-02-08 18:35:32 +04:00
Alexander Shaduri 02dd6176d7 Updated github pages. 2022-02-08 18:32:33 +04:00
Alexander Shaduri d19c6acadd Updated github pages. 2022-02-08 18:26:53 +04:00
Alexander Shaduri 911ec96207 Updated github pages. 2022-02-08 18:10:21 +04:00
Alexander Shaduri 1cefc9d9ba Updated github pages. 2022-02-08 17:27:56 +04:00
Alexander Shaduri da1b73feee Updated github pages. 2022-02-08 17:22:10 +04:00
Alexander Shaduri 8ce7d781a4 Updated github pages. 2022-02-08 17:16:55 +04:00
Alexander Shaduri 3db5941757 Updated github pages. 2022-02-08 16:56:15 +04:00
Alexander Shaduri 8b925ae0c4 Updated github pages. 2022-02-08 15:31:34 +04:00
Alexander Shaduri ea7f65725e Updated github pages and README.md. 2022-02-08 15:28:13 +04:00
Alexander Shaduri 137736d6eb Updated github pages. 2022-02-08 13:05:27 +04:00
Alexander Shaduri d0136e6a71 Updated github pages. 2022-02-07 19:05:35 +04:00
Alexander Shaduri 9abb0ff3a9 Update README.md 2022-02-04 15:42:05 +04:00
Alexander Shaduri b706b114b3 Use ubuntu-latest in github action. 2022-02-04 14:33:41 +04:00
Alexander Shaduri 3085c037ba Bumped Debian package compatibility level to 9. 2022-02-04 14:29:43 +04:00
Alexander Shaduri c34ddd32a5 Split github tier2 builds into standard and flaky actions. 2022-02-04 14:29:26 +04:00
Alexander Shaduri 3c10a1e12a Fix syntax errors in cs.po. 2022-02-04 14:24:19 +04:00
Alexander Shaduri a154a813ad Use Catch2 v2 instead of v3 due to build errors with latest compilers. 2022-02-04 14:24:01 +04:00
Alexander Shaduri 3b5c7365a1 Windows: Embed exe manifest in the resource; don't handle the manifest in NSIS. 2022-02-04 12:02:44 +04:00
Alexander Shaduri 0f78b7e91c Windows: Set GTK_CSD=0 only if no GTK_CSD is set. 2022-02-04 12:02:04 +04:00
Alexander Shaduri cf93bf008f Updated Catch2 to git devel branch 2022-02-02. 2022-02-02 23:42:47 +04:00
Alexander Shaduri 2bbe7788f1 Ubuntu package: Fixed support for Ubuntu 21.10 on OBS. 2022-02-02 23:37:21 +04:00
Alexander Shaduri 025348bfe3 Remove trailing slash from homepage URL. 2022-02-02 23:14:15 +04:00
Alexander Shaduri 4cf809b579 Debian package: Fixed support for Debian Testing and Debian Unstable on OBS. 2022-02-02 23:13:53 +04:00
Alexander Shaduri 9e1d92a7bc Debian package: Build tests and examples, this should fix OBS build failures. 2022-02-02 23:09:20 +04:00
Alexander Shaduri ef94137edc Info Window: Make the text views with output texts use monospace font with the new GTK versions. 2022-02-01 13:46:43 +04:00
Alexander Shaduri 910f71ec9e Info Window: Align and monospace table cells where applicable to improve readability. 2022-02-01 13:31:18 +04:00
Alexander Shaduri f4973cdb4b Handle all tree view styling in per-table cell renderers; this fixes conflicts between renderer styles and markup. 2022-02-01 12:51:48 +04:00
Alexander Shaduri 4dcc8e23e7 List all gtkmm deprecation macros for future reference. 2022-02-01 12:45:41 +04:00
Alexander Shaduri 044193c7ed Command execution popup windows: Use "dialog" type of window instead of "notifications"; this should fix #17 (the popup is floating above all the other applications). 2022-01-31 15:29:14 +04:00
Alexander Shaduri 29b2bb6635 Merge remote-tracking branch 'origin/main' into main 2022-01-31 15:11:12 +04:00
Alexander Shaduri d9f0314655 Code cleanup - reduce std::wcslen usage. 2022-01-31 15:11:04 +04:00
Alexander Shaduri af6c230edc Update devskim-analysis.yml 2022-01-31 15:09:50 +04:00
Alexander Shaduri 01746ab16d Ported some win32_tools.h code to std::filesystem. 2022-01-31 14:38:31 +04:00
Alexander Shaduri 5865134b29 Code cleanup - reduce std::strlen usage. 2022-01-29 22:27:12 +04:00
Alexander Shaduri 39d033c50d Fixed Codacy note in shell script. 2022-01-29 21:48:35 +04:00
Alexander Shaduri f64b3bc82d Added license badge to README.md 2022-01-29 21:45:01 +04:00
Alexander Shaduri 3f2353cc57 Updated README.md for style. 2022-01-29 21:29:49 +04:00
Alexander Shaduri bc20a790da Merge remote-tracking branch 'origin/main' into main 2022-01-29 21:27:48 +04:00
Alexander Shaduri a238770418 Update style. 2022-01-29 21:25:47 +04:00
Alexander Shaduri 90eb339a05 Fixed Codacy warnings in shell scripts. 2022-01-29 21:12:36 +04:00
Alexander Shaduri fa16ff964e Merge remote-tracking branch 'origin/main' into main 2022-01-29 11:57:08 +04:00
Alexander Shaduri ebb864f234 Add nullptr check to on_cell_data_render(), just in case. 2022-01-29 11:56:54 +04:00
Alexander Shaduri 01a33b97a7 Merge pull request #25 from codacy-badger/codacy-badge
Add a Codacy badge to README.md
2022-01-27 23:07:22 +04:00
Alexander Shaduri 8b05464444 Delete msvc-analysis.yml 2022-01-27 23:04:16 +04:00
The Codacy Badger 977396e852 Add Codacy badge 2022-01-27 18:33:50 +00:00
Alexander Shaduri 84b6e84c49 Update devskim-analysis.yml 2022-01-27 22:19:55 +04:00
Alexander Shaduri 33b96b459e Update msvc-analysis.yml 2022-01-27 22:18:08 +04:00
Alexander Shaduri a095f9f6bd Delete scorecards-analysis.yml 2022-01-27 22:01:48 +04:00
Alexander Shaduri 828558bfcc Update devskim-analysis.yml 2022-01-27 21:57:52 +04:00
Alexander Shaduri e49b0cbf8c Update codeql-analysis.yml 2022-01-27 21:49:28 +04:00
Alexander Shaduri 39fc4b2997 Create CODE_OF_CONDUCT.md 2022-01-25 17:14:04 +04:00
Alexander Shaduri 5d2925fd94 Create SECURITY.md 2022-01-25 17:08:56 +04:00
Alexander Shaduri f6a2a1cab5 Create scorecards-analysis.yml 2022-01-25 17:05:30 +04:00
Alexander Shaduri 661bcfe56e Create msvc-analysis.yml 2022-01-25 17:04:03 +04:00
Alexander Shaduri 821da2ce29 Create devskim-analysis.yml 2022-01-25 17:03:11 +04:00
Alexander Shaduri 38ee3fabd9 Create codacy-analysis.yml 2022-01-25 17:02:01 +04:00
Alexander Shaduri ac54d29f66 Create codeql-analysis.yml 2022-01-25 17:00:46 +04:00
Alexander Shaduri b27b04ebf0 Fixed building under Windows. 2022-01-25 16:54:42 +04:00
Alexander Shaduri 055438e740 Place less code in #ifdef _WIN32 to make platform-specific compilation less error-prone. 2022-01-25 16:42:10 +04:00
529 changed files with 68555 additions and 44157 deletions
+17 -3
View File
@@ -2,22 +2,28 @@
# Exceptions:
# bugprone-branch-clone is too noisy in parsing code.
# cert-dcl50-cpp is triggered by debug_print()'s C style.
# bugprone-easily-swappable-parameters is too noisy.
# cert-dcl50-cpp is triggered by hz::string_sprintf()'s C style.
# clang-analyzer-deadcode.DeadStores is too noisy.
# clang-analyzer-cplusplus.NewDeleteLeaks doesn't understand Gtkmm memory management.
# cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers is triggered by attribute database.
# cppcoreguidelines-avoid-do-while is triggered in DBG macros.
# cppcoreguidelines-owning-memory doesn't support deleting Gtkmm objects.
# cppcoreguidelines-pro-type-cstyle-cast needed by GTK C casts.
# cppcoreguidelines-pro-type-reinterpret-cast is needed by WinAPI-facing functions
# cppcoreguidelines-pro-type-vararg is triggered by libdebug's debug_print().
# cppcoreguidelines-pro-bounds-array-to-pointer-decay is triggered by va_start in libdebug's debug_print().
# cppcoreguidelines-pro-type-vararg is triggered by hz::string_sprintf().
# cppcoreguidelines-pro-bounds-array-to-pointer-decay is triggered by va_start in hz::string_sprintf().
# cppcoreguidelines-pro-bounds-pointer-arithmetic is useless (triggered by argv) until we have std::span.
# misc-include-cleaner does not really work.
# misc-no-recursion is too noisy.
# modernize-raw-string-literal is very noisy.
# modernize-use-trailing-return-type is contrary to our style.
# performance-enum-size is too noisy.
# readability-avoid-unconditional-preprocessor-if is triggered on platform-specific code
# readability-convert-member-functions-to-static is triggered for many callbacks.
# readability-function-cognitive-complexity needed by UI constructors.
# readability-isolate-declaration is noisy.
# readability-identifier-length is too noisy.
Checks: >
@@ -27,6 +33,7 @@ Checks: >
-boost-*,
bugprone-*,
-bugprone-branch-clone,
-bugprone-easily-swappable-parameters,
cert-*,
-cert-dcl50-cpp,
clang-analyzer-*,
@@ -35,6 +42,7 @@ Checks: >
concurrency-*,
cppcoreguidelines-*,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-avoid-do-while,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-pro-type-cstyle-cast,
@@ -49,6 +57,7 @@ Checks: >
-llvm-*,
-llvmlibc-*,
misc-*,
-misc-include-cleaner,
-misc-no-recursion,
modernize-*,
-modernize-use-trailing-return-type,
@@ -57,12 +66,15 @@ Checks: >
-objc-*,
openmp-*,
performance-*,
-performance-enum-size,
portability-*,
readability-*,
-readability-avoid-unconditional-preprocessor-if,
-readability-convert-member-functions-to-static,
-readability-function-cognitive-complexity,
-readability-isolate-declaration,
-readability-magic-numbers,
-readability-identifier-length,
-zircon-*
WarningsAsErrors: ''
@@ -82,6 +94,8 @@ CheckOptions:
value: '0'
- key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
value: '1'
- key: misc-include-cleaner.IgnoreHeaders
value: 'libdebug/*;local_glibmm.h;glib/*;gtk/*;gtkmm/*;glibmm/*'
- key: performance-unnecessary-value-param.AllowedTypes
value: 'RefPtr;Ptr$'
- key: readability-braces-around-statements.ShortStatementLines
+28
View File
@@ -0,0 +1,28 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug, enhancement
assignees: ashaduri
---
**Version and Environment**
- GSmartControl version: [Are you using the latest released version or git?]
- OS: [e.g. openSUSE Linux 15.5]
**Describe the Bug**
[A clear and concise description of what the bug is].
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Screenshots**
[If applicable, add screenshots to help explain your problem].
**Additional Context**
[Add any other context about the problem here (GTK+ version, etc.)]
+24
View File
@@ -0,0 +1,24 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ashaduri
---
**Version and Environment**
- GSmartControl version: [Are you using the latest released version or git?]
- OS: [e.g. openSUSE Linux 15.5]
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+15
View File
@@ -0,0 +1,15 @@
---
name: Other issue
about: Issues other than bugs and enhancements
title: ''
labels: ''
assignees: ashaduri
---
**Version and Environment**
- GSmartControl version: [Are you using the latest released version or git?]
- OS: [e.g. openSUSE Linux 15.5]
**Describe the Issue**
[A clear and concise description of what the issue is].
+124
View File
@@ -0,0 +1,124 @@
# GSmartControl – Copilot Instructions
GSmartControl is a C++20 GTK3/Gtkmm GUI for inspecting hard-drive and SSD health via SMART data
(wrapping `smartctl` from smartmontools). It supports Linux, Windows (MSYS2/MinGW), macOS, and BSDs.
## Build
```bash
mkdir build && cd build
# Standard Linux build (uses dev toolchain with warnings enabled)
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_TOOLCHAIN_FILE=../toolchains/linux-dev.cmake
# Windows (MSYS2/MinGW64)
cmake .. -G "MSYS Makefiles" \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_TOOLCHAIN_FILE=../toolchains/win64-mingw-msys2.cmake
# Build on MSYS2/MinGW64 (from build dir)
cmake --build . --target all -j 18
```
The `configure-dev` script is a convenience wrapper: `./configure-dev -t <toolchain> -c <compiler> -b <build_type>`.
Key CMake options:
- `-DAPP_BUILD_TESTS=ON` – enable test targets
- `-DAPP_BUILD_EXAMPLES=ON` – enable example targets
- `-DAPP_COMPILER_ENABLE_WARNINGS=ON` – strict compiler warnings (set automatically by `linux-dev.cmake`)
## Tests
Tests use **Catch2** (vendored in `dependencies/catch2/`). They are only built when `-DAPP_BUILD_TESTS=ON` is passed.
```bash
# Build and run all tests
cmake .. -DAPP_BUILD_TESTS=ON
cmake --build .
ctest -C RelWithDebInfo --rerun-failed --output-on-failure
# Run a single test executable directly (from build dir)
./test_all "[smartctl_parser]" # Catch2 tag filter
./test_all "test name substring" # substring match
```
Test sources live in `src/applib/tests/` and `src/hz/tests/`; they are linked into `src/test_all/`.
## Linting
Clang-tidy config is at `.clang-tidy` in the repo root. Run it via CMake or directly:
```bash
clang-tidy src/applib/storage_device.cpp -- -std=c++20 $(pkg-config --cflags gtkmm-3.0)
```
## Architecture
The codebase is split into libraries and one GUI executable:
| Component | Location | Purpose |
|---|---|---|
| `applib` | `src/applib/` | Core logic: SMART parsing, device detection, command execution |
| `hz` | `src/hz/` | General-purpose C++ utilities (strings, filesystem, error types) |
| `rconfig` | `src/rconfig/` | Runtime config load/save with auto-save support |
| `libdebug` | `src/libdebug/` | Debug logging with named channels |
| `gui` | `src/gui/` | GTK/Gtkmm UI (windows, dialogs, Glade `.ui` files) |
### Parsing pipeline
`smartctl` output is parsed through a strategy pattern:
- JSON parsers (`smartctl_json_ata_parser`, `smartctl_json_nvme_parser`, `smartctl_json_basic_parser`) target smartctl ≥ 7.3.
- Text parsers (`smartctl_text_ata_parser`, `smartctl_text_basic_parser`) handle legacy output.
- Parsed results are stored as `StorageProperty` objects in a `StoragePropertyRepository` on `StorageDevice`.
### Device detection
`StorageDetector` is an abstract interface; platform implementations are:
- `storage_detector_linux.cpp` – scans `/dev/sd*`, `/dev/nvme*`, etc.
- `storage_detector_win32.cpp` – WMI/registry enumeration
- `storage_detector_other.cpp` – generic `/dev` scanning (BSD/macOS)
### Async execution
`AsyncCommandExecutor` wraps `CommandExecutor` (which shells out to `smartctl`) in a background thread.
Completion is signalled via **libsigc++** signals back to the GTK main loop. Never call GTK APIs from the worker thread;
queue them through signals or `Glib::signal_idle()`.
### Error handling
Use `hz::ExpectedValue<T, E>` (wrapping `tl::expected`) for recoverable errors instead of exceptions.
Enum-based error types (`StorageDeviceError`, `SmartctlParserError`) are preferred over string errors.
## Key Conventions
**Naming:**
- Classes: `PascalCase` (e.g., `StorageDevice`, `SmartctlParser`)
- Methods and members: `snake_case`; private/member fields have a trailing `_` (e.g., `device_list_`)
- GUI classes in `src/gui/` are prefixed `Gsc` (e.g., `GscMainWindow`)
- Filenames: `snake_case.cpp` / `snake_case.h`
**Headers:**
- Use `#ifndef FILENAME_H` / `#define FILENAME_H` guards (not `#pragma once`)
- Include order: standard library → third-party (GTK/Gtkmm) → project headers
- All project headers are included relative to `src/` (the include root)
**Modern C++20/23 patterns used throughout:**
- `std::optional<T>` for nullable values
- `hz::ExpectedValue<T, E>` for error-returning functions
- `std::string_view` for non-owning string parameters
- `fmt::format()` (vendored `fmt` library) for string formatting
- Smart pointers exclusively; no raw owning pointers
**Vendored dependencies** are in `dependencies/` and added via `add_subdirectory`.
Do not modify them; prefer upgrading the whole vendored copy.
**Translations:** UI strings are wrapped with `_()` (gettext). `.po` files live in `po/`.
Translations are not yet supported.
**Platform guards:** Use `#ifdef CONFIG_KERNEL_FAMILY_WINDOWS`,
`#ifdef CONFIG_KERNEL_LINUX`, etc.
## Agentic Development
Place all plans and temporary files in `agent_workspace/`. This directory is ignored by Git.
+139 -55
View File
@@ -13,54 +13,107 @@ on:
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: RelWithDebInfo
SMARTMONTOOLS_INSTALLER: smartmontools-7.2-1.win32-setup.exe
SMARTMONTOOLS_URL: https://nav.dl.sourceforge.net/project/smartmontools/smartmontools/7.2/smartmontools-7.2-1.win32-setup.exe
SMARTMONTOOLS_INSTALLER: smartmontools-7.4-1.win32-setup.exe
SMARTMONTOOLS_URL: https://downloads.sourceforge.net/project/smartmontools/smartmontools/7.4/smartmontools-7.4-1.win32-setup.exe
jobs:
linux-ubuntu:
runs-on: ubuntu-20.04
linux-ubuntu-24_04:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Update Package Database
run: sudo apt-get update
- name: Install Dependencies
run: sudo apt-get install libpcre3-dev libgtkmm-3.0-dev gettext
run: sudo apt-get install libgtkmm-3.0-dev gettext
- name: Create Build Directory
run: cmake -E make_directory ${{runner.workspace}}/build
run: cmake -E make_directory build
- name: Configure CMake
shell: bash
working-directory: ${{runner.workspace}}/build
working-directory: ${{github.workspace}}/build
env:
CC: gcc-14
CXX: g++-14
run: >
cmake $GITHUB_WORKSPACE
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DAPP_BUILD_EXAMPLES=ON
-DAPP_BUILD_TESTS=ON
-DAPP_COMPILER_ENABLE_WARNINGS=ON
-DCMAKE_TOOLCHAIN_FILE="$GITHUB_WORKSPACE/toolchains/linux-dev.cmake"
- name: Build
shell: bash
working-directory: ${{runner.workspace}}/build
working-directory: ${{github.workspace}}/build
run: cmake --build . --config $BUILD_TYPE
- name: Test
working-directory: ${{runner.workspace}}/build
working-directory: ${{github.workspace}}/build
shell: bash
run: ctest -C $BUILD_TYPE
run: ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
- name: Pack (cmake install and make binary package)
shell: bash
working-directory: ${{runner.workspace}}/build
working-directory: ${{github.workspace}}/build
run: cpack -G TBZ2
- name: Upload artifacts
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: Linux Packages
path: ${{runner.workspace}}/build/gsmartcontrol-*-Linux*.*
path: ${{github.workspace}}/build/gsmartcontrol-*-Linux*.*
linux-ubuntu-22_04:
# GCC 11
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Update Package Database
run: sudo apt-get update
- name: Install Dependencies
run: sudo apt-get install libgtkmm-3.0-dev gettext
- name: Create Build Directory
run: cmake -E make_directory build
- name: Configure CMake
shell: bash
working-directory: ${{github.workspace}}/build
env:
CC: gcc-11
CXX: g++-11
run: >
cmake $GITHUB_WORKSPACE
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DCMAKE_TOOLCHAIN_FILE="$GITHUB_WORKSPACE/toolchains/linux-dev.cmake"
- name: Build
shell: bash
working-directory: ${{github.workspace}}/build
run: cmake --build . --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build
shell: bash
run: ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
- name: Pack (cmake install and make binary package)
shell: bash
working-directory: ${{github.workspace}}/build
run: cpack -G TBZ2
# - name: Upload artifacts
# uses: actions/upload-artifact@v4
# with:
# name: Linux Packages
# path: ${{github.workspace}}/build/gsmartcontrol-*-Linux*.*
windows-msys2:
@@ -68,12 +121,13 @@ jobs:
strategy:
matrix:
include: [
{ msystem: MINGW64, arch: x86_64 },
{ msystem: MINGW32, arch: i686 }
{ msystem: MINGW64, arch: x86_64, platform: win64, urlpath: mingw64 },
# MSYS2 no longer supports for 32-bit Windows.
# { msystem: MINGW32, arch: i686, platform: win32, urlpath: mingw32 }
]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: msys2/setup-msys2@v2
# p7zip is needed to extract smartmontools
@@ -87,79 +141,109 @@ jobs:
mingw-w64-${{ matrix.arch }}-cmake
mingw-w64-${{ matrix.arch }}-gcc
mingw-w64-${{ matrix.arch }}-fontconfig
mingw-w64-${{ matrix.arch }}-nsis
make
p7zip
- name: Configure CMake
- name: Downgrade Packages to support Windows 7
# librsvg 2.59 requires Windows 8.1 or later (confirmed by dependency walker).
# We need to downgrade to 2.58.
# This contains gdk_pixbuf loader as well, and re-runs the loader cache update.
# https://repo.msys2.org/mingw/mingw32/mingw-w64-i686-librsvg-2.58.0-1-any.pkg.tar.zst
# https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-librsvg-2.58.0-1-any.pkg.tar.zst
shell: msys2 {0}
working-directory: ${{runner.workspace}}
run: >
cmake -B build -S "$GITHUB_WORKSPACE" -G "MSYS Makefiles"
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DAPP_BUILD_EXAMPLES=ON
-DAPP_BUILD_TESTS=ON
-DAPP_COMPILER_ENABLE_WARNINGS=ON
- name: Build
shell: msys2 {0}
working-directory: ${{runner.workspace}}/build
run: cmake --build . --config $BUILD_TYPE
- name: Test
working-directory: ${{runner.workspace}}/build
shell: msys2 {0}
run: ctest -C $BUILD_TYPE
working-directory: ${{github.workspace}}
run: |
wget https://repo.msys2.org/mingw/${{ matrix.urlpath }}/mingw-w64-${{ matrix.arch }}-librsvg-2.58.0-1-any.pkg.tar.zst
pacman -U --noconfirm mingw-w64-${{ matrix.arch }}-librsvg-2.58.0-1-any.pkg.tar.zst
- name: Download Package Requirements
shell: msys2 {0}
working-directory: ${{runner.workspace}}/build
working-directory: ${{github.workspace}}
run: |
mkdir smartmontools
cd smartmontools
mkdir -p build/smartmontools
cd build/smartmontools
wget $SMARTMONTOOLS_URL
- name: Extract Package Requirements (64-bit)
if: ${{ matrix.msystem == 'MINGW64' }}
shell: msys2 {0}
working-directory: ${{runner.workspace}}/build/smartmontools
working-directory: ${{github.workspace}}/build/smartmontools
run: >
7z -bb1 e $SMARTMONTOOLS_INSTALLER
bin64/smartctl.exe
bin64/smartctl-nc.exe
bin/update-smart-drivedb.exe
bin/smartctl.exe
bin/smartctl-nc.exe
bin/update-smart-drivedb.ps1
bin/drivedb.h
- name: Extract Package Requirements (32-bit)
if: ${{ matrix.msystem == 'MINGW32' }}
shell: msys2 {0}
working-directory: ${{runner.workspace}}/build/smartmontools
working-directory: ${{github.workspace}}/build/smartmontools
run: >
7z -bb1 e $SMARTMONTOOLS_INSTALLER
bin/smartctl.exe
bin/smartctl-nc.exe
bin/update-smart-drivedb.exe
bin32/smartctl.exe
bin32/smartctl-nc.exe
bin/update-smart-drivedb.ps1
bin/drivedb.h
- name: List installed files
shell: msys2 {0}
run: |
ls -1R /mingw64
ls -1R /mingw32
- name: List Files in Workspace
shell: msys2 {0}
working-directory: ${{github.workspace}}
run: ls -1R .
- name: Configure CMake
shell: msys2 {0}
run: >
cmake -B build -S "$GITHUB_WORKSPACE"
-G "MSYS Makefiles"
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DCMAKE_TOOLCHAIN_FILE="$GITHUB_WORKSPACE/toolchains/${{ matrix.platform }}-mingw-msys2.cmake"
- name: Build
shell: msys2 {0}
working-directory: ${{github.workspace}}/build
run: cmake --build . --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build
shell: msys2 {0}
run: ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
- name: Package ZIP
shell: msys2 {0}
working-directory: ${{runner.workspace}}/build
working-directory: ${{github.workspace}}/build
run: cpack -G ZIP
- name: Package NSIS (64-bit)
if: ${{ matrix.msystem == 'MINGW64' }}
shell: msys2 {0}
working-directory: ${{runner.workspace}}/build
working-directory: ${{github.workspace}}/build
run: cpack -G NSIS64
- name: Package NSIS (32-bit)
if: ${{ matrix.msystem == 'MINGW32' }}
shell: msys2 {0}
working-directory: ${{runner.workspace}}/build
working-directory: ${{github.workspace}}/build
run: cpack -G NSIS
- name: Upload artifacts
uses: actions/upload-artifact@v2
if: ${{ matrix.msystem == 'MINGW64' }}
uses: actions/upload-artifact@v4
with:
name: Windows Packages
path: ${{runner.workspace}}/build/gsmartcontrol-*-win*.*
name: Windows 64-Bit Packages
path: ${{github.workspace}}/build/gsmartcontrol-*-win*.*
- name: Upload artifacts
if: ${{ matrix.msystem == 'MINGW32' }}
uses: actions/upload-artifact@v4
with:
name: Windows 32-Bit Packages
path: ${{github.workspace}}/build/gsmartcontrol-*-win*.*
+46
View File
@@ -0,0 +1,46 @@
name: Build (Tier 2 platforms with flaky builds)
# FreeBSD build via vmactions/freebsd-vm is known to fail randomly,
# so we don't want it to be triggered on every commit.
# Manually triggered
on: [workflow_dispatch]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: RelWithDebInfo
CXX: clang++-17
jobs:
freebsd:
runs-on: ubuntu-latest
# env:
# variables to pass to VM
# MYTOKEN : ${{ secrets.MYTOKEN }}
steps:
- uses: actions/checkout@v4
- name: Build and test in FreeBSD
id: test
uses: vmactions/freebsd-vm@v1
with:
envs: 'BUILD_TYPE CXX'
usesh: true
sync: rsync
# release: "14.0"
prepare: >
pkg install -y cmake pkgconf gtkmm30 gettext libiconv llvm17
run: >
mkdir build && cd build
cmake ..
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DAPP_BUILD_EXAMPLES=ON
-DAPP_BUILD_TESTS=ON
-DAPP_COMPILER_ENABLE_WARNINGS=ON
cmake --build . --config $BUILD_TYPE
ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
+41 -42
View File
@@ -1,7 +1,14 @@
name: Build (Tier 2 platforms)
# Manually triggered
on: [workflow_dispatch]
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ main ]
pull_request:
branches: [ main ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
@@ -12,19 +19,31 @@ jobs:
macos-homebrew:
runs-on: macos-latest
strategy:
matrix:
include: [
# We need AppleClang 16, but GitHub only has 14 for now.
# { compiler: apple-clang },
{ compiler: clang }
]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install Dependencies
run: brew install pkg-config gtkmm3 pcre cmake
run: brew install pkg-config gtkmm3 cmake
- name: Install Clang Compiler
if: ${{ matrix.compiler == 'clang' }}
run: brew install llvm@17
- name: Create Build Directory
run: cmake -E make_directory ${{runner.workspace}}/build
run: cmake -E make_directory build
- name: Configure CMake
- name: Configure CMake (Apple Clang)
if: ${{ matrix.compiler == 'apple-clang' }}
shell: bash
working-directory: ${{runner.workspace}}/build
working-directory: ${{github.workspace}}/build
run: >
cmake $GITHUB_WORKSPACE
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
@@ -32,45 +51,25 @@ jobs:
-DAPP_BUILD_TESTS=ON
-DAPP_COMPILER_ENABLE_WARNINGS=ON
- name: Configure CMake
if: ${{ matrix.compiler == 'clang' }}
shell: bash
working-directory: ${{github.workspace}}/build
run: >
cmake $GITHUB_WORKSPACE
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DAPP_BUILD_EXAMPLES=ON
-DAPP_BUILD_TESTS=ON
-DAPP_COMPILER_ENABLE_WARNINGS=ON
-DCMAKE_CXX_COMPILER=$(brew --prefix llvm@17)/bin/clang++
- name: Build
shell: bash
working-directory: ${{runner.workspace}}/build
working-directory: ${{github.workspace}}/build
run: cmake --build . --config $BUILD_TYPE
- name: Test
working-directory: ${{runner.workspace}}/build
working-directory: ${{github.workspace}}/build
shell: bash
run: ctest -C $BUILD_TYPE
run: ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
freebsd:
runs-on: macos-latest
# env:
# variables to pass to VM
# MYTOKEN : ${{ secrets.MYTOKEN }}
steps:
- uses: actions/checkout@v2
- name: Build and test in FreeBSD
id: test
uses: vmactions/freebsd-vm@v0.1.2
with:
envs: 'BUILD_TYPE'
usesh: true
sync: rsync
mem: 2048
prepare: >
pkg install -y cmake pkgconf gtkmm30 gettext pcre libiconv
run: >
mkdir build && cd build
cmake ..
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DAPP_BUILD_EXAMPLES=ON
-DAPP_BUILD_TESTS=ON
-DAPP_COMPILER_ENABLE_WARNINGS=ON
cmake --build . --config $BUILD_TYPE
ctest -C $BUILD_TYPE
+61
View File
@@ -0,0 +1,61 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow checks out code, performs a Codacy security scan
# and integrates the results with the
# GitHub Advanced Security code scanning feature. For more information on
# the Codacy security scan action usage and parameters, see
# https://github.com/codacy/codacy-analysis-cli-action.
# For more information on Codacy Analysis CLI in general, see
# https://github.com/codacy/codacy-analysis-cli.
name: Codacy Security Scan
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '27 22 * * 1'
permissions:
contents: read
jobs:
codacy-security-scan:
permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
name: Codacy Security Scan
runs-on: ubuntu-24.04
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v4
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b
with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
verbose: true
output: results.sarif
format: sarif
# Adjust severity of non-security issues
gh-code-scanning-compat: true
# Force 0 exit code to allow SARIF file generation
# This will handover control about PR rejection to the GitHub side
max-allowed-issues: 2147483647
# Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: results.sarif
+85
View File
@@ -0,0 +1,85 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '24 10 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-24.04
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
#packages: read
# only required for workflows in private repositories
#actions: read
#contents: read
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Update Package Database
run: sudo apt-get update
- name: Install Dependencies
run: sudo apt-get install libgtkmm-3.0-dev gettext
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
env:
CC: gcc-13
CXX: g++-13
uses: github/codeql-action/autobuild@v4
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
+36
View File
@@ -0,0 +1,36 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: DevSkim
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
- cron: '25 22 * * 0'
jobs:
lint:
name: DevSkim
runs-on: ubuntu-24.04
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run DevSkim scanner
uses: microsoft/DevSkim-Action@v1
with:
ignore-globs: dummy_to_avoid_action_error,**/.git/**,*.txt,**/dependencies/**,env_tools.h,app_gtkmm_tools.cpp
- name: Upload DevSkim scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: devskim-results.sarif
+140
View File
@@ -0,0 +1,140 @@
name: Windows Release
on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
SMARTMONTOOLS_INSTALLER: smartmontools-7.4-1.win32-setup.exe
SMARTMONTOOLS_URL: https://downloads.sourceforge.net/project/smartmontools/smartmontools/7.4/smartmontools-7.4-1.win32-setup.exe
jobs:
windows-msys2:
runs-on: windows-latest
strategy:
matrix:
include: [
{ msystem: MINGW64, arch: x86_64, platform: win64, urlpath: mingw64 },
{ msystem: MINGW32, arch: i686, platform: win32, urlpath: mingw32 }
]
steps:
- uses: actions/checkout@v4
- uses: msys2/setup-msys2@v2
# p7zip is needed to extract smartmontools
# fontconfig owns /etc/fonts
with:
msystem: ${{ matrix.msystem }}
update: true
install: >-
mingw-w64-${{ matrix.arch }}-gtkmm3
mingw-w64-${{ matrix.arch }}-pkg-config
mingw-w64-${{ matrix.arch }}-cmake
mingw-w64-${{ matrix.arch }}-gcc
mingw-w64-${{ matrix.arch }}-fontconfig
make
p7zip
- name: Downgrade Packages to support Windows 7
# librsvg 2.59 requires Windows 8.1 or later (confirmed by dependency walker).
# We need to downgrade to 2.58.
# This contains gdk_pixbuf loader as well, and re-runs the loader cache update.
# https://repo.msys2.org/mingw/mingw32/mingw-w64-i686-librsvg-2.58.0-1-any.pkg.tar.zst
# https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-librsvg-2.58.0-1-any.pkg.tar.zst
shell: msys2 {0}
working-directory: ${{github.workspace}}
run: |
wget https://repo.msys2.org/mingw/${{ matrix.urlpath }}/mingw-w64-${{ matrix.arch }}-librsvg-2.58.0-1-any.pkg.tar.zst
pacman -U --noconfirm mingw-w64-${{ matrix.arch }}-librsvg-2.58.0-1-any.pkg.tar.zst
- name: Download Package Requirements
shell: msys2 {0}
working-directory: ${{github.workspace}}
run: |
mkdir -p build/smartmontools
cd build/smartmontools
wget $SMARTMONTOOLS_URL
- name: Extract Package Requirements (64-bit)
if: ${{ matrix.msystem == 'MINGW64' }}
shell: msys2 {0}
working-directory: ${{github.workspace}}/build/smartmontools
run: >
7z -bb1 e $SMARTMONTOOLS_INSTALLER
bin/smartctl.exe
bin/smartctl-nc.exe
bin/update-smart-drivedb.ps1
bin/drivedb.h
- name: Extract Package Requirements (32-bit)
if: ${{ matrix.msystem == 'MINGW32' }}
shell: msys2 {0}
working-directory: ${{github.workspace}}/build/smartmontools
run: >
7z -bb1 e $SMARTMONTOOLS_INSTALLER
bin32/smartctl.exe
bin32/smartctl-nc.exe
bin/update-smart-drivedb.ps1
bin/drivedb.h
- name: List installed files
shell: msys2 {0}
run: |
ls -1R /mingw64
ls -1R /mingw32
- name: Configure CMake
shell: msys2 {0}
run: >
cmake -B build -S "$GITHUB_WORKSPACE"
-G "MSYS Makefiles"
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DCMAKE_TOOLCHAIN_FILE="$GITHUB_WORKSPACE/toolchains/${{ matrix.platform }}-mingw-msys2.cmake"
- name: Build
shell: msys2 {0}
working-directory: ${{github.workspace}}/build
run: cmake --build . --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build
shell: msys2 {0}
run: ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
- name: Package ZIP
shell: msys2 {0}
working-directory: ${{github.workspace}}/build
run: cpack -G ZIP
- name: Package NSIS (64-bit)
if: ${{ matrix.msystem == 'MINGW64' }}
shell: msys2 {0}
working-directory: ${{github.workspace}}/build
run: cpack -G NSIS64
- name: Package NSIS (32-bit)
if: ${{ matrix.msystem == 'MINGW32' }}
shell: msys2 {0}
working-directory: ${{github.workspace}}/build
run: cpack -G NSIS
- name: Upload artifacts
if: ${{ matrix.msystem == 'MINGW64' }}
uses: actions/upload-artifact@v4
with:
name: Windows 64-Bit Packages
path: ${{github.workspace}}/build/gsmartcontrol-*-win*.*
- name: Upload artifacts
if: ${{ matrix.msystem == 'MINGW32' }}
uses: actions/upload-artifact@v4
with:
name: Windows 32-Bit Packages
path: ${{github.workspace}}/build/gsmartcontrol-*-win*.*
+5 -1
View File
@@ -1,10 +1,11 @@
# Builds
/0*
/doxygen_doc*
/win32*
/win64*
/cmake-build-*
/build*
/_codeql_build_dir
# Non-project files
/TODO
@@ -28,6 +29,9 @@ Thumbs.db
/.idea
/CMakeLists.txt.user
# Agents
/.codebuddy
# Translations
/po/boldquot.sed
/po/en@boldquot.header
+196
View File
@@ -0,0 +1,196 @@
# This file describes OBS workflows:
# https://openbuildservice.org/help/manuals/obs-user-guide/cha.obs.scm_ci_workflow_integration.html
# Workflow for pull requests
#build_pull_request_workflow:
# steps:
# - branch_package:
# source_project: home:alex_sh:gsmartcontrol:github_ci:main
# source_package: gsmartcontrol
# target_project: home:alex_sh:gsmartcontrol:github_ci:main
#
# - configure_repositories:
# project: home:alex_sh:gsmartcontrol:github_ci:main
# repositories:
# - name: openSUSE_Tumbleweed
# paths:
# - target_project: openSUSE:Factory
# target_repository: snapshot
# architectures:
# - x86_64
# - i586
#
# - set_flags:
# flags:
# - type: publish
# status: disable
# project: home:alex_sh:gsmartcontrol:github_ci:main
#
# filters:
# event: pull_request
# branches:
# only:
# - main
# Workflow for pushes
# Note: This adds new repositories to the project if they do not exist.
build_main_workflow:
steps:
- configure_repositories:
project: home:alex_sh:gsmartcontrol:github_ci:main
repositories:
- name: openSUSE_Tumbleweed
paths:
- target_project: openSUSE:Factory
target_repository: snapshot
architectures:
- x86_64
- name: openSUSE_Slowroll
paths:
- target_project: openSUSE:Slowroll
target_repository: standard
architectures:
- x86_64
- name: openSUSE_Leap_15.6
paths:
- target_project: openSUSE:Leap:15.6
target_repository: standard
architectures:
- x86_64
- name: openSUSE_Leap_15.5
paths:
- target_project: devel:gcc
target_repository: openSUSE_Leap_15.5
- target_project: openSUSE:Leap:15.5
target_repository: standard
architectures:
- x86_64
- name: openSUSE_Factory_ARM
paths:
- target_project: openSUSE:Factory:ARM
target_repository: standard
architectures:
- aarch64
- armv7l
- name: SUSE_SLE-15-SP6
paths:
- target_project: devel:gcc
target_repository: SLE-15
- target_project: SUSE:SLE-15-SP6:GA
target_repository: standard
architectures:
- x86_64
- name: Ubuntu_24.04
paths:
- target_project: openSUSE:Tools
target_repository: xUbuntu_24.04
- target_project: Ubuntu:24.04
target_repository: universe
architectures:
- x86_64
- name: Ubuntu_23.10
paths:
- target_project: openSUSE:Tools
target_repository: xUbuntu_23.10
- target_project: Ubuntu:23.10
target_repository: universe
architectures:
- x86_64
- name: Ubuntu_22.04
paths:
- target_project: openSUSE:Tools
target_repository: xUbuntu_22.04
- target_project: Ubuntu:22.04
target_repository: universe
architectures:
- x86_64
- name: Fedora_Rawhide
paths:
- target_project: openSUSE:Tools
target_repository: Fedora_Rawhide
- target_project: Fedora:Rawhide
target_repository: standard
architectures:
- x86_64
- name: Fedora_41
paths:
- target_project: openSUSE:Tools
target_repository: Fedora_41
- target_project: Fedora:41
target_repository: standard
architectures:
- x86_64
- aarch64
- name: Fedora_40
paths:
- target_project: openSUSE:Tools
target_repository: Fedora_40
- target_project: Fedora:40
target_repository: standard
architectures:
- x86_64
- aarch64
- name: Fedora_39
paths:
- target_project: openSUSE:Tools
target_repository: Fedora_39
- target_project: Fedora:39
target_repository: standard
architectures:
- x86_64
- aarch64
- name: Debian_Unstable
paths:
- target_project: openSUSE:Tools
target_repository: Debian_Unstable
- target_project: Debian:Next
target_repository: standard
architectures:
- x86_64
- name: Debian_Testing
paths:
- target_project: openSUSE:Tools
target_repository: Debian_Testing
- target_project: Debian:Testing
target_repository: update
architectures:
- x86_64
- i586
- set_flags:
flags:
- type: publish
status: enable
project: home:alex_sh:gsmartcontrol:github_ci:main
- type: debuginfo
status: enable
project: home:alex_sh:gsmartcontrol:github_ci:main
- rebuild_package:
project: home:alex_sh:gsmartcontrol:github_ci:main
package: gsmartcontrol
filters:
event: push
branches:
only:
- main
+8 -7
View File
@@ -1,11 +1,11 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2021 Alexander Shaduri <ashaduri@gmail.com>
# (C) 2021 - 2024 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
# 3.12 for CMAKE_PROJECT_VERSION
cmake_minimum_required(VERSION 3.12)
# 3.14 for proper object library support (wrt linking)
cmake_minimum_required(VERSION 3.14)
# Use new policy for option() to supress warnings.
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
@@ -20,7 +20,7 @@ project(gsmartcontrol
)
# Provide DATADIR, etc...
# Provide DATADIR, etc.
include(GNUInstallDirs)
message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}")
@@ -55,8 +55,8 @@ if (WIN32)
PATTERN "CNAME" EXCLUDE
)
else()
install(FILES ${DOC_FILES} DESTINATION "${CMAKE_INSTALL_DOCDIR}/")
install(DIRECTORY docs DESTINATION "${CMAKE_INSTALL_DOCDIR}/"
install(FILES ${DOC_FILES} TYPE DOC)
install(DIRECTORY docs TYPE DOC
PATTERN "*.yml" EXCLUDE
PATTERN "CNAME" EXCLUDE
)
@@ -65,7 +65,8 @@ endif()
# CTest support
include(CTest)
include(${CMAKE_SOURCE_DIR}/dependencies/catch2/Catch2/extras/Catch.cmake)
#include(${CMAKE_SOURCE_DIR}/dependencies/catch2/Catch2/extras/Catch.cmake)
include(${CMAKE_SOURCE_DIR}/dependencies/catch2/Catch2/contrib/Catch.cmake)
add_subdirectory(contrib)
+128
View File
@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
ashaduri@gmail.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
+67 -1
View File
@@ -1,3 +1,69 @@
Version 2.0.2, released on 2025-02-24
Support GCC 11 (and Ubuntu 22.04) by using and vendoring fmt library
(#77).
Support an option of saving smartctl output to text instead of JSON (#76).
Restored pre-2.0.0 runtime support for smartctl < 7.3 (based on Text
parser); this is an unsupported, old method without NVMe, provided
for compatibility only (#77).
Restored pre-2.0.0 support for standard (non-extended) self-test log found
in very old ATA drives; the new JSON parser did not support this
previously (#79).
Better support for temperature values in JSON parser; this fixes
unreasonably large temperature values (#78).
Add a tooltip explaining self-test "lifetime hours" wrapping behavior
(#73).
Windows: Fixed a crash on Windows 7 when opening drive information
by using Windows 7-compatible librsvg (#71).
Windows: Avoid using non-integer font sizes.
Version 2.0.1, released on 2024-11-26
Windows: Fixed a crash when opening a native file dialog (#67).
Version 2.0.0, released on 2024-11-07
New JSON-based parser for smartctl output (requires smartctl 7.3+) (#4).
Support for NVMe drives (self-tests require smartctl 7.4+) (#4).
New "Basic" JSON parser for SCSI, flash, and other non-ATA/NVMe drives.
PCRE library is no longer required (the code has been ported to
std::regex) (#40).
A lot of code has been refactored and modernized using C++17 and C++20
features, removing much of the custom library code.
The build process requires a C++20-compliant compiler now (GCC 13+,
Clang 17+, Apple Clang 15+).
CMake (3.14+) is now used as a build system instead of autotools.
GSmartControl is now licensed under GNU GPL 3 only.
Icons come from Oxygen project now (LGPL 3+) instead of Crystal project.
Documentation in md format comes with the source code ("docs" directory).
Support new versions and prereleases of smartctl (#46, #42).
Better detection of drive types thanks to the JSON parser.
Removed ATA AODC feature, it has been deprecated for a while now.
Information window: Some values are aligned and monospaced to improve
readability.
Fixed command execution popup dialog being on top of all windows (#17).
Other minor UI improvements and fixes.
Windows: Better support for HiDPI (including fractional scaling).
Windows: NSIS package is generated by CPack now.
Windows: Packages are built using GitHub CI now.
Version 1.1.4, released on 2022-02-04
Fixed a crash when trying to render main window icons which have
incomplete data; this fixes a rare crash when scanning devices (#13).
Fixed rendering compatibility issues with newer GTK3 versions.
Fixed build system conflict with C++20 version header (#14).
Fixed "Running command ..." dialog floating above windows of other
applications (#17).
Fixed a crash when system locale is set to invalid locale.
Support Finnish decimal separator (backported from the Debian package)
(#23).
Set LC_NUMERIC=C for smartctl process to avoid locale-dependent number
formatting (#23).
Fixed printing all GTK messages as warnings; the messages are sorted by
severity now.
Add current time to default filename in Save Output dialog.
Support macos stat command in file2csource.sh.
Fixed a few typos (backported from the Debian package).
Windows port now uses Adwaita theme due to issues with win32 theme.
Windows port is dpi-aware now.
Version 1.1.3, released on 2017-11-12
Fixed gsmartcontrol-root not launching if GDK_* variables are not set.
@@ -113,7 +179,7 @@ Version 0.8.6, released on 2011-06-12
included.
In-program help has been expanded considerably.
General improvements to user interface have been implemented (better GNOME
HIG compliance, better tooltips, dialogs, etc...).
HIG compliance, better tooltips, dialogs, etc.).
Added ability to show smartctl output for devices whose info could not be
parsed fully.
Attributes in "brief" format are supported now.
+39 -81
View File
@@ -1,105 +1,65 @@
# GSmartControl
### Hard disk drive and SSD health inspection tool
***Hard disk drive and SSD health inspection tool***
[![Generic badge](https://img.shields.io/badge/Homepage-gsmartcontrol.shaduri.dev-brightgreen.svg)](https://gsmartcontrol.shaduri.dev)
[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/ashaduri/gsmartcontrol?label=Version)](https://gsmartcontrol.shaduri.dev/downloads)
[![license: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Platforms](https://img.shields.io/badge/Platforms-linux%20%7C%20windows%20%7C%20macos%20%7C%20*bsd-blue)](https://gsmartcontrol.shaduri.dev/software-requirements)
[![Packaging status](https://repology.org/badge/tiny-repos/gsmartcontrol.svg?header=Software%20distributions%20and%20repositories)](https://repology.org/project/gsmartcontrol/versions)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/528f4f7aaf0e446abf7e55d2affc7bec)](https://app.codacy.com/gh/ashaduri/gsmartcontrol?utm_source=github.com&utm_medium=referral&utm_content=ashaduri/gsmartcontrol&utm_campaign=Badge_Grade_Settings)
[GSmartControl](https://gsmartcontrol.shaduri.dev/)
---
[GSmartControl](https://gsmartcontrol.shaduri.dev)
is a graphical user interface for smartctl (from [smartmontools](https://www.smartmontools.org/)
package), which is a tool for
querying and controlling [SMART](https://en.wikipedia.org/wiki/S.M.A.R.T.)
querying and controlling [SMART](https://en.wikipedia.org/wiki/Self-Monitoring,_Analysis_and_Reporting_Technology)
(Self-Monitoring, Analysis, and Reporting
Technology) data on modern hard disk and solid-state drives. It allows you to
inspect the drive's SMART data to determine its health, as well as run various
tests on it.
GSmartControl supports ATA drives (both PATA and SATA), various USB to
ATA bridges and drives behind some RAID controllers:
* Adaptec (Linux, some models only)
* Areca (Linux, Windows)
* HP CCISS (Linux)
* HP hpsa / hpahcisr (Linux)
* Intel Matrix Storage (CSMI) (Linux, Windows, FreeBSD)
* LSI 3ware (Linux, Windows)
* LSI MegaRAID (Windows)
Note: Smartmontools supports even more RAID Controllers. The drives
behind such controllers can be manually added to GSmartControl using
"Add Device..." functionality or `--add-device` command-line option.
See [Supported RAID Controllers](https://www.smartmontools.org/wiki/Supported_RAID-Controllers).
## Downloads
The [Downloads](https://gsmartcontrol.shaduri.dev/downloads) page contains
all the available packages of GSmartControl.
## Software Requirements
Note: If using the official Windows package, no additional software is required.
### Build Requirements
* [pcre1](https://www.pcre.org)
* [GTK+ 3](https://www.gtk.org), version 3.4 or higher
* [Gtkmm](https://www.gtkmm.org), version 3.4 or higher
### Runtime Requirements
* [smartmontools](https://www.smartmontools.org/)
* xterm (optional)
### Supported Operating Systems
* Linux - All the popular configurations should work.
* FreeBSD - Tested with DesktopBSD / x86.
* NetBSD - Tested with NetBSD / x86.
* OpenBSD - Tested with OpenBSD / x86-64.
* DragonFlyBSD - Code written but no testing has been performed yet. Expected
to work without any issues.
* Windows Vista SP2 (32-bit and 64-bit), Windows 7 SP1, Windows Server 2008,
Windows 8.1, Windows 10. The Windows port uses pd0, pd1, etc...
for physical drives 0, 1, etc... .
* Mac OS X.
* Solaris.
* QNX - Code written but no testing has been performed yet.
## Features
- automatically reports and highlights any anomalies;
- allows enabling/disabling SMART;
- supports configuration of global and per-drive options for smartctl;
- performs SMART self-tests;
- displays drive identity information, capabilities, attributes, device statistics, etc.;
- can read in smartctl output from a saved file, interpreting it as a read-only virtual device;
- works on most smartctl-supported operating systems;
- has extensive help information.
## Usage
### Supported Hardware
### Command-Line Options
GSmartControl supports SATA, PATA, and NVMe drives, as well as drives
behind some USB bridges and RAID controllers.
Please see the
[Supported Hardware](https://gsmartcontrol.shaduri.dev/supported-hardware) page
for more information.
GSmartControl inherits options from GTK+ and other libraries, so be sure to
run it with `--help` option to get a full list of accepted parameters.
Note: The Windows version may not have a text output at all, so `--help` and
similar arguments won't have any effect.
The most important parameters are:
`-?`, `--help` - Show help options.
`-l`, `--no-locale` - Don't use system locale.
`-V`, `--version` - Display version information.
`--no-scan` - Don't scan devices on startup.
`--no-hide-tabs` - Don't hide non-identity tabs when SMART is disabled. Useful
for debugging.
`--add-virtual <file>` - Load smartctl data from file, creating a virtual drive. You
can specify this option multiple times.
`--add-device <device>::<type>[::<extra_args>]` - Add a device to device list.
This option is useful with `--no-scan` to list certain drives only. You can specify
this option multiple times.
Example:
`--add-device /dev/sda --add-device /dev/twa0::3ware,2 --add-device
'/dev/sdb::::-T permissive'`.
`-v`, `--verbose` - Enable verbose logging; same as `--verbosity-level 5`.
`-q`, `--quiet` - Disable logging; same as `--verbosity-level 0`.
`-b`, `--verbosity-level` - Set verbosity level [0-5].
### Supported Platforms
GSmartControl supports all major desktop operating systems, including
Linux, Windows, macOS, FreeBSD, and other BSD-style operating systems.
Please see the
[Software Requirements](https://gsmartcontrol.shaduri.dev/software-requirements) page
for more information.
## Copyright and Licensing
GSmartControl is Copyright (C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com> and contributors.
GSmartControl is Copyright (C) 2008 - 2025 Alexander Shaduri [ashaduri@gmail.com](mailto:ashaduri@gmail.com) and contributors.
GSmartControl is licensed under the terms of
[GNU General Public License Version 3](https://www.gnu.org/licenses/gpl-3.0.en.html).
@@ -112,7 +72,5 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public Licenses for more details.
This product includes icons from Crystal Project,
copyright 2006-2007 Everaldo Coelho (https://www.everaldo.com).
Crystal Project icons are licensed under [GNU LGPL](https://www.gnu.org/licenses/lgpl-3.0.en.html).
This product includes icons from Oxygen Icons copyright [KDE](https://kde.org)
and licensed under the [GNU LGPL version 3](https://www.gnu.org/licenses/lgpl-3.0.en.html) or later.
+16
View File
@@ -0,0 +1,16 @@
# Security Policy
## Supported Versions
The following versions are supported with security updates:
| Version | Supported |
|----------| ------------------ |
| git main | :white_check_mark: |
| 2.0.x | :white_check_mark: |
| < 2.0.0 | :x: |
## Reporting a Vulnerability
Please report security vulnerabilities privately to
Alexander Shaduri [ashaduri@gmail.com](mailto:ashaduri@gmail.com).
+1
View File
@@ -0,0 +1 @@
*
+2 -1
View File
@@ -5,5 +5,6 @@
###############################################################################
if (NOT WIN32)
install(DIRECTORY "cron-based_noadmin" DESTINATION "${CMAKE_INSTALL_DOCDIR}/contrib/")
install(DIRECTORY "${CMAKE_SOURCE_DIR}/contrib" TYPE DOC
PATTERN "CMakeLists.txt" EXCLUDE)
endif()
@@ -2,8 +2,8 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2008 - 2021 Alex Butcher <alex dot butcher 'at' assursys.co.uk>
# (C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
# (C) 2008 - 2024 Alex Butcher <alex dot butcher 'at' assursys.co.uk>
# (C) 2008 - 2024 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
device="$1";
@@ -13,10 +13,10 @@ if [ "$device" = "" ]; then
exit 1;
fi
dev_base="`basename \"$device\"`"
dev_base=$(basename "$device")
out_file=/var/run/smart-"$dev_base"
# Change the path to smartctl if necessary.
smartctl -x "$device" 2>&1 > "$out_file"
smartctl -x --json=o "$device" > "$out_file" 2>&1
chmod 644 "$out_file"
+3 -3
View File
@@ -2,8 +2,8 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2008 - 2021 Alex Butcher <alex dot butcher 'at' assursys.co.uk>
# (C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
# (C) 2008 - 2022 Alex Butcher <alex dot butcher 'at' assursys.co.uk>
# (C) 2008 - 2022 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
if [ "$1" = "-V" ]; then
@@ -21,7 +21,7 @@ if [ "$device" = "" ]; then
exit 1;
fi
dev_base="`basename \"$device\"`"
dev_base=$(basename "$device")
out_file=/var/run/smart-"$dev_base"
cat "$out_file"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 632 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

+11 -6
View File
@@ -26,12 +26,17 @@ if (WIN32)
install(FILES gsmartcontrol.ico DESTINATION .)
endif()
set (DATA_ICONS
icons/drive-optical.png
icons/drive-harddisk.png
icons/drive-removable-media-usb.png
)
# Install internal icons
if (WIN32)
install(FILES icon_cddvd.png icon_hdd.png
DESTINATION .)
install(FILES ${DATA_ICONS} DESTINATION icons)
else()
install(FILES icon_cddvd.png icon_hdd.png
install(FILES ${DATA_ICONS}
DESTINATION "${CMAKE_INSTALL_DATADIR}/gsmartcontrol/icons")
endif()
@@ -49,10 +54,10 @@ if (NOT WIN32)
DESTINATION "${CMAKE_INSTALL_DATADIR}/polkit-1/actions/")
# Man pages
install(FILES "gsmartcontrol.1" DESTINATION "${CMAKE_INSTALL_MANDIR}/man1/")
install(FILES "gsmartcontrol.1" DESTINATION "${CMAKE_INSTALL_MANDIR}/man1/" RENAME "gsmartcontrol-root.1")
install(FILES "man1/gsmartcontrol.1" DESTINATION "${CMAKE_INSTALL_MANDIR}/man1")
install(FILES "man1/gsmartcontrol.1" DESTINATION "${CMAKE_INSTALL_MANDIR}/man1" RENAME "gsmartcontrol-root.1")
# Scripts (this goes to bin, not sbin, as it doesn't require root privileges before running)
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/gsmartcontrol-root.sh" DESTINATION "${CMAKE_INSTALL_BINDIR}" RENAME "gsmartcontrol-root")
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/gsmartcontrol-root.sh" TYPE BIN RENAME "gsmartcontrol-root")
endif()
-250
View File
@@ -1,250 +0,0 @@
# From https://github.com/vector-of-bool/CMakeCM/blob/master/modules/FindFilesystem.cmake
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindFilesystem
##############
This module supports the C++17 standard library's filesystem utilities. Use the
:imp-target:`std::filesystem` imported target to
Options
*******
The ``COMPONENTS`` argument to this module supports the following values:
.. find-component:: Experimental
:name: fs.Experimental
Allows the module to find the "experimental" Filesystem TS version of the
Filesystem library. This is the library that should be used with the
``std::experimental::filesystem`` namespace.
.. find-component:: Final
:name: fs.Final
Finds the final C++17 standard version of the filesystem library.
If no components are provided, behaves as if the
:find-component:`fs.Final` component was specified.
If both :find-component:`fs.Experimental` and :find-component:`fs.Final` are
provided, first looks for ``Final``, and falls back to ``Experimental`` in case
of failure. If ``Final`` is found, :imp-target:`std::filesystem` and all
:ref:`variables <fs.variables>` will refer to the ``Final`` version.
Imported Targets
****************
.. imp-target:: std::filesystem
The ``std::filesystem`` imported target is defined when any requested
version of the C++ filesystem library has been found, whether it is
*Experimental* or *Final*.
If no version of the filesystem library is available, this target will not
be defined.
.. note::
This target has ``cxx_std_17`` as an ``INTERFACE``
:ref:`compile language standard feature <req-lang-standards>`. Linking
to this target will automatically enable C++17 if no later standard
version is already required on the linking target.
.. _fs.variables:
Variables
*********
.. variable:: CXX_FILESYSTEM_IS_EXPERIMENTAL
Set to ``TRUE`` when the :find-component:`fs.Experimental` version of C++
filesystem library was found, otherwise ``FALSE``.
.. variable:: CXX_FILESYSTEM_HAVE_FS
Set to ``TRUE`` when a filesystem header was found.
.. variable:: CXX_FILESYSTEM_HEADER
Set to either ``filesystem`` or ``experimental/filesystem`` depending on
whether :find-component:`fs.Final` or :find-component:`fs.Experimental` was
found.
.. variable:: CXX_FILESYSTEM_NAMESPACE
Set to either ``std::filesystem`` or ``std::experimental::filesystem``
depending on whether :find-component:`fs.Final` or
:find-component:`fs.Experimental` was found.
Examples
********
Using `find_package(Filesystem)` with no component arguments:
.. code-block:: cmake
find_package(Filesystem REQUIRED)
add_executable(my-program main.cpp)
target_link_libraries(my-program PRIVATE std::filesystem)
#]=======================================================================]
if(TARGET std::filesystem)
# This module has already been processed. Don't do it again.
return()
endif()
cmake_minimum_required(VERSION 3.10)
include(CMakePushCheckState)
include(CheckIncludeFileCXX)
# If we're not cross-compiling, try to run test executables.
# Otherwise, assume that compile + link is a sufficient check.
if(CMAKE_CROSSCOMPILING)
include(CheckCXXSourceCompiles)
macro(_cmcm_check_cxx_source code var)
check_cxx_source_compiles("${code}" ${var})
endmacro()
else()
include(CheckCXXSourceRuns)
macro(_cmcm_check_cxx_source code var)
check_cxx_source_runs("${code}" ${var})
endmacro()
endif()
cmake_push_check_state()
set(CMAKE_REQUIRED_QUIET ${Filesystem_FIND_QUIETLY})
# All of our tests required C++17 or later
set(CMAKE_CXX_STANDARD 17)
# Normalize and check the component list we were given
set(want_components ${Filesystem_FIND_COMPONENTS})
if(Filesystem_FIND_COMPONENTS STREQUAL "")
set(want_components Final)
endif()
# Warn on any unrecognized components
set(extra_components ${want_components})
list(REMOVE_ITEM extra_components Final Experimental)
foreach(component IN LISTS extra_components)
message(WARNING "Extraneous find_package component for Filesystem: ${component}")
endforeach()
# Detect which of Experimental and Final we should look for
set(find_experimental TRUE)
set(find_final TRUE)
if(NOT "Final" IN_LIST want_components)
set(find_final FALSE)
endif()
if(NOT "Experimental" IN_LIST want_components)
set(find_experimental FALSE)
endif()
if(find_final)
check_include_file_cxx("filesystem" _CXX_FILESYSTEM_HAVE_HEADER)
mark_as_advanced(_CXX_FILESYSTEM_HAVE_HEADER)
if(_CXX_FILESYSTEM_HAVE_HEADER)
# We found the non-experimental header. Don't bother looking for the
# experimental one.
set(find_experimental FALSE)
endif()
else()
set(_CXX_FILESYSTEM_HAVE_HEADER FALSE)
endif()
if(find_experimental)
check_include_file_cxx("experimental/filesystem" _CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
mark_as_advanced(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
else()
set(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER FALSE)
endif()
if(_CXX_FILESYSTEM_HAVE_HEADER)
set(_have_fs TRUE)
set(_fs_header filesystem)
set(_fs_namespace std::filesystem)
set(_is_experimental FALSE)
elseif(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
set(_have_fs TRUE)
set(_fs_header experimental/filesystem)
set(_fs_namespace std::experimental::filesystem)
set(_is_experimental TRUE)
else()
set(_have_fs FALSE)
endif()
set(CXX_FILESYSTEM_HAVE_FS ${_have_fs} CACHE BOOL "TRUE if we have the C++ filesystem headers")
set(CXX_FILESYSTEM_HEADER ${_fs_header} CACHE STRING "The header that should be included to obtain the filesystem APIs")
set(CXX_FILESYSTEM_NAMESPACE ${_fs_namespace} CACHE STRING "The C++ namespace that contains the filesystem APIs")
set(CXX_FILESYSTEM_IS_EXPERIMENTAL ${_is_experimental} CACHE BOOL "TRUE if the C++ filesystem library is the experimental version")
set(_found FALSE)
if(CXX_FILESYSTEM_HAVE_FS)
# We have some filesystem library available. Do link checks
string(CONFIGURE [[
#include <cstdlib>
#include <@CXX_FILESYSTEM_HEADER@>
int main() {
auto cwd = @CXX_FILESYSTEM_NAMESPACE@::current_path();
printf("%s", cwd.c_str());
return EXIT_SUCCESS;
}
]] code @ONLY)
# Check a simple filesystem program without any linker flags
_cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_NO_LINK_NEEDED)
set(can_link ${CXX_FILESYSTEM_NO_LINK_NEEDED})
if(NOT CXX_FILESYSTEM_NO_LINK_NEEDED)
set(prev_libraries ${CMAKE_REQUIRED_LIBRARIES})
# Add the libstdc++ flag
set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lstdc++fs)
_cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_STDCPPFS_NEEDED)
set(can_link ${CXX_FILESYSTEM_STDCPPFS_NEEDED})
if(NOT CXX_FILESYSTEM_STDCPPFS_NEEDED)
# Try the libc++ flag
set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lc++fs)
_cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_CPPFS_NEEDED)
set(can_link ${CXX_FILESYSTEM_CPPFS_NEEDED})
endif()
endif()
if(can_link)
add_library(std::filesystem INTERFACE IMPORTED)
set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_17)
set(_found TRUE)
if(CXX_FILESYSTEM_NO_LINK_NEEDED)
# Nothing to add...
elseif(CXX_FILESYSTEM_STDCPPFS_NEEDED)
set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_LINK_LIBRARIES -lstdc++fs)
elseif(CXX_FILESYSTEM_CPPFS_NEEDED)
set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_LINK_LIBRARIES -lc++fs)
endif()
endif()
endif()
cmake_pop_check_state()
set(Filesystem_FOUND ${_found} CACHE BOOL "TRUE if we can run a program using std::filesystem" FORCE)
if(Filesystem_FIND_REQUIRED AND NOT Filesystem_FOUND)
message(FATAL_ERROR "Cannot run simple program using std::filesystem")
endif()
+7
View File
@@ -0,0 +1,7 @@
#!/bin/bash
png_name="gsmartcontrol.png"
# needs imagemagick
convert 16/$png_name 22/$png_name 24/$png_name 32/$png_name \
48/$png_name 64/$png_name 128/$png_name 256/$png_name gsmartcontrol.ico
+7 -10
View File
@@ -2,14 +2,14 @@
###############################################################################
# License: Zlib
# Copyright:
# (C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
# (C) 2008 - 2022 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
# Run gsmartcontrol with root, asking for root password first.
# export GSMARTCONTROL_SU to override a su command (e.g. "kdesu -c").
EXEC_BIN="@CMAKE_INSTALL_FULL_SBINDIR@/gsmartcontrol";
prog_name="gsmartcontrol"
program_name="gsmartcontrol"
# Preserve quotes in arguments
@@ -30,7 +30,7 @@ else
# New syntax:
# gsmartcontrol-root [--desktop=<auto|kde|gnome|other>] [program_options]
for arg in $*; do
for arg in "$@"; do
case $arg in
--desktop=*)
DESKTOP="${arg#*=}";
@@ -45,7 +45,7 @@ fi
if [ "$DESKTOP" != "auto" ] && [ "$DESKTOP" != "kde" ] && \
[ "$DESKTOP" != "gnome" ] && [ "$DESKTOP" != "other" ]; then
echo "Usage: $0 [--desktop=<auto|kde|gnome|other>] [<${prog_name}_options>]";
echo "Usage: $0 [--desktop=<auto|kde|gnome|other>] [<${program_name}_options>]";
exit 1;
fi
@@ -93,7 +93,7 @@ fi
if [ "$GSMARTCONTROL_SU" = "" ]; then
for subin in $candidates; do
which $subin &>/dev/null
which "$subin" &>/dev/null
if [ $? -eq 0 ]; then
found_su="$subin";
break;
@@ -101,7 +101,7 @@ if [ "$GSMARTCONTROL_SU" = "" ]; then
done
if [ "$found_su" = "" ]; then
xmessage "Error launching ${prog_name}: No suitable su mechanism found.
xmessage "Error launching ${program_name}: No suitable su mechanism found.
Try installing PolKit, kdesu, gnomesu, gksu, beesu or sux first.";
exit 1;
fi
@@ -164,8 +164,5 @@ fi
# echo $full_cmd
eval $full_cmd
eval "$full_cmd"
+3 -3
View File
@@ -19,15 +19,15 @@
<screenshots>
<screenshot type="default">
<caption>Main window</caption>
<image>https://gsmartcontrol.sourceforge.io/home/images/main_ok.png</image>
<image>https://gsmartcontrol.shaduri.dev/screenshots/main_ok.png</image>
</screenshot>
<screenshot>
<caption>Drive identity information</caption>
<image>https://gsmartcontrol.sourceforge.io/home/images/info_identity.png</image>
<image>https://gsmartcontrol.shaduri.dev/screenshots/info_identity.png</image>
</screenshot>
<screenshot>
<caption>Attribute list of a failing drive</caption>
<image>https://gsmartcontrol.sourceforge.io/home/images/info_failing.png</image>
<image>https://gsmartcontrol.shaduri.dev/screenshots/info_failing.png</image>
</screenshot>
</screenshots>
</component>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 130 KiB

+31
View File
@@ -13,13 +13,44 @@ Type=Application
Categories=System;Monitor;
Name=GSmartControl
Name[ca]=GSControlIntel
Name[cs]=GSmartControl
Name[es]=GSmartControl
Name[id]=GSmartControl
Name[it]=GSmartControl
Name[ja]=GSmartControl
Name[pt_BR]=GSmartControl
Name[ru]=GSmartControl
Name[sk]=GSmartControl
Name[sv]=GSmartControl
Name[zh_CN]=GSmartControl
# short description, usually shown in parentheses after Name
GenericName=Hard Disk and SSD Health Inspection
GenericName[ca]=Inspecció de salut del disc dur i de l'SSD
GenericName[cs]=Prohlídka zdraví pevných a SSD disků
GenericName[es]=Inspección de la salud de discos duros y SSD
GenericName[fr]=Inspecteur de santé de disque dur et de SSD
GenericName[id]=Pemeriksaan Kesehatan Cakram Keras dan SSD
GenericName[it]=Ispezione della salute del disco rigido e dell'SSD
GenericName[ja]=ハードディスクと SSD の健全状態の調査
GenericName[pt_BR]=Inspeção da integridade de disco rígido e SSD
GenericName[ru]=Проверка состояния жёстких и твердотельных дисков
GenericName[sk]=Zdravotná inšpekcia pevného disku a SSD
GenericName[zh_CN]=机械及固态硬盘健康检测
# tooltip
Comment=Monitor and control SMART data on hard disk and solid-state drives
Comment[ca]=Monitoreu i controleu les dades SMART dels discs durs i dels discs sòlids.
Comment[cs]=Sleduje a nastavuje SMART data na pevném disku a na polovodičových discích
Comment[es]=Monitorice y controle datos de SMART sobre discos duros y unidades de estado sólido
Comment[fr]=Surveille et contrôle les données SMART des disques durs et des SSD
Comment[id]=Pantau dan kendalikan data cerdas pada cakram keras dan SSD
Comment[it]=Monitora e controlla i dati SMART sui dischi rigidi e a stato solido
Comment[ja]=ハードディスクや SSD 内の SMART データの監視と制御
Comment[pt_BR]=Monitorar e controlar dados do SMART em discos rígidos e unidades de estado sólido
Comment[ru]=Мониторинг и контроль данных SMART на жёстких и твердотельных дисках
Comment[sk]=Monitorovanie a kontrola údajov SMART na pevných diskoch a diskoch SSD
Comment[zh_CN]=监测及控制机械硬盘和固态硬盘上的SMART数据
# If it's a name only, it looks for "name.[png|xpm]" file in
# $XDG_DATA_DIRS/icons.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

@@ -45,9 +45,6 @@ Display version information
\fB\-\-no\-scan\fP
Don't scan devices on startup
.TP
\fB\-\-no\-hide\-tabs\fP
Don't hide non\-identity tabs when SMART is disabled. Useful for debugging.
.TP
\fB\-\-add\-virtual\fP
Load smartctl data from file, creating a virtual drive. You
can specify this option multiple times.
@@ -61,6 +58,9 @@ can specify this option multiple times. Example:\fR
\-\-add\-device /dev/sda \-\-add\-device /dev/twa0::3ware,2 \-\-add\-device '/dev/sdb::::-T permissive'
.fi
.TP
\fB\-\-forget\-devices\fP
Forget all previously manually added devices
.TP
\fB\-\-display\fP=\fIDISPLAY\fP
X display to use
.TP
+13 -23
View File
@@ -1,7 +1,7 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2021 - 2022 Alexander Shaduri <ashaduri@gmail.com>
# (C) 2021 - 2024 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
# Disable all warnings
@@ -18,8 +18,8 @@ find_package(PkgConfig REQUIRED) # pkg_check_modules()
# Gtkmm.
# Don't make it REQUIRED, we may want to build only the parsers.
pkg_check_modules(Gtkmm IMPORTED_TARGET GLOBAL "gtkmm-3.0>=3.0")
# Don't make it REQUIRED, we may want to build only the parsers
pkg_check_modules(Gtkmm REQUIRED IMPORTED_TARGET GLOBAL "gtkmm-3.0>=3.0")
add_library(app_gtkmm_interface INTERFACE)
target_link_libraries(app_gtkmm_interface
INTERFACE
@@ -30,16 +30,13 @@ target_compile_definitions(app_gtkmm_interface
ENABLE_GLIB=1
ENABLE_GLIBMM=1
# For porting to GTK4
GTK_DISABLE_DEPRECATED=1
GDK_DISABLE_DEPRECATED=1
GTKMM_DISABLE_DEPRECATED=1
GDKMM_DISABLE_DEPRECATED=1
GLIBMM_DISABLE_DEPRECATED=1
GIOMM_DISABLE_DEPRECATED=1
# GTK_DISABLE_DEPRECATED=1
# GDK_DISABLE_DEPRECATED=1
# GTKMM_DISABLE_DEPRECATED=1
# GDKMM_DISABLE_DEPRECATED=1
# GLIBMM_DISABLE_DEPRECATED=1
# GIOMM_DISABLE_DEPRECATED=1
)
# Don't forget to set the following environment variable to catch deprecated properties and signals at runtime:
#G_ENABLE_DIAGNOSTIC=1
# Support pre-C++17 glibmm with throw(...) exception specifications
pkg_check_modules(Glibmm "glibmm-2.4")
@@ -49,21 +46,12 @@ if ("${Glibmm_VERSION}" VERSION_LESS "2.50.1")
endif()
# pcrecpp from pcre1
pkg_check_modules(Pcrecpp REQUIRED IMPORTED_TARGET GLOBAL libpcrecpp)
add_library(app_pcrecpp_interface INTERFACE)
target_link_libraries(app_pcrecpp_interface
INTERFACE
PkgConfig::Pcrecpp
)
# Gettext libintl
find_package(Intl REQUIRED)
add_library(app_gettext_interface INTERFACE)
if (Intl_INCLUDE_DIRS)
target_include_directories(app_gettext_interface
INTERFACE
SYSTEM INTERFACE
${Intl_INCLUDE_DIRS}
)
endif()
@@ -76,9 +64,11 @@ endif()
# Gettext binaries and macros.
# See https://cmake.org/cmake/help/v3.15/module/FindGettext.html
find_package(Gettext REQUIRED)
# find_package(Gettext REQUIRED)
add_subdirectory(catch2)
add_subdirectory(fmt)
add_subdirectory(nlohmann_json)
add_subdirectory(whereami)
add_subdirectory(tl_expected)
+15 -4
View File
@@ -4,8 +4,19 @@
# (C) 2021 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
#set(CATCH_INSTALL_DOCS OFF CACHE INTERNAL "")
#set(CATCH_INSTALL_EXTRAS OFF CACHE INTERNAL "")
#set(CATCH_DEVELOPMENT_BUILD OFF CACHE INTERNAL "")
#add_subdirectory(Catch2)
add_library(Catch2 INTERFACE)
# Relative sources are allowed only since cmake 3.13.
target_sources(Catch2 INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/Catch2/single_include/catch2/catch.hpp
)
target_include_directories(Catch2
SYSTEM INTERFACE
"${CMAKE_SOURCE_DIR}/dependencies/catch2/Catch2/single_include"
)
add_subdirectory(Catch2)
-2
View File
@@ -29,5 +29,3 @@ cmake-build-*
benchmark-dir
.conan/test_package/build
bazel-*
build-fuzzers
debug-build
-10
View File
@@ -1,10 +0,0 @@
@PACKAGE_INIT@
# Avoid repeatedly including the targets
if(NOT TARGET Catch2::Catch2)
# Provide path for scripts
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
include(${CMAKE_CURRENT_LIST_DIR}/Catch2Targets.cmake)
endif()
-157
View File
@@ -1,157 +0,0 @@
# This file is part of CMake-codecov.
#
# Copyright (c)
# 2015-2017 RWTH Aachen University, Federal Republic of Germany
#
# See the LICENSE file in the package base directory for details
#
# Written by Alexander Haase, alexander.haase@rwth-aachen.de
#
# include required Modules
include(FindPackageHandleStandardArgs)
# Search for gcov binary.
set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET})
set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY})
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach (LANG ${ENABLED_LANGUAGES})
# Gcov evaluation is dependent on the used compiler. Check gcov support for
# each compiler that is used. If gcov binary was already found for this
# compiler, do not try to find it again.
if (NOT GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN)
get_filename_component(COMPILER_PATH "${CMAKE_${LANG}_COMPILER}" PATH)
if ("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "GNU")
# Some distributions like OSX (homebrew) ship gcov with the compiler
# version appended as gcov-x. To find this binary we'll build the
# suggested binary name with the compiler version.
string(REGEX MATCH "^[0-9]+" GCC_VERSION
"${CMAKE_${LANG}_COMPILER_VERSION}")
find_program(GCOV_BIN NAMES gcov-${GCC_VERSION} gcov
HINTS ${COMPILER_PATH})
elseif ("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "Clang")
# Some distributions like Debian ship llvm-cov with the compiler
# version appended as llvm-cov-x.y. To find this binary we'll build
# the suggested binary name with the compiler version.
string(REGEX MATCH "^[0-9]+.[0-9]+" LLVM_VERSION
"${CMAKE_${LANG}_COMPILER_VERSION}")
# llvm-cov prior version 3.5 seems to be not working with coverage
# evaluation tools, but these versions are compatible with the gcc
# gcov tool.
if(LLVM_VERSION VERSION_GREATER 3.4)
find_program(LLVM_COV_BIN NAMES "llvm-cov-${LLVM_VERSION}"
"llvm-cov" HINTS ${COMPILER_PATH})
mark_as_advanced(LLVM_COV_BIN)
if (LLVM_COV_BIN)
find_program(LLVM_COV_WRAPPER "llvm-cov-wrapper" PATHS
${CMAKE_MODULE_PATH})
if (LLVM_COV_WRAPPER)
set(GCOV_BIN "${LLVM_COV_WRAPPER}" CACHE FILEPATH "")
# set additional parameters
set(GCOV_${CMAKE_${LANG}_COMPILER_ID}_ENV
"LLVM_COV_BIN=${LLVM_COV_BIN}" CACHE STRING
"Environment variables for llvm-cov-wrapper.")
mark_as_advanced(GCOV_${CMAKE_${LANG}_COMPILER_ID}_ENV)
endif ()
endif ()
endif ()
if (NOT GCOV_BIN)
# Fall back to gcov binary if llvm-cov was not found or is
# incompatible. This is the default on OSX, but may crash on
# recent Linux versions.
find_program(GCOV_BIN gcov HINTS ${COMPILER_PATH})
endif ()
endif ()
if (GCOV_BIN)
set(GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN "${GCOV_BIN}" CACHE STRING
"${LANG} gcov binary.")
if (NOT CMAKE_REQUIRED_QUIET)
message("-- Found gcov evaluation for "
"${CMAKE_${LANG}_COMPILER_ID}: ${GCOV_BIN}")
endif()
unset(GCOV_BIN CACHE)
endif ()
endif ()
endforeach ()
# Add a new global target for all gcov targets. This target could be used to
# generate the gcov files for the whole project instead of calling <TARGET>-gcov
# for each target.
if (NOT TARGET gcov)
add_custom_target(gcov)
endif (NOT TARGET gcov)
# This function will add gcov evaluation for target <TNAME>. Only sources of
# this target will be evaluated and no dependencies will be added. It will call
# Gcov on any source file of <TNAME> once and store the gcov file in the same
# directory.
function (add_gcov_target TNAME)
set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir)
# We don't have to check, if the target has support for coverage, thus this
# will be checked by add_coverage_target in Findcoverage.cmake. Instead we
# have to determine which gcov binary to use.
get_target_property(TSOURCES ${TNAME} SOURCES)
set(SOURCES "")
set(TCOMPILER "")
foreach (FILE ${TSOURCES})
codecov_path_of_source(${FILE} FILE)
if (NOT "${FILE}" STREQUAL "")
codecov_lang_of_source(${FILE} LANG)
if (NOT "${LANG}" STREQUAL "")
list(APPEND SOURCES "${FILE}")
set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID})
endif ()
endif ()
endforeach ()
# If no gcov binary was found, coverage data can't be evaluated.
if (NOT GCOV_${TCOMPILER}_BIN)
message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.")
return()
endif ()
set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}")
set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}")
set(BUFFER "")
foreach(FILE ${SOURCES})
get_filename_component(FILE_PATH "${TDIR}/${FILE}" PATH)
# call gcov
add_custom_command(OUTPUT ${TDIR}/${FILE}.gcov
COMMAND ${GCOV_ENV} ${GCOV_BIN} ${TDIR}/${FILE}.gcno > /dev/null
DEPENDS ${TNAME} ${TDIR}/${FILE}.gcno
WORKING_DIRECTORY ${FILE_PATH}
)
list(APPEND BUFFER ${TDIR}/${FILE}.gcov)
endforeach()
# add target for gcov evaluation of <TNAME>
add_custom_target(${TNAME}-gcov DEPENDS ${BUFFER})
# add evaluation target to the global gcov target.
add_dependencies(gcov ${TNAME}-gcov)
endfunction (add_gcov_target)
-354
View File
@@ -1,354 +0,0 @@
# This file is part of CMake-codecov.
#
# Copyright (c)
# 2015-2017 RWTH Aachen University, Federal Republic of Germany
#
# See the LICENSE file in the package base directory for details
#
# Written by Alexander Haase, alexander.haase@rwth-aachen.de
#
# configuration
set(LCOV_DATA_PATH "${CMAKE_BINARY_DIR}/lcov/data")
set(LCOV_DATA_PATH_INIT "${LCOV_DATA_PATH}/init")
set(LCOV_DATA_PATH_CAPTURE "${LCOV_DATA_PATH}/capture")
set(LCOV_HTML_PATH "${CMAKE_BINARY_DIR}/lcov/html")
# Search for Gcov which is used by Lcov.
find_package(Gcov)
# This function will add lcov evaluation for target <TNAME>. Only sources of
# this target will be evaluated and no dependencies will be added. It will call
# geninfo on any source file of <TNAME> once and store the info file in the same
# directory.
#
# Note: This function is only a wrapper to define this function always, even if
# coverage is not supported by the compiler or disabled. This function must
# be defined here, because the module will be exited, if there is no coverage
# support by the compiler or it is disabled by the user.
function (add_lcov_target TNAME)
if (LCOV_FOUND)
# capture initial coverage data
lcov_capture_initial_tgt(${TNAME})
# capture coverage data after execution
lcov_capture_tgt(${TNAME})
endif ()
endfunction (add_lcov_target)
# include required Modules
include(FindPackageHandleStandardArgs)
# Search for required lcov binaries.
find_program(LCOV_BIN lcov)
find_program(GENINFO_BIN geninfo)
find_program(GENHTML_BIN genhtml)
find_package_handle_standard_args(lcov
REQUIRED_VARS LCOV_BIN GENINFO_BIN GENHTML_BIN
)
# enable genhtml C++ demangeling, if c++filt is found.
set(GENHTML_CPPFILT_FLAG "")
find_program(CPPFILT_BIN c++filt)
if (NOT CPPFILT_BIN STREQUAL "")
set(GENHTML_CPPFILT_FLAG "--demangle-cpp")
endif (NOT CPPFILT_BIN STREQUAL "")
# enable no-external flag for lcov, if available.
if (GENINFO_BIN AND NOT DEFINED GENINFO_EXTERN_FLAG)
set(FLAG "")
execute_process(COMMAND ${GENINFO_BIN} --help OUTPUT_VARIABLE GENINFO_HELP)
string(REGEX MATCH "external" GENINFO_RES "${GENINFO_HELP}")
if (GENINFO_RES)
set(FLAG "--no-external")
endif ()
set(GENINFO_EXTERN_FLAG "${FLAG}"
CACHE STRING "Geninfo flag to exclude system sources.")
endif ()
# If Lcov was not found, exit module now.
if (NOT LCOV_FOUND)
return()
endif (NOT LCOV_FOUND)
# Create directories to be used.
file(MAKE_DIRECTORY ${LCOV_DATA_PATH_INIT})
file(MAKE_DIRECTORY ${LCOV_DATA_PATH_CAPTURE})
set(LCOV_REMOVE_PATTERNS "")
# This function will merge lcov files to a single target file. Additional lcov
# flags may be set with setting LCOV_EXTRA_FLAGS before calling this function.
function (lcov_merge_files OUTFILE ...)
# Remove ${OUTFILE} from ${ARGV} and generate lcov parameters with files.
list(REMOVE_AT ARGV 0)
# Generate merged file.
string(REPLACE "${CMAKE_BINARY_DIR}/" "" FILE_REL "${OUTFILE}")
add_custom_command(OUTPUT "${OUTFILE}.raw"
COMMAND cat ${ARGV} > ${OUTFILE}.raw
DEPENDS ${ARGV}
COMMENT "Generating ${FILE_REL}"
)
add_custom_command(OUTPUT "${OUTFILE}"
COMMAND ${LCOV_BIN} --quiet -a ${OUTFILE}.raw --output-file ${OUTFILE}
--base-directory ${PROJECT_SOURCE_DIR} ${LCOV_EXTRA_FLAGS}
COMMAND ${LCOV_BIN} --quiet -r ${OUTFILE} ${LCOV_REMOVE_PATTERNS}
--output-file ${OUTFILE} ${LCOV_EXTRA_FLAGS}
DEPENDS ${OUTFILE}.raw
COMMENT "Post-processing ${FILE_REL}"
)
endfunction ()
# Add a new global target to generate initial coverage reports for all targets.
# This target will be used to generate the global initial info file, which is
# used to gather even empty report data.
if (NOT TARGET lcov-capture-init)
add_custom_target(lcov-capture-init)
set(LCOV_CAPTURE_INIT_FILES "" CACHE INTERNAL "")
endif (NOT TARGET lcov-capture-init)
# This function will add initial capture of coverage data for target <TNAME>,
# which is needed to get also data for objects, which were not loaded at
# execution time. It will call geninfo for every source file of <TNAME> once and
# store the info file in the same directory.
function (lcov_capture_initial_tgt TNAME)
# We don't have to check, if the target has support for coverage, thus this
# will be checked by add_coverage_target in Findcoverage.cmake. Instead we
# have to determine which gcov binary to use.
get_target_property(TSOURCES ${TNAME} SOURCES)
set(SOURCES "")
set(TCOMPILER "")
foreach (FILE ${TSOURCES})
codecov_path_of_source(${FILE} FILE)
if (NOT "${FILE}" STREQUAL "")
codecov_lang_of_source(${FILE} LANG)
if (NOT "${LANG}" STREQUAL "")
list(APPEND SOURCES "${FILE}")
set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID})
endif ()
endif ()
endforeach ()
# If no gcov binary was found, coverage data can't be evaluated.
if (NOT GCOV_${TCOMPILER}_BIN)
message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.")
return()
endif ()
set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}")
set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}")
set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir)
set(GENINFO_FILES "")
foreach(FILE ${SOURCES})
# generate empty coverage files
set(OUTFILE "${TDIR}/${FILE}.info.init")
list(APPEND GENINFO_FILES ${OUTFILE})
add_custom_command(OUTPUT ${OUTFILE} COMMAND ${GCOV_ENV} ${GENINFO_BIN}
--quiet --base-directory ${PROJECT_SOURCE_DIR} --initial
--gcov-tool ${GCOV_BIN} --output-filename ${OUTFILE}
${GENINFO_EXTERN_FLAG} ${TDIR}/${FILE}.gcno
DEPENDS ${TNAME}
COMMENT "Capturing initial coverage data for ${FILE}"
)
endforeach()
# Concatenate all files generated by geninfo to a single file per target.
set(OUTFILE "${LCOV_DATA_PATH_INIT}/${TNAME}.info")
set(LCOV_EXTRA_FLAGS "--initial")
lcov_merge_files("${OUTFILE}" ${GENINFO_FILES})
add_custom_target(${TNAME}-capture-init ALL DEPENDS ${OUTFILE})
# add geninfo file generation to global lcov-geninfo target
add_dependencies(lcov-capture-init ${TNAME}-capture-init)
set(LCOV_CAPTURE_INIT_FILES "${LCOV_CAPTURE_INIT_FILES}"
"${OUTFILE}" CACHE INTERNAL ""
)
endfunction (lcov_capture_initial_tgt)
# This function will generate the global info file for all targets. It has to be
# called after all other CMake functions in the root CMakeLists.txt file, to get
# a full list of all targets that generate coverage data.
function (lcov_capture_initial)
# Skip this function (and do not create the following targets), if there are
# no input files.
if ("${LCOV_CAPTURE_INIT_FILES}" STREQUAL "")
return()
endif ()
# Add a new target to merge the files of all targets.
set(OUTFILE "${LCOV_DATA_PATH_INIT}/all_targets.info")
lcov_merge_files("${OUTFILE}" ${LCOV_CAPTURE_INIT_FILES})
add_custom_target(lcov-geninfo-init ALL DEPENDS ${OUTFILE}
lcov-capture-init
)
endfunction (lcov_capture_initial)
# Add a new global target to generate coverage reports for all targets. This
# target will be used to generate the global info file.
if (NOT TARGET lcov-capture)
add_custom_target(lcov-capture)
set(LCOV_CAPTURE_FILES "" CACHE INTERNAL "")
endif (NOT TARGET lcov-capture)
# This function will add capture of coverage data for target <TNAME>, which is
# needed to get also data for objects, which were not loaded at execution time.
# It will call geninfo for every source file of <TNAME> once and store the info
# file in the same directory.
function (lcov_capture_tgt TNAME)
# We don't have to check, if the target has support for coverage, thus this
# will be checked by add_coverage_target in Findcoverage.cmake. Instead we
# have to determine which gcov binary to use.
get_target_property(TSOURCES ${TNAME} SOURCES)
set(SOURCES "")
set(TCOMPILER "")
foreach (FILE ${TSOURCES})
codecov_path_of_source(${FILE} FILE)
if (NOT "${FILE}" STREQUAL "")
codecov_lang_of_source(${FILE} LANG)
if (NOT "${LANG}" STREQUAL "")
list(APPEND SOURCES "${FILE}")
set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID})
endif ()
endif ()
endforeach ()
# If no gcov binary was found, coverage data can't be evaluated.
if (NOT GCOV_${TCOMPILER}_BIN)
message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.")
return()
endif ()
set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}")
set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}")
set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir)
set(GENINFO_FILES "")
foreach(FILE ${SOURCES})
# Generate coverage files. If no .gcda file was generated during
# execution, the empty coverage file will be used instead.
set(OUTFILE "${TDIR}/${FILE}.info")
list(APPEND GENINFO_FILES ${OUTFILE})
add_custom_command(OUTPUT ${OUTFILE}
COMMAND test -f "${TDIR}/${FILE}.gcda"
&& ${GCOV_ENV} ${GENINFO_BIN} --quiet --base-directory
${PROJECT_SOURCE_DIR} --gcov-tool ${GCOV_BIN}
--output-filename ${OUTFILE} ${GENINFO_EXTERN_FLAG}
${TDIR}/${FILE}.gcda
|| cp ${OUTFILE}.init ${OUTFILE}
DEPENDS ${TNAME} ${TNAME}-capture-init
COMMENT "Capturing coverage data for ${FILE}"
)
endforeach()
# Concatenate all files generated by geninfo to a single file per target.
set(OUTFILE "${LCOV_DATA_PATH_CAPTURE}/${TNAME}.info")
lcov_merge_files("${OUTFILE}" ${GENINFO_FILES})
add_custom_target(${TNAME}-geninfo DEPENDS ${OUTFILE})
# add geninfo file generation to global lcov-capture target
add_dependencies(lcov-capture ${TNAME}-geninfo)
set(LCOV_CAPTURE_FILES "${LCOV_CAPTURE_FILES}" "${OUTFILE}" CACHE INTERNAL
""
)
# Add target for generating html output for this target only.
file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/${TNAME})
add_custom_target(${TNAME}-genhtml
COMMAND ${GENHTML_BIN} --quiet --sort --prefix ${PROJECT_SOURCE_DIR}
--baseline-file ${LCOV_DATA_PATH_INIT}/${TNAME}.info
--output-directory ${LCOV_HTML_PATH}/${TNAME}
--title "${CMAKE_PROJECT_NAME} - target ${TNAME}"
${GENHTML_CPPFILT_FLAG} ${OUTFILE}
DEPENDS ${TNAME}-geninfo ${TNAME}-capture-init
)
endfunction (lcov_capture_tgt)
# This function will generate the global info file for all targets. It has to be
# called after all other CMake functions in the root CMakeLists.txt file, to get
# a full list of all targets that generate coverage data.
function (lcov_capture)
# Skip this function (and do not create the following targets), if there are
# no input files.
if ("${LCOV_CAPTURE_FILES}" STREQUAL "")
return()
endif ()
# Add a new target to merge the files of all targets.
set(OUTFILE "${LCOV_DATA_PATH_CAPTURE}/all_targets.info")
lcov_merge_files("${OUTFILE}" ${LCOV_CAPTURE_FILES})
add_custom_target(lcov-geninfo DEPENDS ${OUTFILE} lcov-capture)
# Add a new global target for all lcov targets. This target could be used to
# generate the lcov html output for the whole project instead of calling
# <TARGET>-geninfo and <TARGET>-genhtml for each target. It will also be
# used to generate a html site for all project data together instead of one
# for each target.
if (NOT TARGET lcov)
file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/all_targets)
add_custom_target(lcov
COMMAND ${GENHTML_BIN} --quiet --sort
--baseline-file ${LCOV_DATA_PATH_INIT}/all_targets.info
--output-directory ${LCOV_HTML_PATH}/all_targets
--title "${CMAKE_PROJECT_NAME}" --prefix "${PROJECT_SOURCE_DIR}"
${GENHTML_CPPFILT_FLAG} ${OUTFILE}
DEPENDS lcov-geninfo-init lcov-geninfo
)
endif ()
endfunction (lcov_capture)
# Add a new global target to generate the lcov html report for the whole project
# instead of calling <TARGET>-genhtml for each target (to create an own report
# for each target). Instead of the lcov target it does not require geninfo for
# all targets, so you have to call <TARGET>-geninfo to generate the info files
# the targets you'd like to have in your report or lcov-geninfo for generating
# info files for all targets before calling lcov-genhtml.
file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/selected_targets)
if (NOT TARGET lcov-genhtml)
add_custom_target(lcov-genhtml
COMMAND ${GENHTML_BIN}
--quiet
--output-directory ${LCOV_HTML_PATH}/selected_targets
--title \"${CMAKE_PROJECT_NAME} - targets `find
${LCOV_DATA_PATH_CAPTURE} -name \"*.info\" ! -name
\"all_targets.info\" -exec basename {} .info \\\;`\"
--prefix ${PROJECT_SOURCE_DIR}
--sort
${GENHTML_CPPFILT_FLAG}
`find ${LCOV_DATA_PATH_CAPTURE} -name \"*.info\" ! -name
\"all_targets.info\"`
)
endif (NOT TARGET lcov-genhtml)
-258
View File
@@ -1,258 +0,0 @@
# This file is part of CMake-codecov.
#
# Copyright (c)
# 2015-2017 RWTH Aachen University, Federal Republic of Germany
#
# See the LICENSE file in the package base directory for details
#
# Written by Alexander Haase, alexander.haase@rwth-aachen.de
#
# Add an option to choose, if coverage should be enabled or not. If enabled
# marked targets will be build with coverage support and appropriate targets
# will be added. If disabled coverage will be ignored for *ALL* targets.
option(ENABLE_COVERAGE "Enable coverage build." OFF)
set(COVERAGE_FLAG_CANDIDATES
# gcc and clang
"-O0 -g -fprofile-arcs -ftest-coverage"
# gcc and clang fallback
"-O0 -g --coverage"
)
# Add coverage support for target ${TNAME} and register target for coverage
# evaluation. If coverage is disabled or not supported, this function will
# simply do nothing.
#
# Note: This function is only a wrapper to define this function always, even if
# coverage is not supported by the compiler or disabled. This function must
# be defined here, because the module will be exited, if there is no coverage
# support by the compiler or it is disabled by the user.
function (add_coverage TNAME)
# only add coverage for target, if coverage is support and enabled.
if (ENABLE_COVERAGE)
foreach (TNAME ${ARGV})
add_coverage_target(${TNAME})
endforeach ()
endif ()
endfunction (add_coverage)
# Add global target to gather coverage information after all targets have been
# added. Other evaluation functions could be added here, after checks for the
# specific module have been passed.
#
# Note: This function is only a wrapper to define this function always, even if
# coverage is not supported by the compiler or disabled. This function must
# be defined here, because the module will be exited, if there is no coverage
# support by the compiler or it is disabled by the user.
function (coverage_evaluate)
# add lcov evaluation
if (LCOV_FOUND)
lcov_capture_initial()
lcov_capture()
endif (LCOV_FOUND)
endfunction ()
# Exit this module, if coverage is disabled. add_coverage is defined before this
# return, so this module can be exited now safely without breaking any build-
# scripts.
if (NOT ENABLE_COVERAGE)
return()
endif ()
# Find the reuired flags foreach language.
set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET})
set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY})
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach (LANG ${ENABLED_LANGUAGES})
# Coverage flags are not dependent on language, but the used compiler. So
# instead of searching flags foreach language, search flags foreach compiler
# used.
set(COMPILER ${CMAKE_${LANG}_COMPILER_ID})
if (NOT COVERAGE_${COMPILER}_FLAGS)
foreach (FLAG ${COVERAGE_FLAG_CANDIDATES})
if(NOT CMAKE_REQUIRED_QUIET)
message(STATUS "Try ${COMPILER} code coverage flag = [${FLAG}]")
endif()
set(CMAKE_REQUIRED_FLAGS "${FLAG}")
unset(COVERAGE_FLAG_DETECTED CACHE)
if (${LANG} STREQUAL "C")
include(CheckCCompilerFlag)
check_c_compiler_flag("${FLAG}" COVERAGE_FLAG_DETECTED)
elseif (${LANG} STREQUAL "CXX")
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("${FLAG}" COVERAGE_FLAG_DETECTED)
elseif (${LANG} STREQUAL "Fortran")
# CheckFortranCompilerFlag was introduced in CMake 3.x. To be
# compatible with older Cmake versions, we will check if this
# module is present before we use it. Otherwise we will define
# Fortran coverage support as not available.
include(CheckFortranCompilerFlag OPTIONAL
RESULT_VARIABLE INCLUDED)
if (INCLUDED)
check_fortran_compiler_flag("${FLAG}"
COVERAGE_FLAG_DETECTED)
elseif (NOT CMAKE_REQUIRED_QUIET)
message("-- Performing Test COVERAGE_FLAG_DETECTED")
message("-- Performing Test COVERAGE_FLAG_DETECTED - Failed"
" (Check not supported)")
endif ()
endif()
if (COVERAGE_FLAG_DETECTED)
set(COVERAGE_${COMPILER}_FLAGS "${FLAG}"
CACHE STRING "${COMPILER} flags for code coverage.")
mark_as_advanced(COVERAGE_${COMPILER}_FLAGS)
break()
else ()
message(WARNING "Code coverage is not available for ${COMPILER}"
" compiler. Targets using this compiler will be "
"compiled without it.")
endif ()
endforeach ()
endif ()
endforeach ()
set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE})
# Helper function to get the language of a source file.
function (codecov_lang_of_source FILE RETURN_VAR)
get_filename_component(FILE_EXT "${FILE}" EXT)
string(TOLOWER "${FILE_EXT}" FILE_EXT)
string(SUBSTRING "${FILE_EXT}" 1 -1 FILE_EXT)
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach (LANG ${ENABLED_LANGUAGES})
list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${FILE_EXT}" TEMP)
if (NOT ${TEMP} EQUAL -1)
set(${RETURN_VAR} "${LANG}" PARENT_SCOPE)
return()
endif ()
endforeach()
set(${RETURN_VAR} "" PARENT_SCOPE)
endfunction ()
# Helper function to get the relative path of the source file destination path.
# This path is needed by FindGcov and FindLcov cmake files to locate the
# captured data.
function (codecov_path_of_source FILE RETURN_VAR)
string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _source ${FILE})
# If expression was found, SOURCEFILE is a generator-expression for an
# object library. Currently we found no way to call this function automatic
# for the referenced target, so it must be called in the directoryso of the
# object library definition.
if (NOT "${_source}" STREQUAL "")
set(${RETURN_VAR} "" PARENT_SCOPE)
return()
endif ()
string(REPLACE "${CMAKE_CURRENT_BINARY_DIR}/" "" FILE "${FILE}")
if(IS_ABSOLUTE ${FILE})
file(RELATIVE_PATH FILE ${CMAKE_CURRENT_SOURCE_DIR} ${FILE})
endif()
# get the right path for file
string(REPLACE ".." "__" PATH "${FILE}")
set(${RETURN_VAR} "${PATH}" PARENT_SCOPE)
endfunction()
# Add coverage support for target ${TNAME} and register target for coverage
# evaluation.
function(add_coverage_target TNAME)
# Check if all sources for target use the same compiler. If a target uses
# e.g. C and Fortran mixed and uses different compilers (e.g. clang and
# gfortran) this can trigger huge problems, because different compilers may
# use different implementations for code coverage.
get_target_property(TSOURCES ${TNAME} SOURCES)
set(TARGET_COMPILER "")
set(ADDITIONAL_FILES "")
foreach (FILE ${TSOURCES})
# If expression was found, FILE is a generator-expression for an object
# library. Object libraries will be ignored.
string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _file ${FILE})
if ("${_file}" STREQUAL "")
codecov_lang_of_source(${FILE} LANG)
if (LANG)
list(APPEND TARGET_COMPILER ${CMAKE_${LANG}_COMPILER_ID})
list(APPEND ADDITIONAL_FILES "${FILE}.gcno")
list(APPEND ADDITIONAL_FILES "${FILE}.gcda")
endif ()
endif ()
endforeach ()
list(REMOVE_DUPLICATES TARGET_COMPILER)
list(LENGTH TARGET_COMPILER NUM_COMPILERS)
if (NUM_COMPILERS GREATER 1)
message(WARNING "Can't use code coverage for target ${TNAME}, because "
"it will be compiled by incompatible compilers. Target will be "
"compiled without code coverage.")
return()
elseif (NUM_COMPILERS EQUAL 0)
message(WARNING "Can't use code coverage for target ${TNAME}, because "
"it uses an unknown compiler. Target will be compiled without "
"code coverage.")
return()
elseif (NOT DEFINED "COVERAGE_${TARGET_COMPILER}_FLAGS")
# A warning has been printed before, so just return if flags for this
# compiler aren't available.
return()
endif()
# enable coverage for target
set_property(TARGET ${TNAME} APPEND_STRING
PROPERTY COMPILE_FLAGS " ${COVERAGE_${TARGET_COMPILER}_FLAGS}")
set_property(TARGET ${TNAME} APPEND_STRING
PROPERTY LINK_FLAGS " ${COVERAGE_${TARGET_COMPILER}_FLAGS}")
# Add gcov files generated by compiler to clean target.
set(CLEAN_FILES "")
foreach (FILE ${ADDITIONAL_FILES})
codecov_path_of_source(${FILE} FILE)
list(APPEND CLEAN_FILES "CMakeFiles/${TNAME}.dir/${FILE}")
endforeach()
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
"${CLEAN_FILES}")
add_gcov_target(${TNAME})
add_lcov_target(${TNAME})
endfunction(add_coverage_target)
# Include modules for parsing the collected data and output it in a readable
# format (like gcov and lcov).
find_package(Gcov)
find_package(Lcov)
-79
View File
@@ -1,79 +0,0 @@
include(CheckCXXCompilerFlag)
function(add_cxx_flag_if_supported_to_targets flagname targets)
check_cxx_compiler_flag("${flagname}" HAVE_FLAG_${flagname})
if (HAVE_FLAG_${flagname})
foreach(target ${targets})
target_compile_options(${target} PUBLIC ${flagname})
endforeach()
endif()
endfunction()
# Assumes that it is only called for development builds, where warnings
# and Werror is desired, so it also enables Werror.
function(add_warnings_to_targets targets)
LIST(LENGTH targets TARGETS_LEN)
# For now we just assume 2 possibilities: msvc and msvc-like compilers,
# and other.
if (MSVC)
foreach(target ${targets})
# Force MSVC to consider everything as encoded in utf-8
target_compile_options( ${target} PRIVATE /utf-8 )
# Enable Werror equivalent
if (CATCH_ENABLE_WERROR)
target_compile_options( ${target} PRIVATE /WX )
endif()
# MSVC is currently handled specially
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
STRING(REGEX REPLACE "/W[0-9]" "/W4" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) # override default warning level
target_compile_options( ${target} PRIVATE /w44265 /w44061 /w44062 /w45038 )
endif()
endforeach()
endif()
if (NOT MSVC)
set(CHECKED_WARNING_FLAGS
"-Wall"
"-Wextra"
"-Wpedantic"
"-Wweak-vtables"
"-Wunreachable-code"
"-Wmissing-declarations"
"-Wexit-time-destructors"
"-Wglobal-constructors"
"-Wmissing-noreturn"
"-Wparentheses"
"-Wextra-semi-stmt"
"-Wunreachable-code"
"-Wstrict-aliasing"
"-Wreturn-std-move"
"-Wmissing-braces"
"-Wdeprecated"
"-Wvla"
"-Wundef"
"-Wmisleading-indentation"
"-Wcatch-value"
"-Wabsolute-value"
"-Wreturn-std-move"
"-Wunused-parameter"
"-Wunused-function"
"-Wcall-to-pure-virtual-from-ctor-dtor"
"-Wdeprecated-register"
"-Wsuggest-override"
"-Wshadow"
"-Wold-style-cast"
)
foreach(warning ${CHECKED_WARNING_FLAGS})
add_cxx_flag_if_supported_to_targets(${warning} "${targets}")
endforeach()
if (CATCH_ENABLE_WERROR)
foreach(target ${targets})
# Enable Werror equivalent
target_compile_options( ${target} PRIVATE -Werror )
endforeach()
endif()
endif()
endfunction()
-10
View File
@@ -1,10 +0,0 @@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
pkg_version=@Catch2_VERSION@
Name: Catch2-With-Main
Description: A modern, C++-native test framework for C++14 and above (links in default main)
Version: ${pkg_version}
Requires: catch2 = ${pkg_version}
Cflags: -I${includedir}
Libs: -L${libdir} -lCatch2WithMain
-9
View File
@@ -1,9 +0,0 @@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
Name: Catch2
Description: A modern, C++-native, test framework for C++14 and above
URL: https://github.com/catchorg/Catch2
Version: @Catch2_VERSION@
Cflags: -I${includedir}
Libs: -L${libdir} -lCatch2
-56
View File
@@ -1,56 +0,0 @@
#!/bin/sh
# This file is part of CMake-codecov.
#
# Copyright (c)
# 2015-2017 RWTH Aachen University, Federal Republic of Germany
#
# See the LICENSE file in the package base directory for details
#
# Written by Alexander Haase, alexander.haase@rwth-aachen.de
#
if [ -z "$LLVM_COV_BIN" ]
then
echo "LLVM_COV_BIN not set!" >& 2
exit 1
fi
# Get LLVM version to find out.
LLVM_VERSION=$($LLVM_COV_BIN -version | grep -i "LLVM version" \
| sed "s/^\([A-Za-z ]*\)\([0-9]\).\([0-9]\).*$/\2.\3/g")
if [ "$1" = "-v" ]
then
echo "llvm-cov-wrapper $LLVM_VERSION"
exit 0
fi
if [ -n "$LLVM_VERSION" ]
then
MAJOR=$(echo $LLVM_VERSION | cut -d'.' -f1)
MINOR=$(echo $LLVM_VERSION | cut -d'.' -f2)
if [ $MAJOR -eq 3 ] && [ $MINOR -le 4 ]
then
if [ -f "$1" ]
then
filename=$(basename "$1")
extension="${filename##*.}"
case "$extension" in
"gcno") exec $LLVM_COV_BIN --gcno="$1" ;;
"gcda") exec $LLVM_COV_BIN --gcda="$1" ;;
esac
fi
fi
if [ $MAJOR -eq 3 ] && [ $MINOR -le 5 ]
then
exec $LLVM_COV_BIN $@
fi
fi
exec $LLVM_COV_BIN gcov $@
-208
View File
@@ -1,208 +0,0 @@
cmake_minimum_required(VERSION 3.5)
# detect if Catch is being bundled,
# disable testsuite in that case
if(NOT DEFINED PROJECT_NAME)
set(NOT_SUBPROJECT ON)
endif()
option(CATCH_INSTALL_DOCS "Install documentation alongside library" ON)
option(CATCH_INSTALL_EXTRAS "Install extras alongside library" ON)
option(CATCH_DEVELOPMENT_BUILD "Build tests, enable warnings, enable Werror, etc" OFF)
include(CMakeDependentOption)
cmake_dependent_option(CATCH_BUILD_TESTING "Build the SelfTest project" ON "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_BUILD_EXAMPLES "Build code examples" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_BUILD_EXTRA_TESTS "Build extra tests" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_BUILD_FUZZERS "Build fuzzers" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_ENABLE_COVERAGE "Generate coverage for codecov.io" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_ENABLE_WERROR "Enables Werror during build" ON "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_BUILD_SURROGATES "Enable generating and building surrogate TUs for the main headers" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
# Catch2's build breaks if done in-tree. You probably should not build
# things in tree anyway, but we can allow projects that include Catch2
# as a subproject to build in-tree as long as it is not in our tree.
if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
message(FATAL_ERROR "Building in-source is not supported! Create a build dir and remove ${CMAKE_SOURCE_DIR}/CMakeCache.txt")
endif()
if(CMAKE_VERSION VERSION_GREATER 3.8)
# Enable IPO for CMake versions that support it
cmake_policy(SET CMP0069 NEW)
endif()
project(Catch2 LANGUAGES CXX VERSION 3.0.0)
# Provide path for scripts
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
include(CTest)
# This variable is used in some subdirectories, so we need it here, rather
# than later in the install block
set(CATCH_CMAKE_CONFIG_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Catch2")
# We have some Windows builds that test `wmain` entry point,
# and we need this change to be present in all binaries that
# are built during these tests, so this is required here, before
# the subdirectories are added.
if(CATCH_TEST_USE_WMAIN)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:wmainCRTStartup")
endif()
# Basic paths
set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(SOURCES_DIR ${CATCH_DIR}/src/catch2)
set(SELF_TEST_DIR ${CATCH_DIR}/tests/SelfTest)
set(BENCHMARK_DIR ${CATCH_DIR}/tests/Benchmark)
set(EXAMPLES_DIR ${CATCH_DIR}/examples)
# We need to bring-in the variables defined there to this scope
add_subdirectory(src)
# Build tests only if requested
if (BUILD_TESTING AND CATCH_BUILD_TESTING AND NOT_SUBPROJECT)
find_package(PythonInterp 3 REQUIRED)
if (NOT PYTHONINTERP_FOUND)
message(FATAL_ERROR "Python not found, but required for tests")
endif()
add_subdirectory(tests)
endif()
if(CATCH_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
if(CATCH_BUILD_EXTRA_TESTS)
add_subdirectory(tests/ExtraTests)
endif()
if(CATCH_BUILD_FUZZERS)
add_subdirectory(fuzzing)
endif()
if (CATCH_DEVELOPMENT_BUILD)
add_warnings_to_targets("${CATCH_WARNING_TARGETS}")
endif()
#option(CATCH_USE_VALGRIND "Perform SelfTests with Valgrind" OFF)
#option(CATCH_ENABLE_WERROR "Enable all warnings as errors" ON)
#
#set_property(GLOBAL PROPERTY USE_FOLDERS ON)
#
#
#
#
#
# Only perform the installation steps when Catch is not being used as
# a subproject via `add_subdirectory`, or the destinations will break,
# see https://github.com/catchorg/Catch2/issues/1373
if (NOT_SUBPROJECT)
configure_package_config_file(
${CMAKE_CURRENT_LIST_DIR}/CMake/Catch2Config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/Catch2Config.cmake
INSTALL_DESTINATION
${CATCH_CMAKE_CONFIG_DESTINATION}
)
## TODO: Catch2 main target?
## Install some cpp file as well?
# By default, FooConfigVersion is tied to architecture that it was
# generated on. Because Catch2 is header-only, it is arch-independent
# and thus Catch2ConfigVersion should not be tied to the architecture
# it was generated on.
#
# CMake does not provide a direct customization point for this in
# `write_basic_package_version_file`, but it can be accomplished
# indirectly by temporarily redefining `CMAKE_SIZEOF_VOID_P` to an
# empty string. Note that just undefining the variable could be
# insufficient in cases where the variable was already in CMake cache
set(CATCH2_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
set(CMAKE_SIZEOF_VOID_P "")
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/Catch2ConfigVersion.cmake"
COMPATIBILITY
SameMajorVersion
)
set(CMAKE_SIZEOF_VOID_P ${CATCH2_CMAKE_SIZEOF_VOID_P})
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/Catch2Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/Catch2ConfigVersion.cmake"
DESTINATION
${CATCH_CMAKE_CONFIG_DESTINATION}
)
# Install documentation
if(CATCH_INSTALL_DOCS)
install(
DIRECTORY
docs/
DESTINATION
"${CMAKE_INSTALL_DOCDIR}"
)
endif()
if(CATCH_INSTALL_EXTRAS)
# Install CMake scripts
install(
FILES
"extras/ParseAndAddCatchTests.cmake"
"extras/Catch.cmake"
"extras/CatchAddTests.cmake"
DESTINATION
${CATCH_CMAKE_CONFIG_DESTINATION}
)
# Install debugger helpers
install(
FILES
"extras/gdbinit"
"extras/lldbinit"
DESTINATION
${CMAKE_INSTALL_DATAROOTDIR}/Catch2
)
endif()
## Provide some pkg-config integration
set(PKGCONFIG_INSTALL_DIR
"${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig"
CACHE PATH "Path where catch2.pc is installed"
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/CMake/catch2.pc.in
${CMAKE_CURRENT_BINARY_DIR}/catch2.pc
@ONLY
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/CMake/catch2-with-main.pc.in
${CMAKE_CURRENT_BINARY_DIR}/catch2-with-main.pc
@ONLY
)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/catch2.pc"
"${CMAKE_CURRENT_BINARY_DIR}/catch2-with-main.pc"
DESTINATION
${PKGCONFIG_INSTALL_DIR}
)
# CPack/CMake started taking the package version from project version 3.12
# So we need to set the version manually for older CMake versions
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
endif()
set(CPACK_PACKAGE_CONTACT "https://github.com/catchorg/Catch2/")
include( CPack )
endif(NOT_SUBPROJECT)
+15 -27
View File
@@ -1,39 +1,28 @@
<a id="top"></a>
![Catch2 logo](data/artwork/catch2-logo-small.png)
![catch logo](artwork/catch2-logo-small.png)
[![Github Releases](https://img.shields.io/github/release/catchorg/catch2.svg)](https://github.com/catchorg/catch2/releases)
[![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=devel)](https://travis-ci.org/catchorg/Catch2)
[![Build Status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true&branch=devel)](https://ci.appveyor.com/project/catchorg/catch2)
[![Code Coverage](https://codecov.io/gh/catchorg/Catch2/branch/devel/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://godbolt.org/z/9x9qoM)
[![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=v2.x)](https://travis-ci.org/catchorg/Catch2)
[![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2)
[![codecov](https://codecov.io/gh/catchorg/Catch2/branch/v2.x/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/6JUH8Eybx4CtvkJS)
[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD)
## Catch2 v3 is being developed!
<a href="https://github.com/catchorg/Catch2/releases/download/v2.13.10/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
You are on the `devel` branch, where the next major version, v3, of
Catch2 is being developed. As it is a significant rework, you will
find that parts of this documentation are likely still stuck on v2.
## Catch2 is released!
For stable (and documentation-matching) version of Catch2, [go to the
`v2.x` branch](https://github.com/catchorg/Catch2/tree/v2.x).
If you've been using an earlier version of Catch, please see the
Breaking Changes section of [the release notes](https://github.com/catchorg/Catch2/releases/tag/v2.0.1)
before moving to Catch2. You might also like to read [this blog post](https://levelofindirection.com/blog/catch2-released.html) for more details.
For migrating from the v2 releases to v3, you should look at [our
documentation](docs/migrate-v2-to-v3.md#top). It provides a simple
guidelines on getting started, and collects most common migration
problems.
## What's the Catch2?
Catch2 is mainly a unit testing framework for C++, but it also
provides basic micro-benchmarking features, and simple BDD macros.
Catch2's main advantage is that using it is both simple and natural.
Tests autoregister themselves and do not have to be named with valid
identifiers, assertions look like normal C++ code, and sections provide
a nice way to share set-up and tear-down code in tests.
## What's the Catch?
Catch2 is a multi-paradigm test framework for C++. which also supports
Objective-C (and maybe C).
It is primarily distributed as a single header file, although certain
extensions may require additional headers.
## How to use it
This documentation comprises these three parts:
@@ -42,7 +31,6 @@ This documentation comprises these three parts:
* [Tutorial](docs/tutorial.md#top) - getting started
* [Reference section](docs/Readme.md#top) - all the details
## More
* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/catchorg/Catch2/issues)
* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum) or our [Discord](https://discord.gg/4CWS9zD)
@@ -202,4 +202,5 @@ endfunction()
set(_CATCH_DISCOVER_TESTS_SCRIPT
${CMAKE_CURRENT_LIST_DIR}/CatchAddTests.cmake
CACHE INTERNAL "Catch2 full path to CatchAddTests.cmake helper file"
)
@@ -16,7 +16,10 @@ set(tests)
function(add_command NAME)
set(_args "")
foreach(_arg ${ARGN})
# use ARGV* instead of ARGN, because ARGN splits arrays into multiple arguments
math(EXPR _last_arg ${ARGC}-1)
foreach(_n RANGE 1 ${_last_arg})
set(_arg "${ARGV${_n}}")
if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument
else()
@@ -33,12 +36,17 @@ if(NOT EXISTS "${TEST_EXECUTABLE}")
)
endif()
execute_process(
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-tests --verbosity quiet
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-names-only
OUTPUT_VARIABLE output
RESULT_VARIABLE result
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
)
if(NOT ${result} EQUAL 0)
# Catch --list-test-names-only reports the number of tests, so 0 is... surprising
if(${result} EQUAL 0)
message(WARNING
"Test executable '${TEST_EXECUTABLE}' contains no tests!\n"
)
elseif(${result} LESS 0)
message(FATAL_ERROR
"Error running test executable '${TEST_EXECUTABLE}':\n"
" Result: ${result}\n"
@@ -55,7 +63,11 @@ execute_process(
RESULT_VARIABLE reporters_result
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
)
if(NOT ${reporters_result} EQUAL 0)
if(${reporters_result} EQUAL 0)
message(WARNING
"Test executable '${TEST_EXECUTABLE}' contains no reporters!\n"
)
elseif(${reporters_result} LESS 0)
message(FATAL_ERROR
"Error running test executable '${TEST_EXECUTABLE}':\n"
" Result: ${reporters_result}\n"
@@ -200,7 +200,7 @@ function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
# Escape commas in the test spec
string(REPLACE "," "\\," Name ${Name})
# Work around CMake 3.18.0 change in `add_test()`, before the escaped quotes were neccessary,
# Work around CMake 3.18.0 change in `add_test()`, before the escaped quotes were necessary,
# only with CMake 3.18.0 the escaped double quotes confuse the call. This change is reverted in 3.18.1
# And properly introduced in 3.19 with the CMP0110 policy
if(_cmp0110_value STREQUAL "NEW" OR ${CMAKE_VERSION} VERSION_EQUAL "3.18")
@@ -241,6 +241,7 @@ endfunction()
# entry point
function(ParseAndAddCatchTests TestTarget)
message(DEPRECATION "ParseAndAddCatchTest: function deprecated because of possibility of missed test cases. Consider using 'catch_discover_tests' from 'Catch.cmake'")
ParseAndAddCatchTests_PrintDebugMessage("Started parsing ${TestTarget}")
get_target_property(SourceFiles ${TestTarget} SOURCES)
ParseAndAddCatchTests_PrintDebugMessage("Found the following sources: ${SourceFiles}")
File diff suppressed because it is too large Load Diff
-368
View File
@@ -1,368 +0,0 @@
include(MiscFunctions)
# Please keep these ordered alphabetically
set(BENCHMARK_HEADERS
${SOURCES_DIR}/benchmark/catch_benchmark.hpp
${SOURCES_DIR}/benchmark/catch_benchmark_all.hpp
${SOURCES_DIR}/benchmark/catch_chronometer.hpp
${SOURCES_DIR}/benchmark/catch_clock.hpp
${SOURCES_DIR}/benchmark/catch_constructor.hpp
${SOURCES_DIR}/benchmark/catch_environment.hpp
${SOURCES_DIR}/benchmark/catch_estimate.hpp
${SOURCES_DIR}/benchmark/catch_execution_plan.hpp
${SOURCES_DIR}/benchmark/catch_optimizer.hpp
${SOURCES_DIR}/benchmark/catch_outlier_classification.hpp
${SOURCES_DIR}/benchmark/catch_sample_analysis.hpp
${SOURCES_DIR}/benchmark/detail/catch_analyse.hpp
${SOURCES_DIR}/benchmark/detail/catch_benchmark_function.hpp
${SOURCES_DIR}/benchmark/detail/catch_complete_invoke.hpp
${SOURCES_DIR}/benchmark/detail/catch_estimate_clock.hpp
${SOURCES_DIR}/benchmark/detail/catch_measure.hpp
${SOURCES_DIR}/benchmark/detail/catch_repeat.hpp
${SOURCES_DIR}/benchmark/detail/catch_run_for_at_least.hpp
${SOURCES_DIR}/benchmark/detail/catch_stats.hpp
${SOURCES_DIR}/benchmark/detail/catch_timing.hpp
)
set(BENCHMARK_SOURCES
${SOURCES_DIR}/benchmark/internal/catch_benchmark_combined_tu.cpp
${SOURCES_DIR}/benchmark/detail/catch_stats.cpp
)
SOURCE_GROUP("benchmark" FILES ${BENCHMARK_HEADERS} ${BENCHMARK_SOURCES})
set(INTERNAL_HEADERS
${SOURCES_DIR}/catch_all.hpp
${SOURCES_DIR}/matchers/catch_matchers_all.hpp
${SOURCES_DIR}/generators/catch_generators_all.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_all.hpp
${SOURCES_DIR}/matchers/internal/catch_matchers_impl.hpp
${SOURCES_DIR}/internal/catch_console_width.hpp
${SOURCES_DIR}/internal/catch_container_nonmembers.hpp
${SOURCES_DIR}/internal/catch_noncopyable.hpp
${SOURCES_DIR}/catch_approx.hpp
${SOURCES_DIR}/internal/catch_assertion_handler.hpp
${SOURCES_DIR}/catch_assertion_info.hpp
${SOURCES_DIR}/catch_assertion_result.hpp
${SOURCES_DIR}/internal/catch_test_macro_impl.hpp
${SOURCES_DIR}/internal/catch_test_failure_exception.hpp
${SOURCES_DIR}/internal/catch_case_sensitive.hpp
${SOURCES_DIR}/internal/catch_clara.hpp
${SOURCES_DIR}/internal/catch_commandline.hpp
${SOURCES_DIR}/internal/catch_source_line_info.hpp
${SOURCES_DIR}/internal/catch_compiler_capabilities.hpp
${SOURCES_DIR}/catch_config.hpp
${SOURCES_DIR}/internal/catch_config_android_logwrite.hpp
${SOURCES_DIR}/internal/catch_config_counter.hpp
${SOURCES_DIR}/internal/catch_config_uncaught_exceptions.hpp
${SOURCES_DIR}/internal/catch_config_wchar.hpp
${SOURCES_DIR}/internal/catch_console_colour.hpp
${SOURCES_DIR}/internal/catch_context.hpp
${SOURCES_DIR}/internal/catch_debug_console.hpp
${SOURCES_DIR}/internal/catch_debugger.hpp
${SOURCES_DIR}/internal/catch_decomposer.hpp
${SOURCES_DIR}/internal/catch_enforce.hpp
${SOURCES_DIR}/internal/catch_enum_values_registry.hpp
${SOURCES_DIR}/internal/catch_errno_guard.hpp
${SOURCES_DIR}/internal/catch_exception_translator_registry.hpp
${SOURCES_DIR}/internal/catch_fatal_condition_handler.hpp
${SOURCES_DIR}/internal/catch_unique_name.hpp
${SOURCES_DIR}/generators/catch_generator_exception.hpp
${SOURCES_DIR}/generators/catch_generators.hpp
${SOURCES_DIR}/generators/catch_generators_adapters.hpp
${SOURCES_DIR}/generators/catch_generators_random.hpp
${SOURCES_DIR}/generators/catch_generators_range.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_capture.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_config.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_enum_values_registry.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_exception.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_generatortracker.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_registry_hub.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_reporter.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_reporter_factory.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_reporter_registry.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_runner.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_tag_alias_registry.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_testcase.hpp
${SOURCES_DIR}/internal/catch_lazy_expr.hpp
${SOURCES_DIR}/internal/catch_leak_detector.hpp
${SOURCES_DIR}/internal/catch_list.hpp
${SOURCES_DIR}/matchers/catch_matchers.hpp
${SOURCES_DIR}/matchers/catch_matchers_container_properties.hpp
${SOURCES_DIR}/matchers/catch_matchers_contains.hpp
${SOURCES_DIR}/matchers/catch_matchers_exception.hpp
${SOURCES_DIR}/matchers/catch_matchers_floating_point.hpp
${SOURCES_DIR}/matchers/catch_matchers_predicate.hpp
${SOURCES_DIR}/matchers/catch_matchers_quantifiers.hpp
${SOURCES_DIR}/matchers/catch_matchers_string.hpp
${SOURCES_DIR}/matchers/catch_matchers_templated.hpp
${SOURCES_DIR}/matchers/catch_matchers_vector.hpp
${SOURCES_DIR}/catch_message.hpp
${SOURCES_DIR}/internal/catch_message_info.hpp
${SOURCES_DIR}/internal/catch_meta.hpp
${SOURCES_DIR}/internal/catch_option.hpp
${SOURCES_DIR}/internal/catch_output_redirect.hpp
${SOURCES_DIR}/internal/catch_platform.hpp
${SOURCES_DIR}/internal/catch_polyfills.hpp
${SOURCES_DIR}/internal/catch_preprocessor.hpp
${SOURCES_DIR}/internal/catch_random_number_generator.hpp
${SOURCES_DIR}/catch_reporter_registrars.hpp
${SOURCES_DIR}/internal/catch_reporter_registry.hpp
${SOURCES_DIR}/internal/catch_result_type.hpp
${SOURCES_DIR}/internal/catch_run_context.hpp
${SOURCES_DIR}/internal/catch_section.hpp
${SOURCES_DIR}/catch_section_info.hpp
${SOURCES_DIR}/catch_session.hpp
${SOURCES_DIR}/internal/catch_singletons.hpp
${SOURCES_DIR}/internal/catch_startup_exception_registry.hpp
${SOURCES_DIR}/internal/catch_stream.hpp
${SOURCES_DIR}/internal/catch_stream_end_stop.hpp
${SOURCES_DIR}/internal/catch_string_manip.hpp
${SOURCES_DIR}/internal/catch_stringref.hpp
${SOURCES_DIR}/catch_tag_alias.hpp
${SOURCES_DIR}/catch_tag_alias_autoregistrar.hpp
${SOURCES_DIR}/internal/catch_tag_alias_registry.hpp
${SOURCES_DIR}/catch_test_case_info.hpp
${SOURCES_DIR}/internal/catch_test_case_registry_impl.hpp
${SOURCES_DIR}/internal/catch_test_case_tracker.hpp
${SOURCES_DIR}/catch_template_test_macros.hpp
${SOURCES_DIR}/catch_test_macros.hpp
${SOURCES_DIR}/internal/catch_template_test_registry.hpp
${SOURCES_DIR}/internal/catch_test_registry.hpp
${SOURCES_DIR}/catch_test_spec.hpp
${SOURCES_DIR}/internal/catch_test_spec_parser.hpp
${SOURCES_DIR}/internal/catch_textflow.hpp
${SOURCES_DIR}/catch_timer.hpp
${SOURCES_DIR}/internal/catch_to_string.hpp
${SOURCES_DIR}/catch_tostring.hpp
${SOURCES_DIR}/catch_totals.hpp
${SOURCES_DIR}/catch_translate_exception.hpp
${SOURCES_DIR}/internal/catch_uncaught_exceptions.hpp
${SOURCES_DIR}/internal/catch_unique_ptr.hpp
${SOURCES_DIR}/catch_version.hpp
${SOURCES_DIR}/catch_version_macros.hpp
${SOURCES_DIR}/internal/catch_wildcard_pattern.hpp
${SOURCES_DIR}/internal/catch_windows_h_proxy.hpp
${SOURCES_DIR}/internal/catch_xmlwriter.hpp
)
set(IMPL_SOURCES
${SOURCES_DIR}/catch_approx.cpp
${SOURCES_DIR}/internal/catch_assertion_handler.cpp
${SOURCES_DIR}/catch_assertion_result.cpp
${SOURCES_DIR}/matchers/internal/catch_matchers_combined_tu.cpp
${SOURCES_DIR}/internal/catch_clara.cpp
${SOURCES_DIR}/internal/catch_commandline.cpp
${SOURCES_DIR}/internal/catch_source_line_info.cpp
${SOURCES_DIR}/catch_config.cpp
${SOURCES_DIR}/internal/catch_console_colour.cpp
${SOURCES_DIR}/internal/catch_context.cpp
${SOURCES_DIR}/internal/catch_debug_console.cpp
${SOURCES_DIR}/internal/catch_debugger.cpp
${SOURCES_DIR}/internal/catch_enforce.cpp
${SOURCES_DIR}/internal/catch_enum_values_registry.cpp
${SOURCES_DIR}/internal/catch_exception_translator_registry.cpp
${SOURCES_DIR}/internal/catch_fatal_condition_handler.cpp
${SOURCES_DIR}/generators/internal/catch_generators_combined_tu.cpp
${SOURCES_DIR}/interfaces/catch_interfaces_combined_tu.cpp
${SOURCES_DIR}/interfaces/catch_interfaces_reporter.cpp
${SOURCES_DIR}/internal/catch_list.cpp
${SOURCES_DIR}/matchers/catch_matchers_floating_point.cpp
${SOURCES_DIR}/matchers/catch_matchers_string.cpp
${SOURCES_DIR}/matchers/catch_matchers_templated.cpp
${SOURCES_DIR}/catch_message.cpp
${SOURCES_DIR}/internal/catch_output_redirect.cpp
${SOURCES_DIR}/catch_registry_hub.cpp
${SOURCES_DIR}/internal/catch_combined_tu.cpp
${SOURCES_DIR}/internal/catch_random_number_generator.cpp
${SOURCES_DIR}/internal/catch_reporter_registry.cpp
${SOURCES_DIR}/internal/catch_result_type.cpp
${SOURCES_DIR}/internal/catch_run_context.cpp
${SOURCES_DIR}/internal/catch_section.cpp
${SOURCES_DIR}/catch_session.cpp
${SOURCES_DIR}/internal/catch_singletons.cpp
${SOURCES_DIR}/internal/catch_stream.cpp
${SOURCES_DIR}/internal/catch_stringref.cpp
${SOURCES_DIR}/internal/catch_string_manip.cpp
${SOURCES_DIR}/internal/catch_tag_alias_registry.cpp
${SOURCES_DIR}/catch_test_case_info.cpp
${SOURCES_DIR}/internal/catch_test_case_registry_impl.cpp
${SOURCES_DIR}/internal/catch_test_case_tracker.cpp
${SOURCES_DIR}/internal/catch_test_registry.cpp
${SOURCES_DIR}/internal/catch_textflow.cpp
${SOURCES_DIR}/catch_test_spec.cpp
${SOURCES_DIR}/internal/catch_test_spec_parser.cpp
${SOURCES_DIR}/catch_timer.cpp
${SOURCES_DIR}/catch_tostring.cpp
${SOURCES_DIR}/catch_totals.cpp
${SOURCES_DIR}/catch_version.cpp
${SOURCES_DIR}/internal/catch_wildcard_pattern.cpp
${SOURCES_DIR}/internal/catch_xmlwriter.cpp
)
set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS})
# Please keep these ordered alphabetically
set(REPORTER_HEADERS
${SOURCES_DIR}/reporters/catch_reporters_all.hpp
${SOURCES_DIR}/reporters/catch_reporter_automake.hpp
${SOURCES_DIR}/reporters/catch_reporter_compact.hpp
${SOURCES_DIR}/reporters/catch_reporter_console.hpp
${SOURCES_DIR}/reporters/catch_reporter_cumulative_base.hpp
${SOURCES_DIR}/reporters/catch_reporter_event_listener.hpp
${SOURCES_DIR}/reporters/catch_reporter_helpers.hpp
${SOURCES_DIR}/reporters/catch_reporter_junit.hpp
${SOURCES_DIR}/reporters/catch_reporter_listening.hpp
${SOURCES_DIR}/reporters/catch_reporter_sonarqube.hpp
${SOURCES_DIR}/reporters/catch_reporter_streaming_base.hpp
${SOURCES_DIR}/reporters/catch_reporter_tap.hpp
${SOURCES_DIR}/reporters/catch_reporter_teamcity.hpp
${SOURCES_DIR}/reporters/catch_reporter_xml.hpp
)
set(REPORTER_SOURCES
${SOURCES_DIR}/reporters/catch_reporter_automake.cpp
${SOURCES_DIR}/reporters/catch_reporter_combined_tu.cpp
${SOURCES_DIR}/reporters/catch_reporter_compact.cpp
${SOURCES_DIR}/reporters/catch_reporter_console.cpp
${SOURCES_DIR}/reporters/catch_reporter_cumulative_base.cpp
${SOURCES_DIR}/reporters/catch_reporter_junit.cpp
${SOURCES_DIR}/reporters/catch_reporter_listening.cpp
${SOURCES_DIR}/reporters/catch_reporter_sonarqube.cpp
${SOURCES_DIR}/reporters/catch_reporter_streaming_base.cpp
${SOURCES_DIR}/reporters/catch_reporter_tap.cpp
${SOURCES_DIR}/reporters/catch_reporter_teamcity.cpp
${SOURCES_DIR}/reporters/catch_reporter_xml.cpp
)
set(REPORTER_FILES ${REPORTER_HEADERS} ${REPORTER_SOURCES})
# Fixme: STATIC because for dynamic, we would need to handle visibility
# and I don't want to do the annotations right now
add_library(Catch2 STATIC
${REPORTER_FILES}
${INTERNAL_FILES}
${BENCHMARK_HEADERS}
${BENCHMARK_SOURCES}
)
add_library(Catch2::Catch2 ALIAS Catch2)
if (ANDROID)
target_link_libraries(Catch2 INTERFACE log)
endif()
# depend on bunch of C++11 and C++14 features to have C++14 enabled by default
target_compile_features(Catch2
PUBLIC
cxx_alignas
cxx_alignof
cxx_attributes
cxx_auto_type
cxx_constexpr
cxx_defaulted_functions
cxx_deleted_functions
cxx_final
cxx_lambdas
cxx_noexcept
cxx_override
cxx_range_for
cxx_rvalue_references
cxx_static_assert
cxx_strong_enums
cxx_trailing_return_types
cxx_unicode_literals
cxx_user_literals
cxx_variable_templates
cxx_variadic_macros
)
if (NOT_SUBPROJECT)
target_include_directories(Catch2
PUBLIC
$<BUILD_INTERFACE:${SOURCES_DIR}/..>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
else()
target_include_directories(Catch2
SYSTEM PUBLIC
$<BUILD_INTERFACE:${SOURCES_DIR}/..>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
endif()
add_library(Catch2WithMain STATIC
${SOURCES_DIR}/internal/catch_main.cpp
)
add_library(Catch2::Catch2WithMain ALIAS Catch2WithMain)
target_link_libraries(Catch2WithMain PUBLIC Catch2)
set_target_properties(Catch2WithMain
PROPERTIES
OUTPUT_NAME "Catch2Main"
)
if (NOT_SUBPROJECT)
# create and install an export set for catch target as Catch2::Catch
install(
TARGETS
Catch2
Catch2WithMain
EXPORT
Catch2Targets
DESTINATION
${CMAKE_INSTALL_LIBDIR}
)
install(
EXPORT
Catch2Targets
NAMESPACE
Catch2::
DESTINATION
${CATCH_CMAKE_CONFIG_DESTINATION}
)
# Install the headers
install(DIRECTORY ${SOURCES_DIR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.h*")
endif()
# Some tests require a full recompilation of Catch2 lib with different
# compilation flags. They can link against this target to recompile all
# the sources into the binary.
if (CATCH_BUILD_EXAMPLES OR CATCH_BUILD_EXTRA_TESTS)
add_library(Catch2_buildall_interface INTERFACE)
target_sources(Catch2_buildall_interface INTERFACE
${REPORTER_FILES}
${INTERNAL_FILES}
${BENCHMARK_HEADERS}
${BENCHMARK_SOURCES}
# Also include main entry point
${SOURCES_DIR}/internal/catch_main.cpp
)
target_include_directories(Catch2_buildall_interface
INTERFACE
$<BUILD_INTERFACE:${SOURCES_DIR}/..>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_compile_features(Catch2_buildall_interface
INTERFACE
cxx_alignas
cxx_alignof
cxx_attributes
cxx_auto_type
cxx_constexpr
cxx_defaulted_functions
cxx_deleted_functions
cxx_final
cxx_lambdas
cxx_noexcept
cxx_override
cxx_range_for
cxx_rvalue_references
cxx_static_assert
cxx_strong_enums
cxx_trailing_return_types
cxx_unicode_literals
cxx_user_literals
cxx_variable_templates
cxx_variadic_macros
)
endif()
list(APPEND CATCH_WARNING_TARGETS Catch2 Catch2WithMain)
set(CATCH_WARNING_TARGETS ${CATCH_WARNING_TARGETS} PARENT_SCOPE)
@@ -1,138 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_BENCHMARK_HPP_INCLUDED
#define CATCH_BENCHMARK_HPP_INCLUDED
#include <catch2/interfaces/catch_interfaces_config.hpp>
#include <catch2/internal/catch_context.hpp>
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
#include <catch2/internal/catch_unique_name.hpp>
#include <catch2/benchmark/catch_chronometer.hpp>
#include <catch2/benchmark/catch_clock.hpp>
#include <catch2/benchmark/catch_environment.hpp>
#include <catch2/benchmark/catch_execution_plan.hpp>
#include <catch2/benchmark/detail/catch_estimate_clock.hpp>
#include <catch2/benchmark/detail/catch_complete_invoke.hpp>
#include <catch2/benchmark/detail/catch_analyse.hpp>
#include <catch2/benchmark/detail/catch_benchmark_function.hpp>
#include <catch2/benchmark/detail/catch_run_for_at_least.hpp>
#include <algorithm>
#include <functional>
#include <string>
#include <vector>
#include <cmath>
namespace Catch {
namespace Benchmark {
struct Benchmark {
Benchmark(std::string&& benchmarkName)
: name(std::move(benchmarkName)) {}
template <class FUN>
Benchmark(std::string&& benchmarkName , FUN &&func)
: fun(std::move(func)), name(std::move(benchmarkName)) {}
template <typename Clock>
ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const {
auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun);
int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
}
template <typename Clock = default_clock>
void run() {
auto const* cfg = getCurrentContext().getConfig();
auto env = Detail::measure_environment<Clock>();
getResultCapture().benchmarkPreparing(name);
CATCH_TRY{
auto plan = user_code([&] {
return prepare<Clock>(*cfg, env);
});
BenchmarkInfo info {
name,
plan.estimated_duration.count(),
plan.iterations_per_sample,
cfg->benchmarkSamples(),
cfg->benchmarkResamples(),
env.clock_resolution.mean.count(),
env.clock_cost.mean.count()
};
getResultCapture().benchmarkStarting(info);
auto samples = user_code([&] {
return plan.template run<Clock>(*cfg, env);
});
auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end());
BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
getResultCapture().benchmarkEnded(stats);
} CATCH_CATCH_ALL{
if (translateActiveException() != Detail::benchmarkErrorMsg) // benchmark errors have been reported, otherwise rethrow.
std::rethrow_exception(std::current_exception());
}
}
// sets lambda to be used in fun *and* executes benchmark!
template <typename Fun,
typename std::enable_if<!Detail::is_related<Fun, Benchmark>::value, int>::type = 0>
Benchmark & operator=(Fun func) {
fun = Detail::BenchmarkFunction(func);
run();
return *this;
}
explicit operator bool() {
return true;
}
private:
Detail::BenchmarkFunction fun;
std::string name;
};
}
} // namespace Catch
#define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1
#define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2
#define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\
if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
BenchmarkName = [&](int benchmarkIndex)
#define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\
if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
BenchmarkName = [&]
#if defined(CATCH_CONFIG_PREFIX_ALL)
#define CATCH_BENCHMARK(...) \
INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
#define CATCH_BENCHMARK_ADVANCED(name) \
INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name)
#else
#define BENCHMARK(...) \
INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
#define BENCHMARK_ADVANCED(name) \
INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name)
#endif
#endif // CATCH_BENCHMARK_HPP_INCLUDED
@@ -1,44 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
/** \file
* This is a convenience header for Catch2's benchmarking. It includes
* **all** of Catch2 headers related to benchmarking.
*
* Generally the Catch2 users should use specific includes they need,
* but this header can be used instead for ease-of-experimentation, or
* just plain convenience, at the cost of (significantly) increased
* compilation times.
*
* When a new header is added to either the `benchmark` folder, or to
* the corresponding internal (detail) subfolder, it should be added here.
*/
#ifndef CATCH_BENCHMARK_ALL_HPP_INCLUDED
#define CATCH_BENCHMARK_ALL_HPP_INCLUDED
#include <catch2/benchmark/catch_benchmark.hpp>
#include <catch2/benchmark/catch_chronometer.hpp>
#include <catch2/benchmark/catch_clock.hpp>
#include <catch2/benchmark/catch_constructor.hpp>
#include <catch2/benchmark/catch_environment.hpp>
#include <catch2/benchmark/catch_estimate.hpp>
#include <catch2/benchmark/catch_execution_plan.hpp>
#include <catch2/benchmark/catch_optimizer.hpp>
#include <catch2/benchmark/catch_outlier_classification.hpp>
#include <catch2/benchmark/catch_sample_analysis.hpp>
#include <catch2/benchmark/detail/catch_analyse.hpp>
#include <catch2/benchmark/detail/catch_benchmark_function.hpp>
#include <catch2/benchmark/detail/catch_complete_invoke.hpp>
#include <catch2/benchmark/detail/catch_estimate_clock.hpp>
#include <catch2/benchmark/detail/catch_measure.hpp>
#include <catch2/benchmark/detail/catch_repeat.hpp>
#include <catch2/benchmark/detail/catch_run_for_at_least.hpp>
#include <catch2/benchmark/detail/catch_stats.hpp>
#include <catch2/benchmark/detail/catch_timing.hpp>
#endif // CATCH_BENCHMARK_ALL_HPP_INCLUDED
@@ -1,74 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_CHRONOMETER_HPP_INCLUDED
#define CATCH_CHRONOMETER_HPP_INCLUDED
#include <catch2/benchmark/catch_clock.hpp>
#include <catch2/benchmark/catch_optimizer.hpp>
#include <catch2/benchmark/detail/catch_complete_invoke.hpp>
#include <catch2/internal/catch_meta.hpp>
namespace Catch {
namespace Benchmark {
namespace Detail {
struct ChronometerConcept {
virtual void start() = 0;
virtual void finish() = 0;
virtual ~ChronometerConcept(); // = default;
ChronometerConcept() = default;
ChronometerConcept(ChronometerConcept const&) = default;
ChronometerConcept& operator=(ChronometerConcept const&) = default;
};
template <typename Clock>
struct ChronometerModel final : public ChronometerConcept {
void start() override { started = Clock::now(); }
void finish() override { finished = Clock::now(); }
ClockDuration<Clock> elapsed() const { return finished - started; }
TimePoint<Clock> started;
TimePoint<Clock> finished;
};
} // namespace Detail
struct Chronometer {
public:
template <typename Fun>
void measure(Fun&& fun) { measure(std::forward<Fun>(fun), is_callable<Fun(int)>()); }
int runs() const { return repeats; }
Chronometer(Detail::ChronometerConcept& meter, int repeats_)
: impl(&meter)
, repeats(repeats_) {}
private:
template <typename Fun>
void measure(Fun&& fun, std::false_type) {
measure([&fun](int) { return fun(); }, std::true_type());
}
template <typename Fun>
void measure(Fun&& fun, std::true_type) {
Detail::optimizer_barrier();
impl->start();
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
#endif // CATCH_CHRONOMETER_HPP_INCLUDED
@@ -1,39 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_CLOCK_HPP_INCLUDED
#define CATCH_CLOCK_HPP_INCLUDED
#include <chrono>
#include <ratio>
namespace Catch {
namespace Benchmark {
template <typename Clock>
using ClockDuration = typename Clock::duration;
template <typename Clock>
using FloatDuration = std::chrono::duration<double, typename Clock::period>;
template <typename Clock>
using TimePoint = typename Clock::time_point;
using default_clock = std::chrono::steady_clock;
template <typename Clock>
struct now {
TimePoint<Clock> operator()() const {
return Clock::now();
}
};
using fp_seconds = std::chrono::duration<double, std::ratio<1>>;
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_CLOCK_HPP_INCLUDED
@@ -1,79 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_CONSTRUCTOR_HPP_INCLUDED
#define CATCH_CONSTRUCTOR_HPP_INCLUDED
#include <type_traits>
#include <utility>
namespace Catch {
namespace Benchmark {
namespace Detail {
template <typename T, bool Destruct>
struct ObjectStorage
{
using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
ObjectStorage() : data() {}
ObjectStorage(const ObjectStorage& other)
{
new(&data) T(other.stored_object());
}
ObjectStorage(ObjectStorage&& other)
{
new(&data) T(std::move(other.stored_object()));
}
~ObjectStorage() { destruct_on_exit<T>(); }
template <typename... Args>
void construct(Args&&... args)
{
new (&data) T(std::forward<Args>(args)...);
}
template <bool AllowManualDestruction = !Destruct>
typename std::enable_if<AllowManualDestruction>::type destruct()
{
stored_object().~T();
}
private:
// If this is a constructor benchmark, destruct the underlying object
template <typename U>
void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); }
// Otherwise, don't
template <typename U>
void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { }
T& stored_object() {
return *static_cast<T*>(static_cast<void*>(&data));
}
T const& stored_object() const {
return *static_cast<T*>(static_cast<void*>(&data));
}
TStorage data;
};
} // namespace Detail
template <typename T>
using storage_for = Detail::ObjectStorage<T, true>;
template <typename T>
using destructable_object = Detail::ObjectStorage<T, false>;
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_CONSTRUCTOR_HPP_INCLUDED
@@ -1,37 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_ENVIRONMENT_HPP_INCLUDED
#define CATCH_ENVIRONMENT_HPP_INCLUDED
#include <catch2/benchmark/catch_clock.hpp>
#include <catch2/benchmark/catch_outlier_classification.hpp>
namespace Catch {
namespace Benchmark {
template <typename Duration>
struct EnvironmentEstimate {
Duration mean;
OutlierClassification outliers;
template <typename Duration2>
operator EnvironmentEstimate<Duration2>() const {
return { mean, outliers };
}
};
template <typename Clock>
struct Environment {
using clock_type = Clock;
EnvironmentEstimate<FloatDuration<Clock>> clock_resolution;
EnvironmentEstimate<FloatDuration<Clock>> clock_cost;
};
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_ENVIRONMENT_HPP_INCLUDED
@@ -1,30 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_ESTIMATE_HPP_INCLUDED
#define CATCH_ESTIMATE_HPP_INCLUDED
namespace Catch {
namespace Benchmark {
template <typename Duration>
struct Estimate {
Duration point;
Duration lower_bound;
Duration upper_bound;
double confidence_interval;
template <typename Duration2>
operator Estimate<Duration2>() const {
return { point, lower_bound, upper_bound, confidence_interval };
}
};
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_ESTIMATE_HPP_INCLUDED
@@ -1,57 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_EXECUTION_PLAN_HPP_INCLUDED
#define CATCH_EXECUTION_PLAN_HPP_INCLUDED
#include <catch2/interfaces/catch_interfaces_config.hpp>
#include <catch2/benchmark/catch_clock.hpp>
#include <catch2/benchmark/catch_environment.hpp>
#include <catch2/benchmark/detail/catch_benchmark_function.hpp>
#include <catch2/benchmark/detail/catch_repeat.hpp>
#include <catch2/benchmark/detail/catch_run_for_at_least.hpp>
#include <algorithm>
namespace Catch {
namespace Benchmark {
template <typename Duration>
struct ExecutionPlan {
int iterations_per_sample;
Duration estimated_duration;
Detail::BenchmarkFunction benchmark;
Duration warmup_time;
int warmup_iterations;
template <typename Duration2>
operator ExecutionPlan<Duration2>() const {
return { iterations_per_sample, estimated_duration, benchmark, warmup_time, warmup_iterations };
}
template <typename Clock>
std::vector<FloatDuration<Clock>> run(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const {
// warmup a bit
Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_iterations, Detail::repeat(now<Clock>{}));
std::vector<FloatDuration<Clock>> times;
times.reserve(cfg.benchmarkSamples());
std::generate_n(std::back_inserter(times), cfg.benchmarkSamples(), [this, env] {
Detail::ChronometerModel<Clock> model;
this->benchmark(Chronometer(model, iterations_per_sample));
auto sample_time = model.elapsed() - env.clock_cost.mean;
if (sample_time < FloatDuration<Clock>::zero()) sample_time = FloatDuration<Clock>::zero();
return sample_time / iterations_per_sample;
});
return times;
}
};
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_EXECUTION_PLAN_HPP_INCLUDED
@@ -1,70 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_OPTIMIZER_HPP_INCLUDED
#define CATCH_OPTIMIZER_HPP_INCLUDED
#if defined(_MSC_VER)
# include <atomic> // atomic_thread_fence
#endif
#include <type_traits>
#include <utility>
namespace Catch {
namespace Benchmark {
#if defined(__GNUC__) || defined(__clang__)
template <typename T>
inline void keep_memory(T* p) {
asm volatile("" : : "g"(p) : "memory");
}
inline void keep_memory() {
asm volatile("" : : : "memory");
}
namespace Detail {
inline void optimizer_barrier() { keep_memory(); }
} // namespace Detail
#elif defined(_MSC_VER)
#pragma optimize("", off)
template <typename T>
inline void keep_memory(T* p) {
// thanks @milleniumbug
*reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p);
}
// TODO equivalent keep_memory()
#pragma optimize("", on)
namespace Detail {
inline void optimizer_barrier() {
std::atomic_thread_fence(std::memory_order_seq_cst);
}
} // namespace Detail
#endif
template <typename T>
inline void deoptimize_value(T&& x) {
keep_memory(&x);
}
template <typename Fn, typename... Args>
inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<!std::is_same<void, decltype(fn(args...))>::value>::type {
deoptimize_value(std::forward<Fn>(fn) (std::forward<Args...>(args...)));
}
template <typename Fn, typename... Args>
inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<std::is_same<void, decltype(fn(args...))>::value>::type {
std::forward<Fn>(fn) (std::forward<Args...>(args...));
}
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_OPTIMIZER_HPP_INCLUDED
@@ -1,29 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// 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
#endif // CATCH_OUTLIERS_CLASSIFICATION_HPP_INCLUDED
@@ -1,49 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
#define CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
#include <catch2/benchmark/catch_clock.hpp>
#include <catch2/benchmark/catch_estimate.hpp>
#include <catch2/benchmark/catch_outlier_classification.hpp>
#include <algorithm>
#include <vector>
#include <string>
#include <iterator>
namespace Catch {
namespace Benchmark {
template <typename Duration>
struct SampleAnalysis {
std::vector<Duration> samples;
Estimate<Duration> mean;
Estimate<Duration> standard_deviation;
OutlierClassification outliers;
double outlier_variance;
template <typename Duration2>
operator SampleAnalysis<Duration2>() const {
std::vector<Duration2> samples2;
samples2.reserve(samples.size());
std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); });
return {
std::move(samples2),
mean,
standard_deviation,
outliers,
outlier_variance,
};
}
};
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
@@ -1,79 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_ANALYSE_HPP_INCLUDED
#define CATCH_ANALYSE_HPP_INCLUDED
#include <catch2/benchmark/catch_clock.hpp>
#include <catch2/benchmark/catch_environment.hpp>
#include <catch2/benchmark/catch_sample_analysis.hpp>
#include <catch2/benchmark/detail/catch_stats.hpp>
#include <catch2/interfaces/catch_interfaces_config.hpp>
#include <algorithm>
#include <iterator>
#include <vector>
namespace Catch {
namespace Benchmark {
namespace Detail {
template <typename Duration, typename Iterator>
SampleAnalysis<Duration> analyse(const IConfig &cfg, Environment<Duration>, Iterator first, Iterator last) {
if (!cfg.benchmarkNoAnalysis()) {
std::vector<double> samples;
samples.reserve(last - first);
std::transform(first, last, std::back_inserter(samples), [](Duration d) { return d.count(); });
auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), samples.begin(), samples.end());
auto outliers = Catch::Benchmark::Detail::classify_outliers(samples.begin(), samples.end());
auto wrap_estimate = [](Estimate<double> e) {
return Estimate<Duration> {
Duration(e.point),
Duration(e.lower_bound),
Duration(e.upper_bound),
e.confidence_interval,
};
};
std::vector<Duration> samples2;
samples2.reserve(samples.size());
std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](double d) { return Duration(d); });
return {
std::move(samples2),
wrap_estimate(analysis.mean),
wrap_estimate(analysis.standard_deviation),
outliers,
analysis.outlier_variance,
};
} else {
std::vector<Duration> samples;
samples.reserve(last - first);
Duration mean = Duration(0);
int i = 0;
for (auto it = first; it < last; ++it, ++i) {
samples.push_back(Duration(*it));
mean += Duration(*it);
}
mean /= i;
return {
std::move(samples),
Estimate<Duration>{mean, mean, mean, 0.0},
Estimate<Duration>{Duration(0), Duration(0), Duration(0), 0.0},
OutlierClassification{},
0.0
};
}
}
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_ANALYSE_HPP_INCLUDED
@@ -1,109 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
#define CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
#include <catch2/benchmark/catch_chronometer.hpp>
#include <catch2/benchmark/detail/catch_complete_invoke.hpp>
#include <catch2/internal/catch_meta.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
#include <cassert>
#include <type_traits>
#include <utility>
namespace Catch {
namespace Benchmark {
namespace Detail {
template <typename T>
using Decay = typename std::decay<T>::type;
template <typename T, typename U>
struct is_related
: std::is_same<Decay<T>, Decay<U>> {};
/// We need to reinvent std::function because every piece of code that might add overhead
/// in a measurement context needs to have consistent performance characteristics so that we
/// can account for it in the measurement.
/// Implementations of std::function with optimizations that aren't always applicable, like
/// small buffer optimizations, are not uncommon.
/// This is effectively an implementation of std::function without any such optimizations;
/// it may be slow, but it is consistently slow.
struct BenchmarkFunction {
private:
struct callable {
virtual void call(Chronometer meter) const = 0;
virtual callable* clone() const = 0;
virtual ~callable(); // = default;
callable() = default;
callable(callable const&) = default;
callable& operator=(callable const&) = default;
};
template <typename Fun>
struct model : public callable {
model(Fun&& fun_) : fun(std::move(fun_)) {}
model(Fun const& fun_) : fun(fun_) {}
model<Fun>* clone() const override { return new model<Fun>(*this); }
void call(Chronometer meter) const override {
call(meter, is_callable<Fun(Chronometer)>());
}
void call(Chronometer meter, std::true_type) const {
fun(meter);
}
void call(Chronometer meter, std::false_type) const {
meter.measure(fun);
}
Fun fun;
};
struct do_nothing { void operator()() const {} };
template <typename T>
BenchmarkFunction(model<T>* c) : f(c) {}
public:
BenchmarkFunction()
: f(new model<do_nothing>{ {} }) {}
template <typename Fun,
typename std::enable_if<!is_related<Fun, BenchmarkFunction>::value, int>::type = 0>
BenchmarkFunction(Fun&& fun)
: f(new model<typename std::decay<Fun>::type>(std::forward<Fun>(fun))) {}
BenchmarkFunction( BenchmarkFunction&& that ) noexcept:
f( std::move( that.f ) ) {}
BenchmarkFunction(BenchmarkFunction const& that)
: f(that.f->clone()) {}
BenchmarkFunction&
operator=( BenchmarkFunction&& that ) noexcept {
f = std::move( that.f );
return *this;
}
BenchmarkFunction& operator=(BenchmarkFunction const& that) {
f.reset(that.f->clone());
return *this;
}
void operator()(Chronometer meter) const { f->call(meter); }
private:
Catch::Detail::unique_ptr<callable> f;
};
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
@@ -1,69 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_COMPLETE_INVOKE_HPP_INCLUDED
#define CATCH_COMPLETE_INVOKE_HPP_INCLUDED
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_meta.hpp>
#include <catch2/interfaces/catch_interfaces_capture.hpp>
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
#include <type_traits>
#include <utility>
namespace Catch {
namespace Benchmark {
namespace Detail {
template <typename T>
struct CompleteType { using type = T; };
template <>
struct CompleteType<void> { struct type {}; };
template <typename T>
using CompleteType_t = typename CompleteType<T>::type;
template <typename Result>
struct CompleteInvoker {
template <typename Fun, typename... Args>
static Result invoke(Fun&& fun, Args&&... args) {
return std::forward<Fun>(fun)(std::forward<Args>(args)...);
}
};
template <>
struct CompleteInvoker<void> {
template <typename Fun, typename... Args>
static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) {
std::forward<Fun>(fun)(std::forward<Args>(args)...);
return {};
}
};
// invoke and not return void :(
template <typename Fun, typename... Args>
CompleteType_t<FunctionReturnType<Fun, Args...>> complete_invoke(Fun&& fun, Args&&... args) {
return CompleteInvoker<FunctionReturnType<Fun, Args...>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...);
}
extern const std::string benchmarkErrorMsg;
} // namespace Detail
template <typename Fun>
Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&& fun) {
CATCH_TRY{
return Detail::complete_invoke(std::forward<Fun>(fun));
} CATCH_CATCH_ALL{
getResultCapture().benchmarkFailed(translateActiveException());
CATCH_RUNTIME_ERROR(Detail::benchmarkErrorMsg);
}
}
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_COMPLETE_INVOKE_HPP_INCLUDED
@@ -1,111 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
#define CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
#include <catch2/benchmark/catch_clock.hpp>
#include <catch2/benchmark/catch_environment.hpp>
#include <catch2/benchmark/detail/catch_stats.hpp>
#include <catch2/benchmark/detail/catch_measure.hpp>
#include <catch2/benchmark/detail/catch_run_for_at_least.hpp>
#include <catch2/benchmark/catch_clock.hpp>
#include <algorithm>
#include <iterator>
#include <vector>
#include <cmath>
namespace Catch {
namespace Benchmark {
namespace Detail {
template <typename Clock>
std::vector<double> resolution(int k) {
std::vector<TimePoint<Clock>> times;
times.reserve(k + 1);
std::generate_n(std::back_inserter(times), k + 1, now<Clock>{});
std::vector<double> deltas;
deltas.reserve(k);
std::transform(std::next(times.begin()), times.end(), times.begin(),
std::back_inserter(deltas),
[](TimePoint<Clock> a, TimePoint<Clock> b) { return static_cast<double>((a - b).count()); });
return deltas;
}
const auto warmup_iterations = 10000;
const auto warmup_time = std::chrono::milliseconds(100);
const auto minimum_ticks = 1000;
const auto warmup_seed = 10000;
const auto clock_resolution_estimation_time = std::chrono::milliseconds(500);
const auto clock_cost_estimation_time_limit = std::chrono::seconds(1);
const auto clock_cost_estimation_tick_limit = 100000;
const auto clock_cost_estimation_time = std::chrono::milliseconds(10);
const auto clock_cost_estimation_iterations = 10000;
template <typename Clock>
int warmup() {
return run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_seed, &resolution<Clock>)
.iterations;
}
template <typename Clock>
EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_resolution(int iterations) {
auto r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_resolution_estimation_time), iterations, &resolution<Clock>)
.result;
return {
FloatDuration<Clock>(mean(r.begin(), r.end())),
classify_outliers(r.begin(), r.end()),
};
}
template <typename Clock>
EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) {
auto time_limit = std::min(resolution * clock_cost_estimation_tick_limit, FloatDuration<Clock>(clock_cost_estimation_time_limit));
auto time_clock = [](int k) {
return Detail::measure<Clock>([k] {
for (int i = 0; i < k; ++i) {
volatile auto ignored = Clock::now();
(void)ignored;
}
}).elapsed;
};
time_clock(1);
int iters = clock_cost_estimation_iterations;
auto&& r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_cost_estimation_time), iters, time_clock);
std::vector<double> times;
int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));
times.reserve(nsamples);
std::generate_n(std::back_inserter(times), nsamples, [time_clock, &r] {
return static_cast<double>((time_clock(r.iterations) / r.iterations).count());
});
return {
FloatDuration<Clock>(mean(times.begin(), times.end())),
classify_outliers(times.begin(), times.end()),
};
}
template <typename Clock>
Environment<FloatDuration<Clock>> measure_environment() {
static Environment<FloatDuration<Clock>>* env = nullptr;
if (env) {
return *env;
}
auto iters = Detail::warmup<Clock>();
auto resolution = Detail::estimate_clock_resolution<Clock>(iters);
auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean);
env = new Environment<FloatDuration<Clock>>{ resolution, cost };
return *env;
}
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
@@ -1,34 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_MEASURE_HPP_INCLUDED
#define CATCH_MEASURE_HPP_INCLUDED
#include <catch2/benchmark/catch_clock.hpp>
#include <catch2/benchmark/detail/catch_complete_invoke.hpp>
#include <catch2/benchmark/detail/catch_timing.hpp>
#include <utility>
namespace Catch {
namespace Benchmark {
namespace Detail {
template <typename Clock, typename Fun, typename... Args>
TimingOf<Clock, Fun, Args...> measure(Fun&& fun, Args&&... args) {
auto start = Clock::now();
auto&& r = Detail::complete_invoke(fun, std::forward<Args>(args)...);
auto end = Clock::now();
auto delta = end - start;
return { delta, std::forward<decltype(r)>(r), 1 };
}
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_MEASURE_HPP_INCLUDED
@@ -1,36 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_REPEAT_HPP_INCLUDED
#define CATCH_REPEAT_HPP_INCLUDED
#include <type_traits>
#include <utility>
namespace Catch {
namespace Benchmark {
namespace Detail {
template <typename Fun>
struct repeater {
void operator()(int k) const {
for (int i = 0; i < k; ++i) {
fun();
}
}
Fun fun;
};
template <typename Fun>
repeater<typename std::decay<Fun>::type> repeat(Fun&& fun) {
return { std::forward<Fun>(fun) };
}
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_REPEAT_HPP_INCLUDED
@@ -1,62 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
#define CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
#include <catch2/benchmark/catch_clock.hpp>
#include <catch2/benchmark/catch_chronometer.hpp>
#include <catch2/benchmark/detail/catch_measure.hpp>
#include <catch2/benchmark/detail/catch_complete_invoke.hpp>
#include <catch2/benchmark/detail/catch_timing.hpp>
#include <catch2/internal/catch_meta.hpp>
#include <utility>
#include <type_traits>
namespace Catch {
namespace Benchmark {
namespace Detail {
template <typename Clock, typename Fun>
TimingOf<Clock, Fun, int> measure_one(Fun&& fun, int iters, std::false_type) {
return Detail::measure<Clock>(fun, iters);
}
template <typename Clock, typename Fun>
TimingOf<Clock, Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) {
Detail::ChronometerModel<Clock> meter;
auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters));
return { meter.elapsed(), std::move(result), iters };
}
template <typename Clock, typename Fun>
using run_for_at_least_argument_t = typename std::conditional<is_callable<Fun(Chronometer)>::value, Chronometer, int>::type;
[[noreturn]]
void throw_optimized_away_error();
template <typename Clock, typename Fun>
TimingOf<Clock, Fun, run_for_at_least_argument_t<Clock, Fun>> run_for_at_least(ClockDuration<Clock> how_long, int seed, Fun&& fun) {
auto iters = seed;
while (iters < (1 << 30)) {
auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>());
if (Timing.elapsed >= how_long) {
return { Timing.elapsed, std::move(Timing.result), iters };
}
iters *= 2;
}
throw_optimized_away_error();
}
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
@@ -1,241 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#include <catch2/benchmark/detail/catch_stats.hpp>
#include <catch2/internal/catch_compiler_capabilities.hpp>
#include <cassert>
#include <iterator>
#include <random>
#if defined(CATCH_CONFIG_USE_ASYNC)
#include <future>
#endif
namespace {
using Catch::Benchmark::Detail::sample;
template <typename URng, typename Estimator>
sample resample(URng& rng, int resamples, std::vector<double>::iterator first, std::vector<double>::iterator last, Estimator& estimator) {
auto n = last - first;
std::uniform_int_distribution<decltype(n)> dist(0, n - 1);
sample out;
out.reserve(resamples);
std::generate_n(std::back_inserter(out), resamples, [n, first, &estimator, &dist, &rng] {
std::vector<double> resampled;
resampled.reserve(n);
std::generate_n(std::back_inserter(resampled), n, [first, &dist, &rng] { return first[dist(rng)]; });
return estimator(resampled.begin(), resampled.end());
});
std::sort(out.begin(), out.end());
return out;
}
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;
}
double standard_deviation(std::vector<double>::iterator first, std::vector<double>::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 Catch {
namespace Benchmark {
namespace Detail {
double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last) {
auto count = last - first;
double idx = (count - 1) * k / static_cast<double>(q);
int j = static_cast<int>(idx);
double g = idx - j;
std::nth_element(first, first + j, last);
auto xj = first[j];
if (g == 0) return xj;
auto xj1 = *std::min_element(first + (j + 1), last);
return xj + g * (xj1 - xj);
}
double erfc_inv(double x) {
return erf_inv(1.0 - x);
}
double normal_quantile(double p) {
static const double ROOT_TWO = std::sqrt(2.0);
double result = 0.0;
assert(p >= 0 && p <= 1);
if (p < 0 || p > 1) {
return result;
}
result = -erfc_inv(2.0 * p);
// result *= normal distribution standard deviation (1.0) * sqrt(2)
result *= /*sd * */ ROOT_TWO;
// result += normal disttribution mean (0)
return result;
}
double outlier_variance(Estimate<double> mean, Estimate<double> 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<int>(-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;
}
bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::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<int>(last - first); // seriously, one can't use integral types without hell in C++
auto mean = &Detail::mean<std::vector<double>::iterator>;
auto stddev = &standard_deviation;
#if defined(CATCH_CONFIG_USE_ASYNC)
auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::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<double>::iterator, std::vector<double>::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);
return { mean_estimate, stddev_estimate, outlier_variance };
}
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
@@ -1,138 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_STATS_HPP_INCLUDED
#define CATCH_STATS_HPP_INCLUDED
#include <catch2/benchmark/catch_estimate.hpp>
#include <catch2/benchmark/catch_outlier_classification.hpp>
#include <algorithm>
#include <vector>
#include <numeric>
#include <tuple>
#include <cmath>
#include <utility>
namespace Catch {
namespace Benchmark {
namespace Detail {
using sample = std::vector<double>;
double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last);
template <typename Iterator>
OutlierClassification classify_outliers(Iterator first, Iterator last) {
std::vector<double> 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) {
auto&& 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;
}
return o;
}
template <typename Iterator>
double mean(Iterator first, Iterator last) {
auto count = last - first;
double sum = std::accumulate(first, last, 0.);
return sum / count;
}
template <typename Estimator, typename Iterator>
sample jackknife(Estimator&& estimator, Iterator first, Iterator last) {
auto n = 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));
}
return results;
}
inline double normal_cdf(double x) {
return std::erfc(-x / std::sqrt(2.0)) / 2.0;
}
double erfc_inv(double x);
double normal_quantile(double p);
template <typename Iterator, typename Estimator>
Estimate<double> bootstrap(double confidence_level, Iterator first, 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, sum_cubes;
std::tie(sum_squares, sum_cubes) = std::accumulate(jack.begin(), jack.end(), std::make_pair(0., 0.), [jack_mean](std::pair<double, double> sqcb, double x) -> std::pair<double, double> {
auto d = jack_mean - x;
auto d2 = d * d;
auto d3 = d2 * d;
return { sqcb.first + d2, sqcb.second + d3 };
});
double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5));
int n = static_cast<int>(resample.size());
double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / static_cast<double>(n);
// degenerate case with uniform samples
if (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) -> int {
return std::lround(normal_cdf(x) * 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 = std::max(cumn(a1), 0);
auto hi = std::min(cumn(a2), n - 1);
return { point, resample[lo], resample[hi], confidence_level };
}
double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n);
struct bootstrap_analysis {
Estimate<double> mean;
Estimate<double> standard_deviation;
double outlier_variance;
};
bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last);
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_STATS_HPP_INCLUDED
@@ -1,31 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
// Adapted from donated nonius code.
#ifndef CATCH_TIMING_HPP_INCLUDED
#define CATCH_TIMING_HPP_INCLUDED
#include <catch2/benchmark/catch_clock.hpp>
#include <catch2/benchmark/detail/catch_complete_invoke.hpp>
#include <type_traits>
namespace Catch {
namespace Benchmark {
template <typename Duration, typename Result>
struct Timing {
Duration elapsed;
Result result;
int iterations;
};
template <typename Clock, typename Func, typename... Args>
using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>;
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_TIMING_HPP_INCLUDED
@@ -1,95 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
/** \file
* This is a special TU that combines what would otherwise be a very
* small benchmarking-related TUs into one bigger TU.
*
* The reason for this is compilation performance improvements by
* avoiding reparsing headers for many small TUs, instead having this
* one TU include bit more, but having it all parsed only once.
*
* To avoid heavy-tail problem with compilation times, each "subpart"
* of Catch2 has its own combined TU like this.
*/
////////////////////////////////////////////
// vvv formerly catch_chronometer.cpp vvv //
////////////////////////////////////////////
#include <catch2/benchmark/catch_chronometer.hpp>
namespace Catch {
namespace Benchmark {
namespace Detail {
ChronometerConcept::~ChronometerConcept() = default;
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
///////////////////////////////////////////////////
// vvv formerly catch_benchmark_function.cpp vvv //
///////////////////////////////////////////////////
#include <catch2/benchmark/detail/catch_benchmark_function.hpp>
namespace Catch {
namespace Benchmark {
namespace Detail {
BenchmarkFunction::callable::~callable() = default;
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
////////////////////////////////////////////////
// vvv formerly catch_complete_invoke.cpp vvv //
////////////////////////////////////////////////
#include <catch2/benchmark/detail/catch_complete_invoke.hpp>
namespace Catch {
namespace Benchmark {
namespace Detail {
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
const std::string benchmarkErrorMsg = "a benchmark failed to run successfully";
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
/////////////////////////////////////////////////
// vvv formerly catch_run_for_at_least.cpp vvv //
/////////////////////////////////////////////////
#include <catch2/benchmark/detail/catch_run_for_at_least.hpp>
#include <exception>
#include <catch2/internal/catch_enforce.hpp>
namespace Catch {
namespace Benchmark {
namespace Detail {
struct optimized_away_error : std::exception {
const char* what() const noexcept override;
};
const char* optimized_away_error::what() const noexcept {
return "could not measure benchmark, maybe it was optimized away";
}
void throw_optimized_away_error() {
Catch::throw_exception(optimized_away_error{});
}
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
-111
View File
@@ -1,111 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
/** \file
* This is a convenience header for Catch2. It includes **all** of Catch2 headers.
*
* Generally the Catch2 users should use specific includes they need,
* but this header can be used instead for ease-of-experimentation, or
* just plain convenience, at the cost of (significantly) increased
* compilation times.
*
* When a new header is added to either the top level folder, or to the
* corresponding internal subfolder, it should be added here. Headers
* added to the various subparts (e.g. matchers, generators, etc...),
* should go their respective catch-all headers.
*/
#ifndef CATCH_ALL_HPP_INCLUDED
#define CATCH_ALL_HPP_INCLUDED
#include <catch2/benchmark/catch_benchmark_all.hpp>
#include <catch2/catch_approx.hpp>
#include <catch2/catch_assertion_info.hpp>
#include <catch2/catch_assertion_result.hpp>
#include <catch2/catch_config.hpp>
#include <catch2/catch_message.hpp>
#include <catch2/catch_reporter_registrars.hpp>
#include <catch2/catch_section_info.hpp>
#include <catch2/catch_session.hpp>
#include <catch2/catch_tag_alias.hpp>
#include <catch2/catch_tag_alias_autoregistrar.hpp>
#include <catch2/catch_template_test_macros.hpp>
#include <catch2/catch_test_case_info.hpp>
#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_test_spec.hpp>
#include <catch2/catch_timer.hpp>
#include <catch2/catch_tostring.hpp>
#include <catch2/catch_totals.hpp>
#include <catch2/catch_translate_exception.hpp>
#include <catch2/catch_version.hpp>
#include <catch2/catch_version_macros.hpp>
#include <catch2/generators/catch_generators_all.hpp>
#include <catch2/interfaces/catch_interfaces_all.hpp>
#include <catch2/internal/catch_assertion_handler.hpp>
#include <catch2/internal/catch_case_sensitive.hpp>
#include <catch2/internal/catch_clara.hpp>
#include <catch2/internal/catch_commandline.hpp>
#include <catch2/internal/catch_compiler_capabilities.hpp>
#include <catch2/internal/catch_config_android_logwrite.hpp>
#include <catch2/internal/catch_config_counter.hpp>
#include <catch2/internal/catch_config_uncaught_exceptions.hpp>
#include <catch2/internal/catch_config_wchar.hpp>
#include <catch2/internal/catch_console_colour.hpp>
#include <catch2/internal/catch_console_width.hpp>
#include <catch2/internal/catch_container_nonmembers.hpp>
#include <catch2/internal/catch_context.hpp>
#include <catch2/internal/catch_debug_console.hpp>
#include <catch2/internal/catch_debugger.hpp>
#include <catch2/internal/catch_decomposer.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_enum_values_registry.hpp>
#include <catch2/internal/catch_errno_guard.hpp>
#include <catch2/internal/catch_exception_translator_registry.hpp>
#include <catch2/internal/catch_fatal_condition_handler.hpp>
#include <catch2/internal/catch_lazy_expr.hpp>
#include <catch2/internal/catch_leak_detector.hpp>
#include <catch2/internal/catch_list.hpp>
#include <catch2/internal/catch_message_info.hpp>
#include <catch2/internal/catch_meta.hpp>
#include <catch2/internal/catch_noncopyable.hpp>
#include <catch2/internal/catch_option.hpp>
#include <catch2/internal/catch_output_redirect.hpp>
#include <catch2/internal/catch_platform.hpp>
#include <catch2/internal/catch_polyfills.hpp>
#include <catch2/internal/catch_preprocessor.hpp>
#include <catch2/internal/catch_random_number_generator.hpp>
#include <catch2/internal/catch_reporter_registry.hpp>
#include <catch2/internal/catch_result_type.hpp>
#include <catch2/internal/catch_run_context.hpp>
#include <catch2/internal/catch_section.hpp>
#include <catch2/internal/catch_singletons.hpp>
#include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_startup_exception_registry.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_stream_end_stop.hpp>
#include <catch2/internal/catch_string_manip.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_tag_alias_registry.hpp>
#include <catch2/internal/catch_template_test_registry.hpp>
#include <catch2/internal/catch_test_case_registry_impl.hpp>
#include <catch2/internal/catch_test_case_tracker.hpp>
#include <catch2/internal/catch_test_failure_exception.hpp>
#include <catch2/internal/catch_test_macro_impl.hpp>
#include <catch2/internal/catch_test_registry.hpp>
#include <catch2/internal/catch_test_spec_parser.hpp>
#include <catch2/internal/catch_textflow.hpp>
#include <catch2/internal/catch_to_string.hpp>
#include <catch2/internal/catch_uncaught_exceptions.hpp>
#include <catch2/internal/catch_unique_name.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
#include <catch2/internal/catch_wildcard_pattern.hpp>
#include <catch2/internal/catch_windows_h_proxy.hpp>
#include <catch2/internal/catch_xmlwriter.hpp>
#include <catch2/matchers/catch_matchers_all.hpp>
#include <catch2/reporters/catch_reporters_all.hpp>
#endif // CATCH_ALL_HPP_INCLUDED
-84
View File
@@ -1,84 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_approx.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <cmath>
#include <limits>
namespace {
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
// But without the subtraction to allow for INFINITY in comparison
bool marginComparison(double lhs, double rhs, double margin) {
return (lhs + margin >= rhs) && (rhs + margin >= lhs);
}
}
namespace Catch {
Approx::Approx ( double value )
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
m_margin( 0.0 ),
m_scale( 0.0 ),
m_value( value )
{}
Approx Approx::custom() {
return Approx( 0 );
}
Approx Approx::operator-() const {
auto temp(*this);
temp.m_value = -temp.m_value;
return temp;
}
std::string Approx::toString() const {
ReusableStringStream rss;
rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
return rss.str();
}
bool Approx::equalityComparisonImpl(const double other) const {
// First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
// Thanks to Richard Harris for his help refining the scaled margin value
return marginComparison(m_value, other, m_margin)
|| marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(std::isinf(m_value)? 0 : m_value)));
}
void Approx::setMargin(double newMargin) {
CATCH_ENFORCE(newMargin >= 0,
"Invalid Approx::margin: " << newMargin << '.'
<< " Approx::Margin has to be non-negative.");
m_margin = newMargin;
}
void Approx::setEpsilon(double newEpsilon) {
CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0,
"Invalid Approx::epsilon: " << newEpsilon << '.'
<< " Approx::epsilon has to be in [0, 1]");
m_epsilon = newEpsilon;
}
namespace literals {
Approx operator "" _a(long double val) {
return Approx(val);
}
Approx operator "" _a(unsigned long long val) {
return Approx(val);
}
} // end namespace literals
std::string StringMaker<Catch::Approx>::convert(Catch::Approx const& value) {
return value.toString();
}
} // end namespace Catch
-128
View File
@@ -1,128 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_APPROX_HPP_INCLUDED
#define CATCH_APPROX_HPP_INCLUDED
#include <catch2/catch_tostring.hpp>
#include <type_traits>
namespace Catch {
class Approx {
private:
bool equalityComparisonImpl(double other) const;
// Sets and validates the new margin (margin >= 0)
void setMargin(double margin);
// Sets and validates the new epsilon (0 < epsilon < 1)
void setEpsilon(double epsilon);
public:
explicit Approx ( double value );
static Approx custom();
Approx operator-() const;
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
Approx operator()( T const& value ) {
Approx approx( static_cast<double>(value) );
approx.m_epsilon = m_epsilon;
approx.m_margin = m_margin;
approx.m_scale = m_scale;
return approx;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
explicit Approx( T const& value ): Approx(static_cast<double>(value))
{}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
friend bool operator == ( const T& lhs, Approx const& rhs ) {
auto lhs_v = static_cast<double>(lhs);
return rhs.equalityComparisonImpl(lhs_v);
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
friend bool operator == ( Approx const& lhs, const T& rhs ) {
return operator==( rhs, lhs );
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
friend bool operator != ( T const& lhs, Approx const& rhs ) {
return !operator==( lhs, rhs );
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
friend bool operator != ( Approx const& lhs, T const& rhs ) {
return !operator==( rhs, lhs );
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
friend bool operator <= ( T const& lhs, Approx const& rhs ) {
return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
friend bool operator <= ( Approx const& lhs, T const& rhs ) {
return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
friend bool operator >= ( T const& lhs, Approx const& rhs ) {
return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
friend bool operator >= ( Approx const& lhs, T const& rhs ) {
return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
Approx& epsilon( T const& newEpsilon ) {
double epsilonAsDouble = static_cast<double>(newEpsilon);
setEpsilon(epsilonAsDouble);
return *this;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
Approx& margin( T const& newMargin ) {
double marginAsDouble = static_cast<double>(newMargin);
setMargin(marginAsDouble);
return *this;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
Approx& scale( T const& newScale ) {
m_scale = static_cast<double>(newScale);
return *this;
}
std::string toString() const;
private:
double m_epsilon;
double m_margin;
double m_scale;
double m_value;
};
namespace literals {
Approx operator "" _a(long double val);
Approx operator "" _a(unsigned long long val);
} // end namespace literals
template<>
struct StringMaker<Catch::Approx> {
static std::string convert(Catch::Approx const& value);
};
} // end namespace Catch
#endif // CATCH_APPROX_HPP_INCLUDED
@@ -1,28 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_ASSERTION_INFO_HPP_INCLUDED
#define CATCH_ASSERTION_INFO_HPP_INCLUDED
#include <catch2/internal/catch_result_type.hpp>
#include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_stringref.hpp>
namespace Catch {
struct AssertionInfo {
// AssertionInfo() = delete;
StringRef macroName;
SourceLineInfo lineInfo;
StringRef capturedExpression;
ResultDisposition::Flags resultDisposition;
};
} // end namespace Catch
#endif // CATCH_ASSERTION_INFO_HPP_INCLUDED
@@ -1,105 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_assertion_result.hpp>
#include <catch2/internal/catch_stream.hpp>
namespace Catch {
AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression):
lazyExpression(_lazyExpression),
resultType(_resultType) {}
std::string AssertionResultData::reconstructExpression() const {
if( reconstructedExpression.empty() ) {
if( lazyExpression ) {
ReusableStringStream rss;
rss << lazyExpression;
reconstructedExpression = rss.str();
}
}
return reconstructedExpression;
}
AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
: m_info( info ),
m_resultData( data )
{}
// Result was a success
bool AssertionResult::succeeded() const {
return Catch::isOk( m_resultData.resultType );
}
// Result was a success, or failure is suppressed
bool AssertionResult::isOk() const {
return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
}
ResultWas::OfType AssertionResult::getResultType() const {
return m_resultData.resultType;
}
bool AssertionResult::hasExpression() const {
return !m_info.capturedExpression.empty();
}
bool AssertionResult::hasMessage() const {
return !m_resultData.message.empty();
}
std::string AssertionResult::getExpression() const {
// Possibly overallocating by 3 characters should be basically free
std::string expr; expr.reserve(m_info.capturedExpression.size() + 3);
if (isFalseTest(m_info.resultDisposition)) {
expr += "!(";
}
expr += m_info.capturedExpression;
if (isFalseTest(m_info.resultDisposition)) {
expr += ')';
}
return expr;
}
std::string AssertionResult::getExpressionInMacro() const {
std::string expr;
if( m_info.macroName.empty() )
expr = static_cast<std::string>(m_info.capturedExpression);
else {
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
expr += m_info.macroName;
expr += "( ";
expr += m_info.capturedExpression;
expr += " )";
}
return expr;
}
bool AssertionResult::hasExpandedExpression() const {
return hasExpression() && getExpandedExpression() != getExpression();
}
std::string AssertionResult::getExpandedExpression() const {
std::string expr = m_resultData.reconstructExpression();
return expr.empty()
? getExpression()
: expr;
}
std::string AssertionResult::getMessage() const {
return m_resultData.message;
}
SourceLineInfo AssertionResult::getSourceInfo() const {
return m_info.lineInfo;
}
StringRef AssertionResult::getTestMacroName() const {
return m_info.macroName;
}
} // end namespace Catch
@@ -1,60 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_ASSERTION_RESULT_HPP_INCLUDED
#define CATCH_ASSERTION_RESULT_HPP_INCLUDED
#include <catch2/catch_assertion_info.hpp>
#include <catch2/internal/catch_result_type.hpp>
#include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_lazy_expr.hpp>
#include <string>
namespace Catch {
struct AssertionResultData
{
AssertionResultData() = delete;
AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression );
std::string message;
mutable std::string reconstructedExpression;
LazyExpression lazyExpression;
ResultWas::OfType resultType;
std::string reconstructExpression() const;
};
class AssertionResult {
public:
AssertionResult() = delete;
AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
bool isOk() const;
bool succeeded() const;
ResultWas::OfType getResultType() const;
bool hasExpression() const;
bool hasMessage() const;
std::string getExpression() const;
std::string getExpressionInMacro() const;
bool hasExpandedExpression() const;
std::string getExpandedExpression() const;
std::string getMessage() const;
SourceLineInfo getSourceInfo() const;
StringRef getTestMacroName() const;
//protected:
AssertionInfo m_info;
AssertionResultData m_resultData;
};
} // end namespace Catch
#endif // CATCH_ASSERTION_RESULT_HPP_INCLUDED
-93
View File
@@ -1,93 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_config.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_string_manip.hpp>
#include <catch2/internal/catch_test_spec_parser.hpp>
#include <catch2/interfaces/catch_interfaces_tag_alias_registry.hpp>
namespace Catch {
Config::Config( ConfigData const& data )
: m_data( data ),
m_stream( openStream() )
{
// We need to trim filter specs to avoid trouble with superfluous
// whitespace (esp. important for bdd macros, as those are manually
// aligned with whitespace).
for (auto& elem : m_data.testsOrTags) {
elem = trim(elem);
}
for (auto& elem : m_data.sectionsToRun) {
elem = trim(elem);
}
TestSpecParser parser(ITagAliasRegistry::get());
if (!m_data.testsOrTags.empty()) {
m_hasTestFilters = true;
for (auto const& testOrTags : m_data.testsOrTags) {
parser.parse(testOrTags);
}
}
m_testSpec = parser.testSpec();
}
Config::~Config() = default;
std::string const& Config::getFilename() const {
return m_data.outputFilename ;
}
bool Config::listTests() const { return m_data.listTests; }
bool Config::listTags() const { return m_data.listTags; }
bool Config::listReporters() const { return m_data.listReporters; }
std::string Config::getProcessName() const { return m_data.processName; }
std::string const& Config::getReporterName() const { return m_data.reporterName; }
std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
TestSpec const& Config::testSpec() const { return m_testSpec; }
bool Config::hasTestFilters() const { return m_hasTestFilters; }
bool Config::showHelp() const { return m_data.showHelp; }
// IConfig interface
bool Config::allowThrows() const { return !m_data.noThrow; }
std::ostream& Config::stream() const { return m_stream->stream(); }
std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); }
bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); }
ShowDurations Config::showDurations() const { return m_data.showDurations; }
double Config::minDuration() const { return m_data.minDuration; }
TestRunOrder Config::runOrder() const { return m_data.runOrder; }
unsigned int Config::rngSeed() const { return m_data.rngSeed; }
UseColour Config::useColour() const { return m_data.useColour; }
bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; }
int Config::abortAfter() const { return m_data.abortAfter; }
bool Config::showInvisibles() const { return m_data.showInvisibles; }
Verbosity Config::verbosity() const { return m_data.verbosity; }
bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; }
int Config::benchmarkSamples() const { return m_data.benchmarkSamples; }
double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; }
unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; }
std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); }
IStream const* Config::openStream() {
return Catch::makeStream(m_data.outputFilename);
}
} // end namespace Catch
-124
View File
@@ -1,124 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_CONFIG_HPP_INCLUDED
#define CATCH_CONFIG_HPP_INCLUDED
#include <catch2/catch_test_spec.hpp>
#include <catch2/interfaces/catch_interfaces_config.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
#include <vector>
#include <string>
namespace Catch {
struct IStream;
struct ConfigData {
bool listTests = false;
bool listTags = false;
bool listReporters = false;
bool showSuccessfulTests = false;
bool shouldDebugBreak = false;
bool noThrow = false;
bool showHelp = false;
bool showInvisibles = false;
bool filenamesAsTags = false;
bool libIdentify = false;
int abortAfter = -1;
unsigned int rngSeed = 0;
bool benchmarkNoAnalysis = false;
unsigned int benchmarkSamples = 100;
double benchmarkConfidenceInterval = 0.95;
unsigned int benchmarkResamples = 100000;
std::chrono::milliseconds::rep benchmarkWarmupTime = 100;
Verbosity verbosity = Verbosity::Normal;
WarnAbout::What warnings = WarnAbout::Nothing;
ShowDurations showDurations = ShowDurations::DefaultForReporter;
double minDuration = -1;
TestRunOrder runOrder = TestRunOrder::Declared;
UseColour useColour = UseColour::Auto;
WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
std::string outputFilename;
std::string name;
std::string processName;
#ifndef CATCH_CONFIG_DEFAULT_REPORTER
#define CATCH_CONFIG_DEFAULT_REPORTER "console"
#endif
std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
#undef CATCH_CONFIG_DEFAULT_REPORTER
std::vector<std::string> testsOrTags;
std::vector<std::string> sectionsToRun;
};
class Config : public IConfig {
public:
Config() = default;
Config( ConfigData const& data );
~Config() override; // = default in the cpp file
std::string const& getFilename() const;
bool listTests() const;
bool listTags() const;
bool listReporters() const;
std::string getProcessName() const;
std::string const& getReporterName() const;
std::vector<std::string> const& getTestsOrTags() const override;
std::vector<std::string> const& getSectionsToRun() const override;
TestSpec const& testSpec() const override;
bool hasTestFilters() const override;
bool showHelp() const;
// IConfig interface
bool allowThrows() const override;
std::ostream& stream() const override;
std::string name() const override;
bool includeSuccessfulResults() const override;
bool warnAboutMissingAssertions() const override;
bool warnAboutNoTests() const override;
ShowDurations showDurations() const override;
double minDuration() const override;
TestRunOrder runOrder() const override;
unsigned int rngSeed() const override;
UseColour useColour() const override;
bool shouldDebugBreak() const override;
int abortAfter() const override;
bool showInvisibles() const override;
Verbosity verbosity() const override;
bool benchmarkNoAnalysis() const override;
int benchmarkSamples() const override;
double benchmarkConfidenceInterval() const override;
unsigned int benchmarkResamples() const override;
std::chrono::milliseconds benchmarkWarmupTime() const override;
private:
IStream const* openStream();
ConfigData m_data;
Detail::unique_ptr<IStream const> m_stream;
TestSpec m_testSpec;
bool m_hasTestFilters = false;
};
} // end namespace Catch
#endif // CATCH_CONFIG_HPP_INCLUDED
-118
View File
@@ -1,118 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_message.hpp>
#include <catch2/interfaces/catch_interfaces_capture.hpp>
#include <catch2/internal/catch_uncaught_exceptions.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <cassert>
#include <stack>
namespace Catch {
////////////////////////////////////////////////////////////////////////////
Catch::MessageBuilder::MessageBuilder( StringRef const& macroName,
SourceLineInfo const& lineInfo,
ResultWas::OfType type )
:m_info(macroName, lineInfo, type) {}
////////////////////////////////////////////////////////////////////////////
ScopedMessage::ScopedMessage( MessageBuilder const& builder ):
m_info( builder.m_info ) {
m_info.message = builder.m_stream.str();
getResultCapture().pushScopedMessage( m_info );
}
ScopedMessage::ScopedMessage( ScopedMessage&& old ) noexcept:
m_info( std::move( old.m_info ) ) {
old.m_moved = true;
}
ScopedMessage::~ScopedMessage() {
if ( !uncaught_exceptions() && !m_moved ){
getResultCapture().popScopedMessage(m_info);
}
}
Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) {
auto trimmed = [&] (size_t start, size_t end) {
while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) {
++start;
}
while (names[end] == ',' || isspace(static_cast<unsigned char>(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<char> openings;
for (size_t pos = 0; pos < names.size(); ++pos) {
char c = names[pos];
switch (c) {
case '[':
case '{':
case '(':
// It is basically impossible to disambiguate between
// comparison and start of template args in this context
// case '<':
openings.push(c);
break;
case ']':
case '}':
case ')':
// case '>':
openings.pop();
break;
case '"':
case '\'':
pos = skipq(pos, c);
break;
case ',':
if (start != pos && openings.empty()) {
m_messages.emplace_back(macroName, lineInfo, resultType);
m_messages.back().message = static_cast<std::string>(trimmed(start, pos));
m_messages.back().message += " := ";
start = pos;
}
}
}
assert(openings.empty() && "Mismatched openings");
m_messages.emplace_back(macroName, lineInfo, resultType);
m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1));
m_messages.back().message += " := ";
}
Capturer::~Capturer() {
if ( !uncaught_exceptions() ){
assert( m_captured == m_messages.size() );
for( size_t i = 0; i < m_captured; ++i )
m_resultCapture.popScopedMessage( m_messages[i] );
}
}
void Capturer::captureValue( size_t index, std::string const& value ) {
assert( index < m_messages.size() );
m_messages[index].message += value;
m_resultCapture.pushScopedMessage( m_messages[index] );
m_captured++;
}
} // end namespace Catch
-144
View File
@@ -1,144 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_MESSAGE_HPP_INCLUDED
#define CATCH_MESSAGE_HPP_INCLUDED
#include <catch2/internal/catch_result_type.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_stream_end_stop.hpp>
#include <catch2/internal/catch_message_info.hpp>
#include <catch2/interfaces/catch_interfaces_capture.hpp>
#include <catch2/catch_tostring.hpp>
#include <string>
#include <vector>
namespace Catch {
struct SourceLineInfo;
struct MessageStream {
template<typename T>
MessageStream& operator << ( T const& value ) {
m_stream << value;
return *this;
}
ReusableStringStream m_stream;
};
struct MessageBuilder : MessageStream {
MessageBuilder( StringRef const& macroName,
SourceLineInfo const& lineInfo,
ResultWas::OfType type );
template<typename T>
MessageBuilder& operator << ( T const& value ) {
m_stream << value;
return *this;
}
MessageInfo m_info;
};
class ScopedMessage {
public:
explicit ScopedMessage( MessageBuilder const& builder );
ScopedMessage( ScopedMessage& duplicate ) = delete;
ScopedMessage( ScopedMessage&& old ) noexcept;
~ScopedMessage();
MessageInfo m_info;
bool m_moved = false;
};
class Capturer {
std::vector<MessageInfo> m_messages;
IResultCapture& m_resultCapture = getResultCapture();
size_t m_captured = 0;
public:
Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
Capturer(Capturer const&) = delete;
Capturer& operator=(Capturer const&) = delete;
~Capturer();
void captureValue( size_t index, std::string const& value );
template<typename T>
void captureValues( size_t index, T const& value ) {
captureValue( index, Catch::Detail::stringify( value ) );
}
template<typename T, typename... Ts>
void captureValues( size_t index, T const& value, Ts const&... values ) {
captureValue( index, Catch::Detail::stringify(value) );
captureValues( index+1, values... );
}
};
} // end namespace Catch
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
do { \
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( false )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
Catch::Capturer varName( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \
varName.captureValues( 0, __VA_ARGS__ )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_INFO( macroName, log ) \
Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
#define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg )
#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
#define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", __VA_ARGS__ )
#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
#define CATCH_INFO( msg ) (void)(0)
#define CATCH_UNSCOPED_INFO( msg ) (void)(0)
#define CATCH_WARN( msg ) (void)(0)
#define CATCH_CAPTURE( ... ) (void)(0)
#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
#define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", __VA_ARGS__ )
#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
#define INFO( msg ) (void)(0)
#define UNSCOPED_INFO( msg ) (void)(0)
#define WARN( msg ) (void)(0)
#define CAPTURE( ... ) (void)(0)
#endif // end of user facing macro declarations
#endif // CATCH_MESSAGE_HPP_INCLUDED
@@ -1,103 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
#include <catch2/internal/catch_context.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_test_case_registry_impl.hpp>
#include <catch2/internal/catch_reporter_registry.hpp>
#include <catch2/internal/catch_exception_translator_registry.hpp>
#include <catch2/internal/catch_tag_alias_registry.hpp>
#include <catch2/internal/catch_startup_exception_registry.hpp>
#include <catch2/internal/catch_singletons.hpp>
#include <catch2/internal/catch_enum_values_registry.hpp>
#include <catch2/catch_test_case_info.hpp>
#include <catch2/internal/catch_noncopyable.hpp>
#include <catch2/interfaces/catch_interfaces_reporter_factory.hpp>
namespace Catch {
namespace {
class RegistryHub : public IRegistryHub,
public IMutableRegistryHub,
private Detail::NonCopyable {
public: // IRegistryHub
RegistryHub() = default;
IReporterRegistry const& getReporterRegistry() const override {
return m_reporterRegistry;
}
ITestCaseRegistry const& getTestCaseRegistry() const override {
return m_testCaseRegistry;
}
IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override {
return m_exceptionTranslatorRegistry;
}
ITagAliasRegistry const& getTagAliasRegistry() const override {
return m_tagAliasRegistry;
}
StartupExceptionRegistry const& getStartupExceptionRegistry() const override {
return m_exceptionRegistry;
}
public: // IMutableRegistryHub
void registerReporter( std::string const& name, IReporterFactoryPtr factory ) override {
m_reporterRegistry.registerReporter( name, std::move(factory) );
}
void registerListener( IReporterFactoryPtr factory ) override {
m_reporterRegistry.registerListener( std::move(factory) );
}
void registerTest( Detail::unique_ptr<TestCaseInfo>&& testInfo, Detail::unique_ptr<ITestInvoker>&& invoker ) override {
m_testCaseRegistry.registerTest( std::move(testInfo), std::move(invoker) );
}
void registerTranslator( const IExceptionTranslator* translator ) override {
m_exceptionTranslatorRegistry.registerTranslator( translator );
}
void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override {
m_tagAliasRegistry.add( alias, tag, lineInfo );
}
void registerStartupException() noexcept override {
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
m_exceptionRegistry.add(std::current_exception());
#else
CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
#endif
}
IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override {
return m_enumValuesRegistry;
}
private:
TestRegistry m_testCaseRegistry;
ReporterRegistry m_reporterRegistry;
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
TagAliasRegistry m_tagAliasRegistry;
StartupExceptionRegistry m_exceptionRegistry;
Detail::EnumValuesRegistry m_enumValuesRegistry;
};
}
using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
IRegistryHub const& getRegistryHub() {
return RegistryHubSingleton::get();
}
IMutableRegistryHub& getMutableRegistryHub() {
return RegistryHubSingleton::getMutable();
}
void cleanUp() {
cleanupSingletons();
cleanUpContext();
}
std::string translateActiveException() {
return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
}
} // end namespace Catch
@@ -1,83 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
#define CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
#include <catch2/interfaces/catch_interfaces_reporter_factory.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
namespace Catch {
struct IStreamingReporter;
using IStreamingReporterPtr = Detail::unique_ptr<IStreamingReporter>;
template <typename T>
class ReporterFactory : public IReporterFactory {
IStreamingReporterPtr create( ReporterConfig const& config ) const override {
return Detail::make_unique<T>( config );
}
std::string getDescription() const override {
return T::getDescription();
}
};
template<typename T>
class ReporterRegistrar {
public:
explicit ReporterRegistrar( std::string const& name ) {
getMutableRegistryHub().registerReporter( name, Detail::make_unique<ReporterFactory<T>>() );
}
};
template<typename T>
class ListenerRegistrar {
class ListenerFactory : public IReporterFactory {
IStreamingReporterPtr create( ReporterConfig const& config ) const override {
return Detail::make_unique<T>(config);
}
std::string getDescription() const override {
return std::string();
}
};
public:
ListenerRegistrar() {
getMutableRegistryHub().registerListener( Detail::make_unique<ListenerFactory>() );
}
};
}
#if !defined(CATCH_CONFIG_DISABLE)
#define CATCH_REGISTER_REPORTER( name, reporterType ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
#define CATCH_REGISTER_LISTENER( listenerType ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
#else // CATCH_CONFIG_DISABLE
#define CATCH_REGISTER_REPORTER(name, reporterType)
#define CATCH_REGISTER_LISTENER(listenerType)
#endif // CATCH_CONFIG_DISABLE
#endif // CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
@@ -1,41 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_SECTION_INFO_HPP_INCLUDED
#define CATCH_SECTION_INFO_HPP_INCLUDED
#include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/catch_totals.hpp>
#include <string>
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(std::move(_name)),
lineInfo(_lineInfo)
{}
std::string name;
SourceLineInfo lineInfo;
};
struct SectionEndInfo {
SectionInfo sectionInfo;
Counts prevAssertions;
double durationInSeconds;
};
} // end namespace Catch
#endif // CATCH_SECTION_INFO_HPP_INCLUDED
-305
View File
@@ -1,305 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_session.hpp>
#include <catch2/internal/catch_console_colour.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_list.hpp>
#include <catch2/internal/catch_context.hpp>
#include <catch2/internal/catch_run_context.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/catch_test_spec.hpp>
#include <catch2/catch_version.hpp>
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
#include <catch2/internal/catch_startup_exception_registry.hpp>
#include <catch2/internal/catch_textflow.hpp>
#include <catch2/internal/catch_windows_h_proxy.hpp>
#include <catch2/reporters/catch_reporter_listening.hpp>
#include <catch2/interfaces/catch_interfaces_reporter_registry.hpp>
#include <catch2/interfaces/catch_interfaces_reporter_factory.hpp>
#include <algorithm>
#include <iomanip>
#include <set>
namespace Catch {
namespace {
const int MaxExitCode = 255;
IStreamingReporterPtr createReporter(std::string const& reporterName, IConfig const* config) {
auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config);
CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'");
return reporter;
}
IStreamingReporterPtr makeReporter(Config const* config) {
if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) {
return createReporter(config->getReporterName(), config);
}
// On older platforms, returning unique_ptr<ListeningReporter>
// when the return type is unique_ptr<IStreamingReporter>
// doesn't compile without a std::move call. However, this causes
// a warning on newer platforms. Thus, we have to work around
// it a bit and downcast the pointer manually.
auto ret = Detail::unique_ptr<IStreamingReporter>(new ListeningReporter(config));
auto& multi = static_cast<ListeningReporter&>(*ret);
auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
for (auto const& listener : listeners) {
multi.addListener(listener->create(Catch::ReporterConfig(config)));
}
multi.addReporter(createReporter(config->getReporterName(), config));
return ret;
}
class TestGroup {
public:
explicit TestGroup(IStreamingReporterPtr&& reporter, Config const* config):
m_reporter(reporter.get()),
m_config{config},
m_context{config, std::move(reporter)} {
auto const& allTestCases = getAllTestCasesSorted(*m_config);
m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config);
auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
if (m_matches.empty() && invalidArgs.empty()) {
for (auto const& test : allTestCases)
if (!test.getTestCaseInfo().isHidden())
m_tests.emplace(&test);
} else {
for (auto const& match : m_matches)
m_tests.insert(match.tests.begin(), match.tests.end());
}
}
Totals execute() {
auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
Totals totals;
m_context.testGroupStarting(m_config->name(), 1, 1);
for (auto const& testCase : m_tests) {
if (!m_context.aborting())
totals += m_context.runTest(*testCase);
else
m_reporter->skipTest(testCase->getTestCaseInfo());
}
for (auto const& match : m_matches) {
if (match.tests.empty()) {
m_reporter->noMatchingTestCases(match.name);
totals.error = -1;
}
}
if (!invalidArgs.empty()) {
for (auto const& invalidArg: invalidArgs)
m_reporter->reportInvalidArguments(invalidArg);
}
m_context.testGroupEnded(m_config->name(), totals, 1, 1);
return totals;
}
private:
using Tests = std::set<TestCaseHandle const*>;
IStreamingReporter* m_reporter;
Config const* m_config;
RunContext m_context;
Tests m_tests;
TestSpec::Matches m_matches;
};
void applyFilenamesAsTags() {
for (auto const& testInfo : getRegistryHub().getTestCaseRegistry().getAllInfos()) {
testInfo->addFilenameTag();
}
}
} // anon namespace
Session::Session() {
static bool alreadyInstantiated = false;
if( alreadyInstantiated ) {
CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); }
CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); }
}
// There cannot be exceptions at startup in no-exception mode.
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
if ( !exceptions.empty() ) {
config();
getCurrentMutableContext().setConfig(m_config.get());
m_startupExceptions = true;
Colour colourGuard( Colour::Red );
Catch::cerr() << "Errors occurred during startup!" << '\n';
// iterate over all exceptions and notify user
for ( const auto& ex_ptr : exceptions ) {
try {
std::rethrow_exception(ex_ptr);
} catch ( std::exception const& ex ) {
Catch::cerr() << TextFlow::Column( ex.what() ).indent(2) << '\n';
}
}
}
#endif
alreadyInstantiated = true;
m_cli = makeCommandLineParser( m_configData );
}
Session::~Session() {
Catch::cleanUp();
}
void Session::showHelp() const {
Catch::cout()
<< "\nCatch v" << libraryVersion() << "\n"
<< m_cli << std::endl
<< "For more detailed usage please see the project docs\n" << std::endl;
}
void Session::libIdentify() {
Catch::cout()
<< std::left << std::setw(16) << "description: " << "A Catch2 test executable\n"
<< std::left << std::setw(16) << "category: " << "testframework\n"
<< std::left << std::setw(16) << "framework: " << "Catch Test\n"
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
}
int Session::applyCommandLine( int argc, char const * const * argv ) {
if( m_startupExceptions )
return 1;
auto result = m_cli.parse( Clara::Args( argc, argv ) );
if( !result ) {
config();
getCurrentMutableContext().setConfig(m_config.get());
Catch::cerr()
<< Colour( Colour::Red )
<< "\nError(s) in input:\n"
<< TextFlow::Column( result.errorMessage() ).indent( 2 )
<< "\n\n";
Catch::cerr() << "Run with -? for usage\n" << std::endl;
return MaxExitCode;
}
if( m_configData.showHelp )
showHelp();
if( m_configData.libIdentify )
libIdentify();
m_config.reset();
return 0;
}
#if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
int Session::applyCommandLine( int argc, wchar_t const * const * argv ) {
char **utf8Argv = new char *[ argc ];
for ( int i = 0; i < argc; ++i ) {
int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr );
utf8Argv[ i ] = new char[ bufSize ];
WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr );
}
int returnCode = applyCommandLine( argc, utf8Argv );
for ( int i = 0; i < argc; ++i )
delete [] utf8Argv[ i ];
delete [] utf8Argv;
return returnCode;
}
#endif
void Session::useConfigData( ConfigData const& configData ) {
m_configData = configData;
m_config.reset();
}
int Session::run() {
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
static_cast<void>(std::getchar());
}
int exitCode = runInternal();
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
static_cast<void>(std::getchar());
}
return exitCode;
}
Clara::Parser const& Session::cli() const {
return m_cli;
}
void Session::cli( Clara::Parser const& newParser ) {
m_cli = newParser;
}
ConfigData& Session::configData() {
return m_configData;
}
Config& Session::config() {
if( !m_config )
m_config = Detail::make_unique<Config>( m_configData );
return *m_config;
}
int Session::runInternal() {
if( m_startupExceptions )
return 1;
if (m_configData.showHelp || m_configData.libIdentify) {
return 0;
}
CATCH_TRY {
config(); // Force config to be constructed
seedRng( *m_config );
if (m_configData.filenamesAsTags) {
applyFilenamesAsTags();
}
// Set up global config instance before we start calling into other functions
getCurrentMutableContext().setConfig(m_config.get());
// Create reporter(s) so we can route listings through them
auto reporter = makeReporter(m_config.get());
// Handle list request
if (list(*reporter, *m_config)) {
return 0;
}
TestGroup tests { std::move(reporter), m_config.get() };
auto const totals = tests.execute();
if( m_config->warnAboutNoTests() && totals.error == -1 )
return 2;
// Note that on unices only the lower 8 bits are usually used, clamping
// the return value to 255 prevents false negative when some multiple
// of 256 tests has failed
return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
}
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
catch( std::exception& ex ) {
Catch::cerr() << ex.what() << std::endl;
return MaxExitCode;
}
#endif
}
} // end namespace Catch
-62
View File
@@ -1,62 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_SESSION_HPP_INCLUDED
#define CATCH_SESSION_HPP_INCLUDED
#include <catch2/internal/catch_commandline.hpp>
#include <catch2/internal/catch_noncopyable.hpp>
#include <catch2/catch_config.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
#include <catch2/internal/catch_config_wchar.hpp>
namespace Catch {
class Session : Detail::NonCopyable {
public:
Session();
~Session();
void showHelp() const;
void libIdentify();
int applyCommandLine( int argc, char const * const * argv );
#if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
int applyCommandLine( int argc, wchar_t const * const * argv );
#endif
void useConfigData( ConfigData const& configData );
template<typename CharT>
int run(int argc, CharT const * const argv[]) {
if (m_startupExceptions)
return 1;
int returnCode = applyCommandLine(argc, argv);
if (returnCode == 0)
returnCode = run();
return returnCode;
}
int run();
Clara::Parser const& cli() const;
void cli( Clara::Parser const& newParser );
ConfigData& configData();
Config& config();
private:
int runInternal();
Clara::Parser m_cli;
ConfigData m_configData;
Detail::unique_ptr<Config> m_config;
bool m_startupExceptions = false;
};
} // end namespace Catch
#endif // CATCH_SESSION_HPP_INCLUDED
@@ -1,29 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_TAG_ALIAS_HPP_INCLUDED
#define CATCH_TAG_ALIAS_HPP_INCLUDED
#include <catch2/internal/catch_source_line_info.hpp>
#include <string>
namespace Catch {
struct TagAlias {
TagAlias(std::string const& _tag, SourceLineInfo _lineInfo):
tag(_tag),
lineInfo(_lineInfo)
{}
std::string tag;
SourceLineInfo lineInfo;
};
} // end namespace Catch
#endif // CATCH_TAG_ALIAS_HPP_INCLUDED

Some files were not shown because too many files have changed in this diff Show More