pkgsrc-WIP-changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

prusaslicer: Support Catch2 v3.



Module Name:	pkgsrc-wip
Committed By:	Paul Ripke <stix%stix.id.au@localhost>
Pushed By:	stix
Date:		Sat Apr 20 18:00:31 2024 +1000
Changeset:	607e9059625e3a126b9e64b7958d3c13e5854f99

Modified Files:
	prusaslicer/Makefile
	prusaslicer/distinfo
	prusaslicer/patches/patch-tests_fff__print_test__data.cpp
Added Files:
	prusaslicer/patches/patch-tests_CMakeLists.txt
	prusaslicer/patches/patch-tests_arrange_test__arrange.cpp
	prusaslicer/patches/patch-tests_arrange_test__arrange__integration.cpp
	prusaslicer/patches/patch-tests_catch__main.hpp
	prusaslicer/patches/patch-tests_fff__print_test__avoid__crossing__perimeters.cpp
	prusaslicer/patches/patch-tests_fff__print_test__bridges.cpp
	prusaslicer/patches/patch-tests_fff__print_test__clipper.cpp
	prusaslicer/patches/patch-tests_fff__print_test__cooling.cpp
	prusaslicer/patches/patch-tests_fff__print_test__custom__gcode.cpp
	prusaslicer/patches/patch-tests_fff__print_test__extrusion__entity.cpp
	prusaslicer/patches/patch-tests_fff__print_test__fill.cpp
	prusaslicer/patches/patch-tests_fff__print_test__flow.cpp
	prusaslicer/patches/patch-tests_fff__print_test__gaps.cpp
	prusaslicer/patches/patch-tests_fff__print_test__gcode.cpp
	prusaslicer/patches/patch-tests_fff__print_test__gcode__travels.cpp
	prusaslicer/patches/patch-tests_fff__print_test__gcodefindreplace.cpp
	prusaslicer/patches/patch-tests_fff__print_test__gcodewriter.cpp
	prusaslicer/patches/patch-tests_fff__print_test__layers.cpp
	prusaslicer/patches/patch-tests_fff__print_test__model.cpp
	prusaslicer/patches/patch-tests_fff__print_test__multi.cpp
	prusaslicer/patches/patch-tests_fff__print_test__perimeters.cpp
	prusaslicer/patches/patch-tests_fff__print_test__print.cpp
	prusaslicer/patches/patch-tests_fff__print_test__printgcode.cpp
	prusaslicer/patches/patch-tests_fff__print_test__printobject.cpp
	prusaslicer/patches/patch-tests_fff__print_test__retraction.cpp
	prusaslicer/patches/patch-tests_fff__print_test__shells.cpp
	prusaslicer/patches/patch-tests_fff__print_test__skirt__brim.cpp
	prusaslicer/patches/patch-tests_fff__print_test__support__material.cpp
	prusaslicer/patches/patch-tests_fff__print_test__thin__walls.cpp
	prusaslicer/patches/patch-tests_fff__print_test__trianglemesh.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__3mf.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__aabbindirect.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__anyptr.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__arachne.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__arc__welder.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__astar.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__clipper__offset.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__clipper__utils.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__color.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__config.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__curve__fitting.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__cut__surface.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__elephant__foot__compensation.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__emboss.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__expolygon.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__geometry.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__hollowing.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__indexed__triangle__set.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__jump__point__search.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__kdtreeindirect.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__line.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__marchingsquares.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__meshboolean.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__mutable__polygon.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__mutable__priority__queue.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__optimizers.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__placeholder__parser.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__png__io.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__point.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__polygon.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__polyline.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__quadric__edge__collapse.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__region__expansion.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__static__map.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__stl.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__support__spots__generator.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__surface__mesh.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__timeutils.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__triangulation.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__utils.cpp
	prusaslicer/patches/patch-tests_libslic3r_test__voronoi.cpp
	prusaslicer/patches/patch-tests_sla__print_sla__archive__readwrite__tests.cpp
	prusaslicer/patches/patch-tests_sla__print_sla__print__tests.cpp
	prusaslicer/patches/patch-tests_sla__print_sla__raycast__tests.cpp
	prusaslicer/patches/patch-tests_sla__print_sla__supptgen__tests.cpp
	prusaslicer/patches/patch-tests_sla__print_sla__supptreeutils__tests.cpp
	prusaslicer/patches/patch-tests_sla__print_sla__test__utils.cpp
	prusaslicer/patches/patch-tests_sla__print_sla__test__utils.hpp
	prusaslicer/patches/patch-tests_slic3rutils_slic3r__arrangejob__tests.cpp
	prusaslicer/patches/patch-tests_slic3rutils_slic3r__jobs__tests.cpp
	prusaslicer/patches/patch-tests_slic3rutils_slic3r__version__tests.cpp
	prusaslicer/patches/patch-tests_thumbnails_test__thumbnails__ini__string.cpp
	prusaslicer/patches/patch-tests_thumbnails_test__thumbnails__input__string.cpp

Log Message:
prusaslicer: Support Catch2 v3.

Based on https://github.com/prusa3d/PrusaSlicer/issues/11567

To see a diff of this commit:
https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=607e9059625e3a126b9e64b7958d3c13e5854f99

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

diffstat:
 prusaslicer/Makefile                               |   1 +
 prusaslicer/distinfo                               |  85 ++++++++++++-
 prusaslicer/patches/patch-tests_CMakeLists.txt     |  25 ++++
 .../patches/patch-tests_arrange_test__arrange.cpp  |  44 +++++++
 ...ch-tests_arrange_test__arrange__integration.cpp |  52 ++++++++
 prusaslicer/patches/patch-tests_catch__main.hpp    |  61 +++++++++
 ...ff__print_test__avoid__crossing__perimeters.cpp |  13 ++
 .../patch-tests_fff__print_test__bridges.cpp       |  13 ++
 .../patch-tests_fff__print_test__clipper.cpp       |  13 ++
 .../patch-tests_fff__print_test__cooling.cpp       |  13 ++
 .../patch-tests_fff__print_test__custom__gcode.cpp |  13 ++
 .../patches/patch-tests_fff__print_test__data.cpp  |  18 +--
 ...ch-tests_fff__print_test__extrusion__entity.cpp | 102 +++++++++++++++
 .../patches/patch-tests_fff__print_test__fill.cpp  |  32 +++++
 .../patches/patch-tests_fff__print_test__flow.cpp  |  94 ++++++++++++++
 .../patches/patch-tests_fff__print_test__gaps.cpp  |  13 ++
 .../patches/patch-tests_fff__print_test__gcode.cpp |  34 +++++
 ...patch-tests_fff__print_test__gcode__travels.cpp |  29 +++++
 ...tch-tests_fff__print_test__gcodefindreplace.cpp |  13 ++
 .../patch-tests_fff__print_test__gcodewriter.cpp   |  49 ++++++++
 .../patch-tests_fff__print_test__layers.cpp        |  35 ++++++
 .../patches/patch-tests_fff__print_test__model.cpp |  13 ++
 .../patches/patch-tests_fff__print_test__multi.cpp |  13 ++
 .../patch-tests_fff__print_test__perimeters.cpp    |  13 ++
 .../patches/patch-tests_fff__print_test__print.cpp |  13 ++
 .../patch-tests_fff__print_test__printgcode.cpp    |  58 +++++++++
 .../patch-tests_fff__print_test__printobject.cpp   |  67 ++++++++++
 .../patch-tests_fff__print_test__retraction.cpp    |  30 +++++
 .../patch-tests_fff__print_test__shells.cpp        |  13 ++
 .../patch-tests_fff__print_test__skirt__brim.cpp   |  68 ++++++++++
 ...ch-tests_fff__print_test__support__material.cpp |  13 ++
 .../patch-tests_fff__print_test__thin__walls.cpp   |  13 ++
 .../patch-tests_fff__print_test__trianglemesh.cpp  |  13 ++
 .../patches/patch-tests_libslic3r_test__3mf.cpp    |  13 ++
 .../patch-tests_libslic3r_test__aabbindirect.cpp   |  98 +++++++++++++++
 .../patches/patch-tests_libslic3r_test__anyptr.cpp |  13 ++
 .../patch-tests_libslic3r_test__arachne.cpp        |  13 ++
 .../patch-tests_libslic3r_test__arc__welder.cpp    |  22 ++++
 .../patches/patch-tests_libslic3r_test__astar.cpp  |  33 +++++
 ...patch-tests_libslic3r_test__clipper__offset.cpp | 113 +++++++++++++++++
 .../patch-tests_libslic3r_test__clipper__utils.cpp | 139 +++++++++++++++++++++
 .../patches/patch-tests_libslic3r_test__color.cpp  |  13 ++
 .../patches/patch-tests_libslic3r_test__config.cpp |  14 +++
 .../patch-tests_libslic3r_test__curve__fitting.cpp |  56 +++++++++
 .../patch-tests_libslic3r_test__cut__surface.cpp   |  20 +++
 ...ibslic3r_test__elephant__foot__compensation.cpp |  13 ++
 .../patches/patch-tests_libslic3r_test__emboss.cpp |  31 +++++
 .../patch-tests_libslic3r_test__expolygon.cpp      |  38 ++++++
 .../patch-tests_libslic3r_test__geometry.cpp       |  13 ++
 .../patch-tests_libslic3r_test__hollowing.cpp      |  15 +++
 ...ests_libslic3r_test__indexed__triangle__set.cpp |  16 +++
 ...h-tests_libslic3r_test__jump__point__search.cpp |  13 ++
 .../patch-tests_libslic3r_test__kdtreeindirect.cpp |  13 ++
 .../patches/patch-tests_libslic3r_test__line.cpp   |  26 ++++
 ...patch-tests_libslic3r_test__marchingsquares.cpp |  13 ++
 .../patch-tests_libslic3r_test__meshboolean.cpp    |  31 +++++
 ...atch-tests_libslic3r_test__mutable__polygon.cpp |  13 ++
 ...ts_libslic3r_test__mutable__priority__queue.cpp |  17 +++
 .../patch-tests_libslic3r_test__optimizers.cpp     |  13 ++
 ...h-tests_libslic3r_test__placeholder__parser.cpp |  83 ++++++++++++
 .../patch-tests_libslic3r_test__png__io.cpp        |  16 +++
 .../patches/patch-tests_libslic3r_test__point.cpp  |  22 ++++
 .../patch-tests_libslic3r_test__polygon.cpp        |  13 ++
 .../patch-tests_libslic3r_test__polyline.cpp       |  16 +++
 ...sts_libslic3r_test__quadric__edge__collapse.cpp |  22 ++++
 ...tch-tests_libslic3r_test__region__expansion.cpp |  63 ++++++++++
 .../patch-tests_libslic3r_test__static__map.cpp    |  13 ++
 .../patches/patch-tests_libslic3r_test__stl.cpp    |  13 ++
 ...s_libslic3r_test__support__spots__generator.cpp |  22 ++++
 .../patch-tests_libslic3r_test__surface__mesh.cpp  |  21 ++++
 .../patch-tests_libslic3r_test__timeutils.cpp      |  13 ++
 .../patch-tests_libslic3r_test__triangulation.cpp  |  13 ++
 .../patches/patch-tests_libslic3r_test__utils.cpp  |  13 ++
 .../patch-tests_libslic3r_test__voronoi.cpp        |  33 +++++
 ...s_sla__print_sla__archive__readwrite__tests.cpp |  13 ++
 .../patch-tests_sla__print_sla__print__tests.cpp   |  34 +++++
 .../patch-tests_sla__print_sla__raycast__tests.cpp |  65 ++++++++++
 ...patch-tests_sla__print_sla__supptgen__tests.cpp |  13 ++
 ...-tests_sla__print_sla__supptreeutils__tests.cpp |  72 +++++++++++
 .../patch-tests_sla__print_sla__test__utils.cpp    |  63 ++++++++++
 .../patch-tests_sla__print_sla__test__utils.hpp    |  18 +++
 ...tests_slic3rutils_slic3r__arrangejob__tests.cpp |  53 ++++++++
 ...patch-tests_slic3rutils_slic3r__jobs__tests.cpp |  14 +++
 ...ch-tests_slic3rutils_slic3r__version__tests.cpp |  13 ++
 ...ts_thumbnails_test__thumbnails__ini__string.cpp |  13 ++
 ..._thumbnails_test__thumbnails__input__string.cpp |  20 +++
 86 files changed, 2649 insertions(+), 9 deletions(-)

diffs:
diff --git a/prusaslicer/Makefile b/prusaslicer/Makefile
index 3832475a2e..80cdd4478e 100644
--- a/prusaslicer/Makefile
+++ b/prusaslicer/Makefile
@@ -44,6 +44,7 @@ pre-configure:
 .include "../../devel/at-spi2-atk/buildlink3.mk"
 .include "../../devel/atk/buildlink3.mk"
 .include "../../devel/boost-headers/buildlink3.mk"
+.include "../../devel/catch2/buildlink3.mk"
 .include "../../devel/glib2/buildlink3.mk"
 .include "../../devel/libepoll-shim/buildlink3.mk"
 .include "../../devel/libffi/buildlink3.mk"
diff --git a/prusaslicer/distinfo b/prusaslicer/distinfo
index 4d1f478683..9b9a8f9b7a 100644
--- a/prusaslicer/distinfo
+++ b/prusaslicer/distinfo
@@ -59,4 +59,87 @@ SHA1 (patch-src_slic3r_Utils_FontConfigHelp.hpp) = 8027a1bc90a7f0ad1b53787a25f1e
 SHA1 (patch-src_slic3r_Utils_Serial.cpp) = 77dbb4e3526e932c04b8020b6f808278d1319bdb
 SHA1 (patch-src_slic3r_Utils_WifiScanner.cpp) = a7c8d6dfb43ddaca651df13b487b43dd51b32719
 SHA1 (patch-src_slic3r_Utils_WxFontUtils.cpp) = cc033a04f3219b0f4229344e14d44be63192db60
-SHA1 (patch-tests_fff__print_test__data.cpp) = 588e2a7ea980d82b7bb43eb7522b639101d0a337
+SHA1 (patch-tests_CMakeLists.txt) = 89670b4a0a74f9cf985b4b3f0e7aa3f83d8b8a36
+SHA1 (patch-tests_arrange_test__arrange.cpp) = e51371c9c4a41a54ebf7d8a220e61053e967d2aa
+SHA1 (patch-tests_arrange_test__arrange__integration.cpp) = 94f9a1e67647baf5563f13d2ead6d666a2a04e22
+SHA1 (patch-tests_catch__main.hpp) = cbcf811b2ac9d95c4a16e34068fa64a771f6527d
+SHA1 (patch-tests_fff__print_test__avoid__crossing__perimeters.cpp) = 7ecee4420340190017bea14e51f9f20e9a9d40ec
+SHA1 (patch-tests_fff__print_test__bridges.cpp) = 9ed9cfdb94800fdef8b70aeae90ed43f3378cd1a
+SHA1 (patch-tests_fff__print_test__clipper.cpp) = 47456223cbc4a5a5794a5de398fb6605a7ee8015
+SHA1 (patch-tests_fff__print_test__cooling.cpp) = 4b899035319adcec50c2222fe7bd2c785c550d05
+SHA1 (patch-tests_fff__print_test__custom__gcode.cpp) = d6aaf70b53a1547faff1134d5e88c7b0318aea39
+SHA1 (patch-tests_fff__print_test__data.cpp) = b1203f9e7e3571233370536e72a2c61a233852d2
+SHA1 (patch-tests_fff__print_test__extrusion__entity.cpp) = 4a6f77474bd1575a3ee32ebae3eb1f67d937207f
+SHA1 (patch-tests_fff__print_test__fill.cpp) = 81ad1633c84fb236ef2585108af2dd63f31ac850
+SHA1 (patch-tests_fff__print_test__flow.cpp) = 9ed579f2f11b8c633fd80ebe51a5e4986cdab757
+SHA1 (patch-tests_fff__print_test__gaps.cpp) = 166e0cf758eb72f2d5f80ab8cbf084afd586163e
+SHA1 (patch-tests_fff__print_test__gcode.cpp) = 7ef4648a3f7928e86d91a79568d39677a395ee80
+SHA1 (patch-tests_fff__print_test__gcode__travels.cpp) = 3af188fc7625b7bdc47e3436abc8d2e31afb92de
+SHA1 (patch-tests_fff__print_test__gcodefindreplace.cpp) = 1dcc0187fef0527f111996fa83dcfdbb9ad21ab9
+SHA1 (patch-tests_fff__print_test__gcodewriter.cpp) = 48d3caf9e158ff1c0499be1d0d23121f4b53ebd1
+SHA1 (patch-tests_fff__print_test__layers.cpp) = a110baa86741ac1d660760272be54eb61931453f
+SHA1 (patch-tests_fff__print_test__model.cpp) = 327cc6ebb5a91cea1f79d596740f8b59c79b7d89
+SHA1 (patch-tests_fff__print_test__multi.cpp) = da0c20fedbabca4b83733f5cf1696e726051ee45
+SHA1 (patch-tests_fff__print_test__perimeters.cpp) = aadde9bcddcd0e1989f05cb73b21633f5a573f21
+SHA1 (patch-tests_fff__print_test__print.cpp) = 70d12a80f17506eb302ae690316fb4950e7b50cd
+SHA1 (patch-tests_fff__print_test__printgcode.cpp) = 26f51fc96dfa04ba9db7a7cf22a84b71e48e359f
+SHA1 (patch-tests_fff__print_test__printobject.cpp) = c66c3cf170de6a83c9c51d6648b662f3a256c694
+SHA1 (patch-tests_fff__print_test__retraction.cpp) = 9d680474692d291bd9aaff7ed6a96aae2dc663df
+SHA1 (patch-tests_fff__print_test__shells.cpp) = c96072233c9f35a798971b9fd220ccbb423d82c3
+SHA1 (patch-tests_fff__print_test__skirt__brim.cpp) = 5bdddb6929c85a5c53da5b9a1f96fdb975955eee
+SHA1 (patch-tests_fff__print_test__support__material.cpp) = 2c0b98b3f885b058fc15f11699c48dea0632bb3a
+SHA1 (patch-tests_fff__print_test__thin__walls.cpp) = 5d7a126ca4ae7bd2d3bcfec21ae8114258d35f0f
+SHA1 (patch-tests_fff__print_test__trianglemesh.cpp) = d3a4800afb6d9c237385775dce5a244d72237920
+SHA1 (patch-tests_libslic3r_test__3mf.cpp) = a2200bd6dfc4024634350aa6e986caee44cea376
+SHA1 (patch-tests_libslic3r_test__aabbindirect.cpp) = 85524ec599031d073a44d49bad4e39e7ba5934f1
+SHA1 (patch-tests_libslic3r_test__anyptr.cpp) = 0cdcc5ae139aa0ec0d1cadbe2785b8c4279ecc10
+SHA1 (patch-tests_libslic3r_test__arachne.cpp) = d40888298291756d161b553e1e49cc095e961f4b
+SHA1 (patch-tests_libslic3r_test__arc__welder.cpp) = ada362d80154f25daa1a355a80ac0d46cf9ec314
+SHA1 (patch-tests_libslic3r_test__astar.cpp) = 6841f6c717469772f1fd37ad3e749f40401e1dfa
+SHA1 (patch-tests_libslic3r_test__clipper__offset.cpp) = 8a0250b77cf9577d21639fdc40f01add11988ae5
+SHA1 (patch-tests_libslic3r_test__clipper__utils.cpp) = df03001635d24f34f51ab4d01091b73db066ba33
+SHA1 (patch-tests_libslic3r_test__color.cpp) = 53ef8ce1f1a25b7a08c17759cfc78538a0fdbb24
+SHA1 (patch-tests_libslic3r_test__config.cpp) = 87545bb2dd53e05a9b8fb09b4a4c1af193e754da
+SHA1 (patch-tests_libslic3r_test__curve__fitting.cpp) = 3d905c88deac5dc6696a5c98ece0707270df50e2
+SHA1 (patch-tests_libslic3r_test__cut__surface.cpp) = 48e106514f7e458e97f7ddff73be53203a72e3b4
+SHA1 (patch-tests_libslic3r_test__elephant__foot__compensation.cpp) = fb5fa38edec00d560fbfdedf48695757815ff970
+SHA1 (patch-tests_libslic3r_test__emboss.cpp) = 1dace2789dfa1cfc79eac8f71541bd29e83585df
+SHA1 (patch-tests_libslic3r_test__expolygon.cpp) = 9d5ce4d2619a24751f22b178fd1985876734d1f1
+SHA1 (patch-tests_libslic3r_test__geometry.cpp) = a3b8f9f0384cf0fe01f3dd92e8b52a477d38ec4d
+SHA1 (patch-tests_libslic3r_test__hollowing.cpp) = 21b3f2decbdf170bfa841fa6698f8398faae35a9
+SHA1 (patch-tests_libslic3r_test__indexed__triangle__set.cpp) = 613a11b74b0f99e9191c76a9494ad783f994bce8
+SHA1 (patch-tests_libslic3r_test__jump__point__search.cpp) = 31d5c690e300c420ca75e52f6f65e25ccfd3b7e2
+SHA1 (patch-tests_libslic3r_test__kdtreeindirect.cpp) = 6163ec75ca824e44840c2e9f2a196dc9f869712b
+SHA1 (patch-tests_libslic3r_test__line.cpp) = d540e905a1cc42bd05ecdac0690e462740564786
+SHA1 (patch-tests_libslic3r_test__marchingsquares.cpp) = 701f11ff7e66e1f9d74e6424e33a01b75d923ee4
+SHA1 (patch-tests_libslic3r_test__meshboolean.cpp) = 31a6e9bf3a3fc3dc74e8587187af9c2b67eec550
+SHA1 (patch-tests_libslic3r_test__mutable__polygon.cpp) = 520d8d53df9da5a16b6b8f9f33b1915b4ca7a75f
+SHA1 (patch-tests_libslic3r_test__mutable__priority__queue.cpp) = 2cba211ebb7a23623a61f868d6643ec52ddfafd2
+SHA1 (patch-tests_libslic3r_test__optimizers.cpp) = 53a5373798aef3fbe4b710b4ff9d818505b4931d
+SHA1 (patch-tests_libslic3r_test__placeholder__parser.cpp) = 5f30b562f1a69f5e3ee22de9eadb98b53a752946
+SHA1 (patch-tests_libslic3r_test__png__io.cpp) = 0ad327a63ef606c0d41af6cf60e8517743ff4ee4
+SHA1 (patch-tests_libslic3r_test__point.cpp) = cc62a20c1058e2a35b0d85f884f9a07e2ccaca47
+SHA1 (patch-tests_libslic3r_test__polygon.cpp) = 2c8a7bf99b08eeeb5296d40a34a92e2e66dc5274
+SHA1 (patch-tests_libslic3r_test__polyline.cpp) = caf306c874cc71f2e93ba59113ae080028b4b06f
+SHA1 (patch-tests_libslic3r_test__quadric__edge__collapse.cpp) = da14d39e5ebcbb5683615675a316d1289ca67fef
+SHA1 (patch-tests_libslic3r_test__region__expansion.cpp) = 053c8ae2ec557275960273d3c3c8147c71dc450b
+SHA1 (patch-tests_libslic3r_test__static__map.cpp) = d6f84ff708642c31ddd838671b18fb673f2d0a91
+SHA1 (patch-tests_libslic3r_test__stl.cpp) = accbe373f5a33dcdb34276e0013ef7a2e359eabe
+SHA1 (patch-tests_libslic3r_test__support__spots__generator.cpp) = c929b9f869b0a9000cf03e027a89f951f14f8768
+SHA1 (patch-tests_libslic3r_test__surface__mesh.cpp) = 25112b64fbab6a6cf4654af79f04360169a689cf
+SHA1 (patch-tests_libslic3r_test__timeutils.cpp) = c75d00e97b5413e531a2b509ef4d43682f0ce5fc
+SHA1 (patch-tests_libslic3r_test__triangulation.cpp) = 84a81713f93dfe5f4401a8fe89d9ac6daa53b4e4
+SHA1 (patch-tests_libslic3r_test__utils.cpp) = 48c0600c0c903aa04080a6653d1831bdef54d26a
+SHA1 (patch-tests_libslic3r_test__voronoi.cpp) = beab4970dc32237334e46b422309852e280e26cd
+SHA1 (patch-tests_sla__print_sla__archive__readwrite__tests.cpp) = 064eefb0d093af63c8a91eb92fe12a0264ae8c46
+SHA1 (patch-tests_sla__print_sla__print__tests.cpp) = fe5a6a602901069088af73da7b5f63d40329f522
+SHA1 (patch-tests_sla__print_sla__raycast__tests.cpp) = 2a78f94de919695e72df0636ea937e89fec2a5d4
+SHA1 (patch-tests_sla__print_sla__supptgen__tests.cpp) = 4128d2edba4b7683b1976d4f121e5cce6a2271f9
+SHA1 (patch-tests_sla__print_sla__supptreeutils__tests.cpp) = 683f98679a50d5146fe7173c10291a76bca81c32
+SHA1 (patch-tests_sla__print_sla__test__utils.cpp) = 16b7c0ba877a7f8be2171b7b99b18bdf3f847d12
+SHA1 (patch-tests_sla__print_sla__test__utils.hpp) = f04aeb14ad5966cf9d091512cfbb7caf9448092b
+SHA1 (patch-tests_slic3rutils_slic3r__arrangejob__tests.cpp) = 3cd6288e6ceeafde1885600d475f63b041b4ed45
+SHA1 (patch-tests_slic3rutils_slic3r__jobs__tests.cpp) = bba4e4256b6bfdbb011d51bb542acc60c8f705e3
+SHA1 (patch-tests_slic3rutils_slic3r__version__tests.cpp) = 4ac34b33f56f3cd56c4905b05eff0198c3bb0b72
+SHA1 (patch-tests_thumbnails_test__thumbnails__ini__string.cpp) = 110e0b85bc583f90626eafae9f5e7f57e4d287f5
+SHA1 (patch-tests_thumbnails_test__thumbnails__input__string.cpp) = ea069808217c1bff1863b540d6ab66714f41c41b
diff --git a/prusaslicer/patches/patch-tests_CMakeLists.txt b/prusaslicer/patches/patch-tests_CMakeLists.txt
new file mode 100644
index 0000000000..560edadce8
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_CMakeLists.txt
@@ -0,0 +1,25 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/CMakeLists.txt.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/CMakeLists.txt
+@@ -1,7 +1,7 @@
+ # TODO Add individual tests as executables in separate directories
+ # add_subirectory(<testcase>)
+ 
+-find_package(Catch2 2.9 REQUIRED)
++find_package(Catch2 REQUIRED)
+ 
+ include(Catch)
+ 
+@@ -13,7 +13,7 @@ set(CATCH_EXTRA_ARGS "" CACHE STRING "Ex
+ add_library(test_common INTERFACE)
+ target_include_directories(test_common INTERFACE ${CMAKE_CURRENT_LIST_DIR})
+ target_compile_definitions(test_common INTERFACE TEST_DATA_DIR=R"\(${TEST_DATA_DIR}\)" CATCH_CONFIG_FAST_COMPILE)
+-target_link_libraries(test_common INTERFACE Catch2::Catch2)
++target_link_libraries(test_common INTERFACE Catch2::Catch2WithMain)
+ 
+ if (APPLE)
+     target_link_libraries(test_common INTERFACE "-liconv -framework IOKit" "-framework CoreFoundation" -lc++)
diff --git a/prusaslicer/patches/patch-tests_arrange_test__arrange.cpp b/prusaslicer/patches/patch-tests_arrange_test__arrange.cpp
new file mode 100644
index 0000000000..aa9b038ab2
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_arrange_test__arrange.cpp
@@ -0,0 +1,44 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/arrange/test_arrange.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/arrange/test_arrange.cpp
+@@ -1,4 +1,7 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_template_test_macros.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ #include "test_utils.hpp"
+ 
+ #include <libslic3r/Execution/ExecutionSeq.hpp>
+@@ -40,6 +43,9 @@
+ 
+ #include <random>
+ 
++using Catch::Matchers::WithinRel;
++using Catch::Matchers::WithinAbs;
++
+ template<class ArrItem = Slic3r::arr2::ArrangeItem>
+ static std::vector<ArrItem> prusa_parts(double infl = 0.) {
+     using namespace Slic3r;
+@@ -930,7 +936,7 @@ TEST_CASE("Optimal nfp position search w
+ 
+                 Slic3r::Vec2crd D = bed.center - item.shape.center();
+                 REQUIRE(item.translation == D);
+-                REQUIRE(score == Approx(0.).margin(EPSILON));
++                REQUIRE_THAT(score, WithinAbs(0., EPSILON));
+             }
+         }
+     }
+@@ -1063,7 +1069,7 @@ TEMPLATE_TEST_CASE("Test if allowed item
+     bool packed = pack(strategy, bed, itm);
+ 
+     REQUIRE(packed);
+-    REQUIRE(get_rotation(itm) == Approx(PI));
++    REQUIRE_THAT(get_rotation(itm), WithinRel(PI));
+ }
+ 
+ //TEST_CASE("NFP optimizing test", "[arrange2]") {
diff --git a/prusaslicer/patches/patch-tests_arrange_test__arrange__integration.cpp b/prusaslicer/patches/patch-tests_arrange_test__arrange__integration.cpp
new file mode 100644
index 0000000000..0278d83743
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_arrange_test__arrange__integration.cpp
@@ -0,0 +1,52 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/arrange/test_arrange_integration.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/arrange/test_arrange_integration.cpp
+@@ -1,4 +1,10 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_template_test_macros.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/generators/catch_generators.hpp>
++#include <catch2/generators/catch_generators_adapters.hpp>
++#include <catch2/generators/catch_generators_range.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ #include "test_utils.hpp"
+ 
+ #include <libslic3r/Arrange/Arrange.hpp>
+@@ -12,6 +18,8 @@
+ #include "libslic3r/Format/3mf.hpp"
+ #include "libslic3r/ModelArrange.hpp"
+ 
++using Catch::Matchers::WithinRel;
++
+ static Slic3r::Model get_example_model_with_20mm_cube()
+ {
+     using namespace Slic3r;
+@@ -560,10 +568,10 @@ TEST_CASE("Virtual bed handlers - Stride
+                 auto ref_pos = tr * Vec3d::Zero();
+ 
+                 auto displace = bed_index * (unscaled(vbh.stride_scaled()));
+-                REQUIRE(ref_pos.x() == Approx(-displace));
++                REQUIRE_THAT(ref_pos.x(), WithinRel(-displace));
+ 
+                 auto ref_pos_mi = mi_to_move.get_matrix() * Vec3d::Zero();
+-                REQUIRE(ref_pos_mi.x() == Approx(instance_displace.x() + (bed_index >= 0) * displace));
++                REQUIRE_THAT(ref_pos_mi.x(), WithinRel(instance_displace.x() + (bed_index >= 0) * displace));
+             }
+         }
+     }
+@@ -868,8 +876,8 @@ bool settings_eq(const Slic3r::arr2::Arr
+ {
+     return v1.is_rotation_enabled() == v2.is_rotation_enabled() &&
+            v1.get_arrange_strategy() == v2.get_arrange_strategy() &&
+-           v1.get_distance_from_bed() == Approx(v2.get_distance_from_bed()) &&
+-           v1.get_distance_from_objects() == Approx(v2.get_distance_from_objects()) &&
++           WithinRel(v2.get_distance_from_bed()).match(v1.get_distance_from_bed()) &&
++           WithinRel(v2.get_distance_from_objects()).match(v1.get_distance_from_objects()) &&
+            v1.get_geometry_handling() == v2.get_geometry_handling() &&
+            v1.get_xl_alignment() == v2.get_xl_alignment();
+         ;
diff --git a/prusaslicer/patches/patch-tests_catch__main.hpp b/prusaslicer/patches/patch-tests_catch__main.hpp
new file mode 100644
index 0000000000..fb4b3367bc
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_catch__main.hpp
@@ -0,0 +1,61 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/catch_main.hpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/catch_main.hpp
+@@ -3,52 +3,6 @@
+ 
+ #define CATCH_CONFIG_EXTERNAL_INTERFACES
+ #define CATCH_CONFIG_MAIN
+-// #define CATCH_CONFIG_DEFAULT_REPORTER "verboseconsole"
+-#include <catch2/catch.hpp>
+-
+-namespace Catch {
+-struct VerboseConsoleReporter : public ConsoleReporter {
+-    double duration = 0.;
+-    using ConsoleReporter::ConsoleReporter;
+-    
+-    void testCaseStarting(TestCaseInfo const& _testInfo) override
+-    {
+-        Colour::use(Colour::Cyan);
+-        stream << "Testing ";
+-        Colour::use(Colour::None);
+-        stream << _testInfo.name << std::endl;
+-        ConsoleReporter::testCaseStarting(_testInfo);
+-    }
+-    
+-    void sectionStarting(const SectionInfo &_sectionInfo) override
+-    {
+-        if (_sectionInfo.name != currentTestCaseInfo->name)
+-            stream << _sectionInfo.name << std::endl;
+-        
+-        ConsoleReporter::sectionStarting(_sectionInfo);
+-    }
+-    
+-    void sectionEnded(const SectionStats &_sectionStats) override {
+-        duration += _sectionStats.durationInSeconds;
+-        ConsoleReporter::sectionEnded(_sectionStats);
+-    } 
+-    
+-    void testCaseEnded(TestCaseStats const& stats) override
+-    {
+-        if (stats.totals.assertions.allOk()) {
+-            Colour::use(Colour::BrightGreen);
+-            stream << "Passed";
+-            Colour::use(Colour::None);
+-            stream << " in " << duration << " [seconds]\n" << std::endl;
+-        }
+-        
+-        duration = 0.;            
+-        ConsoleReporter::testCaseEnded(stats);
+-    }
+-};
+-
+-CATCH_REGISTER_REPORTER( "verboseconsole", VerboseConsoleReporter )
+-
+-} // namespace Catch
++#include <catch2/catch_test_macros.hpp>
+ 
+ #endif // CATCH_MAIN
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__avoid__crossing__perimeters.cpp b/prusaslicer/patches/patch-tests_fff__print_test__avoid__crossing__perimeters.cpp
new file mode 100644
index 0000000000..3b96b6356b
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__avoid__crossing__perimeters.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_avoid_crossing_perimeters.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_avoid_crossing_perimeters.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "test_data.hpp"
+ 
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__bridges.cpp b/prusaslicer/patches/patch-tests_fff__print_test__bridges.cpp
new file mode 100644
index 0000000000..6f51591028
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__bridges.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_bridges.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_bridges.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <libslic3r/BridgeDetector.hpp>
+ #include <libslic3r/Geometry.hpp>
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__clipper.cpp b/prusaslicer/patches/patch-tests_fff__print_test__clipper.cpp
new file mode 100644
index 0000000000..2f6e35f0ca
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__clipper.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_clipper.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_clipper.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "test_data.hpp"
+ #include "libslic3r/ClipperZUtils.hpp"
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__cooling.cpp b/prusaslicer/patches/patch-tests_fff__print_test__cooling.cpp
new file mode 100644
index 0000000000..7289dee0ac
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__cooling.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_cooling.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_cooling.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <numeric>
+ #include <sstream>
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__custom__gcode.cpp b/prusaslicer/patches/patch-tests_fff__print_test__custom__gcode.cpp
new file mode 100644
index 0000000000..3905f47e48
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__custom__gcode.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_custom_gcode.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_custom_gcode.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <exception>
+ #include <numeric>
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__data.cpp b/prusaslicer/patches/patch-tests_fff__print_test__data.cpp
index dee537adda..fe0c7dcf8c 100644
--- a/prusaslicer/patches/patch-tests_fff__print_test__data.cpp
+++ b/prusaslicer/patches/patch-tests_fff__print_test__data.cpp
@@ -1,14 +1,16 @@
 $NetBSD$
 
-Missing include.
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
 
---- tests/fff_print/test_data.cpp.orig	2023-03-13 13:20:26.000000000 +0000
+--- tests/fff_print/test_data.cpp.orig	2024-04-09 12:13:15.323843373 +0000
 +++ tests/fff_print/test_data.cpp
-@@ -8,6 +8,7 @@
- #include "libslic3r/Format/STL.hpp"
+@@ -399,7 +399,7 @@ bool contains_regex(const std::string &d
  
- #include <cstdlib>
-+#include <fstream>
- #include <string>
+ } } // namespace Slic3r::Test
  
- #include <boost/nowide/cstdio.hpp>
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ SCENARIO("init_print functionality", "[test_data]") {
+ 	GIVEN("A default config") {
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__extrusion__entity.cpp b/prusaslicer/patches/patch-tests_fff__print_test__extrusion__entity.cpp
new file mode 100644
index 0000000000..3985ac6133
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__extrusion__entity.cpp
@@ -0,0 +1,102 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_extrusion_entity.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_extrusion_entity.cpp
+@@ -1,4 +1,7 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_approx.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ 
+ #include <cstdlib>
+ 
+@@ -11,6 +14,8 @@
+ #include "test_data.hpp"
+ 
+ using namespace Slic3r;
++using Catch::Approx;
++using Catch::Matchers::WithinRel;
+ 
+ static inline Slic3r::Point random_point(float LO=-50, float HI=50) 
+ {
+@@ -62,11 +67,11 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEnt
+         ExtrusionLoop loop;
+         loop.paths.emplace_back(new_extrusion_path(square.split_at_first_point(), ExtrusionRole::ExternalPerimeter, 1.));
+         THEN("polygon area") {
+-            REQUIRE(loop.polygon().area() == Approx(square.area()));
+-            REQUIRE(loop.area() == Approx(square.area()));
++            REQUIRE_THAT(loop.polygon().area(), WithinRel(square.area()));
++            REQUIRE_THAT(loop.area(), WithinRel(square.area()));
+         }
+         THEN("loop length") {
+-            REQUIRE(loop.length() == Approx(square.length()));
++            REQUIRE_THAT(loop.length(), WithinRel(square.length()));
+         }
+ 
+         WHEN("cloned") {
+@@ -112,14 +117,14 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEnt
+         }
+         double tot_len = polyline1.length() + polyline2.length();
+         THEN("length") {
+-            REQUIRE(loop.length() == Approx(tot_len));
++            REQUIRE_THAT(loop.length(), WithinRel(tot_len));
+         }
+ 
+         WHEN("splitting at intermediate point") {
+             auto loop2 = std::unique_ptr<ExtrusionLoop>(dynamic_cast<ExtrusionLoop*>(loop.clone()));
+             loop2->split_at_vertex(polyline1.points[1]);
+             THEN("length after splitting is unchanged") {
+-                REQUIRE(loop2->length() == Approx(tot_len));
++                REQUIRE_THAT(loop2->length(), WithinRel(tot_len));
+             }
+             THEN("loop contains three paths after splitting") {
+                 REQUIRE(loop2->paths.size() == 3);
+@@ -151,7 +156,7 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEnt
+                 double l2 = 0;
+                 for (const ExtrusionPath &p : paths)
+                     l2 += p.length();
+-                REQUIRE(l2 == Approx(l - 3.));
++                REQUIRE_THAT(l2, WithinRel(l - 3.));
+             }
+         }
+         
+@@ -159,7 +164,7 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEnt
+             auto loop2 = std::unique_ptr<ExtrusionLoop>(dynamic_cast<ExtrusionLoop*>(loop.clone()));
+             loop2->split_at_vertex(polyline2.points.front());
+             THEN("length after splitting is unchanged") {
+-                REQUIRE(loop2->length() == Approx(tot_len));
++                REQUIRE_THAT(loop2->length(), WithinRel(tot_len));
+             }
+             THEN("loop contains two paths after splitting") {
+                 REQUIRE(loop2->paths.size() == 2);
+@@ -189,7 +194,7 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEnt
+             auto loop2 = std::unique_ptr<ExtrusionLoop>(dynamic_cast<ExtrusionLoop*>(loop.clone()));
+             loop2->split_at(point, false, 0);
+             THEN("length after splitting is unchanged") {
+-                REQUIRE(loop2->length() == Approx(tot_len));
++                REQUIRE_THAT(loop2->length(), WithinRel(tot_len));
+             }
+             Point expected_start_point(200, 150);
+             THEN("expected starting point") {
+@@ -220,7 +225,7 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEnt
+             if (! loop.split_at_vertex(point))
+                 loop.split_at(point, false, 0);
+             THEN("total length is preserved after splitting") {
+-                REQUIRE(loop.length() == Approx(len));
++                REQUIRE_THAT(loop.length(), WithinRel(len));
+             }
+             THEN("order is correctly preserved after splitting") {
+                 REQUIRE(loop.paths.front().role() == ExtrusionRole::ExternalPerimeter);
+@@ -243,7 +248,7 @@ SCENARIO("ExtrusionLoop", "[ExtrusionEnt
+         double len = loop.length();
+         THEN("split_at() preserves total length") {
+             loop.split_at({ 15896783, 15868739 }, false, 0);
+-            REQUIRE(loop.length() == Approx(len));
++            REQUIRE_THAT(loop.length(), WithinRel(len));
+         }
+     }
+ }
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__fill.cpp b/prusaslicer/patches/patch-tests_fff__print_test__fill.cpp
new file mode 100644
index 0000000000..a35901e5d5
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__fill.cpp
@@ -0,0 +1,32 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_fill.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_fill.cpp
+@@ -1,4 +1,6 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ 
+ #include <numeric>
+ #include <sstream>
+@@ -18,6 +20,7 @@
+ 
+ using namespace Slic3r;
+ using namespace std::literals;
++using Catch::Matchers::WithinRel;
+ 
+ bool test_if_solid_surface_filled(const ExPolygon& expolygon, double flow_spacing, double angle = 0, double density = 1.0);
+ 
+@@ -25,7 +28,7 @@ bool test_if_solid_surface_filled(const 
+ TEST_CASE("Fill: adjusted solid distance") {
+     int surface_width = 250;
+     int distance = Slic3r::Flow::solid_spacing(surface_width, 47);
+-    REQUIRE(distance == Approx(50));
++    REQUIRE_THAT(distance, WithinRel(50));
+     REQUIRE(surface_width % distance == 0);
+ }
+ #endif
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__flow.cpp b/prusaslicer/patches/patch-tests_fff__print_test__flow.cpp
new file mode 100644
index 0000000000..098624cb47
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__flow.cpp
@@ -0,0 +1,94 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_flow.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_flow.cpp
+@@ -1,4 +1,6 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ 
+ #include <numeric>
+ #include <sstream>
+@@ -12,6 +14,7 @@
+ 
+ using namespace Slic3r::Test;
+ using namespace Slic3r;
++using Catch::Matchers::WithinRel;
+ 
+ SCENARIO("Extrusion width specifics", "[Flow]") {
+ 
+@@ -22,7 +25,7 @@ SCENARIO("Extrusion width specifics", "[
+         parser.parse_buffer(Slic3r::Test::slice({ Slic3r::Test::TestMesh::cube_20x20x20 }, config),
+             [&E_per_mm_bottom, layer_height] (Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line)
+         { 
+-            if (self.z() == Approx(layer_height).margin(0.01)) { // only consider first layer
++            if (WithinRel(layer_height, 0.01).match(self.z())) { // only consider first layer
+                 if (line.extruding(self) && line.dist_XY(self) > 0)
+                     E_per_mm_bottom.emplace_back(line.dist_E(self) / line.dist_XY(self));
+             }
+@@ -30,7 +33,7 @@ SCENARIO("Extrusion width specifics", "[
+         THEN("First layer width applies to everything on first layer.") {
+             REQUIRE(E_per_mm_bottom.size() > 0);
+             const double E_per_mm_avg = std::accumulate(E_per_mm_bottom.cbegin(), E_per_mm_bottom.cend(), 0.0) / static_cast<double>(E_per_mm_bottom.size());
+-            bool pass = (std::count_if(E_per_mm_bottom.cbegin(), E_per_mm_bottom.cend(), [E_per_mm_avg] (const double& v) { return v == Approx(E_per_mm_avg); }) == 0);
++            bool pass = (std::count_if(E_per_mm_bottom.cbegin(), E_per_mm_bottom.cend(), [E_per_mm_avg] (const double& v) { return WithinRel(E_per_mm_avg).match(v); }) == 0);
+             REQUIRE(pass);
+         }
+         THEN("First layer width does not apply to upper layer.") {
+@@ -156,18 +159,18 @@ SCENARIO("Flow: Flow math for non-bridge
+         // Spacing for non-bridges is has some overlap
+         THEN("External perimeter flow has spacing fixed to 1.125 * nozzle_diameter") {
+             auto flow = Flow::new_from_config_width(frExternalPerimeter, ConfigOptionFloatOrPercent(0, false), nozzle_diameter, layer_height);
+-            REQUIRE(flow.spacing() == Approx(1.125 * nozzle_diameter - layer_height * (1.0 - PI / 4.0)));
++            REQUIRE_THAT(flow.spacing(), WithinRel(1.125 * nozzle_diameter - layer_height * (1.0 - PI / 4.0), EPSILON));
+         }
+ 
+         THEN("Internal perimeter flow has spacing fixed to 1.125 * nozzle_diameter") {
+             auto flow = Flow::new_from_config_width(frPerimeter, ConfigOptionFloatOrPercent(0, false), nozzle_diameter, layer_height);
+-            REQUIRE(flow.spacing() == Approx(1.125 *nozzle_diameter - layer_height * (1.0 - PI / 4.0)));
++            REQUIRE_THAT(flow.spacing(), WithinRel(1.125 *nozzle_diameter - layer_height * (1.0 - PI / 4.0), EPSILON));
+         }
+         THEN("Spacing for supplied width is 0.8927f") {
+             auto flow = Flow::new_from_config_width(frExternalPerimeter, width, nozzle_diameter, layer_height);
+-            REQUIRE(flow.spacing() == Approx(width.value - layer_height * (1.0 - PI / 4.0)));
++            REQUIRE_THAT(flow.spacing(), WithinRel(width.value - layer_height * (1.0 - PI / 4.0), EPSILON));
+             flow = Flow::new_from_config_width(frPerimeter, width, nozzle_diameter, layer_height);
+-            REQUIRE(flow.spacing() == Approx(width.value - layer_height * (1.0 - PI / 4.0)));
++            REQUIRE_THAT(flow.spacing(), WithinRel(width.value - layer_height * (1.0 - PI / 4.0), EPSILON));
+         }
+     }
+     /// Check the min/max
+@@ -178,14 +181,14 @@ SCENARIO("Flow: Flow math for non-bridge
+             layer_height = 0.15f;
+             THEN("Max width is set.") {
+                 auto flow = Flow::new_from_config_width(frPerimeter, ConfigOptionFloatOrPercent(0, false), nozzle_diameter, layer_height);
+-                REQUIRE(flow.width() == Approx(1.125 * nozzle_diameter));
++                REQUIRE_THAT(flow.width(), WithinRel(1.125 * nozzle_diameter));
+             }
+         }
+         WHEN("Layer height is set to 0.25") {
+             layer_height = 0.25f;
+             THEN("Min width is set.") {
+                 auto flow = Flow::new_from_config_width(frPerimeter, ConfigOptionFloatOrPercent(0, false), nozzle_diameter, layer_height);
+-                REQUIRE(flow.width() == Approx(1.125 * nozzle_diameter));
++                REQUIRE_THAT(flow.width(), WithinRel(1.125 * nozzle_diameter));
+             }
+         }
+     }
+@@ -216,10 +219,10 @@ SCENARIO("Flow: Flow math for bridges", 
+         WHEN("Flow role is frExternalPerimeter") {
+             auto flow = Flow::bridging_flow(nozzle_diameter * sqrt(bridge_flow), nozzle_diameter);
+             THEN("Bridge width is same as nozzle diameter") {
+-                REQUIRE(flow.width() == Approx(nozzle_diameter));
++                REQUIRE_THAT(flow.width(), WithinRel(nozzle_diameter));
+             }
+             THEN("Bridge spacing is same as nozzle diameter + BRIDGE_EXTRA_SPACING") {
+-                REQUIRE(flow.spacing() == Approx(nozzle_diameter + BRIDGE_EXTRA_SPACING));
++                REQUIRE_THAT(flow.spacing(), WithinRel(nozzle_diameter + BRIDGE_EXTRA_SPACING, EPSILON));
+             }
+         }
+     }
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__gaps.cpp b/prusaslicer/patches/patch-tests_fff__print_test__gaps.cpp
new file mode 100644
index 0000000000..4054e70edd
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__gaps.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_gaps.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_gaps.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/GCodeReader.hpp"
+ #include "libslic3r/Geometry/ConvexHull.hpp"
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__gcode.cpp b/prusaslicer/patches/patch-tests_fff__print_test__gcode.cpp
new file mode 100644
index 0000000000..1dddd1b16b
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__gcode.cpp
@@ -0,0 +1,34 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_gcode.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_gcode.cpp
+@@ -2,7 +2,8 @@
+  * Mostly ported from t/gcode.t
+  */
+ 
+-#include <catch2/catch.hpp>
++#include <catch2/catch_approx.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <memory>
+ #include <regex>
+@@ -15,6 +16,7 @@
+ 
+ using namespace Slic3r;
+ using namespace Test;
++using Catch::Approx;
+ 
+ constexpr bool debug_files = false;
+ 
+@@ -66,7 +68,7 @@ TEST_CASE("Wiping speeds", "[GCode]") {
+         INFO("Wipe moves don\'t retract faster than configured speed");
+         CHECK(retract_speed < expected_retract_speed);
+     }
+-    INFO("No wiping after layer change")
++    INFO("No wiping after layer change");
+     CHECK(!wiping_on_new_layer);
+ }
+ 
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__gcode__travels.cpp b/prusaslicer/patches/patch-tests_fff__print_test__gcode__travels.cpp
new file mode 100644
index 0000000000..0daaf14ae6
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__gcode__travels.cpp
@@ -0,0 +1,29 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_gcode_travels.cpp.orig	2024-04-14 02:13:14.663964766 +0000
++++ tests/fff_print/test_gcode_travels.cpp
+@@ -1,4 +1,9 @@
+-#include <catch2/catch.hpp>
++#include <vector>
++
++#include <catch2/catch_approx.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_vector.hpp>
+ #include <libslic3r/GCode/Travels.hpp>
+ #include <libslic3r/ExPolygon.hpp>
+ #include <libslic3r/GCode.hpp>
+@@ -6,8 +11,9 @@
+ 
+ using namespace Slic3r;
+ using namespace Slic3r::GCode::Impl::Travels;
++using Catch::Approx;
+ 
+-struct ApproxEqualsPoints : public Catch::MatcherBase<Points> {
++struct ApproxEqualsPoints : public Catch::Matchers::MatcherBase<Points> {
+     ApproxEqualsPoints(const Points& expected, unsigned tolerance): expected(expected), tolerance(tolerance) {}
+     bool match(const Points& points) const override {
+         if (points.size() != expected.size()) {
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__gcodefindreplace.cpp b/prusaslicer/patches/patch-tests_fff__print_test__gcodefindreplace.cpp
new file mode 100644
index 0000000000..5e1b12213a
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__gcodefindreplace.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_gcodefindreplace.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_gcodefindreplace.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <memory>
+ 
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__gcodewriter.cpp b/prusaslicer/patches/patch-tests_fff__print_test__gcodewriter.cpp
new file mode 100644
index 0000000000..a3e5463bc2
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__gcodewriter.cpp
@@ -0,0 +1,49 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_gcodewriter.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_gcodewriter.cpp
+@@ -1,10 +1,13 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_string.hpp>
+ 
+ #include <memory>
+ 
+ #include "libslic3r/GCode/GCodeWriter.hpp"
+ 
+ using namespace Slic3r;
++using Catch::Matchers::Equals;
+ 
+ SCENARIO("set_speed emits values with fixed-point output.", "[GCodeWriter]") {
+ 
+@@ -12,22 +15,22 @@ SCENARIO("set_speed emits values with fi
+         GCodeWriter writer;
+         WHEN("set_speed is called to set speed to 99999.123") {
+             THEN("Output string is G1 F99999.123") {
+-                REQUIRE_THAT(writer.set_speed(99999.123), Catch::Equals("G1 F99999.123\n"));
++                REQUIRE_THAT(writer.set_speed(99999.123), Equals("G1 F99999.123\n"));
+             }
+         }
+         WHEN("set_speed is called to set speed to 1") {
+             THEN("Output string is G1 F1") {
+-                REQUIRE_THAT(writer.set_speed(1.0), Catch::Equals("G1 F1\n"));
++                REQUIRE_THAT(writer.set_speed(1.0), Equals("G1 F1\n"));
+             }
+         }
+         WHEN("set_speed is called to set speed to 203.200022") {
+             THEN("Output string is G1 F203.2") {
+-                REQUIRE_THAT(writer.set_speed(203.200022), Catch::Equals("G1 F203.2\n"));
++                REQUIRE_THAT(writer.set_speed(203.200022), Equals("G1 F203.2\n"));
+             }
+         }
+         WHEN("set_speed is called to set speed to 203.200522") {
+             THEN("Output string is G1 F203.201") {
+-                REQUIRE_THAT(writer.set_speed(203.200522), Catch::Equals("G1 F203.201\n"));
++                REQUIRE_THAT(writer.set_speed(203.200522), Equals("G1 F203.201\n"));
+             }
+         }
+     }
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__layers.cpp b/prusaslicer/patches/patch-tests_fff__print_test__layers.cpp
new file mode 100644
index 0000000000..a8eef41763
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__layers.cpp
@@ -0,0 +1,35 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_layers.cpp.orig	2024-04-14 02:13:14.684876605 +0000
++++ tests/fff_print/test_layers.cpp
+@@ -2,11 +2,13 @@
+ * Ported from t/layers.t
+ */
+ 
+-#include <catch2/catch.hpp>
++#include <catch2/catch_approx.hpp>
++#include <catch2/catch_test_macros.hpp>
+ #include "test_data.hpp"
+ 
+ using namespace Slic3r;
+ using namespace Slic3r::Test;
++using Catch::Approx;
+ 
+ void check_layers(const DynamicPrintConfig& config) {
+ 	GCodeReader parser;
+@@ -27,10 +29,10 @@ void check_layers(const DynamicPrintConf
+     const double layer_height = config.opt_float("layer_height");
+     INFO("Correct first layer height.");
+     CHECK(z.at(0) == Approx(first_layer_height + z_offset));
+-    INFO("Correct second layer height")
++    INFO("Correct second layer height");
+     CHECK(z.at(1) == Approx(first_layer_height + layer_height + z_offset));
+ 
+-    INFO("Correct layer height")
++    INFO("Correct layer height");
+     for (const double increment : tcb::span{increments}.subspan(1)) {
+         CHECK(increment == Approx(layer_height));
+     }
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__model.cpp b/prusaslicer/patches/patch-tests_fff__print_test__model.cpp
new file mode 100644
index 0000000000..5b678cf8b4
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__model.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_model.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_model.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/libslic3r.h"
+ #include "libslic3r/Model.hpp"
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__multi.cpp b/prusaslicer/patches/patch-tests_fff__print_test__multi.cpp
new file mode 100644
index 0000000000..d197423ae8
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__multi.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_multi.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_multi.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <numeric>
+ #include <sstream>
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__perimeters.cpp b/prusaslicer/patches/patch-tests_fff__print_test__perimeters.cpp
new file mode 100644
index 0000000000..66a398b169
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__perimeters.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_perimeters.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_perimeters.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <numeric>
+ #include <sstream>
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__print.cpp b/prusaslicer/patches/patch-tests_fff__print_test__print.cpp
new file mode 100644
index 0000000000..f4bdf8690e
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__print.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_print.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_print.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/libslic3r.h"
+ #include "libslic3r/Print.hpp"
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__printgcode.cpp b/prusaslicer/patches/patch-tests_fff__print_test__printgcode.cpp
new file mode 100644
index 0000000000..03077abbd0
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__printgcode.cpp
@@ -0,0 +1,58 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_printgcode.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_printgcode.cpp
+@@ -1,4 +1,6 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ 
+ #include "libslic3r/libslic3r.h"
+ #include "libslic3r/GCodeReader.hpp"
+@@ -10,6 +12,7 @@
+ 
+ using namespace Slic3r;
+ using namespace Slic3r::Test;
++using Catch::Matchers::WithinRel;
+ 
+ boost::regex perimeters_regex("G1 X[-0-9.]* Y[-0-9.]* E[-0-9.]* ; perimeter");
+ boost::regex infill_regex("G1 X[-0-9.]* Y[-0-9.]* E[-0-9.]* ; infill");
+@@ -79,7 +82,7 @@ SCENARIO( "PrintGCode basic functionalit
+                 reader.parse_buffer(gcode, [&final_z] (GCodeReader& self, const GCodeReader::GCodeLine& line) {
+                     final_z = std::max<double>(final_z, static_cast<double>(self.z())); // record the highest Z point we reach
+                 });
+-                REQUIRE(final_z == Approx(20.));
++                REQUIRE_THAT(final_z, WithinRel(20.));
+             }
+         }
+         WHEN("output is executed with complete objects and two differently-sized meshes") {
+@@ -121,7 +124,7 @@ SCENARIO( "PrintGCode basic functionalit
+                 reader.parse_buffer(gcode, [&final_z] (GCodeReader& self, const GCodeReader::GCodeLine& line) {
+                     final_z = std::max(final_z, static_cast<double>(self.z())); // record the highest Z point we reach
+                 });
+-                REQUIRE(final_z == Approx(20.1));
++                REQUIRE_THAT(final_z, WithinRel(20.1, EPSILON));
+             }
+             THEN("Z height resets on object change") {
+                 double final_z = 0.0;
+@@ -257,14 +260,14 @@ SCENARIO( "PrintGCode basic functionalit
+ 				REQUIRE(pos < gcode.size());
+ 				double z = 0;
+ 				REQUIRE((sscanf(gcode.data() + pos, "(%lf mm)", &z) == 1));
+-				REQUIRE(z == Approx(20.));
++				REQUIRE_THAT(z, WithinRel(20.));
+ 				// Second object
+ 				pos = gcode.find(";Layer:399 ", pos);
+ 				REQUIRE(pos != std::string::npos);
+ 				pos += token.size();
+ 				REQUIRE(pos < gcode.size());
+ 				REQUIRE((sscanf(gcode.data() + pos, "(%lf mm)", &z) == 1));
+-				REQUIRE(z == Approx(20.));
++				REQUIRE_THAT(z, WithinRel(20.));
+ 			}
+         }
+     }
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__printobject.cpp b/prusaslicer/patches/patch-tests_fff__print_test__printobject.cpp
new file mode 100644
index 0000000000..eb53bab5a5
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__printobject.cpp
@@ -0,0 +1,67 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_printobject.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_printobject.cpp
+@@ -1,4 +1,6 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ 
+ #include "libslic3r/libslic3r.h"
+ #include "libslic3r/Print.hpp"
+@@ -8,6 +10,7 @@
+ 
+ using namespace Slic3r;
+ using namespace Slic3r::Test;
++using Catch::Matchers::WithinRel;
+ 
+ SCENARIO("PrintObject: object layer heights", "[PrintObject]") {
+     GIVEN("20mm cube and default initial config, initial layer height of 2mm") {
+@@ -25,7 +28,7 @@ SCENARIO("PrintObject: object layer heig
+             AND_THEN("Each layer is approximately 2mm above the previous Z") {
+                 coordf_t last = 0.0;
+                 for (size_t i = 0; i < layers.size(); ++ i) {
+-                    REQUIRE((layers[i]->print_z - last) == Approx(2.0));
++                    REQUIRE_THAT((layers[i]->print_z - last), WithinRel(2.0));
+                     last = layers[i]->print_z;
+                 }
+             }
+@@ -42,10 +45,10 @@ SCENARIO("PrintObject: object layer heig
+                 REQUIRE(layers.size() == 3);
+             }
+             AND_THEN("Layer 0 is at 2mm") {
+-                REQUIRE(layers.front()->print_z == Approx(2.0));
++                REQUIRE_THAT(layers.front()->print_z, WithinRel(2.0));
+             }
+             AND_THEN("Layer 1 is at 12mm") {
+-                REQUIRE(layers[1]->print_z == Approx(12.0));
++                REQUIRE_THAT(layers[1]->print_z, WithinRel(12.0));
+             }
+         }
+         WHEN("generate_object_layers() is called for 15mm layer heights and nozzle diameter of 16mm") {
+@@ -60,10 +63,10 @@ SCENARIO("PrintObject: object layer heig
+                 REQUIRE(layers.size() == 2);
+             }
+             AND_THEN("Layer 0 is at 2mm") {
+-                REQUIRE(layers[0]->print_z == Approx(2.0));
++                REQUIRE_THAT(layers[0]->print_z, WithinRel(2.0));
+             }
+             AND_THEN("Layer 1 is at 17mm") {
+-                REQUIRE(layers[1]->print_z == Approx(17.0));
++                REQUIRE_THAT(layers[1]->print_z, WithinRel(17.0));
+             }
+         }
+ #if 0
+@@ -79,7 +82,7 @@ SCENARIO("PrintObject: object layer heig
+                 CHECK(layers.size() == 5);
+                 coordf_t last = 2.0;
+                 for (size_t i = 1; i < layers.size(); i++) {
+-                    REQUIRE((layers[i]->print_z - last) == Approx(5.0));
++                    REQUIRE_THAT((layers[i]->print_z - last), WithinRel(5.0));
+                     last = layers[i]->print_z;
+                 }
+             }
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__retraction.cpp b/prusaslicer/patches/patch-tests_fff__print_test__retraction.cpp
new file mode 100644
index 0000000000..8ac4043037
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__retraction.cpp
@@ -0,0 +1,30 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_retraction.cpp.orig	2024-04-14 02:13:14.728519199 +0000
++++ tests/fff_print/test_retraction.cpp
+@@ -2,10 +2,12 @@
+  * Ported from t/retraction.t
+  */
+ 
+-#include <catch2/catch.hpp>
++#include <catch2/catch_approx.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <libslic3r/GCodeReader.hpp>
+ #include <libslic3r/Config.hpp>
++using Catch::Approx;
+ 
+ #include "test_data.hpp"
+ #include <regex>
+@@ -77,7 +79,7 @@ void check_gcode(std::initializer_list<T
+                 lift_dist = line.dist_Z(self);
+             }
+             if (line.dist_Z(self) < 0) {
+-                INFO("Must be lifted before going down.")
++                INFO("Must be lifted before going down.");
+                 CHECK(lifted);
+                 INFO("Going down by the same amount of the lift or by the amount needed to get to next layer");
+                 CHECK((
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__shells.cpp b/prusaslicer/patches/patch-tests_fff__print_test__shells.cpp
new file mode 100644
index 0000000000..d482a1eab7
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__shells.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_shells.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_shells.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/GCodeReader.hpp"
+ 
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__skirt__brim.cpp b/prusaslicer/patches/patch-tests_fff__print_test__skirt__brim.cpp
new file mode 100644
index 0000000000..e38108cd84
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__skirt__brim.cpp
@@ -0,0 +1,68 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_skirt_brim.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_skirt_brim.cpp
+@@ -1,4 +1,6 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ 
+ #include "libslic3r/GCodeReader.hpp"
+ #include "libslic3r/Config.hpp"
+@@ -10,6 +12,7 @@
+ 
+ using namespace Slic3r::Test;
+ using namespace Slic3r;
++using Catch::Matchers::WithinRel;
+ 
+ /// Helper method to find the tool used for the brim (always the first extrusion)
+ static int get_brim_tool(const std::string &gcode)
+@@ -54,7 +57,7 @@ TEST_CASE("Skirt height is honored", "[S
+     double support_speed = config.opt<Slic3r::ConfigOptionFloat>("support_material_speed")->value * MM_PER_MIN;
+ 	GCodeReader parser;
+     parser.parse_buffer(gcode, [&layers_with_skirt, &support_speed] (Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line) {
+-        if (line.extruding(self) && self.f() == Approx(support_speed)) {
++        if (line.extruding(self) && WithinRel(support_speed).match(self.f())) {
+             layers_with_skirt[self.z()] = 1;
+         }
+     });
+@@ -90,8 +93,8 @@ SCENARIO("Original Slic3r Skirt/Brim tes
+                 double support_speed = config.opt<Slic3r::ConfigOptionFloat>("support_material_speed")->value * MM_PER_MIN;
+ 			    Slic3r::GCodeReader parser;
+                 parser.parse_buffer(gcode, [&brim_generated, support_speed] (Slic3r::GCodeReader& self, const Slic3r::GCodeReader::GCodeLine& line) {
+-                    if (self.z() == Approx(0.3) || line.new_Z(self) == Approx(0.3)) {
+-                        if (line.extruding(self) && self.f() == Approx(support_speed)) {
++                    if (WithinRel(0.3, EPSILON).match(self.z()) || WithinRel(0.3, EPSILON).match(line.new_Z(self))) {
++                        if (line.extruding(self) && WithinRel(support_speed, EPSILON).match(self.f())) {
+                             brim_generated = true;
+                         }
+                     }
+@@ -234,20 +237,20 @@ SCENARIO("Original Slic3r Skirt/Brim tes
+                     // std::cerr << line.cmd() << "\n";
+ 					if (boost::starts_with(line.cmd(), "T")) {
+ 						tool = atoi(line.cmd().data() + 1);
+-					} else if (self.z() == Approx(config.opt<ConfigOptionFloat>("first_layer_height")->value)) {
++					} else if (WithinRel(config.opt<ConfigOptionFloat>("first_layer_height")->value).match(self.z())) {
+                         // on first layer
+ 						if (line.extruding(self) && line.dist_XY(self) > 0) {
+                             float speed = ( self.f() > 0 ?  self.f() : line.new_F(self));
+                             // std::cerr << "Tool " << tool << "\n";
+-                            if (speed == Approx(support_speed) && tool == config.opt_int("perimeter_extruder") - 1) {
++                            if (WithinRel(support_speed).match(speed) && tool == config.opt_int("perimeter_extruder") - 1) {
+                                 // Skirt uses first material extruder, support material speed.
+                                 skirt_length += line.dist_XY(self);
+                             } else
+                                 extrusion_points.push_back(Slic3r::Point::new_scale(line.new_X(self), line.new_Y(self)));
+                         }
+                     }
+-                    if (self.z() == Approx(0.3) || line.new_Z(self) == Approx(0.3)) {
+-                        if (line.extruding(self) && self.f() == Approx(support_speed)) {
++                    if (WithinRel(0.3).match(self.z()) || WithinRel(0.3).match(line.new_Z(self))) {
++                        if (line.extruding(self) && WithinRel(support_speed).match(self.f())) {
+                         }
+                     }
+                 });
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__support__material.cpp b/prusaslicer/patches/patch-tests_fff__print_test__support__material.cpp
new file mode 100644
index 0000000000..71b0b4ef63
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__support__material.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_support_material.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_support_material.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/GCodeReader.hpp"
+ #include "libslic3r/Layer.hpp"
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__thin__walls.cpp b/prusaslicer/patches/patch-tests_fff__print_test__thin__walls.cpp
new file mode 100644
index 0000000000..3288540370
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__thin__walls.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_thin_walls.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_thin_walls.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <numeric>
+ #include <sstream>
diff --git a/prusaslicer/patches/patch-tests_fff__print_test__trianglemesh.cpp b/prusaslicer/patches/patch-tests_fff__print_test__trianglemesh.cpp
new file mode 100644
index 0000000000..e67117a0aa
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_fff__print_test__trianglemesh.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/fff_print/test_trianglemesh.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/fff_print/test_trianglemesh.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/TriangleMesh.hpp"
+ #include "libslic3r/TriangleMeshSlicer.hpp"
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__3mf.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__3mf.cpp
new file mode 100644
index 0000000000..09de8cba03
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__3mf.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_3mf.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_3mf.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/Model.hpp"
+ #include "libslic3r/Format/3mf.hpp"
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__aabbindirect.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__aabbindirect.cpp
new file mode 100644
index 0000000000..ee1c9d0f32
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__aabbindirect.cpp
@@ -0,0 +1,98 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_aabbindirect.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_aabbindirect.cpp
+@@ -1,5 +1,7 @@
+ #include <algorithm>
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ #include <test_utils.hpp>
+ 
+ #include <libslic3r/TriangleMesh.hpp>
+@@ -7,6 +9,8 @@
+ #include <libslic3r/AABBTreeLines.hpp>
+ 
+ using namespace Slic3r;
++using Catch::Matchers::WithinRel;
++using Catch::Matchers::WithinAbs;
+ 
+ TEST_CASE("Building a tree over a box, ray caster and closest query", "[AABBIndirect]")
+ {
+@@ -24,7 +28,7 @@ TEST_CASE("Building a tree over a box, r
+ 		hit);
+ 
+     REQUIRE(intersected);
+-    REQUIRE(hit.t == Approx(5.));
++    REQUIRE_THAT(hit.t, WithinRel(5.));
+ 
+     std::vector<igl::Hit> hits;
+ 	bool intersected2 = AABBTreeIndirect::intersect_ray_all_hits(
+@@ -35,8 +39,8 @@ TEST_CASE("Building a tree over a box, r
+ 		hits);
+     REQUIRE(intersected2);
+     REQUIRE(hits.size() == 2);
+-    REQUIRE(hits.front().t == Approx(5.));
+-    REQUIRE(hits.back().t == Approx(6.));
++    REQUIRE_THAT(hits.front().t, WithinRel(5.));
++    REQUIRE_THAT(hits.back().t, WithinRel(6.));
+ 
+     size_t hit_idx;
+     Vec3d  closest_point;
+@@ -45,20 +49,20 @@ TEST_CASE("Building a tree over a box, r
+ 		tree,
+         Vec3d(0.3, 0.5, -5.),
+ 		hit_idx, closest_point);
+-    REQUIRE(squared_distance == Approx(5. * 5.));
+-    REQUIRE(closest_point.x() == Approx(0.3));
+-    REQUIRE(closest_point.y() == Approx(0.5));
+-    REQUIRE(closest_point.z() == Approx(0.));
++    REQUIRE_THAT(squared_distance, WithinRel(5. * 5.));
++    REQUIRE_THAT(closest_point.x(), WithinRel(0.3));
++    REQUIRE_THAT(closest_point.y(), WithinRel(0.5));
++    REQUIRE_THAT(closest_point.z(), WithinAbs(0., EPSILON));
+ 
+     squared_distance = AABBTreeIndirect::squared_distance_to_indexed_triangle_set(
+ 		tmesh.its.vertices, tmesh.its.indices,
+ 		tree,
+         Vec3d(0.3, 0.5, 5.),
+ 		hit_idx, closest_point);
+-    REQUIRE(squared_distance == Approx(4. * 4.));
+-    REQUIRE(closest_point.x() == Approx(0.3));
+-    REQUIRE(closest_point.y() == Approx(0.5));
+-    REQUIRE(closest_point.z() == Approx(1.));
++    REQUIRE_THAT(squared_distance, WithinRel(4. * 4.));
++    REQUIRE_THAT(closest_point.x(), WithinRel(0.3));
++    REQUIRE_THAT(closest_point.y(), WithinRel(0.5));
++    REQUIRE_THAT(closest_point.z(), WithinRel(1.));
+ }
+ 
+ TEST_CASE("Creating a several 2d lines, testing closest point query", "[AABBIndirect]")
+@@ -75,17 +79,17 @@ TEST_CASE("Creating a several 2d lines, 
+     Vec2d hit_point_out;
+     auto sqr_dist = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, Vec2d(0.0, 0.0), hit_idx_out,
+             hit_point_out);
+-    REQUIRE(sqr_dist == Approx(0.0));
++    REQUIRE_THAT(sqr_dist, WithinAbs(0.0, EPSILON));
+     REQUIRE((hit_idx_out == 0 || hit_idx_out == 3));
+-    REQUIRE(hit_point_out.x() == Approx(0.0));
+-    REQUIRE(hit_point_out.y() == Approx(0.0));
++    REQUIRE_THAT(hit_point_out.x(), WithinAbs(0.0, EPSILON));
++    REQUIRE_THAT(hit_point_out.y(), WithinAbs(0.0, EPSILON));
+ 
+     sqr_dist = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, Vec2d(1.5, 0.5), hit_idx_out,
+             hit_point_out);
+-    REQUIRE(sqr_dist == Approx(0.25));
++    REQUIRE_THAT(sqr_dist, WithinRel(0.25));
+     REQUIRE(hit_idx_out == 1);
+-    REQUIRE(hit_point_out.x() == Approx(1.0));
+-    REQUIRE(hit_point_out.y() == Approx(0.5));
++    REQUIRE_THAT(hit_point_out.x(), WithinRel(1.0));
++    REQUIRE_THAT(hit_point_out.y(), WithinRel(0.5));
+ }
+ 
+ TEST_CASE("Creating a several 2d lines, testing all lines in radius query", "[AABBIndirect]")
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__anyptr.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__anyptr.cpp
new file mode 100644
index 0000000000..2b04a6e4fb
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__anyptr.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_anyptr.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_anyptr.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <libslic3r/libslic3r.h>
+ #include <libslic3r/AnyPtr.hpp>
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__arachne.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__arachne.cpp
new file mode 100644
index 0000000000..b289234497
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__arachne.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_arachne.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_arachne.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/Arachne/WallToolPaths.hpp"
+ #include "libslic3r/ClipperUtils.hpp"
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__arc__welder.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__arc__welder.cpp
new file mode 100644
index 0000000000..c7de0b555b
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__arc__welder.cpp
@@ -0,0 +1,22 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_arc_welder.cpp.orig	2024-04-14 02:13:14.797323585 +0000
++++ tests/libslic3r/test_arc_welder.cpp
+@@ -1,4 +1,5 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_approx.hpp>
++#include <catch2/catch_test_macros.hpp>
+ #include <test_utils.hpp>
+ 
+ #include <random>
+@@ -9,6 +10,7 @@
+ #include <libslic3r/libslic3r.h>
+ 
+ using namespace Slic3r;
++using Catch::Approx;
+ 
+ TEST_CASE("arc basics", "[ArcWelder]") {
+     using namespace Slic3r::Geometry;
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__astar.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__astar.cpp
new file mode 100644
index 0000000000..81a77ba037
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__astar.cpp
@@ -0,0 +1,33 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_astar.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_astar.cpp
+@@ -1,4 +1,7 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_template_test_macros.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ 
+ #include "libslic3r/BoundingBox.hpp"
+ #include "libslic3r/AStar.hpp"
+@@ -6,6 +9,7 @@
+ #include "libslic3r/PointGrid.hpp"
+ 
+ using namespace Slic3r;
++using Catch::Matchers::WithinRel;
+ 
+ TEST_CASE("Testing basic invariants of AStar", "[AStar]") {
+     struct DummyTracer {
+@@ -397,7 +401,7 @@ TEST_CASE("Zero heuristic function shoul
+     // arrive to the source within less hops than the full number of nodes.
+     for (size_t i = 0, k = 0; i < graph.nodes.size(); ++i, k = 0) {
+         GraphTracer::QNode *q = &graph.nodes[i];
+-        REQUIRE(q->g == Approx(ref_distances[i]));
++        REQUIRE_THAT(q->g, WithinRel(ref_distances[i]));
+         while (k++ < graph.nodes.size() && q->parent != astar::Unassigned)
+             q = &graph.nodes[q->parent];
+ 
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__clipper__offset.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__clipper__offset.cpp
new file mode 100644
index 0000000000..2bb4ab6e73
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__clipper__offset.cpp
@@ -0,0 +1,113 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_clipper_offset.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_clipper_offset.cpp
+@@ -1,4 +1,6 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ 
+ #include <iostream>
+ #include <boost/filesystem.hpp>
+@@ -8,6 +10,7 @@
+ #include "libslic3r/SVG.hpp"
+ 
+ using namespace Slic3r;
++using Catch::Matchers::WithinRel;
+ 
+ // #define TESTS_EXPORT_SVGS
+ 
+@@ -32,7 +35,7 @@ SCENARIO("Constant offset", "[ClipperUti
+ #endif
+ 					THEN("Area is 22^2mm2") {
+ 						REQUIRE(output.size() == 1);
+-						REQUIRE(output.front().area() == Approx(22. * 22. * s * s));
++						REQUIRE_THAT(output.front().area(), WithinRel(22. * 22. * s * s));
+ 					}
+ 				}
+ 				DYNAMIC_SECTION("minus 1mm, miter " << miter << "x") {
+@@ -46,7 +49,7 @@ SCENARIO("Constant offset", "[ClipperUti
+ #endif
+ 					THEN("Area is 18^2mm2") {
+ 						REQUIRE(output.size() == 1);
+-						REQUIRE(output.front().area() == Approx(18. * 18. * s * s));
++						REQUIRE_THAT(output.front().area(), WithinRel(18. * 18. * s * s));
+ 					}
+ 				}
+ 			}
+@@ -64,7 +67,7 @@ SCENARIO("Constant offset", "[ClipperUti
+ #endif
+ 					THEN("Area is 22^2mm2") {
+ 						REQUIRE(output.size() == 1);
+-						REQUIRE(output.front().area() == Approx(22. * 22. * s * s));
++						REQUIRE_THAT(output.front().area(), WithinRel(22. * 22. * s * s));
+ 					}
+ 				}
+ 				DYNAMIC_SECTION("minus 1mm, miter " << miter << "x") {
+@@ -78,7 +81,7 @@ SCENARIO("Constant offset", "[ClipperUti
+ #endif
+ 					THEN("Area is 18^2mm2") {
+ 						REQUIRE(output.size() == 1);
+-						REQUIRE(output.front().area() == Approx(18. * 18. * s * s));
++						REQUIRE_THAT(output.front().area(), WithinRel(18. * 18. * s * s));
+ 					}
+ 				}
+ 			}
+@@ -106,7 +109,7 @@ SCENARIO("Constant offset", "[ClipperUti
+ #endif
+ 						THEN("Area is 22^2-8^2 mm2") {
+ 							REQUIRE(output.size() == 1);
+-							REQUIRE(output.front().area() == Approx((22. * 22. - 8. * 8.) * s * s));
++							REQUIRE_THAT(output.front().area(), WithinRel((22. * 22. - 8. * 8.) * s * s));
+ 						}
+ 					}
+ 					WHEN("minus 1mm") {
+@@ -120,7 +123,7 @@ SCENARIO("Constant offset", "[ClipperUti
+ #endif
+ 						THEN("Area is 18^2-12^2 mm2") {
+ 							REQUIRE(output.size() == 1);
+-							REQUIRE(output.front().area() == Approx((18. * 18. - 12. * 12.) * s * s));
++							REQUIRE_THAT(output.front().area(), WithinRel((18. * 18. - 12. * 12.) * s * s));
+ 						}
+ 					}
+ 				}
+@@ -140,7 +143,7 @@ SCENARIO("Constant offset", "[ClipperUti
+ #endif
+ 						THEN("Area is 22^2-8^2 mm2") {
+ 							REQUIRE(output.size() == 1);
+-							REQUIRE(output.front().area() == Approx((22. * 22. - 8. * 8.) * s * s));
++							REQUIRE_THAT(output.front().area(), WithinRel((22. * 22. - 8. * 8.) * s * s));
+ 						}
+ 					}
+ 					WHEN("minus 1mm") {
+@@ -154,7 +157,7 @@ SCENARIO("Constant offset", "[ClipperUti
+ #endif
+ 						THEN("Area is 18^2-12^2 mm2") {
+ 							REQUIRE(output.size() == 1);
+-							REQUIRE(output.front().area() == Approx((18. * 18. - 12. * 12.) * s * s));
++							REQUIRE_THAT(output.front().area(), WithinRel((18. * 18. - 12. * 12.) * s * s));
+ 						}
+ 					}
+ 				}
+@@ -186,7 +189,7 @@ SCENARIO("Constant offset", "[ClipperUti
+ #endif
+ 					THEN("Area matches") {
+ 						REQUIRE(output.size() == 1);
+-						REQUIRE(output.front().area() == Approx(area_offsetted));
++						REQUIRE_THAT(output.front().area(), WithinRel(area_offsetted, EPSILON));
+ 					}
+ 				}
+ 			}
+@@ -205,7 +208,7 @@ SCENARIO("Constant offset", "[ClipperUti
+ #endif
+ 					THEN("Area matches") {
+ 						REQUIRE(output.size() == 1);
+-						REQUIRE(output.front().area() == Approx(area_offsetted));
++						REQUIRE_THAT(output.front().area(), WithinRel(area_offsetted, EPSILON));
+ 					}
+ 				}
+ 			}
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__clipper__utils.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__clipper__utils.cpp
new file mode 100644
index 0000000000..baf1452fd6
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__clipper__utils.cpp
@@ -0,0 +1,139 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_clipper_utils.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_clipper_utils.cpp
+@@ -1,4 +1,6 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ 
+ #include <numeric>
+ #include <iostream>
+@@ -9,6 +11,7 @@
+ #include "libslic3r/SVG.hpp"
+ 
+ using namespace Slic3r;
++using Catch::Matchers::WithinRel;
+ 
+ SCENARIO("Various Clipper operations - xs/t/11_clipper.t", "[ClipperUtils]") {
+ 	// CCW oriented contour
+@@ -122,7 +125,7 @@ SCENARIO("Various Clipper operations - x
+ 			REQUIRE(result.size() == 1);
+ 		}
+ 		THEN("intersection_pl - result has same length as subject polyline") {
+-			REQUIRE(result.front().length() == Approx(subject.length()));
++			REQUIRE_THAT(result.front().length(), WithinRel(subject.length()));
+ 		}
+ 	}
+ 
+@@ -185,7 +188,7 @@ SCENARIO("Various Clipper operations - t
+                 ExPolygon match({ { 20, 18 }, { 10, 18 }, { 10, 12 }, { 20, 12 } },
+                                 { { 14, 16 }, { 16, 16 }, { 16, 14 }, { 14, 14 } });
+                 REQUIRE(intersection.size() == 1);
+-                REQUIRE(intersection.front().area() == Approx(match.area()));
++                REQUIRE_THAT(intersection.front().area(), WithinRel(match.area()));
+             }
+         }
+ 
+@@ -193,39 +196,39 @@ SCENARIO("Various Clipper operations - t
+         WHEN("Clipping line 1") {
+             Polylines intersection = intersection_pl({ Polyline { { 15, 18 }, { 15, 15 } } }, expolygons);
+             THEN("line is clipped to square with hole") {
+-                REQUIRE((Vec2f(15, 18) - Vec2f(15, 16)).norm() == Approx(intersection.front().length()));
++                REQUIRE_THAT((Vec2f(15, 18) - Vec2f(15, 16)).norm(), WithinRel(intersection.front().length()));
+             }
+         }
+         WHEN("Clipping line 2") {
+             Polylines intersection = intersection_pl({ Polyline { { 15, 15 }, { 15, 12 } } }, expolygons);
+             THEN("line is clipped to square with hole") {
+-                REQUIRE((Vec2f(15, 14) - Vec2f(15, 12)).norm() == Approx(intersection.front().length()));
++                REQUIRE_THAT((Vec2f(15, 14) - Vec2f(15, 12)).norm(), WithinRel(intersection.front().length()));
+             }
+         }
+         WHEN("Clipping line 3") {
+             Polylines intersection = intersection_pl({ Polyline { { 12, 18 }, { 18, 18 } } }, expolygons);
+             THEN("line is clipped to square with hole") {
+-                REQUIRE((Vec2f(18, 18) - Vec2f(12, 18)).norm() == Approx(intersection.front().length()));
++                REQUIRE_THAT((Vec2f(18, 18) - Vec2f(12, 18)).norm(), WithinRel(intersection.front().length()));
+             }
+         }
+         WHEN("Clipping line 4") {
+             Polylines intersection = intersection_pl({ Polyline { { 5, 15 }, { 30, 15 } } }, expolygons);
+             THEN("line is clipped to square with hole") {
+-                REQUIRE((Vec2f(14, 15) - Vec2f(10, 15)).norm() == Approx(intersection.front().length()));
+-                REQUIRE((Vec2f(20, 15) - Vec2f(16, 15)).norm() == Approx(intersection[1].length()));
++                REQUIRE_THAT((Vec2f(14, 15) - Vec2f(10, 15)).norm(), WithinRel(intersection.front().length()));
++                REQUIRE_THAT((Vec2f(20, 15) - Vec2f(16, 15)).norm(), WithinRel(intersection[1].length()));
+             }
+         }
+         WHEN("Clipping line 5") {
+             Polylines intersection = intersection_pl({ Polyline { { 30, 15 }, { 5, 15 } } }, expolygons);
+             THEN("reverse line is clipped to square with hole") {
+-                REQUIRE((Vec2f(20, 15) - Vec2f(16, 15)).norm() == Approx(intersection.front().length()));
+-                REQUIRE((Vec2f(14, 15) - Vec2f(10, 15)).norm() == Approx(intersection[1].length()));
++                REQUIRE_THAT((Vec2f(20, 15) - Vec2f(16, 15)).norm(), WithinRel(intersection.front().length()));
++                REQUIRE_THAT((Vec2f(14, 15) - Vec2f(10, 15)).norm(), WithinRel(intersection[1].length()));
+             }
+         }
+         WHEN("Clipping line 6") {
+             Polylines intersection = intersection_pl({ Polyline { { 10, 18 }, { 20, 18 } } }, expolygons);
+             THEN("tangent line is clipped to square with hole") {
+-                REQUIRE((Vec2f(20, 18) - Vec2f(10, 18)).norm() == Approx(intersection.front().length()));
++                REQUIRE_THAT((Vec2f(20, 18) - Vec2f(10, 18)).norm(), WithinRel(intersection.front().length()));
+             }
+         }
+     }
+@@ -246,7 +249,7 @@ SCENARIO("Various Clipper operations - t
+ 			ExPolygons diff = Slic3r::diff_ex(Polygons{ square, square2 }, Polygons{ hole });
+             THEN("difference of a cw from two ccw is a contour with one hole") {
+                 REQUIRE(diff.size() == 1);
+-                REQUIRE(diff.front().area() == Approx(ExPolygon({ {40, 40}, {0, 40}, {0, 0}, {40, 0} }, { {15, 25}, {25, 25}, {25, 15}, {15, 15} }).area()));
++                REQUIRE_THAT(diff.front().area(), WithinRel(ExPolygon({ {40, 40}, {0, 40}, {0, 0}, {40, 0} }, { {15, 25}, {25, 25}, {25, 15}, {15, 15} }).area()));
+             }
+         }
+     }
+@@ -296,8 +299,8 @@ SCENARIO("Various Clipper operations - t
+             auto line = Polyline::new_scale({ { 152.742,288.086671142818 }, { 152.742,34.166466971035 } });    
+             Polylines intersection = intersection_pl(line, to_polygons(circle_with_hole));
+             THEN("clipped to two pieces") {
+-                REQUIRE(intersection.front().length() == Approx((Vec2d(152742000, 215178843) - Vec2d(152742000, 288086661)).norm()));
+-                REQUIRE(intersection[1].length() == Approx((Vec2d(152742000, 35166477) - Vec2d(152742000, 108087507)).norm()));
++                REQUIRE_THAT(intersection.front().length(), WithinRel((Vec2d(152742000, 215178843) - Vec2d(152742000, 288086661)).norm()));
++                REQUIRE_THAT(intersection[1].length(), WithinRel((Vec2d(152742000, 35166477) - Vec2d(152742000, 108087507)).norm()));
+             }
+         }
+     }
+@@ -360,25 +363,25 @@ TEST_CASE("Traversing Clipper PolyTree",
+ 
+     SECTION("Traverse into Polygons WITHOUT spatial ordering") {
+         Polygons output;
+-        REQUIRE(area_sum == Approx(polytree_area(tree.GetFirst(), &output)));
++        REQUIRE_THAT(area_sum, WithinRel(polytree_area(tree.GetFirst(), &output)));
+         REQUIRE(output.size() == reference.size());
+     }
+     
+     SECTION("Traverse into ExPolygons WITHOUT spatial ordering") {
+         ExPolygons output;
+-        REQUIRE(area_sum == Approx(polytree_area(tree.GetFirst(), &output)));
++        REQUIRE_THAT(area_sum, WithinRel(polytree_area(tree.GetFirst(), &output)));
+         REQUIRE(count_polys(output) == reference.size());
+     }
+     
+     SECTION("Traverse into Polygons WITH spatial ordering") {
+         Polygons output;
+-        REQUIRE(area_sum == Approx(polytree_area<e_ordering::ON>(tree.GetFirst(), &output)));
++        REQUIRE_THAT(area_sum, WithinRel(polytree_area<e_ordering::ON>(tree.GetFirst(), &output)));
+         REQUIRE(output.size() == reference.size());
+     }
+     
+     SECTION("Traverse into ExPolygons WITH spatial ordering") {
+         ExPolygons output;
+-        REQUIRE(area_sum == Approx(polytree_area<e_ordering::ON>(tree.GetFirst(), &output)));
++        REQUIRE_THAT(area_sum, WithinRel(polytree_area<e_ordering::ON>(tree.GetFirst(), &output)));
+         REQUIRE(count_polys(output) == reference.size());
+     }
+ }
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__color.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__color.cpp
new file mode 100644
index 0000000000..10d0de7975
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__color.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_color.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_color.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ #include "libslic3r/libslic3r.h"
+ 
+ #include "libslic3r/Color.hpp"
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__config.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__config.cpp
new file mode 100644
index 0000000000..962e8efd73
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__config.cpp
@@ -0,0 +1,14 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_config.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_config.cpp
+@@ -1,4 +1,5 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers_vector.hpp>
+ 
+ #include "libslic3r/Config.hpp"
+ #include "libslic3r/PrintConfig.hpp"
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__curve__fitting.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__curve__fitting.cpp
new file mode 100644
index 0000000000..fd21f2d14b
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__curve__fitting.cpp
@@ -0,0 +1,56 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_curve_fitting.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_curve_fitting.cpp
+@@ -1,10 +1,14 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ #include <test_utils.hpp>
+ 
+ #include <libslic3r/Geometry/Curves.hpp>
+ #include <libslic3r/Utils.hpp>
+ #include <libslic3r/SVG.hpp>
+ 
++using Catch::Matchers::WithinRel;
++
+ TEST_CASE("Curves: cubic b spline fit test", "[Curves]") {
+     using namespace Slic3r;
+     using namespace Slic3r::Geometry;
+@@ -31,14 +35,11 @@ TEST_CASE("Curves: cubic b spline fit te
+ 
+     auto bspline = fit_cubic_bspline(observations, observation_points, weights, 1);
+ 
+-    Approx ap(1.0f);
+-    ap.epsilon(0.1f);
+-
+     for (int p = 0; p < 200; ++p) {
+         float fitted_val = bspline.get_fitted_value(fx(p))(0);
+         float expected = fy(p);
+ 
+-        REQUIRE(fitted_val == ap(expected));
++        REQUIRE_THAT(fitted_val, WithinRel(expected, 0.1f));
+ 
+     }
+ }
+@@ -106,13 +107,10 @@ TEST_CASE("Curves: polynomial fit test",
+     Vec2f fmin { fx(0), fy(0) };
+     Vec2f fmax { fx(200), fy(200) };
+ 
+-    Approx ap(1.0f);
+-    ap.epsilon(0.1f);
+-
+     auto poly = fit_polynomial(observations, observation_points, weights, 2);
+ 
+-    REQUIRE(poly.coefficients(0, 0) == ap(1));
+-    REQUIRE(poly.coefficients(0, 1) == ap(-2));
+-    REQUIRE(poly.coefficients(0, 2) == ap(1));
++    REQUIRE_THAT(poly.coefficients(0, 0), WithinRel(1, 0.1f));
++    REQUIRE_THAT(poly.coefficients(0, 1), WithinRel(-2, 0.1f));
++    REQUIRE_THAT(poly.coefficients(0, 2), WithinRel(1, 0.1f));
+ }
+ 
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__cut__surface.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__cut__surface.cpp
new file mode 100644
index 0000000000..8b4dbc125d
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__cut__surface.cpp
@@ -0,0 +1,20 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_cut_surface.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_cut_surface.cpp
+@@ -1,10 +1,10 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <libslic3r/CutSurface.hpp>
+ #include <libslic3r/TriangleMesh.hpp> // its_make_cube + its_merge
+ 
+ using namespace Slic3r;
+-TEST_CASE("Cut character from surface", "[]")
++TEST_CASE("Cut character from surface")
+ {
+     std::string font_path = std::string(TEST_DATA_DIR) +
+                             "/../../resources/fonts/NotoSans-Regular.ttf";
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__elephant__foot__compensation.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__elephant__foot__compensation.cpp
new file mode 100644
index 0000000000..cc38bf4fa5
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__elephant__foot__compensation.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_elephant_foot_compensation.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_elephant_foot_compensation.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <iostream>
+ #include <boost/filesystem.hpp>
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__emboss.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__emboss.cpp
new file mode 100644
index 0000000000..18130c1c6f
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__emboss.cpp
@@ -0,0 +1,31 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_emboss.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_emboss.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <libslic3r/Emboss.hpp>
+ #include <libslic3r/SVG.hpp> // only debug visualization
+@@ -412,7 +412,7 @@ TEST_CASE("ray segment intersection", "[
+     CHECK(abs(*t1 - *t2) < std::numeric_limits<double>::epsilon());
+ }
+ 
+-TEST_CASE("triangle intersection", "[]")
++TEST_CASE("triangle intersection")
+ {
+     Vec2d                point(1, 1);
+     Vec2d                dir(-1, 0);
+@@ -481,7 +481,7 @@ TEST_CASE("Italic check", "[Emboss]") 
+ #endif // FONT_DIR_PATH
+ 
+ #include "libslic3r/CutSurface.hpp"
+-TEST_CASE("Cut surface", "[]")
++TEST_CASE("Cut surface")
+ {
+     std::string  font_path  = get_font_filepath();
+     char         letter     = '%';
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__expolygon.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__expolygon.cpp
new file mode 100644
index 0000000000..05cfa14c9c
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__expolygon.cpp
@@ -0,0 +1,38 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_expolygon.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_expolygon.cpp
+@@ -1,10 +1,13 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ 
+ #include "libslic3r/Point.hpp"
+ #include "libslic3r/Polygon.hpp"
+ #include "libslic3r/ExPolygon.hpp"
+ 
+ using namespace Slic3r;
++using Catch::Matchers::WithinRel;
+ 
+ static inline bool points_close(const Point &p1, const Point &p2)
+ {
+@@ -30,7 +33,7 @@ SCENARIO("Basics", "[ExPolygon]") {
+             REQUIRE(expolygon.is_valid());
+         }
+         THEN("expolygon area") {
+-            REQUIRE(expolygon.area() == Approx(100*100-20*20));
++            REQUIRE_THAT(expolygon.area(), WithinRel(100.0*100-20*20));
+         }
+         WHEN("Expolygon scaled") {
+             ExPolygon expolygon2 = expolygon;
+@@ -160,4 +163,4 @@ TEST_CASE("Serialization of expolygons t
+     }
+ 
+     CHECK(expolys == expolys_loaded);
+-}
+\ No newline at end of file
++}
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__geometry.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__geometry.cpp
new file mode 100644
index 0000000000..b7ee4889d6
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__geometry.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_geometry.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_geometry.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/Point.hpp"
+ #include "libslic3r/BoundingBox.hpp"
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__hollowing.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__hollowing.cpp
new file mode 100644
index 0000000000..deb926a960
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__hollowing.cpp
@@ -0,0 +1,15 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_hollowing.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_hollowing.cpp
+@@ -1,6 +1,6 @@
+ #include <iostream>
+ #include <fstream>
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/SLA/Hollowing.hpp"
+ 
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__indexed__triangle__set.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__indexed__triangle__set.cpp
new file mode 100644
index 0000000000..f47891e6e3
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__indexed__triangle__set.cpp
@@ -0,0 +1,16 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_indexed_triangle_set.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_indexed_triangle_set.cpp
+@@ -1,6 +1,7 @@
+ #include <iostream>
+ #include <fstream>
+-#include <catch2/catch.hpp>
++#include <random>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/TriangleMesh.hpp"
+ 
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__jump__point__search.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__jump__point__search.cpp
new file mode 100644
index 0000000000..1217a10672
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__jump__point__search.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_jump_point_search.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_jump_point_search.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ #include "libslic3r/BoundingBox.hpp"
+ #include "libslic3r/JumpPointSearch.hpp"
+ 
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__kdtreeindirect.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__kdtreeindirect.cpp
new file mode 100644
index 0000000000..399a395671
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__kdtreeindirect.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_kdtreeindirect.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_kdtreeindirect.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/KDTreeIndirect.hpp"
+ #include "libslic3r/Execution/ExecutionSeq.hpp"
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__line.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__line.cpp
new file mode 100644
index 0000000000..87f2f1def7
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__line.cpp
@@ -0,0 +1,26 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_line.cpp.orig	2024-04-14 02:09:53.235169800 +0000
++++ tests/libslic3r/test_line.cpp
+@@ -2,7 +2,8 @@
+  * Ported from xs/t/10_line.t
+  */
+ 
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/generators/catch_generators.hpp>
+ #include <libslic3r/Line.hpp>
+ #include "test_utils.hpp"
+ 
+@@ -37,7 +38,7 @@ TEST_CASE("Parallel lines under angles",
+     CHECK(line.parallel_to(line.direction()));
+     INFO("Line is parallel to its direction + PI");
+     line.parallel_to(line.direction() + M_PI);
+-    INFO("line is parallel to its direction - PI")
++    INFO("line is parallel to its direction - PI");
+     line.parallel_to(line.direction() - M_PI);
+ 
+     SECTION("Line is parallel within epsilon") {
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__marchingsquares.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__marchingsquares.cpp
new file mode 100644
index 0000000000..a38691aac2
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__marchingsquares.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_marchingsquares.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_marchingsquares.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ #include <test_utils.hpp>
+ 
+ #include <fstream>
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__meshboolean.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__meshboolean.cpp
new file mode 100644
index 0000000000..81450ed51b
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__meshboolean.cpp
@@ -0,0 +1,31 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_meshboolean.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_meshboolean.cpp
+@@ -1,10 +1,13 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ #include <test_utils.hpp>
+ 
+ #include <libslic3r/TriangleMesh.hpp>
+ #include <libslic3r/MeshBoolean.hpp>
+ 
+ using namespace Slic3r;
++using Catch::Matchers::WithinRel;
+ 
+ TEST_CASE("CGAL and TriangleMesh conversions", "[MeshBoolean]") {
+     TriangleMesh sphere = make_sphere(1.);
+@@ -19,7 +22,7 @@ TEST_CASE("CGAL and TriangleMesh convers
+     REQUIRE(M.its.vertices.size() == sphere.its.vertices.size());
+     REQUIRE(M.its.indices.size() == sphere.its.indices.size());
+     
+-    REQUIRE(M.volume() == Approx(sphere.volume()));
++    REQUIRE_THAT(M.volume(), WithinRel(sphere.volume()));
+     
+     REQUIRE(! MeshBoolean::cgal::does_self_intersect(M));
+ }
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__mutable__polygon.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__mutable__polygon.cpp
new file mode 100644
index 0000000000..810369f2d1
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__mutable__polygon.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_mutable_polygon.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_mutable_polygon.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/Point.hpp"
+ #include "libslic3r/MutablePolygon.hpp"
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__mutable__priority__queue.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__mutable__priority__queue.cpp
new file mode 100644
index 0000000000..029dafea8e
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__mutable__priority__queue.cpp
@@ -0,0 +1,17 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_mutable_priority_queue.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_mutable_priority_queue.cpp
+@@ -1,6 +1,8 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
++#include <algorithm>
+ #include <queue>
++#include <random>
+ 
+ #include "libslic3r/MutablePriorityQueue.hpp"
+ 
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__optimizers.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__optimizers.cpp
new file mode 100644
index 0000000000..f1f3870e03
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__optimizers.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_optimizers.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_optimizers.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ #include <test_utils.hpp>
+ 
+ #include <libslic3r/Optimize/BruteforceOptimizer.hpp>
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__placeholder__parser.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__placeholder__parser.cpp
new file mode 100644
index 0000000000..8bd8d2720b
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__placeholder__parser.cpp
@@ -0,0 +1,83 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_placeholder_parser.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_placeholder_parser.cpp
+@@ -1,9 +1,13 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ 
+ #include "libslic3r/PlaceholderParser.hpp"
+ #include "libslic3r/PrintConfig.hpp"
+ 
+ using namespace Slic3r;
++using Catch::Matchers::WithinRel;
++using Catch::Matchers::WithinAbs;
+ 
+ SCENARIO("Placeholder parser scripting", "[PlaceholderParser]") {
+ 	PlaceholderParser 	parser;
+@@ -69,17 +73,17 @@ SCENARIO("Placeholder parser scripting",
+     SECTION("math: 2*3") { REQUIRE(parser.process("{2*3}") == "6"); }
+     SECTION("math: 2*3/6") { REQUIRE(parser.process("{2*3/6}") == "1"); }
+     SECTION("math: 2*3/12") { REQUIRE(parser.process("{2*3/12}") == "0"); }
+-    SECTION("math: 2.*3/12") { REQUIRE(std::stod(parser.process("{2.*3/12}")) == Approx(0.5)); }
+-    SECTION("math: 10 % 2.5") { REQUIRE(std::stod(parser.process("{10%2.5}")) == Approx(0.)); }
+-    SECTION("math: 11 % 2.5") { REQUIRE(std::stod(parser.process("{11%2.5}")) == Approx(1.)); }
++    SECTION("math: 2.*3/12") { REQUIRE_THAT(std::stod(parser.process("{2.*3/12}")), WithinRel(0.5)); }
++    SECTION("math: 10 % 2.5") { REQUIRE_THAT(std::stod(parser.process("{10%2.5}")), WithinAbs(0., EPSILON)); }
++    SECTION("math: 11 % 2.5") { REQUIRE_THAT(std::stod(parser.process("{11%2.5}")), WithinRel(1.)); }
+     SECTION("math: 2*(3-12)") { REQUIRE(parser.process("{2*(3-12)}") == "-18"); }
+     SECTION("math: 2*foo*(3-12)") { REQUIRE(parser.process("{2*foo*(3-12)}") == "0"); }
+     SECTION("math: 2*bar*(3-12)") { REQUIRE(parser.process("{2*bar*(3-12)}") == "-36"); }
+-    SECTION("math: 2.5*bar*(3-12)") { REQUIRE(std::stod(parser.process("{2.5*bar*(3-12)}")) == Approx(-45)); }
++    SECTION("math: 2.5*bar*(3-12)") { REQUIRE_THAT(std::stod(parser.process("{2.5*bar*(3-12)}")), WithinRel(-45.0)); }
+     SECTION("math: min(12, 14)") { REQUIRE(parser.process("{min(12, 14)}") == "12"); }
+     SECTION("math: max(12, 14)") { REQUIRE(parser.process("{max(12, 14)}") == "14"); }
+-    SECTION("math: min(13.4, -1238.1)") { REQUIRE(std::stod(parser.process("{min(13.4, -1238.1)}")) == Approx(-1238.1)); }
+-    SECTION("math: max(13.4, -1238.1)") { REQUIRE(std::stod(parser.process("{max(13.4, -1238.1)}")) == Approx(13.4)); }
++    SECTION("math: min(13.4, -1238.1)") { REQUIRE_THAT(std::stod(parser.process("{min(13.4, -1238.1)}")), WithinRel(-1238.1)); }
++    SECTION("math: max(13.4, -1238.1)") { REQUIRE_THAT(std::stod(parser.process("{max(13.4, -1238.1)}")), WithinRel(13.4)); }
+     SECTION("math: int(13.4)") { REQUIRE(parser.process("{int(13.4)}") == "13"); }
+     SECTION("math: int(-13.4)") { REQUIRE(parser.process("{int(-13.4)}") == "-13"); }
+     SECTION("math: round(13.4)") { REQUIRE(parser.process("{round(13.4)}") == "13"); }
+@@ -101,19 +105,19 @@ SCENARIO("Placeholder parser scripting",
+     SECTION("math: ternary3") { REQUIRE(parser.process("{12 == 13 ? 1 - 1 * unknown_symbol : 2 * 2}") == "4"); }
+     SECTION("math: ternary4") { REQUIRE(parser.process("{12 == 2 * 6 ? 1 - 1 : 2 * unknown_symbol}") == "0"); }
+     SECTION("math: ternary nested") { REQUIRE(parser.process("{12 == 2 * 6 ? 3 - 1 != 2 ? does_not_exist : 0 * 0 - 0 / 1 + 12345 : bull ? 3 - cokoo : 2 * unknown_symbol}") == "12345"); }
+-    SECTION("math: interpolate_table(13.84375892476, (0, 0), (20, 20))") { REQUIRE(std::stod(parser.process("{interpolate_table(13.84375892476, (0, 0), (20, 20))}")) == Approx(13.84375892476)); }
+-    SECTION("math: interpolate_table(13, (0, 0), (20, 20), (30, 20))") { REQUIRE(std::stod(parser.process("{interpolate_table(13, (0, 0), (20, 20), (30, 20))}")) == Approx(13.)); }
+-    SECTION("math: interpolate_table(25, (0, 0), (20, 20), (30, 20))") { REQUIRE(std::stod(parser.process("{interpolate_table(25, (0, 0), (20, 20), (30, 20))}")) == Approx(20.)); }
++    SECTION("math: interpolate_table(13.84375892476, (0, 0), (20, 20))") { REQUIRE_THAT(std::stod(parser.process("{interpolate_table(13.84375892476, (0, 0), (20, 20))}")), WithinRel(13.84375892476, EPSILON)); }
++    SECTION("math: interpolate_table(13, (0, 0), (20, 20), (30, 20))") { REQUIRE_THAT(std::stod(parser.process("{interpolate_table(13, (0, 0), (20, 20), (30, 20))}")), WithinRel(13.)); }
++    SECTION("math: interpolate_table(25, (0, 0), (20, 20), (30, 20))") { REQUIRE_THAT(std::stod(parser.process("{interpolate_table(25, (0, 0), (20, 20), (30, 20))}")), WithinRel(20.)); }
+ 
+     // Test the "coFloatOrPercent" and "xxx_extrusion_width" substitutions.
+     // first_layer_extrusion_width ratio_over first_layer_heigth.
+-    SECTION("perimeter_extrusion_width") { REQUIRE(std::stod(parser.process("{perimeter_extrusion_width}")) == Approx(0.67500001192092896)); }
+-    SECTION("first_layer_extrusion_width") { REQUIRE(std::stod(parser.process("{first_layer_extrusion_width}")) == Approx(0.9)); }
+-    SECTION("support_material_xy_spacing") { REQUIRE(std::stod(parser.process("{support_material_xy_spacing}")) == Approx(0.3375)); }
++    SECTION("perimeter_extrusion_width") { REQUIRE_THAT(std::stod(parser.process("{perimeter_extrusion_width}")), WithinRel(0.67500001192092896, EPSILON)); }
++    SECTION("first_layer_extrusion_width") { REQUIRE_THAT(std::stod(parser.process("{first_layer_extrusion_width}")), WithinRel(0.9)); }
++    SECTION("support_material_xy_spacing") { REQUIRE_THAT(std::stod(parser.process("{support_material_xy_spacing}")), WithinRel(0.3375)); }
+     // external_perimeter_speed over perimeter_speed
+-    SECTION("external_perimeter_speed") { REQUIRE(std::stod(parser.process("{external_perimeter_speed}")) == Approx(30.)); }
++    SECTION("external_perimeter_speed") { REQUIRE_THAT(std::stod(parser.process("{external_perimeter_speed}")), WithinRel(30.)); }
+     // infill_overlap over perimeter_extrusion_width
+-    SECTION("infill_overlap") { REQUIRE(std::stod(parser.process("{infill_overlap}")) == Approx(0.16875)); }
++    SECTION("infill_overlap") { REQUIRE_THAT(std::stod(parser.process("{infill_overlap}")), WithinRel(0.16875)); }
+     // If first_layer_speed is set to percent, then it is applied over respective extrusion types by overriding their respective speeds.
+     // The PlaceholderParser has no way to know which extrusion type the caller has in mind, therefore it throws.
+     SECTION("first_layer_speed") { REQUIRE_THROWS(parser.process("{first_layer_speed}")); }
+@@ -173,7 +177,7 @@ SCENARIO("Placeholder parser scripting",
+         DynamicConfig config_outputs;
+         config_outputs.set_key_value("writable_floats", new ConfigOptionFloats({ 0., 0., 0. }));
+         parser.process("{writable_floats[1] = 33}", 0, nullptr, &config_outputs, nullptr);
+-        REQUIRE(config_outputs.opt_float("writable_floats", 1) == Approx(33.));
++        REQUIRE_THAT(config_outputs.opt_float("writable_floats", 1), WithinRel(33.));
+     }
+ }
+ 
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__png__io.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__png__io.cpp
new file mode 100644
index 0000000000..1614fd65fa
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__png__io.cpp
@@ -0,0 +1,16 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_png_io.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_png_io.cpp
+@@ -2,7 +2,7 @@
+ #define NOMINMAX
+ #endif
+ 
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <numeric>
+ 
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__point.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__point.cpp
new file mode 100644
index 0000000000..5557b26ee1
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__point.cpp
@@ -0,0 +1,22 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_point.cpp.orig	2024-04-14 02:13:14.912947878 +0000
++++ tests/libslic3r/test_point.cpp
+@@ -5,11 +5,13 @@
+  *  and cross product uses doubles
+  */
+ 
+-#include <catch2/catch.hpp>
++#include <catch2/catch_approx.hpp>
++#include <catch2/catch_test_macros.hpp>
+ #include <libslic3r/Point.hpp>
+ #include "test_utils.hpp"
+ 
+ using namespace Slic3r;
++using Catch::Approx;
+ 
+ TEST_CASE("Nearest point", "[Point]") {
+     const Point point{10, 15};
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__polygon.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__polygon.cpp
new file mode 100644
index 0000000000..f72048b652
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__polygon.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_polygon.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_polygon.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/Point.hpp"
+ #include "libslic3r/Polygon.hpp"
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__polyline.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__polyline.cpp
new file mode 100644
index 0000000000..8a95b25974
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__polyline.cpp
@@ -0,0 +1,16 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_polyline.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_polyline.cpp
+@@ -1,7 +1,7 @@
+ /**
+ * Ported from xs/t/09_polyline.t
+ */
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/Point.hpp"
+ #include "libslic3r/Polyline.hpp"
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__quadric__edge__collapse.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__quadric__edge__collapse.cpp
new file mode 100644
index 0000000000..7c714e3de7
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__quadric__edge__collapse.cpp
@@ -0,0 +1,22 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_quadric_edge_collapse.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_quadric_edge_collapse.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ #include <test_utils.hpp>
+ 
+ #include <libslic3r/QuadricEdgeCollapse.hpp>
+@@ -240,7 +240,7 @@ TEST_CASE("Simplify frog_legs.obj to 5% 
+ }
+ 
+ #include <libigl/igl/qslim.h>
+-TEST_CASE("Simplify frog_legs.obj to 5% by IGL/qslim", "[]")
++TEST_CASE("Simplify frog_legs.obj to 5% by IGL/qslim")
+ {
+     std::string  obj_filename    = "frog_legs.obj";
+     TriangleMesh mesh            = load_model(obj_filename);
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__region__expansion.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__region__expansion.cpp
new file mode 100644
index 0000000000..89f7b68325
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__region__expansion.cpp
@@ -0,0 +1,63 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_region_expansion.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_region_expansion.cpp
+@@ -1,4 +1,6 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ 
+ #include <libslic3r/libslic3r.h>
+ #include <libslic3r/Algorithm/RegionExpansion.hpp>
+@@ -8,6 +10,7 @@
+ #include <libslic3r/SVG.cpp>
+ 
+ using namespace Slic3r;
++using Catch::Matchers::WithinRel;
+ 
+ //#define DEBUG_TEMP_DIR "d:\\temp\\"
+ 
+@@ -27,7 +30,7 @@ SCENARIO("Region expansion basics", "[Re
+                 REQUIRE(expanded.size() == 1);
+             }
+             THEN("The area of the anchor is 10mm2") {
+-                REQUIRE(area(expanded.front()) == Approx(expansion * ten));
++                REQUIRE_THAT(area(expanded.front()), WithinRel(expansion * ten));
+             }
+         };
+ 
+@@ -61,8 +64,8 @@ SCENARIO("Region expansion basics", "[Re
+                 REQUIRE(expanded.front().size() == 2);
+             }
+             THEN("The area of each anchor is 10mm2") {
+-                REQUIRE(area(expanded.front().front()) == Approx(expansion * ten));
+-                REQUIRE(area(expanded.front().back()) == Approx(expansion * ten));
++                REQUIRE_THAT(area(expanded.front().front()), WithinRel(expansion * ten));
++                REQUIRE_THAT(area(expanded.front().back()), WithinRel(expansion * ten));
+             }
+         }
+ 
+@@ -77,8 +80,8 @@ SCENARIO("Region expansion basics", "[Re
+                 REQUIRE(expanded.front().size() == 2);
+             }
+             THEN("The area of each anchor is 100mm2") {
+-                REQUIRE(area(expanded.front().front()) == Approx(sqr<double>(ten)));
+-                REQUIRE(area(expanded.front().back()) == Approx(sqr<double>(ten)));
++                REQUIRE_THAT(area(expanded.front().front()), WithinRel(sqr<double>(ten)));
++                REQUIRE_THAT(area(expanded.front().back()), WithinRel(sqr<double>(ten)));
+             }
+         }
+     }
+@@ -247,7 +250,7 @@ SCENARIO("Region expansion basics", "[Re
+             THEN("The anchor expands into a single region with two holes, fully covering the boundary") {
+                 REQUIRE(expanded.size() == 1);
+                 REQUIRE(expanded.front().size() == 3);
+-                REQUIRE(area(expanded.front()) == Approx(area(boundary)));
++                REQUIRE_THAT(area(expanded.front()), WithinRel(area(boundary)));
+             }
+         }
+     }
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__static__map.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__static__map.cpp
new file mode 100644
index 0000000000..c3c474ef91
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__static__map.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_static_map.cpp.orig	2024-04-14 02:13:14.943711298 +0000
++++ tests/libslic3r/test_static_map.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ #include <string_view>
+ 
+ #include "libslic3r/StaticMap.hpp"
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__stl.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__stl.cpp
new file mode 100644
index 0000000000..c2b0f4419e
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__stl.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_stl.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_stl.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/Model.hpp"
+ #include "libslic3r/Format/STL.hpp"
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__support__spots__generator.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__support__spots__generator.cpp
new file mode 100644
index 0000000000..8da1bad740
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__support__spots__generator.cpp
@@ -0,0 +1,22 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_support_spots_generator.cpp.orig	2024-04-14 02:13:14.959463307 +0000
++++ tests/libslic3r/test_support_spots_generator.cpp
+@@ -1,9 +1,13 @@
+ #include "libslic3r/Point.hpp"
+-#include <catch2/catch.hpp>
++#include <catch2/catch_approx.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ #include <libslic3r/SupportSpotsGenerator.hpp>
+ 
+ using namespace Slic3r;
+ using namespace SupportSpotsGenerator;
++using Catch::Approx;
+ 
+ namespace Rectangle {
+ const float width = 10;
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__surface__mesh.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__surface__mesh.cpp
new file mode 100644
index 0000000000..100250c001
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__surface__mesh.cpp
@@ -0,0 +1,21 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_surface_mesh.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_surface_mesh.cpp
+@@ -1,10 +1,12 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_approx.hpp>
++#include <catch2/catch_test_macros.hpp>
+ #include <test_utils.hpp>
+ 
+ 
+ #include <libslic3r/SurfaceMesh.hpp>
+ 
+ using namespace Slic3r;
++using Catch::Approx;
+ 
+ 
+ // Generate a broken cube mesh. Face 8 is inverted, face 11 is missing.
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__timeutils.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__timeutils.cpp
new file mode 100644
index 0000000000..e79b84c5cb
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__timeutils.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_timeutils.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_timeutils.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/Time.hpp"
+ 
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__triangulation.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__triangulation.cpp
new file mode 100644
index 0000000000..89951038ed
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__triangulation.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_triangulation.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_triangulation.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <libslic3r/Triangulation.hpp>
+ #include <libslic3r/SVG.hpp> // only debug visualization
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__utils.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__utils.cpp
new file mode 100644
index 0000000000..a9bbd880c5
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__utils.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_utils.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_utils.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/libslic3r.h"
+ 
diff --git a/prusaslicer/patches/patch-tests_libslic3r_test__voronoi.cpp b/prusaslicer/patches/patch-tests_libslic3r_test__voronoi.cpp
new file mode 100644
index 0000000000..8b6d1aa433
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_libslic3r_test__voronoi.cpp
@@ -0,0 +1,33 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/libslic3r/test_voronoi.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/libslic3r/test_voronoi.cpp
+@@ -1,4 +1,6 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ #include <test_utils.hpp>
+ 
+ #include <libslic3r/Polygon.hpp>
+@@ -25,6 +27,8 @@ using namespace Slic3r;
+ 
+ using VD = Geometry::VoronoiDiagram;
+ 
++using Catch::Matchers::WithinRel;
++
+ // https://svn.boost.org/trac10/ticket/12067
+ // This bug seems to be confirmed.
+ // Vojtech supposes that there may be no Voronoi edges produced for
+@@ -69,7 +73,7 @@ TEST_CASE("Voronoi missing edges - point
+         vd, pts, Lines());
+ #endif
+ 
+-//    REQUIRE(closest_point.z() == Approx(1.));
++//    REQUIRE_THAT(closest_point.z(), WithinRel(1.));
+ }
+ 
+ // https://svn.boost.org/trac10/ticket/12707
diff --git a/prusaslicer/patches/patch-tests_sla__print_sla__archive__readwrite__tests.cpp b/prusaslicer/patches/patch-tests_sla__print_sla__archive__readwrite__tests.cpp
new file mode 100644
index 0000000000..1d724ddb2f
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_sla__print_sla__archive__readwrite__tests.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/sla_print/sla_archive_readwrite_tests.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/sla_print/sla_archive_readwrite_tests.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ #include <test_utils.hpp>
+ 
+ #include "libslic3r/SLAPrint.hpp"
diff --git a/prusaslicer/patches/patch-tests_sla__print_sla__print__tests.cpp b/prusaslicer/patches/patch-tests_sla__print_sla__print__tests.cpp
new file mode 100644
index 0000000000..db3c459f9e
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_sla__print_sla__print__tests.cpp
@@ -0,0 +1,34 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/sla_print/sla_print_tests.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/sla_print/sla_print_tests.cpp
+@@ -9,6 +9,8 @@
+ #include <libslic3r/SLA/SupportTreeMesher.hpp>
+ #include <libslic3r/BranchingTree/PointCloud.hpp>
+ 
++using Catch::Matchers::WithinRel;
++
+ namespace {
+ 
+ const char *const BELOW_PAD_TEST_OBJECTS[] = {
+@@ -194,8 +196,8 @@ TEST_CASE("InitializedRasterShouldBeNONE
+     sla::RasterGrayscaleAAGammaPower raster(res, pixdim, {}, 1.);
+     REQUIRE(raster.resolution().width_px == res.width_px);
+     REQUIRE(raster.resolution().height_px == res.height_px);
+-    REQUIRE(raster.pixel_dimensions().w_mm == Approx(pixdim.w_mm));
+-    REQUIRE(raster.pixel_dimensions().h_mm == Approx(pixdim.h_mm));
++    REQUIRE_THAT(raster.pixel_dimensions().w_mm, WithinRel(pixdim.w_mm));
++    REQUIRE_THAT(raster.pixel_dimensions().h_mm, WithinRel(pixdim.h_mm));
+ }
+ 
+ TEST_CASE("MirroringShouldBeCorrect", "[SLARasterOutput]") {
+@@ -269,5 +271,5 @@ TEST_CASE("Test concurrency")
+ 
+     double s = execution::accumulate(ex_tbb, vals.begin(), vals.end(), 0.);
+ 
+-    REQUIRE(s == Approx(ref));
++    REQUIRE_THAT(s, WithinRel(ref));
+ }
diff --git a/prusaslicer/patches/patch-tests_sla__print_sla__raycast__tests.cpp b/prusaslicer/patches/patch-tests_sla__print_sla__raycast__tests.cpp
new file mode 100644
index 0000000000..9a2ae74acb
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_sla__print_sla__raycast__tests.cpp
@@ -0,0 +1,65 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/sla_print/sla_raycast_tests.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/sla_print/sla_raycast_tests.cpp
+@@ -1,4 +1,6 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ #include <test_utils.hpp>
+ 
+ #include <libslic3r/AABBMesh.hpp>
+@@ -6,6 +8,8 @@
+ 
+ #include "sla_test_utils.hpp"
+ 
++using Catch::Matchers::WithinRel;
++
+ using namespace Slic3r;
+ 
+ // First do a simple test of the hole raycaster.
+@@ -20,8 +24,8 @@ TEST_CASE("Raycaster - find intersection
+     s = {-1.f, 0, 5.f};
+     dir = {1.f, 0, 0};
+     hole.get_intersections(s, dir, out);
+-    REQUIRE(out[0].first == Approx(-4.f));
+-    REQUIRE(out[1].first == Approx(6.f));
++    REQUIRE_THAT(out[0].first, WithinRel(-4.f));
++    REQUIRE_THAT(out[1].first, WithinRel(6.f));
+ 
+     // Start outside and cast parallel to axis.
+     s = {0, 0, -1.f};
+@@ -70,25 +74,25 @@ TEST_CASE("Raycaster with loaded drillho
+     Vec3d s = center.cast<double>();
+     // Fire from center, should hit the interior wall
+     auto hit = emesh.query_ray_hit(s, {0, 1., 0.});
+-    REQUIRE(hit.distance() == Approx(boxbb.size().x() / 2 - hcfg.min_thickness));
++    REQUIRE_THAT(hit.distance(), WithinRel(boxbb.size().x() / 2 - hcfg.min_thickness));
+     
+     // Fire upward from hole center, hit distance equals the radius (hits the
+     // side of the hole cut.
+     s.y() = hcfg.min_thickness / 2;
+     hit = emesh.query_ray_hit(s, {0, 0., 1.});
+-    REQUIRE(hit.distance() == Approx(radius));
++    REQUIRE_THAT(hit.distance(), WithinRel(radius));
+ 
+     // Fire from outside, hit the back side of the cube interior
+     s.y() = -1.;
+     hit = emesh.query_ray_hit(s, {0, 1., 0.});
+-    REQUIRE(hit.distance() == Approx(boxbb.max.y() - hcfg.min_thickness - s.y()));
++    REQUIRE_THAT(hit.distance(), WithinRel(boxbb.max.y() - hcfg.min_thickness - s.y()));
+     
+     // Fire downwards from above the hole cylinder. Has to go through the cyl.
+     // as it was not there.
+     s = center.cast<double>();
+     s.z() = boxbb.max.z() - hcfg.min_thickness - 1.;
+     hit = emesh.query_ray_hit(s, {0, 0., -1.});
+-    REQUIRE(hit.distance() == Approx(s.z() - boxbb.min.z() - hcfg.min_thickness));
++    REQUIRE_THAT(hit.distance(), WithinRel(s.z() - boxbb.min.z() - hcfg.min_thickness));
+ 
+     // Check for support tree correctness
+     test_support_model_collision("20mm_cube.obj", {}, hcfg, holes);
diff --git a/prusaslicer/patches/patch-tests_sla__print_sla__supptgen__tests.cpp b/prusaslicer/patches/patch-tests_sla__print_sla__supptgen__tests.cpp
new file mode 100644
index 0000000000..2114518eb6
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_sla__print_sla__supptgen__tests.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/sla_print/sla_supptgen_tests.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/sla_print/sla_supptgen_tests.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ #include <test_utils.hpp>
+ 
+ #include <libslic3r/ExPolygon.hpp>
diff --git a/prusaslicer/patches/patch-tests_sla__print_sla__supptreeutils__tests.cpp b/prusaslicer/patches/patch-tests_sla__print_sla__supptreeutils__tests.cpp
new file mode 100644
index 0000000000..c0acfac3be
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_sla__print_sla__supptreeutils__tests.cpp
@@ -0,0 +1,72 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/sla_print/sla_supptreeutils_tests.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/sla_print/sla_supptreeutils_tests.cpp
+@@ -1,4 +1,6 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ #include <test_utils.hpp>
+ 
+ #include <unordered_set>
+@@ -7,6 +9,9 @@
+ #include "libslic3r/SLA/SupportTreeUtils.hpp"
+ #include "libslic3r/SLA/SupportTreeUtilsLegacy.hpp"
+ 
++using Catch::Matchers::WithinRel;
++using Catch::Matchers::WithinAbs;
++
+ // Test pair hash for 'nums' random number pairs.
+ template <class I, class II> void test_pairhash()
+ {
+@@ -99,7 +104,7 @@ static void eval_ground_conn(const Slic3
+     REQUIRE(conn.path.back().r < conn.pillar_base->r_top);
+ 
+     // The end radius and the pillar base's upper radius should match
+-    REQUIRE(conn.pillar_base->r_top == Approx(end_r));
++    REQUIRE_THAT(conn.pillar_base->r_top, WithinRel(end_r));
+ }
+ 
+ TEST_CASE("Pillar search dumb case", "[suptreeutils]") {
+@@ -119,7 +124,7 @@ TEST_CASE("Pillar search dumb case", "[s
+ 
+         REQUIRE(conn);
+ //        REQUIRE(conn.path.size() == 1);
+-        REQUIRE(conn.pillar_base->pos.z() == Approx(ground_level(sm)));
++        REQUIRE_THAT(conn.pillar_base->pos.z(), WithinRel(ground_level(sm)));
+     }
+ 
+     SECTION("with zero R source and destination") {
+@@ -134,8 +139,8 @@ TEST_CASE("Pillar search dumb case", "[s
+ 
+         REQUIRE(conn);
+ //        REQUIRE(conn.path.size() == 1);
+-        REQUIRE(conn.pillar_base->pos.z() == Approx(ground_level(sm)));
+-        REQUIRE(conn.pillar_base->r_top == Approx(0.));
++        REQUIRE_THAT(conn.pillar_base->pos.z(), WithinRel(ground_level(sm)));
++        REQUIRE_THAT(conn.pillar_base->r_top, WithinAbs(0., EPSILON));
+     }
+ 
+     SECTION("with zero init direction") {
+@@ -150,7 +155,7 @@ TEST_CASE("Pillar search dumb case", "[s
+ 
+         REQUIRE(conn);
+ //        REQUIRE(conn.path.size() == 1);
+-        REQUIRE(conn.pillar_base->pos.z() == Approx(ground_level(sm)));
++        REQUIRE_THAT(conn.pillar_base->pos.z(), WithinRel(ground_level(sm)));
+     }
+ }
+ 
+@@ -278,7 +283,7 @@ TEST_CASE("Find ground route just above 
+ 
+     REQUIRE(conn);
+ 
+-    REQUIRE(conn.pillar_base->pos.z() >= Approx(ground_level(sm)));
++    REQUIRE(conn.pillar_base->pos.z() >= ground_level(sm));
+ }
+ 
+ TEST_CASE("BranchingSupports::MergePointFinder", "[suptreeutils]") {
diff --git a/prusaslicer/patches/patch-tests_sla__print_sla__test__utils.cpp b/prusaslicer/patches/patch-tests_sla__print_sla__test__utils.cpp
new file mode 100644
index 0000000000..05ed2933e2
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_sla__print_sla__test__utils.cpp
@@ -0,0 +1,63 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/sla_print/sla_test_utils.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/sla_print/sla_test_utils.cpp
+@@ -6,6 +6,8 @@
+ 
+ #include <iomanip>
+ 
++using Catch::Matchers::WithinRel;
++
+ void test_support_model_collision(
+     const std::string            &obj_filename,
+     const sla::SupportTreeConfig &input_supportcfg,
+@@ -182,7 +184,7 @@ void test_supports(const std::string    
+         allowed_zmin = zmin - 2 * supportcfg.head_back_radius_mm;
+ 
+ #ifndef NDEBUG
+-    if (!(obb.min.z() >= Approx(allowed_zmin)) || !(obb.max.z() <= Approx(zmax)))
++    if (!(obb.min.z() >= allowed_zmin) || !(obb.max.z() <= zmax))
+     {
+         indexed_triangle_set its;
+         treebuilder.retrieve_full_mesh(its);
+@@ -193,8 +195,8 @@ void test_supports(const std::string    
+     }
+ #endif
+ 
+-    REQUIRE(obb.min.z() >= Approx(allowed_zmin));
+-    REQUIRE(obb.max.z() <= Approx(zmax));
++    REQUIRE(obb.min.z() >= allowed_zmin);
++    REQUIRE(obb.max.z() <= zmax);
+ 
+     // Move out the support tree into the byproducts, we can examine it further
+     // in various tests.
+@@ -240,7 +242,7 @@ void check_support_tree_integrity(const 
+     };
+     
+     for (auto &bridge : stree.bridges()) chck_bridge(bridge, max_bridgelen);
+-    REQUIRE(max_bridgelen <= Approx(cfg.max_bridge_length_mm));
++    REQUIRE(max_bridgelen <= cfg.max_bridge_length_mm);
+     
+     max_bridgelen = 0;
+     for (auto &bridge : stree.crossbridges()) chck_bridge(bridge, max_bridgelen);
+@@ -272,7 +274,7 @@ void test_pad(const std::string &obj_fil
+     check_validity(out.mesh);
+     
+     auto bb = out.mesh.bounding_box();
+-    REQUIRE(bb.max.z() - bb.min.z() == Approx(padcfg.full_height()));
++    REQUIRE_THAT(bb.max.z() - bb.min.z(), WithinRel(padcfg.full_height()));
+ }
+ 
+ static void _test_concave_hull(const Polygons &hull, const ExPolygons &polys)
+@@ -285,7 +287,7 @@ static void _test_concave_hull(const Pol
+     double cchull_area = 0;
+     for (const Slic3r::Polygon &p : hull) cchull_area += p.area();
+     
+-    REQUIRE(cchull_area >= Approx(polys_area));
++    REQUIRE(cchull_area >= polys_area);
+     
+     size_t cchull_holes = 0;
+     for (const Slic3r::Polygon &p : hull)
diff --git a/prusaslicer/patches/patch-tests_sla__print_sla__test__utils.hpp b/prusaslicer/patches/patch-tests_sla__print_sla__test__utils.hpp
new file mode 100644
index 0000000000..6e6f9651ee
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_sla__print_sla__test__utils.hpp
@@ -0,0 +1,18 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/sla_print/sla_test_utils.hpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/sla_print/sla_test_utils.hpp
+@@ -1,7 +1,9 @@
+ #ifndef SLA_TEST_UTILS_HPP
+ #define SLA_TEST_UTILS_HPP
+ 
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ #include <test_utils.hpp>
+ 
+ // Debug
diff --git a/prusaslicer/patches/patch-tests_slic3rutils_slic3r__arrangejob__tests.cpp b/prusaslicer/patches/patch-tests_slic3rutils_slic3r__arrangejob__tests.cpp
new file mode 100644
index 0000000000..1d9e8d5013
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_slic3rutils_slic3r__arrangejob__tests.cpp
@@ -0,0 +1,53 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/slic3rutils/slic3r_arrangejob_tests.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/slic3rutils/slic3r_arrangejob_tests.cpp
+@@ -1,4 +1,6 @@
+-#include "catch2/catch.hpp"
++#include <catch2/catch_template_test_macros.hpp>
++#include <catch2/matchers/catch_matchers.hpp>
++#include <catch2/matchers/catch_matchers_floating_point.hpp>
+ #include "test_utils.hpp"
+ 
+ #include <random>
+@@ -13,6 +15,8 @@
+ 
+ #include "libslic3r/Format/3mf.hpp"
+ 
++using Catch::Matchers::WithinRel;
++
+ class RandomArrangeSettings: public Slic3r::arr2::ArrangeSettingsView {
+     Slic3r::arr2::ArrangeSettingsDb::Values m_v;
+ 
+@@ -143,7 +147,7 @@ TEST_CASE("Basic arrange with cube", "[a
+             std::swap(sz.x(), sz.y());
+ 
+         double d_obj = settings.get_distance_from_objects();
+-        REQUIRE(sz.y() == Approx(2. * bb1.size().y() + d_obj));
++        REQUIRE_THAT(sz.y(), WithinRel(2. * bb1.size().y() + d_obj, EPSILON));
+     }
+ 
+     SECTION("Selected cube (different object), needs to go beside existing") {
+@@ -177,7 +181,7 @@ TEST_CASE("Basic arrange with cube", "[a
+             std::swap(sz.x(), sz.y());
+ 
+         double d_obj = settings.get_distance_from_objects();
+-        REQUIRE(sz.y() == Approx(2. * bb1.size().y() + d_obj));
++        REQUIRE_THAT(sz.y(), WithinRel(2. * bb1.size().y() + d_obj, EPSILON));
+     }
+ 
+     SECTION("Four cubes needs to touch each other after arrange") {
+@@ -229,8 +233,8 @@ TEST_CASE("Basic arrange with cube", "[a
+         REQUIRE(c == bounding_box(bed).center());
+ 
+         float d_obj = settings.get_distance_from_objects();
+-        REQUIRE(pilebb.size().x() == Approx(2. * 20. + d_obj));
+-        REQUIRE(pilebb.size().y() == Approx(2. * 20. + d_obj));
++        REQUIRE_THAT(pilebb.size().x(), WithinRel(2. * 20. + d_obj));
++        REQUIRE_THAT(pilebb.size().y(), WithinRel(2. * 20. + d_obj));
+     }
+ }
+ 
diff --git a/prusaslicer/patches/patch-tests_slic3rutils_slic3r__jobs__tests.cpp b/prusaslicer/patches/patch-tests_slic3rutils_slic3r__jobs__tests.cpp
new file mode 100644
index 0000000000..35f09ad037
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_slic3rutils_slic3r__jobs__tests.cpp
@@ -0,0 +1,14 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/slic3rutils/slic3r_jobs_tests.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/slic3rutils/slic3r_jobs_tests.cpp
+@@ -1,4 +1,5 @@
+-#include "catch2/catch.hpp"
++#include <catch2/catch_template_test_macros.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include <chrono>
+ #include <thread>
diff --git a/prusaslicer/patches/patch-tests_slic3rutils_slic3r__version__tests.cpp b/prusaslicer/patches/patch-tests_slic3rutils_slic3r__version__tests.cpp
new file mode 100644
index 0000000000..ba6ae8817b
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_slic3rutils_slic3r__version__tests.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/slic3rutils/slic3r_version_tests.cpp.orig	2024-02-29 13:03:32.000000000 +0000
++++ tests/slic3rutils/slic3r_version_tests.cpp
+@@ -1,4 +1,4 @@
+-#include "catch2/catch.hpp"
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "slic3r/Config/Version.hpp"
+ 
diff --git a/prusaslicer/patches/patch-tests_thumbnails_test__thumbnails__ini__string.cpp b/prusaslicer/patches/patch-tests_thumbnails_test__thumbnails__ini__string.cpp
new file mode 100644
index 0000000000..a27236496c
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_thumbnails_test__thumbnails__ini__string.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/thumbnails/test_thumbnails_ini_string.cpp.orig	2024-04-14 02:13:15.056763916 +0000
++++ tests/thumbnails/test_thumbnails_ini_string.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ 
+ #include "libslic3r/Config.hpp"
+ #include "libslic3r/PrintConfig.hpp"
diff --git a/prusaslicer/patches/patch-tests_thumbnails_test__thumbnails__input__string.cpp b/prusaslicer/patches/patch-tests_thumbnails_test__thumbnails__input__string.cpp
new file mode 100644
index 0000000000..d60eb5b58c
--- /dev/null
+++ b/prusaslicer/patches/patch-tests_thumbnails_test__thumbnails__input__string.cpp
@@ -0,0 +1,20 @@
+$NetBSD$
+
+Support Catch2 v3.
+Based on https://github.com/prusa3d/PrusaSlicer/issues/11567
+
+--- tests/thumbnails/test_thumbnails_input_string.cpp.orig	2024-04-14 02:13:15.066070658 +0000
++++ tests/thumbnails/test_thumbnails_input_string.cpp
+@@ -1,4 +1,4 @@
+-#include <catch2/catch.hpp>
++#include <catch2/catch_test_macros.hpp>
+ #include <test_utils.hpp>
+ 
+ #include <libslic3r/GCode/Thumbnails.hpp>
+@@ -149,4 +149,4 @@ TEST_CASE("Invalid value Thumbnails", "[
+         REQUIRE(errors.has(ThumbnailError::InvalidVal));
+         REQUIRE(thumbnails.size() == 2);
+     }
+-}
+\ No newline at end of file
++}



Home | Main Index | Thread Index | Old Index