From dd418bdf33568cd313cdc6c9676f8520b3991d26 Mon Sep 17 00:00:00 2001 From: f0gel Date: Tue, 16 Jul 2024 14:15:52 +0200 Subject: [PATCH 01/28] macos-12 workflow --- .github/workflows/test_suite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_suite.yml b/.github/workflows/test_suite.yml index ff488c6..12c9c47 100644 --- a/.github/workflows/test_suite.yml +++ b/.github/workflows/test_suite.yml @@ -9,7 +9,7 @@ jobs: name: Testing C-Runtime strategy: matrix: - os: [ubuntu-latest, macos-latest] + os: [macos-12] runs-on: ${{ matrix.os }} steps: - name: Checkout From 06bdea79220031708c752ff7d2ff64f51adef988 Mon Sep 17 00:00:00 2001 From: f0gel Date: Tue, 16 Jul 2024 14:29:15 +0200 Subject: [PATCH 02/28] test macos-latest-large --- .github/workflows/test_suite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_suite.yml b/.github/workflows/test_suite.yml index 12c9c47..05158c2 100644 --- a/.github/workflows/test_suite.yml +++ b/.github/workflows/test_suite.yml @@ -9,7 +9,7 @@ jobs: name: Testing C-Runtime strategy: matrix: - os: [macos-12] + os: [macos-latest-large] runs-on: ${{ matrix.os }} steps: - name: Checkout From 8f44c26a0fdfe968db152b7be1de097f8ab7f0f6 Mon Sep 17 00:00:00 2001 From: f0gel Date: Tue, 16 Jul 2024 14:33:43 +0200 Subject: [PATCH 03/28] macos-latest --- .github/workflows/test_suite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_suite.yml b/.github/workflows/test_suite.yml index 05158c2..9d296e4 100644 --- a/.github/workflows/test_suite.yml +++ b/.github/workflows/test_suite.yml @@ -9,7 +9,7 @@ jobs: name: Testing C-Runtime strategy: matrix: - os: [macos-latest-large] + os: [macos-latest] runs-on: ${{ matrix.os }} steps: - name: Checkout From eeaf0c268777e8acf959ce79a5f6de05340d7e81 Mon Sep 17 00:00:00 2001 From: f0gel Date: Tue, 16 Jul 2024 14:40:41 +0200 Subject: [PATCH 04/28] ubuntu-latest --- .github/workflows/test_suite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_suite.yml b/.github/workflows/test_suite.yml index 9d296e4..2e311ac 100644 --- a/.github/workflows/test_suite.yml +++ b/.github/workflows/test_suite.yml @@ -9,7 +9,7 @@ jobs: name: Testing C-Runtime strategy: matrix: - os: [macos-latest] + os: [ubuntu-latest] runs-on: ${{ matrix.os }} steps: - name: Checkout From f842af4fab2025572b913e96210cedb4ed9edec4 Mon Sep 17 00:00:00 2001 From: f0gel Date: Tue, 16 Jul 2024 14:43:15 +0200 Subject: [PATCH 05/28] g++-13 -> g++ --- c-runtime/test/Systemtests/makefile | 58 ++++++++++++++--------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/c-runtime/test/Systemtests/makefile b/c-runtime/test/Systemtests/makefile index a545b93..0c0baf0 100644 --- a/c-runtime/test/Systemtests/makefile +++ b/c-runtime/test/Systemtests/makefile @@ -64,87 +64,87 @@ echo: @echo ${RUN} test_declaration_and_assignment: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.out -w -fpermissive $(TESTDIR)/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.out -w -fpermissive $(TESTDIR)/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.c* $(C_FILES_TEST) test_arithmetic_ops: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ArithmeticOps/TestArithmeticOps.out -w -fpermissive $(TESTDIR)/Systemtests/ArithmeticOps/TestArithmeticOps.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ArithmeticOps/TestArithmeticOps.out -w -fpermissive $(TESTDIR)/Systemtests/ArithmeticOps/TestArithmeticOps.c* $(C_FILES_TEST) test_comparison_ops: - g++-13 --version - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestComparisonOps.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestComparisonOps.c* $(C_FILES_TEST) + g++ --version + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestComparisonOps.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestComparisonOps.c* $(C_FILES_TEST) test_greater_equal_op: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterEqualOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterEqualOp.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterEqualOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterEqualOp.c* $(C_FILES_TEST) test_greater_op: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterOp.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterOp.c* $(C_FILES_TEST) test_less_equal_op: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestLessEqualOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestLessEqualOp.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestLessEqualOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestLessEqualOp.c* $(C_FILES_TEST) test_less_op: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestLessOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestLessOp.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestLessOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestLessOp.c* $(C_FILES_TEST) test_logical_ops: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/LogicalOps/TestLogicalOps.out -w -fpermissive $(TESTDIR)/Systemtests/LogicalOps/TestLogicalOps.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/LogicalOps/TestLogicalOps.out -w -fpermissive $(TESTDIR)/Systemtests/LogicalOps/TestLogicalOps.c* $(C_FILES_TEST) test_if_statement: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestIfStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestIfStatement.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestIfStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestIfStatement.c* $(C_FILES_TEST) test_else_statement: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestElseStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestElseStatement.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestElseStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestElseStatement.c* $(C_FILES_TEST) test_elif_statement: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestElifStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestElifStatement.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestElifStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestElifStatement.c* $(C_FILES_TEST) test_while_statement: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestWhileStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestWhileStatement.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestWhileStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestWhileStatement.c* $(C_FILES_TEST) test_cast_int: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastInt.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastInt.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastInt.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastInt.c* $(C_FILES_TEST) test_cast_string: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastString.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastString.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastString.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastString.c* $(C_FILES_TEST) test_id: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestId.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestId.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestId.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestId.c* $(C_FILES_TEST) test_print: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestPrint.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestPrint.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestPrint.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestPrint.c* $(C_FILES_TEST) test_type: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestType.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestType.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestType.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestType.c* $(C_FILES_TEST) test_function_params: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParams.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParams.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParams.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParams.c* $(C_FILES_TEST) test_function_params_throws: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParamsThrows.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParamsThrows.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParamsThrows.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParamsThrows.c* $(C_FILES_TEST) test_function_body: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionBody.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionBody.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionBody.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionBody.c* $(C_FILES_TEST) test_function_return: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionReturn.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionReturn.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionReturn.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionReturn.c* $(C_FILES_TEST) test_function_recursion: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionRecursion.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionRecursion.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionRecursion.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionRecursion.c* $(C_FILES_TEST) test_class_init: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInit.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInit.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInit.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInit.c* $(C_FILES_TEST) test_class_init_throws: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInitThrows.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInitThrows.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInitThrows.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInitThrows.c* $(C_FILES_TEST) test_class_members: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassMembers.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassMembers.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassMembers.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassMembers.c* $(C_FILES_TEST) test_class_inheritance: - g++-13 --version - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInheritance.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInheritance.c* $(C_FILES_TEST) + g++ --version + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInheritance.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInheritance.c* $(C_FILES_TEST) test_wuppie: - g++-13 -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/wuppie.out -w -fpermissive $(TESTDIR)/Systemtests/wuppie.c* $(C_FILES_TEST) + g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/wuppie.out -w -fpermissive $(TESTDIR)/Systemtests/wuppie.c* $(C_FILES_TEST) clean: From d5f42ed35bb8fc0a1933537e9223abd22ab79f8d Mon Sep 17 00:00:00 2001 From: f0gel Date: Tue, 16 Jul 2024 14:46:33 +0200 Subject: [PATCH 06/28] macos-latest with g++ instead g++-13 --- .github/workflows/test_suite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_suite.yml b/.github/workflows/test_suite.yml index 2e311ac..ff488c6 100644 --- a/.github/workflows/test_suite.yml +++ b/.github/workflows/test_suite.yml @@ -9,7 +9,7 @@ jobs: name: Testing C-Runtime strategy: matrix: - os: [ubuntu-latest] + os: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.os }} steps: - name: Checkout From faf9c7f34681c21871c26cedc8f982faac6255ca Mon Sep 17 00:00:00 2001 From: f0gel Date: Tue, 16 Jul 2024 14:50:25 +0200 Subject: [PATCH 07/28] macos-latest only --- .github/workflows/test_suite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_suite.yml b/.github/workflows/test_suite.yml index ff488c6..9d296e4 100644 --- a/.github/workflows/test_suite.yml +++ b/.github/workflows/test_suite.yml @@ -9,7 +9,7 @@ jobs: name: Testing C-Runtime strategy: matrix: - os: [ubuntu-latest, macos-latest] + os: [macos-latest] runs-on: ${{ matrix.os }} steps: - name: Checkout From a25054f61ec76628fc2df3b54dbb188f415d6483 Mon Sep 17 00:00:00 2001 From: f0gel Date: Tue, 16 Jul 2024 14:56:18 +0200 Subject: [PATCH 08/28] ubuntu-24.04 beta --- .github/workflows/test_suite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_suite.yml b/.github/workflows/test_suite.yml index 9d296e4..506cf1e 100644 --- a/.github/workflows/test_suite.yml +++ b/.github/workflows/test_suite.yml @@ -9,7 +9,7 @@ jobs: name: Testing C-Runtime strategy: matrix: - os: [macos-latest] + os: [ubuntu-24.04] runs-on: ${{ matrix.os }} steps: - name: Checkout From c0e8aa431536c836b3c3799ae64a840a1a288152 Mon Sep 17 00:00:00 2001 From: f0gel Date: Sat, 20 Jul 2024 22:13:50 +0200 Subject: [PATCH 09/28] CC makefile variable --- c-runtime/Makefile | 10 +++-- c-runtime/test/Systemtests/makefile | 62 ++++++++++++++--------------- 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/c-runtime/Makefile b/c-runtime/Makefile index 7e8e06e..d164726 100644 --- a/c-runtime/Makefile +++ b/c-runtime/Makefile @@ -45,11 +45,11 @@ else # not for now CFLAGS += -DNDEBUG endif -################# +##################### # Default g++ Flags # -################# +##################### -CXXFLAGS ?= -std=c++14 +#CXXFLAGS ?= ########### # Targets # @@ -130,10 +130,12 @@ test_run: make -f $(TESTDIR)/Systemtests/makefile run .PHONY: test_target -test_target: +test_target: curl_catch d=$$(date +%s)\ ; make -f $(TESTDIR)/Systemtests/makefile test_greater_equal_op \ && echo "Build took $$(($$(date +%s)-d)) seconds" + make run_target + make test_clean .PHONY: run_target run_target: diff --git a/c-runtime/test/Systemtests/makefile b/c-runtime/test/Systemtests/makefile index 0c0baf0..489de23 100644 --- a/c-runtime/test/Systemtests/makefile +++ b/c-runtime/test/Systemtests/makefile @@ -1,3 +1,5 @@ +CC := g++ + RUNDECLA := /test/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.out RUNARITOPS := /test/Systemtests/ArithmeticOps/TestArithmeticOps.out RUNCOMPOPS := /test/Systemtests/ComparisonOps/TestComparisonOps.out @@ -25,8 +27,6 @@ RUNCLASSINITTHROWS := /test/Systemtests/Classes/TestClassInitThrows.out RUNCLASSMEMBERS := /test/Systemtests/Classes/TestClassMembers.out RUNCLASSINHERITANCE := /test/Systemtests/Classes/TestClassInheritance.out -CXXFLAGS ?= -std=c++14 - .PHONY : all run echo test_declaration_and_assignment test_arithmetic_ops test_comparison_ops test_greater_equal_op test_greater_op test_less_equal_op test_less_op test_logical_ops test_if_statement test_else_statement test_elif_statement test_while_statement test_cast_int test_cast_string test_id test_print test_type test_function_params test_function_params_throws test_function_body test_function_return test_function_recursion test_class_init test_class_init_throws test_class_members test_class_inheritance clean all: test_declaration_and_assignment test_arithmetic_ops test_comparison_ops test_greater_equal_op test_greater_op test_less_equal_op test_less_op test_logical_ops test_if_statement test_else_statement test_elif_statement test_while_statement test_cast_int test_cast_string test_print test_type test_function_params test_function_params_throws test_function_body test_function_return test_function_recursion test_class_init test_class_init_throws test_class_members test_class_inheritance run @@ -64,87 +64,87 @@ echo: @echo ${RUN} test_declaration_and_assignment: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.out -w -fpermissive $(TESTDIR)/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.out -w -fpermissive $(TESTDIR)/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.c* $(C_FILES_TEST) test_arithmetic_ops: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ArithmeticOps/TestArithmeticOps.out -w -fpermissive $(TESTDIR)/Systemtests/ArithmeticOps/TestArithmeticOps.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ArithmeticOps/TestArithmeticOps.out -w -fpermissive $(TESTDIR)/Systemtests/ArithmeticOps/TestArithmeticOps.c* $(C_FILES_TEST) test_comparison_ops: - g++ --version - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestComparisonOps.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestComparisonOps.c* $(C_FILES_TEST) + $(CC) --version + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestComparisonOps.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestComparisonOps.c* $(C_FILES_TEST) test_greater_equal_op: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterEqualOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterEqualOp.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterEqualOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterEqualOp.c* $(C_FILES_TEST) test_greater_op: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterOp.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterOp.c* $(C_FILES_TEST) test_less_equal_op: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestLessEqualOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestLessEqualOp.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestLessEqualOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestLessEqualOp.c* $(C_FILES_TEST) test_less_op: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestLessOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestLessOp.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestLessOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestLessOp.c* $(C_FILES_TEST) test_logical_ops: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/LogicalOps/TestLogicalOps.out -w -fpermissive $(TESTDIR)/Systemtests/LogicalOps/TestLogicalOps.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/LogicalOps/TestLogicalOps.out -w -fpermissive $(TESTDIR)/Systemtests/LogicalOps/TestLogicalOps.c* $(C_FILES_TEST) test_if_statement: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestIfStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestIfStatement.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestIfStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestIfStatement.c* $(C_FILES_TEST) test_else_statement: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestElseStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestElseStatement.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestElseStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestElseStatement.c* $(C_FILES_TEST) test_elif_statement: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestElifStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestElifStatement.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestElifStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestElifStatement.c* $(C_FILES_TEST) test_while_statement: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestWhileStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestWhileStatement.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestWhileStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestWhileStatement.c* $(C_FILES_TEST) test_cast_int: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastInt.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastInt.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastInt.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastInt.c* $(C_FILES_TEST) test_cast_string: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastString.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastString.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastString.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastString.c* $(C_FILES_TEST) test_id: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestId.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestId.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestId.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestId.c* $(C_FILES_TEST) test_print: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestPrint.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestPrint.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestPrint.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestPrint.c* $(C_FILES_TEST) test_type: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestType.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestType.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestType.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestType.c* $(C_FILES_TEST) test_function_params: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParams.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParams.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParams.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParams.c* $(C_FILES_TEST) test_function_params_throws: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParamsThrows.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParamsThrows.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParamsThrows.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParamsThrows.c* $(C_FILES_TEST) test_function_body: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionBody.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionBody.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionBody.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionBody.c* $(C_FILES_TEST) test_function_return: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionReturn.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionReturn.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionReturn.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionReturn.c* $(C_FILES_TEST) test_function_recursion: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionRecursion.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionRecursion.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionRecursion.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionRecursion.c* $(C_FILES_TEST) test_class_init: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInit.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInit.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInit.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInit.c* $(C_FILES_TEST) test_class_init_throws: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInitThrows.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInitThrows.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInitThrows.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInitThrows.c* $(C_FILES_TEST) test_class_members: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassMembers.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassMembers.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassMembers.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassMembers.c* $(C_FILES_TEST) test_class_inheritance: - g++ --version - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInheritance.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInheritance.c* $(C_FILES_TEST) + $(CC) --version + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInheritance.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInheritance.c* $(C_FILES_TEST) test_wuppie: - g++ -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/wuppie.out -w -fpermissive $(TESTDIR)/Systemtests/wuppie.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/wuppie.out -w -fpermissive $(TESTDIR)/Systemtests/wuppie.c* $(C_FILES_TEST) clean: From 7f5814785249d76f21876cc843a384607106b102 Mon Sep 17 00:00:00 2001 From: f0gel Date: Sat, 20 Jul 2024 22:35:21 +0200 Subject: [PATCH 10/28] macos-latest --- .github/workflows/test_suite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_suite.yml b/.github/workflows/test_suite.yml index 506cf1e..9d296e4 100644 --- a/.github/workflows/test_suite.yml +++ b/.github/workflows/test_suite.yml @@ -9,7 +9,7 @@ jobs: name: Testing C-Runtime strategy: matrix: - os: [ubuntu-24.04] + os: [macos-latest] runs-on: ${{ matrix.os }} steps: - name: Checkout From 9b61de882a2ac803d9d5ff81969ed3384f11f464 Mon Sep 17 00:00:00 2001 From: f0gel Date: Sat, 20 Jul 2024 22:37:17 +0200 Subject: [PATCH 11/28] easier testing --- .github/workflows/test_suite.yml | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/.github/workflows/test_suite.yml b/.github/workflows/test_suite.yml index 9d296e4..de7f466 100644 --- a/.github/workflows/test_suite.yml +++ b/.github/workflows/test_suite.yml @@ -19,24 +19,7 @@ jobs: run: make clean - name: Exec makefile working-directory: ./c-runtime - run: make test + run: make test_target - name: Clean Up working-directory: ./c-runtime run: make test_clean ; make clean - - languagefeatures: - name: Testing CBuilder (Java) - strategy: - matrix: - os: [ubuntu-latest, macos-latest] - runs-on: ${{ matrix.os }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up JDK 21 - uses: actions/setup-java@v4 - with: - java-version: '21' - distribution: 'temurin' - - name: Build with Gradle - run: ./gradlew test From 4773bf73de1f3318718884d64b1f7b29bdb72a11 Mon Sep 17 00:00:00 2001 From: f0gel Date: Sat, 20 Jul 2024 23:43:59 +0200 Subject: [PATCH 12/28] Upgrade Catch2 v2.x to 3.x --- c-runtime/Makefile | 9 +- .../ArithmeticOps/TestArithmeticOps.cpp | 2 +- .../BuiltInFunctions/TestCastInt.cpp | 2 +- .../BuiltInFunctions/TestCastString.cpp | 2 +- .../Systemtests/BuiltInFunctions/TestId.cpp | 2 +- .../BuiltInFunctions/TestPrint.cpp | 2 +- .../Systemtests/BuiltInFunctions/TestType.cpp | 2 +- .../Classes/TestClassInheritance.cpp | 26 +- .../Systemtests/Classes/TestClassInit.cpp | 34 +- .../Classes/TestClassInitThrows.cpp | 32 +- .../Systemtests/Classes/TestClassMembers.cpp | 31 +- .../ComparisonOps/TestComparisonOps.cpp | 28 +- .../ComparisonOps/TestGreaterEqualOp.cpp | 4 +- .../ComparisonOps/TestGreaterOp.cpp | 4 +- .../ComparisonOps/TestLessEqualOp.cpp | 4 +- .../Systemtests/ComparisonOps/TestLessOp.cpp | 4 +- .../Conditions/TestElifStatement.cpp | 2 +- .../Conditions/TestElseStatement.cpp | 2 +- .../Conditions/TestIfStatement.cpp | 2 +- .../Conditions/TestWhileStatement.cpp | 2 +- .../TestDeclarationAndAssignment.cpp | 2 +- .../FunctionCalls/TestFunctionBody.cpp | 41 +- .../FunctionCalls/TestFunctionParams.cpp | 40 +- .../TestFunctionParamsThrows.cpp | 36 +- .../FunctionCalls/TestFunctionRecursion.cpp | 26 +- .../FunctionCalls/TestFunctionReturn.cpp | 29 +- .../Systemtests/LogicalOps/TestLogicalOps.cpp | 2 +- c-runtime/test/Systemtests/makefile | 69 +- c-runtime/test/Systemtests/wuppie.cpp | 2 +- c-runtime/test/include/catch_amalgamated.hpp | 14057 ++++++++++++++++ c-runtime/test/src/catch_amalgamated.cpp | 11638 +++++++++++++ 31 files changed, 25867 insertions(+), 271 deletions(-) create mode 100644 c-runtime/test/include/catch_amalgamated.hpp create mode 100644 c-runtime/test/src/catch_amalgamated.cpp diff --git a/c-runtime/Makefile b/c-runtime/Makefile index d164726..30d3543 100644 --- a/c-runtime/Makefile +++ b/c-runtime/Makefile @@ -16,7 +16,7 @@ export TESTDIR := $(realpath ./test) export INCLUDEDIRTEST := $(realpath ./test/include) export SRCDIRTEST := $(realpath ./test/src) -export C_FILES_TEST := $(wildcard ./test/src/test/*.c ./test/src/test/*/*.c* ./src/*.c ./src/*/*.c*) +export C_FILES_TEST := $(wildcard ./test/src/test/*.c ./test/src/test/*/*.c* ./test/src/*.cpp) export C_FILES_TEST := $(filter-out ./src/program.c, $(C_FILES_TEST)) export C_FILES := $(wildcard ./src/*.c ./src/*/*.c*) export C_FILES := $(filter-out ./src/program.c, $(C_FILES)) @@ -106,7 +106,8 @@ lint: #https://github.com/catchorg/Catch2/blob/v2.x/include/catch.hpp .PHONY: curl_catch curl_catch: - curl -o $(TESTDIR)/include/catch.hpp https://raw.githubusercontent.com/catchorg/Catch2/v2.x/single_include/catch2/catch.hpp + curl -o $(TESTDIR)/include/catch_amalgamated.hpp https://raw.githubusercontent.com/catchorg/Catch2/devel/extras/catch_amalgamated.hpp + curl -o $(TESTDIR)/src/catch_amalgamated.cpp https://raw.githubusercontent.com/catchorg/Catch2/devel/extras/catch_amalgamated.cpp .PHONY: test test: curl_catch @@ -132,11 +133,11 @@ test_run: .PHONY: test_target test_target: curl_catch d=$$(date +%s)\ - ; make -f $(TESTDIR)/Systemtests/makefile test_greater_equal_op \ + ; make -f $(TESTDIR)/Systemtests/makefile test_function_params \ && echo "Build took $$(($$(date +%s)-d)) seconds" make run_target make test_clean .PHONY: run_target run_target: - ./test/Systemtests/ComparisonOps/TestGreaterEqualOp.out + ./test/Systemtests/FunctionCalls/TestFunctionParams.out diff --git a/c-runtime/test/Systemtests/ArithmeticOps/TestArithmeticOps.cpp b/c-runtime/test/Systemtests/ArithmeticOps/TestArithmeticOps.cpp index 6a71b3e..f9f0bb5 100644 --- a/c-runtime/test/Systemtests/ArithmeticOps/TestArithmeticOps.cpp +++ b/c-runtime/test/Systemtests/ArithmeticOps/TestArithmeticOps.cpp @@ -2,7 +2,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" diff --git a/c-runtime/test/Systemtests/BuiltInFunctions/TestCastInt.cpp b/c-runtime/test/Systemtests/BuiltInFunctions/TestCastInt.cpp index bd39437..d003211 100644 --- a/c-runtime/test/Systemtests/BuiltInFunctions/TestCastInt.cpp +++ b/c-runtime/test/Systemtests/BuiltInFunctions/TestCastInt.cpp @@ -2,7 +2,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" diff --git a/c-runtime/test/Systemtests/BuiltInFunctions/TestCastString.cpp b/c-runtime/test/Systemtests/BuiltInFunctions/TestCastString.cpp index 51d5988..da9b742 100644 --- a/c-runtime/test/Systemtests/BuiltInFunctions/TestCastString.cpp +++ b/c-runtime/test/Systemtests/BuiltInFunctions/TestCastString.cpp @@ -2,7 +2,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" diff --git a/c-runtime/test/Systemtests/BuiltInFunctions/TestId.cpp b/c-runtime/test/Systemtests/BuiltInFunctions/TestId.cpp index d96879f..a9fc1ab 100644 --- a/c-runtime/test/Systemtests/BuiltInFunctions/TestId.cpp +++ b/c-runtime/test/Systemtests/BuiltInFunctions/TestId.cpp @@ -5,7 +5,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" diff --git a/c-runtime/test/Systemtests/BuiltInFunctions/TestPrint.cpp b/c-runtime/test/Systemtests/BuiltInFunctions/TestPrint.cpp index 899da22..81ec3cd 100644 --- a/c-runtime/test/Systemtests/BuiltInFunctions/TestPrint.cpp +++ b/c-runtime/test/Systemtests/BuiltInFunctions/TestPrint.cpp @@ -7,7 +7,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" diff --git a/c-runtime/test/Systemtests/BuiltInFunctions/TestType.cpp b/c-runtime/test/Systemtests/BuiltInFunctions/TestType.cpp index e75bb4c..f543d05 100644 --- a/c-runtime/test/Systemtests/BuiltInFunctions/TestType.cpp +++ b/c-runtime/test/Systemtests/BuiltInFunctions/TestType.cpp @@ -2,7 +2,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" diff --git a/c-runtime/test/Systemtests/Classes/TestClassInheritance.cpp b/c-runtime/test/Systemtests/Classes/TestClassInheritance.cpp index 2fdd199..2af92e0 100644 --- a/c-runtime/test/Systemtests/Classes/TestClassInheritance.cpp +++ b/c-runtime/test/Systemtests/Classes/TestClassInheritance.cpp @@ -1,8 +1,8 @@ -#define CATCH_CONFIG_RUNNER +#define CATCH_CONFIG_MAIN #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "test/test_helpers.h" #include "test/Classes/TestClassInheritanceHelpers.h" @@ -10,28 +10,10 @@ __MPyObj *A; __MPyObj *B; -int main( int argc, char* argv[] ) { - // global setup... - __mpy_builtins_setup(); - - int result = 0; - - try{ - result = Catch::Session().run( argc, argv ); - } - catch (const std::runtime_error& error){ - printf(""); - } - - __mpy_builtins_cleanup(); - // global clean-up... Why is this working ? .... - - return result; -} - int inheritance(){ __MPyObj *child; + __mpy_builtins_setup(); child = __mpy_obj_init_object(); __mpy_obj_ref_inc(child); @@ -65,6 +47,8 @@ int inheritance(){ __mpy_obj_ref_dec(A); __mpy_obj_ref_dec(B); + __mpy_builtins_cleanup(); + return 0; } diff --git a/c-runtime/test/Systemtests/Classes/TestClassInit.cpp b/c-runtime/test/Systemtests/Classes/TestClassInit.cpp index 1973482..81c60ce 100644 --- a/c-runtime/test/Systemtests/Classes/TestClassInit.cpp +++ b/c-runtime/test/Systemtests/Classes/TestClassInit.cpp @@ -1,8 +1,8 @@ -#define CATCH_CONFIG_RUNNER +#define CATCH_CONFIG_MAIN #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "test/test_helpers.h" #include "test/Classes/TestClassInitHelpers.h" @@ -12,28 +12,12 @@ __MPyObj *init_one_param; __MPyObj *init_multiple_params; -int main( int argc, char* argv[] ) { - // global setup... - __mpy_builtins_setup(); - - int result = 0; - - try{ - result = Catch::Session().run( argc, argv ); - } - catch (const std::runtime_error& error){ - printf(""); - } - - __mpy_builtins_cleanup(); - // global clean-up... Why is this working ? .... - - return result; -} - int init_class_no_params(){ __MPyObj *x; + __mpy_builtins_setup(); + + __mpy_builtins_setup(); x = __mpy_obj_init_object(); __mpy_obj_ref_inc(x); @@ -58,12 +42,15 @@ int init_class_no_params(){ __mpy_obj_ref_dec(init_no_params); + __mpy_builtins_cleanup(); + return 0; } int init_class_one_param(){ __MPyObj *x; + __mpy_builtins_setup(); x = __mpy_obj_init_object(); __mpy_obj_ref_inc(x); @@ -89,12 +76,15 @@ int init_class_one_param(){ print_mpyobj(x); + __mpy_builtins_cleanup(); + return 0; } int init_class_multiple_params(){ __MPyObj *x; + __mpy_builtins_setup(); x = __mpy_obj_init_object(); __mpy_obj_ref_inc(x); @@ -119,6 +109,8 @@ int init_class_multiple_params(){ print_mpyobj(x); + __mpy_builtins_cleanup(); + return 0; } diff --git a/c-runtime/test/Systemtests/Classes/TestClassInitThrows.cpp b/c-runtime/test/Systemtests/Classes/TestClassInitThrows.cpp index 3948efa..4200215 100644 --- a/c-runtime/test/Systemtests/Classes/TestClassInitThrows.cpp +++ b/c-runtime/test/Systemtests/Classes/TestClassInitThrows.cpp @@ -1,8 +1,8 @@ -#define CATCH_CONFIG_RUNNER +#define CATCH_CONFIG_MAIN #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "test/test_helpers.h" #include "test/Classes/TestClassInitHelpers.h" @@ -14,28 +14,10 @@ __MPyObj *init_multiple_params; void exit(int status); -int main( int argc, char* argv[] ) { - // global setup... - __mpy_builtins_setup(); - - int result = 0; - - try{ - result = Catch::Session().run( argc, argv ); - } - catch (const std::runtime_error& error){ - printf(""); - } - - __mpy_builtins_cleanup(); - // global clean-up... Why is this working ? .... - - return result; -} - int init_class_no_params_but_one_provided(){ __MPyObj *x; + __mpy_builtins_setup(); x = __mpy_obj_init_object(); __mpy_obj_ref_inc(x); @@ -62,12 +44,15 @@ int init_class_no_params_but_one_provided(){ __mpy_obj_ref_dec(init_no_params); + __mpy_builtins_cleanup(); + return 0; } int init_class_one_param_but_none_provided(){ __MPyObj *x; + __mpy_builtins_setup(); x = __mpy_obj_init_object(); __mpy_obj_ref_inc(x); @@ -93,12 +78,15 @@ int init_class_one_param_but_none_provided(){ print_mpyobj(x); + __mpy_builtins_cleanup(); + return 0; } int init_class_multiple_params_but_less_provided(){ __MPyObj *x; + __mpy_builtins_setup(); x = __mpy_obj_init_object(); __mpy_obj_ref_inc(x); @@ -123,6 +111,8 @@ int init_class_multiple_params_but_less_provided(){ print_mpyobj(x); + __mpy_builtins_cleanup(); + return 0; } diff --git a/c-runtime/test/Systemtests/Classes/TestClassMembers.cpp b/c-runtime/test/Systemtests/Classes/TestClassMembers.cpp index dd10df0..97a0926 100644 --- a/c-runtime/test/Systemtests/Classes/TestClassMembers.cpp +++ b/c-runtime/test/Systemtests/Classes/TestClassMembers.cpp @@ -1,36 +1,16 @@ -#define CATCH_CONFIG_RUNNER +#define CATCH_CONFIG_MAIN -#include - -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "test/test_helpers.h" #include "test/Classes/TestClassMembersHelpers.h" __MPyObj *getter_setter; -int main( int argc, char* argv[] ) { - // global setup... - __mpy_builtins_setup(); - - int result = 0; - - try{ - result = Catch::Session().run( argc, argv ); - } - catch (const std::runtime_error& error){ - printf(""); - } - - __mpy_builtins_cleanup(); - // global clean-up... Why is this working ? .... - - return result; -} - int getX_from_class(){ __MPyObj *myClass; __MPyObj *returnValueGetter; + __mpy_builtins_setup(); myClass = __mpy_obj_init_object(); __mpy_obj_ref_inc(myClass); @@ -76,6 +56,8 @@ int getX_from_class(){ print_mpyobj_int(returnValueGetter); + __mpy_builtins_cleanup(); + return (*(int*)(returnValueGetter->content)); } @@ -83,6 +65,7 @@ int setX_from_class(){ __MPyObj *myClass; __MPyObj *returnValueGetter; + __mpy_builtins_setup(); myClass = __mpy_obj_init_object(); __mpy_obj_ref_inc(myClass); @@ -136,6 +119,8 @@ int setX_from_class(){ print_mpyobj_int(returnValueGetter); + __mpy_builtins_cleanup(); + return (*(int*)(returnValueGetter->content)); } diff --git a/c-runtime/test/Systemtests/ComparisonOps/TestComparisonOps.cpp b/c-runtime/test/Systemtests/ComparisonOps/TestComparisonOps.cpp index c4d767f..a26c520 100644 --- a/c-runtime/test/Systemtests/ComparisonOps/TestComparisonOps.cpp +++ b/c-runtime/test/Systemtests/ComparisonOps/TestComparisonOps.cpp @@ -1,8 +1,8 @@ -#define CATCH_CONFIG_RUNNER +#define CATCH_CONFIG_MAIN #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" @@ -16,28 +16,10 @@ #include "type-hierarchy/type.h" #include "test/test_helpers.h" -int main( int argc, char* argv[] ) { - // global setup... - __mpy_builtins_setup(); - - int result = 0; - - try{ - result = Catch::Session().run( argc, argv ); - } - catch (const std::runtime_error& error){ - printf("Hello World"); - } - - __mpy_builtins_cleanup(); - // global clean-up... Why is this working ? .... - - return result; -} - int eq_op(int i, int j){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -51,6 +33,7 @@ int eq_op(int i, int j){ print_mpyobj_int(a); + __mpy_builtins_cleanup(); return (*(int*)(a->content)) == (i == j) ? 1 : 0; } @@ -58,6 +41,7 @@ int eq_op(int i, int j){ int ne_op(int i, int j){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -71,6 +55,8 @@ int ne_op(int i, int j){ print_mpyobj_int(a); + __mpy_builtins_cleanup(); + return (*(int*)(a->content)) == (i != j) ? 1 : 0; } diff --git a/c-runtime/test/Systemtests/ComparisonOps/TestGreaterEqualOp.cpp b/c-runtime/test/Systemtests/ComparisonOps/TestGreaterEqualOp.cpp index 5ff0e93..3c2e1ce 100644 --- a/c-runtime/test/Systemtests/ComparisonOps/TestGreaterEqualOp.cpp +++ b/c-runtime/test/Systemtests/ComparisonOps/TestGreaterEqualOp.cpp @@ -2,7 +2,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" @@ -42,4 +42,4 @@ TEST_CASE("GENERATE GE OP"){ auto i = GENERATE(1, 3, 5); auto j = GENERATE(2, 4, 5); CHECK(ge_op(i, j) == 1); -} \ No newline at end of file +} diff --git a/c-runtime/test/Systemtests/ComparisonOps/TestGreaterOp.cpp b/c-runtime/test/Systemtests/ComparisonOps/TestGreaterOp.cpp index fbaf119..ace2583 100644 --- a/c-runtime/test/Systemtests/ComparisonOps/TestGreaterOp.cpp +++ b/c-runtime/test/Systemtests/ComparisonOps/TestGreaterOp.cpp @@ -2,7 +2,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" @@ -43,4 +43,4 @@ TEST_CASE("GENERATE GT OP"){ auto i = GENERATE(1, 3, 5); auto j = GENERATE(2, 4, 6); CHECK(gt_op(i, j) == 1); -} \ No newline at end of file +} diff --git a/c-runtime/test/Systemtests/ComparisonOps/TestLessEqualOp.cpp b/c-runtime/test/Systemtests/ComparisonOps/TestLessEqualOp.cpp index e41406c..18a2402 100644 --- a/c-runtime/test/Systemtests/ComparisonOps/TestLessEqualOp.cpp +++ b/c-runtime/test/Systemtests/ComparisonOps/TestLessEqualOp.cpp @@ -2,7 +2,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" @@ -42,4 +42,4 @@ TEST_CASE("GENERATE LE OP"){ auto i = GENERATE(1, 3, 5); auto j = GENERATE(2, 4, 5); CHECK(le_op(i, j) == 1); -} \ No newline at end of file +} diff --git a/c-runtime/test/Systemtests/ComparisonOps/TestLessOp.cpp b/c-runtime/test/Systemtests/ComparisonOps/TestLessOp.cpp index 84569c1..93609a4 100644 --- a/c-runtime/test/Systemtests/ComparisonOps/TestLessOp.cpp +++ b/c-runtime/test/Systemtests/ComparisonOps/TestLessOp.cpp @@ -2,7 +2,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" @@ -43,4 +43,4 @@ TEST_CASE("GENERATE LT OP"){ auto i = GENERATE(1, 3, 5); auto j = GENERATE(2, 4, 5); CHECK(lt_op(i, j) == 1); -} \ No newline at end of file +} diff --git a/c-runtime/test/Systemtests/Conditions/TestElifStatement.cpp b/c-runtime/test/Systemtests/Conditions/TestElifStatement.cpp index 0c1cade..c347e5c 100644 --- a/c-runtime/test/Systemtests/Conditions/TestElifStatement.cpp +++ b/c-runtime/test/Systemtests/Conditions/TestElifStatement.cpp @@ -2,7 +2,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" diff --git a/c-runtime/test/Systemtests/Conditions/TestElseStatement.cpp b/c-runtime/test/Systemtests/Conditions/TestElseStatement.cpp index f7833dc..0fbea33 100644 --- a/c-runtime/test/Systemtests/Conditions/TestElseStatement.cpp +++ b/c-runtime/test/Systemtests/Conditions/TestElseStatement.cpp @@ -2,7 +2,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" diff --git a/c-runtime/test/Systemtests/Conditions/TestIfStatement.cpp b/c-runtime/test/Systemtests/Conditions/TestIfStatement.cpp index b6d6487..12e7fa2 100644 --- a/c-runtime/test/Systemtests/Conditions/TestIfStatement.cpp +++ b/c-runtime/test/Systemtests/Conditions/TestIfStatement.cpp @@ -2,7 +2,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" diff --git a/c-runtime/test/Systemtests/Conditions/TestWhileStatement.cpp b/c-runtime/test/Systemtests/Conditions/TestWhileStatement.cpp index f326159..6fa6a84 100644 --- a/c-runtime/test/Systemtests/Conditions/TestWhileStatement.cpp +++ b/c-runtime/test/Systemtests/Conditions/TestWhileStatement.cpp @@ -2,7 +2,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" diff --git a/c-runtime/test/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.cpp b/c-runtime/test/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.cpp index a62a9d8..53b81c2 100644 --- a/c-runtime/test/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.cpp +++ b/c-runtime/test/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.cpp @@ -6,7 +6,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" diff --git a/c-runtime/test/Systemtests/FunctionCalls/TestFunctionBody.cpp b/c-runtime/test/Systemtests/FunctionCalls/TestFunctionBody.cpp index 435871d..044b61b 100644 --- a/c-runtime/test/Systemtests/FunctionCalls/TestFunctionBody.cpp +++ b/c-runtime/test/Systemtests/FunctionCalls/TestFunctionBody.cpp @@ -1,8 +1,8 @@ -#define CATCH_CONFIG_RUNNER +#define CATCH_CONFIG_MAIN #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "test/test_helpers.h" #include "test/FunctionCalls/TestFunctionBodyHelpers.h" @@ -18,28 +18,10 @@ __MPyObj *return_add; __MPyObj *return_add_conditional; -int main( int argc, char* argv[] ) { - // global setup... - __mpy_builtins_setup(); - - int result = 0; - - try{ - result = Catch::Session().run( argc, argv ); - } - catch (const std::runtime_error& error){ - printf("Hello World"); - } - - __mpy_builtins_cleanup(); - // global clean-up... Why is this working ? .... - - return result; -} - int minimal_body(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -55,12 +37,15 @@ int minimal_body(){ __mpy_obj_ref_dec(minimalistic_body); + __mpy_builtins_cleanup(); + return (*(int*)(a->content)); } int print_from_func_body(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -75,12 +60,15 @@ int print_from_func_body(){ __mpy_obj_ref_dec(print_from_func); + __mpy_builtins_cleanup(); + return (*(int*)(a->content)); } int local_var_body(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -96,12 +84,15 @@ int local_var_body(){ __mpy_obj_ref_dec(return_local_var); + __mpy_builtins_cleanup(); + return (*(int*)(a->content)); } int param_body(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -117,12 +108,15 @@ int param_body(){ __mpy_obj_ref_dec(return_param_body); + __mpy_builtins_cleanup(); + return (*(int*)(a->content)); } int return_add_body(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -138,12 +132,15 @@ int return_add_body(){ __mpy_obj_ref_dec(return_add); + __mpy_builtins_cleanup(); + return (*(int*)(a->content)) == 4 ? 1 : 0; } int return_add_conditional_body(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -159,6 +156,8 @@ int return_add_conditional_body(){ __mpy_obj_ref_dec(return_add_conditional); + __mpy_builtins_cleanup(); + return (*(int*)(a->content)) == 4 ? 1 : 0; } diff --git a/c-runtime/test/Systemtests/FunctionCalls/TestFunctionParams.cpp b/c-runtime/test/Systemtests/FunctionCalls/TestFunctionParams.cpp index 69918bf..2488a59 100644 --- a/c-runtime/test/Systemtests/FunctionCalls/TestFunctionParams.cpp +++ b/c-runtime/test/Systemtests/FunctionCalls/TestFunctionParams.cpp @@ -1,8 +1,8 @@ -#define CATCH_CONFIG_RUNNER +#define CATCH_CONFIG_MAIN #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "test/test_helpers.h" #include "test/FunctionCalls/TestFunctionParamsHelpers.h" @@ -14,28 +14,10 @@ __MPyObj *func3; __MPyObj *func4; -int main( int argc, char* argv[] ) { - // global setup... - __mpy_builtins_setup(); - - int result = 0; - - try{ - result = Catch::Session().run( argc, argv ); - } - catch (const std::runtime_error& error){ - printf("Hello World"); - } - - __mpy_builtins_cleanup(); - // global clean-up... Why is this working ? .... - - return result; -} - int empty_params(const char* expected){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -52,12 +34,15 @@ int empty_params(const char* expected){ print_mpyobj_str(a); + __mpy_builtins_cleanup(); + return strcmp(((__MPyStrContent*)a->content)->string, expected); } int one_param(__MPyObj *param1, __MPyObj *expected, int isNumeric){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -79,12 +64,16 @@ int one_param(__MPyObj *param1, __MPyObj *expected, int isNumeric){ } print_mpyobj_int(a); + + __mpy_builtins_cleanup(); + return (*(int*)(a->content)) == (*(int*)(expected->content)) ? 1 : 0; } int one_param_print_call(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -100,12 +89,15 @@ int one_param_print_call(){ __mpy_obj_ref_dec(func4); + __mpy_builtins_cleanup(); + return 0; } int multiple_params(__MPyObj *param1, __MPyObj *param2, __MPyObj *expected, int isNumeric){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -122,10 +114,16 @@ int multiple_params(__MPyObj *param1, __MPyObj *param2, __MPyObj *expected, int if(!isNumeric){ print_mpyobj_str(a); + + __mpy_builtins_cleanup(); + return strcmp(((__MPyStrContent*)a->content)->string, ((__MPyStrContent*)expected->content)->string); } print_mpyobj_int(a); + + __mpy_builtins_cleanup(); + return (*(int*)(a->content)) == (*(int*)(expected->content)) ? 1 : 0; } diff --git a/c-runtime/test/Systemtests/FunctionCalls/TestFunctionParamsThrows.cpp b/c-runtime/test/Systemtests/FunctionCalls/TestFunctionParamsThrows.cpp index c7071cb..29776ec 100644 --- a/c-runtime/test/Systemtests/FunctionCalls/TestFunctionParamsThrows.cpp +++ b/c-runtime/test/Systemtests/FunctionCalls/TestFunctionParamsThrows.cpp @@ -1,8 +1,8 @@ -#define CATCH_CONFIG_RUNNER +#define CATCH_CONFIG_MAIN #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "test/test_helpers.h" #include "test/FunctionCalls/TestFunctionParamsHelpers.h" @@ -14,28 +14,10 @@ __MPyObj *throws5; void exit(int status); -int main( int argc, char* argv[] ) { - // global setup... - __mpy_builtins_setup(); - - int result = 0; - - try{ - result = Catch::Session().run( argc, argv ); - } - catch (const std::runtime_error& error){ - printf("Hello World"); - } - - __mpy_builtins_cleanup(); - // global clean-up... Why is this working ? .... - - return result; -} - int no_param_but_provided(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -50,12 +32,15 @@ int no_param_but_provided(){ __mpy_obj_ref_dec(func_throws1); + __mpy_builtins_cleanup(); + return 0; } int one_param_but_none_provided(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -71,12 +56,15 @@ int one_param_but_none_provided(){ __mpy_obj_ref_dec(throws2); + __mpy_builtins_cleanup(); + return 0; } int one_param_but_two_provided(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -92,11 +80,14 @@ int one_param_but_two_provided(){ __mpy_obj_ref_dec(throws3); + __mpy_builtins_cleanup(); + return 0; } int one_param_but_void_function_provided(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -111,12 +102,14 @@ int one_param_but_void_function_provided(){ __mpy_obj_ref_dec(throws4); + __mpy_builtins_cleanup(); return 0; } int two_params_but_one_provided(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -131,6 +124,7 @@ int two_params_but_one_provided(){ __mpy_obj_ref_dec(throws5); + __mpy_builtins_cleanup(); return 0; } diff --git a/c-runtime/test/Systemtests/FunctionCalls/TestFunctionRecursion.cpp b/c-runtime/test/Systemtests/FunctionCalls/TestFunctionRecursion.cpp index 354347f..f474a98 100644 --- a/c-runtime/test/Systemtests/FunctionCalls/TestFunctionRecursion.cpp +++ b/c-runtime/test/Systemtests/FunctionCalls/TestFunctionRecursion.cpp @@ -1,33 +1,15 @@ -#define CATCH_CONFIG_RUNNER +#define CATCH_CONFIG_MAIN #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "test/test_helpers.h" #include "test/FunctionCalls/TestFunctionRecursionHelpers.h" -int main( int argc, char* argv[] ) { - // global setup... - __mpy_builtins_setup(); - - int result = 0; - - try{ - result = Catch::Session().run( argc, argv ); - } - catch (const std::runtime_error& error){ - printf(""); - } - - __mpy_builtins_cleanup(); - // global clean-up... Why is this working ? .... - - return result; -} - int rec(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -45,6 +27,8 @@ int rec(){ print_mpyobj_int(a); + __mpy_builtins_cleanup(); + return (*(int*)(a->content)) == 0 ? 1 : 0; } diff --git a/c-runtime/test/Systemtests/FunctionCalls/TestFunctionReturn.cpp b/c-runtime/test/Systemtests/FunctionCalls/TestFunctionReturn.cpp index d1ad429..756e796 100644 --- a/c-runtime/test/Systemtests/FunctionCalls/TestFunctionReturn.cpp +++ b/c-runtime/test/Systemtests/FunctionCalls/TestFunctionReturn.cpp @@ -1,8 +1,8 @@ -#define CATCH_CONFIG_RUNNER +#define CATCH_CONFIG_MAIN #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "test/test_helpers.h" #include "test/FunctionCalls/TestFunctionReturnHelpers.h" @@ -12,28 +12,10 @@ __MPyObj *return_tuple_literal_throws; __MPyObj *return_void_function_call_print; -int main( int argc, char* argv[] ) { - // global setup... - __mpy_builtins_setup(); - - int result = 0; - - try{ - result = Catch::Session().run( argc, argv ); - } - catch (const std::runtime_error& error){ - printf("Hello World"); - } - - __mpy_builtins_cleanup(); - // global clean-up... Why is this working ? .... - - return result; -} - int return_expr(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -49,12 +31,14 @@ int return_expr(){ __mpy_obj_ref_dec(return_expression); + __mpy_builtins_cleanup(); return (*(int*)(a->content)); } int return_tuple_literal(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -71,12 +55,14 @@ int return_tuple_literal(){ __mpy_obj_ref_dec(return_tuple_literal_throws); + __mpy_builtins_cleanup(); return 1; } int return_print(){ __MPyObj *a; + __mpy_builtins_setup(); a = __mpy_obj_init_object(); __mpy_obj_ref_inc(a); @@ -94,6 +80,7 @@ int return_print(){ __mpy_obj_ref_dec(return_void_function_call_print); + __mpy_builtins_cleanup(); return 1; } diff --git a/c-runtime/test/Systemtests/LogicalOps/TestLogicalOps.cpp b/c-runtime/test/Systemtests/LogicalOps/TestLogicalOps.cpp index aa9994f..ac74fd8 100644 --- a/c-runtime/test/Systemtests/LogicalOps/TestLogicalOps.cpp +++ b/c-runtime/test/Systemtests/LogicalOps/TestLogicalOps.cpp @@ -2,7 +2,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" diff --git a/c-runtime/test/Systemtests/makefile b/c-runtime/test/Systemtests/makefile index 489de23..2f83f61 100644 --- a/c-runtime/test/Systemtests/makefile +++ b/c-runtime/test/Systemtests/makefile @@ -27,9 +27,10 @@ RUNCLASSINITTHROWS := /test/Systemtests/Classes/TestClassInitThrows.out RUNCLASSMEMBERS := /test/Systemtests/Classes/TestClassMembers.out RUNCLASSINHERITANCE := /test/Systemtests/Classes/TestClassInheritance.out -.PHONY : all run echo test_declaration_and_assignment test_arithmetic_ops test_comparison_ops test_greater_equal_op test_greater_op test_less_equal_op test_less_op test_logical_ops test_if_statement test_else_statement test_elif_statement test_while_statement test_cast_int test_cast_string test_id test_print test_type test_function_params test_function_params_throws test_function_body test_function_return test_function_recursion test_class_init test_class_init_throws test_class_members test_class_inheritance clean - -all: test_declaration_and_assignment test_arithmetic_ops test_comparison_ops test_greater_equal_op test_greater_op test_less_equal_op test_less_op test_logical_ops test_if_statement test_else_statement test_elif_statement test_while_statement test_cast_int test_cast_string test_print test_type test_function_params test_function_params_throws test_function_body test_function_return test_function_recursion test_class_init test_class_init_throws test_class_members test_class_inheritance run +.PHONY : all run echo test_declaration_and_assignment test_arithmetic_ops test_comparison_ops test_greater_equal_op test_greater_op test_less_equal_op test_less_op test_logical_ops test_if_statement test_else_statement test_elif_statement test_while_statement test_cast_int test_cast_string test_id test_print test_type test_function_body test_function_return test_function_recursion test_class_init test_class_members test_class_inheritance clean +#Disabled tests: test_function_params, test_function_params_throws, test_class_init_throws +#To Enable add to all target, .PHONY and remove comment from run target! +all: test_declaration_and_assignment test_arithmetic_ops test_comparison_ops test_greater_equal_op test_greater_op test_less_equal_op test_less_op test_logical_ops test_if_statement test_else_statement test_elif_statement test_while_statement test_cast_int test_cast_string test_print test_type test_function_body test_function_return test_function_recursion test_class_init test_class_members test_class_inheritance run run: .$(RUNDECLA) @@ -48,13 +49,13 @@ run: .$(RUNCASTSTRING) .$(RUNPRINT) .$(RUNTYPE) - .$(RUNFUNPARAMS) - .$(RUNFUNPARAMSTHROWS) + #.$(RUNFUNPARAMS) + #.$(RUNFUNPARAMSTHROWS) .$(RUNFUNBODY) .$(RUNFUNRET) .$(RUNFUNREC) .$(RUNCLASSINIT) - .$(RUNCLASSINITTHROWS) + #.$(RUNCLASSINITTHROWS) .$(RUNCLASSMEMBERS) .$(RUNCLASSINHERITANCE) @@ -64,87 +65,87 @@ echo: @echo ${RUN} test_declaration_and_assignment: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.out -w -fpermissive $(TESTDIR)/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.out -w -fpermissive $(TESTDIR)/Systemtests/DeclarationAndAssignment/TestDeclarationAndAssignment.c* $(C_FILES_TEST) $(C_FILES) test_arithmetic_ops: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ArithmeticOps/TestArithmeticOps.out -w -fpermissive $(TESTDIR)/Systemtests/ArithmeticOps/TestArithmeticOps.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ArithmeticOps/TestArithmeticOps.out -w -fpermissive $(TESTDIR)/Systemtests/ArithmeticOps/TestArithmeticOps.c* $(C_FILES_TEST) $(C_FILES) test_comparison_ops: $(CC) --version - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestComparisonOps.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestComparisonOps.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestComparisonOps.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestComparisonOps.c* $(C_FILES_TEST) $(C_FILES) test_greater_equal_op: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterEqualOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterEqualOp.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterEqualOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterEqualOp.c* $(C_FILES_TEST) $(C_FILES) test_greater_op: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterOp.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestGreaterOp.c* $(C_FILES_TEST) $(C_FILES) test_less_equal_op: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestLessEqualOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestLessEqualOp.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestLessEqualOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestLessEqualOp.c* $(C_FILES_TEST) $(C_FILES) test_less_op: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestLessOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestLessOp.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/ComparisonOps/TestLessOp.out -w -fpermissive $(TESTDIR)/Systemtests/ComparisonOps/TestLessOp.c* $(C_FILES_TEST) $(C_FILES) test_logical_ops: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/LogicalOps/TestLogicalOps.out -w -fpermissive $(TESTDIR)/Systemtests/LogicalOps/TestLogicalOps.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/LogicalOps/TestLogicalOps.out -w -fpermissive $(TESTDIR)/Systemtests/LogicalOps/TestLogicalOps.c* $(C_FILES_TEST) $(C_FILES) test_if_statement: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestIfStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestIfStatement.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestIfStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestIfStatement.c* $(C_FILES_TEST) $(C_FILES) test_else_statement: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestElseStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestElseStatement.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestElseStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestElseStatement.c* $(C_FILES_TEST) $(C_FILES) test_elif_statement: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestElifStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestElifStatement.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestElifStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestElifStatement.c* $(C_FILES_TEST) $(C_FILES) test_while_statement: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestWhileStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestWhileStatement.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Conditions/TestWhileStatement.out -w -fpermissive $(TESTDIR)/Systemtests/Conditions/TestWhileStatement.c* $(C_FILES_TEST) $(C_FILES) test_cast_int: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastInt.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastInt.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastInt.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastInt.c* $(C_FILES_TEST) $(C_FILES) test_cast_string: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastString.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastString.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastString.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestCastString.c* $(C_FILES_TEST) $(C_FILES) test_id: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestId.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestId.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestId.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestId.c* $(C_FILES_TEST) $(C_FILES) test_print: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestPrint.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestPrint.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestPrint.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestPrint.c* $(C_FILES_TEST) $(C_FILES) test_type: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestType.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestType.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/BuiltInFunctions/TestType.out -w -fpermissive $(TESTDIR)/Systemtests/BuiltInFunctions/TestType.c* $(C_FILES_TEST) $(C_FILES) -test_function_params: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParams.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParams.c* $(C_FILES_TEST) +#test_function_params: + #$(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParams.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParams.c* $(C_FILES_TEST) $(C_FILES) test_function_params_throws: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParamsThrows.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParamsThrows.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParamsThrows.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionParamsThrows.c* $(C_FILES_TEST) $(C_FILES) test_function_body: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionBody.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionBody.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionBody.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionBody.c* $(C_FILES_TEST) $(C_FILES) test_function_return: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionReturn.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionReturn.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionReturn.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionReturn.c* $(C_FILES_TEST) $(C_FILES) test_function_recursion: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionRecursion.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionRecursion.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionRecursion.out -w -fpermissive $(TESTDIR)/Systemtests/FunctionCalls/TestFunctionRecursion.c* $(C_FILES_TEST) $(C_FILES) test_class_init: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInit.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInit.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInit.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInit.c* $(C_FILES_TEST) $(C_FILES) test_class_init_throws: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInitThrows.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInitThrows.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInitThrows.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInitThrows.c* $(C_FILES_TEST) $(C_FILES) test_class_members: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassMembers.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassMembers.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassMembers.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassMembers.c* $(C_FILES_TEST) $(C_FILES) test_class_inheritance: $(CC) --version - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInheritance.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInheritance.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/Classes/TestClassInheritance.out -w -fpermissive $(TESTDIR)/Systemtests/Classes/TestClassInheritance.c* $(C_FILES_TEST) $(C_FILES) test_wuppie: - $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/wuppie.out -w -fpermissive $(TESTDIR)/Systemtests/wuppie.c* $(C_FILES_TEST) + $(CC) -I $(INCLUDEDIR) -I $(INCLUDEDIRTEST) -o $(TESTDIR)/Systemtests/wuppie.out -w -fpermissive $(TESTDIR)/Systemtests/wuppie.c* $(C_FILES_TEST) $(C_FILES) clean: diff --git a/c-runtime/test/Systemtests/wuppie.cpp b/c-runtime/test/Systemtests/wuppie.cpp index 09e0473..a322426 100644 --- a/c-runtime/test/Systemtests/wuppie.cpp +++ b/c-runtime/test/Systemtests/wuppie.cpp @@ -2,7 +2,7 @@ #include -#include "catch.hpp" +#include "catch_amalgamated.hpp" #include "assert.h" #include "mpy_aliases.h" #include "mpy_obj.h" diff --git a/c-runtime/test/include/catch_amalgamated.hpp b/c-runtime/test/include/catch_amalgamated.hpp new file mode 100644 index 0000000..6cc67e7 --- /dev/null +++ b/c-runtime/test/include/catch_amalgamated.hpp @@ -0,0 +1,14057 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 + +// Catch v3.6.0 +// Generated: 2024-05-05 20:53:27.071502 +// ---------------------------------------------------------- +// This file is an amalgamation of multiple different files. +// You probably shouldn't edit it directly. +// ---------------------------------------------------------- +#ifndef CATCH_AMALGAMATED_HPP_INCLUDED +#define CATCH_AMALGAMATED_HPP_INCLUDED + + +/** \file + * This is a convenience header for Catch2. It includes **all** of Catch2 headers. + * + * Generally the Catch2 users should use specific includes they need, + * but this header can be used instead for ease-of-experimentation, or + * just plain convenience, at the cost of (significantly) increased + * compilation times. + * + * When a new header is added to either the top level folder, or to the + * corresponding internal subfolder, it should be added here. Headers + * added to the various subparts (e.g. matchers, generators, etc...), + * should go their respective catch-all headers. + */ + +#ifndef CATCH_ALL_HPP_INCLUDED +#define CATCH_ALL_HPP_INCLUDED + + + +/** \file + * This is a convenience header for Catch2's benchmarking. It includes + * **all** of Catch2 headers related to benchmarking. + * + * Generally the Catch2 users should use specific includes they need, + * but this header can be used instead for ease-of-experimentation, or + * just plain convenience, at the cost of (significantly) increased + * compilation times. + * + * When a new header is added to either the `benchmark` folder, or to + * the corresponding internal (detail) subfolder, it should be added here. + */ + +#ifndef CATCH_BENCHMARK_ALL_HPP_INCLUDED +#define CATCH_BENCHMARK_ALL_HPP_INCLUDED + + + +// Adapted from donated nonius code. + +#ifndef CATCH_BENCHMARK_HPP_INCLUDED +#define CATCH_BENCHMARK_HPP_INCLUDED + + + +#ifndef CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED +#define CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Detect a number of compiler features - by compiler +// The following features are defined: +// +// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? +// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? +// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + + + +#ifndef CATCH_PLATFORM_HPP_INCLUDED +#define CATCH_PLATFORM_HPP_INCLUDED + +// See e.g.: +// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html +#ifdef __APPLE__ +# ifndef __has_extension +# define __has_extension(x) 0 +# endif +# include +# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ + (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) +# define CATCH_PLATFORM_MAC +# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) +# define CATCH_PLATFORM_IPHONE +# endif + +#elif defined(linux) || defined(__linux) || defined(__linux__) +# define CATCH_PLATFORM_LINUX + +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) +# define CATCH_PLATFORM_WINDOWS + +# if defined( WINAPI_FAMILY ) && ( WINAPI_FAMILY == WINAPI_FAMILY_APP ) +# define CATCH_PLATFORM_WINDOWS_UWP +# endif + +#elif defined(__ORBIS__) || defined(__PROSPERO__) +# define CATCH_PLATFORM_PLAYSTATION + +#endif + +#endif // CATCH_PLATFORM_HPP_INCLUDED + +#ifdef __cplusplus + +# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +# define CATCH_CPP17_OR_GREATER +# endif + +# if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) +# define CATCH_CPP20_OR_GREATER +# endif + +#endif + +// Only GCC compiler should be used in this block, so other compilers trying to +// mask themselves as GCC should be ignored. +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) && !defined(__NVCOMPILER) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) + +// This only works on GCC 9+. so we have to also add a global suppression of Wparentheses +// for older versions of GCC. +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ + _Pragma( "GCC diagnostic ignored \"-Wunused-result\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + _Pragma( "GCC diagnostic ignored \"-Wunused-variable\"" ) + +# define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ + _Pragma( "GCC diagnostic ignored \"-Wuseless-cast\"" ) + +# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ + _Pragma( "GCC diagnostic ignored \"-Wshadow\"" ) + +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + +#endif + +#if defined(__NVCOMPILER) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "diag push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "diag pop" ) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress declared_but_not_referenced" ) +#endif + +#if defined(__CUDACC__) && !defined(__clang__) +# ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ +// New pragmas introduced in CUDA 11.5+ +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic pop" ) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "nv_diag_suppress 177" ) +# else +# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress 177" ) +# endif +#endif + +// clang-cl defines _MSC_VER as well as __clang__, which could cause the +// start/stop internal suppression macros to be double defined. +#if defined(__clang__) && !defined(_MSC_VER) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) + +#endif // __clang__ && !_MSC_VER + +#if defined(__clang__) + +// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug +// which results in calls to destructors being emitted for each temporary, +// without a matching initialization. In practice, this can result in something +// like `std::string::~string` being called on an uninitialized value. +// +// For example, this code will likely segfault under IBM XL: +// ``` +// REQUIRE(std::string("12") + "34" == "1234") +// ``` +// +// Similarly, NVHPC's implementation of `__builtin_constant_p` has a bug which +// results in calls to the immediately evaluated lambda expressions to be +// reported as unevaluated lambdas. +// https://developer.nvidia.com/nvidia_bug/3321845. +// +// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. +# if !defined(__ibmxl__) && !defined(__CUDACC__) && !defined( __NVCOMPILER ) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ +# endif + + +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") + +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) + +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) + +# define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wcomma\"" ) + +# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wshadow\"" ) + +#endif // __clang__ + + +//////////////////////////////////////////////////////////////////////////////// +// We know some environments not to support full POSIX signals +#if defined( CATCH_PLATFORM_WINDOWS ) || \ + defined( CATCH_PLATFORM_PLAYSTATION ) || \ + defined( __CYGWIN__ ) || \ + defined( __QNX__ ) || \ + defined( __EMSCRIPTEN__ ) || \ + defined( __DJGPP__ ) || \ + defined( __OS400__ ) +# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#else +# define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Assume that some platforms do not support getenv. +#if defined( CATCH_PLATFORM_WINDOWS_UWP ) || \ + defined( CATCH_PLATFORM_PLAYSTATION ) || \ + defined( _GAMING_XBOX ) +# define CATCH_INTERNAL_CONFIG_NO_GETENV +#else +# define CATCH_INTERNAL_CONFIG_GETENV +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Android somehow still does not support std::to_string +#if defined(__ANDROID__) +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Not all Windows environments support SEH properly +#if defined(__MINGW32__) +# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#endif + +//////////////////////////////////////////////////////////////////////////////// +// PS4 +#if defined(__ORBIS__) +# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Cygwin +#ifdef __CYGWIN__ + +// Required for some versions of Cygwin to declare gettimeofday +// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin +# define _BSD_SOURCE +// some versions of cygwin (most) do not support std::to_string. Use the libstd check. +// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 +# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ + && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) + +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING + +# endif +#endif // __CYGWIN__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#if defined(_MSC_VER) + +// We want to defer to nvcc-specific warning suppression if we are compiled +// with nvcc masquerading for MSVC. +# if !defined( __CUDACC__ ) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + __pragma( warning( push ) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + __pragma( warning( pop ) ) +# endif + +// Universal Windows platform does not support SEH +// Or console colours (or console at all...) +# if defined(CATCH_PLATFORM_WINDOWS_UWP) +# define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 +# else +# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +# endif + +// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ +// _MSVC_TRADITIONAL == 0 means new conformant preprocessor +// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor +# if !defined(__clang__) // Handle Clang masquerading for msvc +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif // MSVC_TRADITIONAL +# endif // __clang__ + +#endif // _MSC_VER + +#if defined(_REENTRANT) || defined(_MSC_VER) +// Enable async processing, as -pthread is specified or no additional linking is required +# define CATCH_INTERNAL_CONFIG_USE_ASYNC +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// Check if we are compiled with -fno-exceptions or equivalent +#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) +# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED +#endif + + +//////////////////////////////////////////////////////////////////////////////// +// Embarcadero C++Build +#if defined(__BORLANDC__) + #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// RTX is a special version of Windows that is real time. +// This means that it is detected as Windows, but does not provide +// the same set of capabilities as real Windows does. +#if defined(UNDER_RTSS) || defined(RTX64_BUILD) + #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH + #define CATCH_INTERNAL_CONFIG_NO_ASYNC + #define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 +#endif + +#if !defined(_GLIBCXX_USE_C99_MATH_TR1) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Various stdlib support checks that require __has_include +#if defined(__has_include) + // Check if string_view is available and usable + #if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW + #endif + + // Check if optional is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if byte is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # include + # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0) + # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # endif + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if variant is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # if defined(__clang__) && (__clang_major__ < 8) + // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 + // fix should be in clang 8, workaround in libstdc++ 8.2 + # include + # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # define CATCH_CONFIG_NO_CPP17_VARIANT + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__clang__) && (__clang_major__ < 8) + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // defined(__has_include) + + +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) +# define CATCH_CONFIG_WINDOWS_SEH +#endif +// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. +#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) +# define CATCH_CONFIG_POSIX_SIGNALS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GETENV) && !defined(CATCH_INTERNAL_CONFIG_NO_GETENV) && !defined(CATCH_CONFIG_NO_GETENV) && !defined(CATCH_CONFIG_GETENV) +# define CATCH_CONFIG_GETENV +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) +# define CATCH_CONFIG_CPP11_TO_STRING +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) +# define CATCH_CONFIG_CPP17_OPTIONAL +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) +# define CATCH_CONFIG_CPP17_STRING_VIEW +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) +# define CATCH_CONFIG_CPP17_VARIANT +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +# define CATCH_CONFIG_CPP17_BYTE +#endif + + +#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) +# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) +# define CATCH_CONFIG_NEW_CAPTURE +#endif + +#if !defined( CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED ) && \ + !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) && \ + !defined( CATCH_CONFIG_NO_DISABLE_EXCEPTIONS ) +# define CATCH_CONFIG_DISABLE_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) +# define CATCH_CONFIG_POLYFILL_ISNAN +#endif + +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +# define CATCH_CONFIG_USE_ASYNC +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +# define CATCH_CONFIG_GLOBAL_NEXTAFTER +#endif + + +// Even if we do not think the compiler has that warning, we still have +// to provide a macro that can be used by the code. +#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS +#endif +#if !defined( CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS ) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif +#if !defined( CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS ) +# define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS +#endif +#if !defined( CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS ) +# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS +#endif + + +// The goal of this macro is to avoid evaluation of the arguments, but +// still have the compiler warn on problems inside... +#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) +#endif + +#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#elif defined(__clang__) && (__clang_major__ < 5) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + + +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#define CATCH_TRY if ((true)) +#define CATCH_CATCH_ALL if ((false)) +#define CATCH_CATCH_ANON(type) if ((false)) +#else +#define CATCH_TRY try +#define CATCH_CATCH_ALL catch (...) +#define CATCH_CATCH_ANON(type) catch (type) +#endif + +#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) +#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#endif + +#if defined( CATCH_PLATFORM_WINDOWS ) && \ + !defined( CATCH_CONFIG_COLOUR_WIN32 ) && \ + !defined( CATCH_CONFIG_NO_COLOUR_WIN32 ) && \ + !defined( CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 ) +# define CATCH_CONFIG_COLOUR_WIN32 +#endif + +#if defined( CATCH_CONFIG_SHARED_LIBRARY ) && defined( _MSC_VER ) && \ + !defined( CATCH_CONFIG_STATIC ) +# ifdef Catch2_EXPORTS +# define CATCH_EXPORT //__declspec( dllexport ) // not needed +# else +# define CATCH_EXPORT __declspec( dllimport ) +# endif +#else +# define CATCH_EXPORT +#endif + +#endif // CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + + +#ifndef CATCH_CONTEXT_HPP_INCLUDED +#define CATCH_CONTEXT_HPP_INCLUDED + + +namespace Catch { + + class IResultCapture; + class IConfig; + + class Context { + IConfig const* m_config = nullptr; + IResultCapture* m_resultCapture = nullptr; + + CATCH_EXPORT static Context* currentContext; + friend Context& getCurrentMutableContext(); + friend Context const& getCurrentContext(); + static void createContext(); + friend void cleanUpContext(); + + public: + IResultCapture* getResultCapture() const { return m_resultCapture; } + IConfig const* getConfig() const { return m_config; } + void setResultCapture( IResultCapture* resultCapture ); + void setConfig( IConfig const* config ); + }; + + Context& getCurrentMutableContext(); + + inline Context const& getCurrentContext() { + // We duplicate the logic from `getCurrentMutableContext` here, + // to avoid paying the call overhead in debug mode. + if ( !Context::currentContext ) { Context::createContext(); } + // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn) + return *Context::currentContext; + } + + void cleanUpContext(); + + class SimplePcg32; + SimplePcg32& sharedRng(); +} + +#endif // CATCH_CONTEXT_HPP_INCLUDED + + +#ifndef CATCH_MOVE_AND_FORWARD_HPP_INCLUDED +#define CATCH_MOVE_AND_FORWARD_HPP_INCLUDED + +#include + +//! Replacement for std::move with better compile time performance +#define CATCH_MOVE(...) static_cast&&>(__VA_ARGS__) + +//! Replacement for std::forward with better compile time performance +#define CATCH_FORWARD(...) static_cast(__VA_ARGS__) + +#endif // CATCH_MOVE_AND_FORWARD_HPP_INCLUDED + + +#ifndef CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED +#define CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED + +namespace Catch { + + //! Used to signal that an assertion macro failed + struct TestFailureException{}; + //! Used to signal that the remainder of a test should be skipped + struct TestSkipException {}; + + /** + * Outlines throwing of `TestFailureException` into a single TU + * + * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers. + */ + [[noreturn]] void throw_test_failure_exception(); + + /** + * Outlines throwing of `TestSkipException` into a single TU + * + * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers. + */ + [[noreturn]] void throw_test_skip_exception(); + +} // namespace Catch + +#endif // CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED + + +#ifndef CATCH_UNIQUE_NAME_HPP_INCLUDED +#define CATCH_UNIQUE_NAME_HPP_INCLUDED + + + + +/** \file + * Wrapper for the CONFIG configuration option + * + * When generating internal unique names, there are two options. Either + * we mix in the current line number, or mix in an incrementing number. + * We prefer the latter, using `__COUNTER__`, but users might want to + * use the former. + */ + +#ifndef CATCH_CONFIG_COUNTER_HPP_INCLUDED +#define CATCH_CONFIG_COUNTER_HPP_INCLUDED + + +#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) + #define CATCH_INTERNAL_CONFIG_COUNTER +#endif + +#if defined( CATCH_INTERNAL_CONFIG_COUNTER ) && \ + !defined( CATCH_CONFIG_NO_COUNTER ) && \ + !defined( CATCH_CONFIG_COUNTER ) +# define CATCH_CONFIG_COUNTER +#endif + + +#endif // CATCH_CONFIG_COUNTER_HPP_INCLUDED +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif + +#endif // CATCH_UNIQUE_NAME_HPP_INCLUDED + + +#ifndef CATCH_INTERFACES_CAPTURE_HPP_INCLUDED +#define CATCH_INTERFACES_CAPTURE_HPP_INCLUDED + +#include +#include + + + +#ifndef CATCH_STRINGREF_HPP_INCLUDED +#define CATCH_STRINGREF_HPP_INCLUDED + +#include +#include +#include +#include + +#include + +namespace Catch { + + /// A non-owning string class (similar to the forthcoming std::string_view) + /// Note that, because a StringRef may be a substring of another string, + /// it may not be null terminated. + class StringRef { + public: + using size_type = std::size_t; + using const_iterator = const char*; + + static constexpr size_type npos{ static_cast( -1 ) }; + + private: + static constexpr char const* const s_empty = ""; + + char const* m_start = s_empty; + size_type m_size = 0; + + public: // construction + constexpr StringRef() noexcept = default; + + StringRef( char const* rawChars ) noexcept; + + constexpr StringRef( char const* rawChars, size_type size ) noexcept + : m_start( rawChars ), + m_size( size ) + {} + + StringRef( std::string const& stdString ) noexcept + : m_start( stdString.c_str() ), + m_size( stdString.size() ) + {} + + explicit operator std::string() const { + return std::string(m_start, m_size); + } + + public: // operators + auto operator == ( StringRef other ) const noexcept -> bool { + return m_size == other.m_size + && (std::memcmp( m_start, other.m_start, m_size ) == 0); + } + auto operator != (StringRef other) const noexcept -> bool { + return !(*this == other); + } + + constexpr auto operator[] ( size_type index ) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } + + bool operator<(StringRef rhs) const noexcept; + + public: // named queries + constexpr auto empty() const noexcept -> bool { + return m_size == 0; + } + constexpr auto size() const noexcept -> size_type { + return m_size; + } + + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + constexpr StringRef substr(size_type start, size_type length) const noexcept { + if (start < m_size) { + const auto shortened_size = m_size - start; + return StringRef(m_start + start, (shortened_size < length) ? shortened_size : length); + } else { + return StringRef(); + } + } + + // Returns the current start pointer. May not be null-terminated. + constexpr char const* data() const noexcept { + return m_start; + } + + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } + + + friend std::string& operator += (std::string& lhs, StringRef rhs); + friend std::ostream& operator << (std::ostream& os, StringRef str); + friend std::string operator+(StringRef lhs, StringRef rhs); + + /** + * Provides a three-way comparison with rhs + * + * Returns negative number if lhs < rhs, 0 if lhs == rhs, and a positive + * number if lhs > rhs + */ + int compare( StringRef rhs ) const; + }; + + + constexpr auto operator ""_sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + return StringRef( rawChars, size ); + } +} // namespace Catch + +constexpr auto operator ""_catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { + return Catch::StringRef( rawChars, size ); +} + +#endif // CATCH_STRINGREF_HPP_INCLUDED + + +#ifndef CATCH_RESULT_TYPE_HPP_INCLUDED +#define CATCH_RESULT_TYPE_HPP_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + // TODO: Should explicit skip be considered "not OK" (cf. isOk)? I.e., should it have the failure bit? + ExplicitSkip = 4, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, + + FatalErrorCondition = 0x200 | FailureBit + + }; }; + + bool isOk( ResultWas::OfType resultType ); + bool isJustInfo( int flags ); + + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x01, + + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test + }; }; + + ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); + + bool shouldContinueOnFailure( int flags ); + inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + bool shouldSuppressFailure( int flags ); + +} // end namespace Catch + +#endif // CATCH_RESULT_TYPE_HPP_INCLUDED + + +#ifndef CATCH_UNIQUE_PTR_HPP_INCLUDED +#define CATCH_UNIQUE_PTR_HPP_INCLUDED + +#include +#include + + +namespace Catch { +namespace Detail { + /** + * A reimplementation of `std::unique_ptr` for improved compilation performance + * + * Does not support arrays nor custom deleters. + */ + template + class unique_ptr { + T* m_ptr; + public: + constexpr unique_ptr(std::nullptr_t = nullptr): + m_ptr{} + {} + explicit constexpr unique_ptr(T* ptr): + m_ptr(ptr) + {} + + template ::value>> + unique_ptr(unique_ptr&& from): + m_ptr(from.release()) + {} + + template ::value>> + unique_ptr& operator=(unique_ptr&& from) { + reset(from.release()); + + return *this; + } + + unique_ptr(unique_ptr const&) = delete; + unique_ptr& operator=(unique_ptr const&) = delete; + + unique_ptr(unique_ptr&& rhs) noexcept: + m_ptr(rhs.m_ptr) { + rhs.m_ptr = nullptr; + } + unique_ptr& operator=(unique_ptr&& rhs) noexcept { + reset(rhs.release()); + + return *this; + } + + ~unique_ptr() { + delete m_ptr; + } + + T& operator*() { + assert(m_ptr); + return *m_ptr; + } + T const& operator*() const { + assert(m_ptr); + return *m_ptr; + } + T* operator->() noexcept { + assert(m_ptr); + return m_ptr; + } + T const* operator->() const noexcept { + assert(m_ptr); + return m_ptr; + } + + T* get() { return m_ptr; } + T const* get() const { return m_ptr; } + + void reset(T* ptr = nullptr) { + delete m_ptr; + m_ptr = ptr; + } + + T* release() { + auto temp = m_ptr; + m_ptr = nullptr; + return temp; + } + + explicit operator bool() const { + return m_ptr; + } + + friend void swap(unique_ptr& lhs, unique_ptr& rhs) { + auto temp = lhs.m_ptr; + lhs.m_ptr = rhs.m_ptr; + rhs.m_ptr = temp; + } + }; + + //! Specialization to cause compile-time error for arrays + template + class unique_ptr; + + template + unique_ptr make_unique(Args&&... args) { + return unique_ptr(new T(CATCH_FORWARD(args)...)); + } + + +} // end namespace Detail +} // end namespace Catch + +#endif // CATCH_UNIQUE_PTR_HPP_INCLUDED + + +#ifndef CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED +#define CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED + + + +// Adapted from donated nonius code. + +#ifndef CATCH_CLOCK_HPP_INCLUDED +#define CATCH_CLOCK_HPP_INCLUDED + +#include + +namespace Catch { + namespace Benchmark { + using IDuration = std::chrono::nanoseconds; + using FDuration = std::chrono::duration; + + template + using TimePoint = typename Clock::time_point; + + using default_clock = std::chrono::steady_clock; + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_CLOCK_HPP_INCLUDED + +namespace Catch { + + // We cannot forward declare the type with default template argument + // multiple times, so it is split out into a separate header so that + // we can prevent multiple declarations in dependees + template + struct BenchmarkStats; + +} // end namespace Catch + +#endif // CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED + +namespace Catch { + + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct SectionEndInfo; + struct MessageInfo; + struct MessageBuilder; + struct Counts; + struct AssertionReaction; + struct SourceLineInfo; + + class ITransientExpression; + class IGeneratorTracker; + + struct BenchmarkInfo; + + namespace Generators { + class GeneratorUntypedBase; + using GeneratorBasePtr = Catch::Detail::unique_ptr; + } + + + class IResultCapture { + public: + virtual ~IResultCapture(); + + virtual void notifyAssertionStarted( AssertionInfo const& info ) = 0; + virtual bool sectionStarted( StringRef sectionName, + SourceLineInfo const& sectionLineInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionEndInfo&& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo&& endInfo ) = 0; + + virtual IGeneratorTracker* + acquireGeneratorTracker( StringRef generatorName, + SourceLineInfo const& lineInfo ) = 0; + virtual IGeneratorTracker* + createGeneratorTracker( StringRef generatorName, + SourceLineInfo lineInfo, + Generators::GeneratorBasePtr&& generator ) = 0; + + virtual void benchmarkPreparing( StringRef name ) = 0; + virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; + virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0; + virtual void benchmarkFailed( StringRef error ) = 0; + + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual void emplaceUnscopedMessage( MessageBuilder&& builder ) = 0; + + virtual void handleFatalErrorCondition( StringRef message ) = 0; + + virtual void handleExpr + ( AssertionInfo const& info, + ITransientExpression const& expr, + AssertionReaction& reaction ) = 0; + virtual void handleMessage + ( AssertionInfo const& info, + ResultWas::OfType resultType, + StringRef message, + AssertionReaction& reaction ) = 0; + virtual void handleUnexpectedExceptionNotThrown + ( AssertionInfo const& info, + AssertionReaction& reaction ) = 0; + virtual void handleUnexpectedInflightException + ( AssertionInfo const& info, + std::string&& message, + AssertionReaction& reaction ) = 0; + virtual void handleIncomplete + ( AssertionInfo const& info ) = 0; + virtual void handleNonExpr + ( AssertionInfo const &info, + ResultWas::OfType resultType, + AssertionReaction &reaction ) = 0; + + + + virtual bool lastAssertionPassed() = 0; + virtual void assertionPassed() = 0; + + // Deprecated, do not use: + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + virtual void exceptionEarlyReported() = 0; + }; + + IResultCapture& getResultCapture(); +} + +#endif // CATCH_INTERFACES_CAPTURE_HPP_INCLUDED + + +#ifndef CATCH_INTERFACES_CONFIG_HPP_INCLUDED +#define CATCH_INTERFACES_CONFIG_HPP_INCLUDED + + + +#ifndef CATCH_NONCOPYABLE_HPP_INCLUDED +#define CATCH_NONCOPYABLE_HPP_INCLUDED + +namespace Catch { + namespace Detail { + + //! Deriving classes become noncopyable and nonmovable + class NonCopyable { + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable&& ) = delete; + NonCopyable& operator=( NonCopyable const& ) = delete; + NonCopyable& operator=( NonCopyable&& ) = delete; + + protected: + NonCopyable() noexcept = default; + }; + + } // namespace Detail +} // namespace Catch + +#endif // CATCH_NONCOPYABLE_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + enum class Verbosity { + Quiet = 0, + Normal, + High + }; + + struct WarnAbout { enum What { + Nothing = 0x00, + //! A test case or leaf section did not run any assertions + NoAssertions = 0x01, + //! A command line test spec matched no test cases + UnmatchedTestSpec = 0x02, + }; }; + + enum class ShowDurations { + DefaultForReporter, + Always, + Never + }; + enum class TestRunOrder { + Declared, + LexicographicallySorted, + Randomized + }; + enum class ColourMode : std::uint8_t { + //! Let Catch2 pick implementation based on platform detection + PlatformDefault, + //! Use ANSI colour code escapes + ANSI, + //! Use Win32 console colour API + Win32, + //! Don't use any colour + None + }; + struct WaitForKeypress { enum When { + Never, + BeforeStart = 1, + BeforeExit = 2, + BeforeStartAndExit = BeforeStart | BeforeExit + }; }; + + class TestSpec; + class IStream; + + class IConfig : public Detail::NonCopyable { + public: + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual StringRef name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual bool warnAboutUnmatchedTestSpecs() const = 0; + virtual bool zeroTestsCountAsSuccess() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations showDurations() const = 0; + virtual double minDuration() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual bool hasTestFilters() const = 0; + virtual std::vector const& getTestsOrTags() const = 0; + virtual TestRunOrder runOrder() const = 0; + virtual uint32_t rngSeed() const = 0; + virtual unsigned int shardCount() const = 0; + virtual unsigned int shardIndex() const = 0; + virtual ColourMode defaultColourMode() const = 0; + virtual std::vector const& getSectionsToRun() const = 0; + virtual Verbosity verbosity() const = 0; + + virtual bool skipBenchmarks() const = 0; + virtual bool benchmarkNoAnalysis() const = 0; + virtual unsigned int benchmarkSamples() const = 0; + virtual double benchmarkConfidenceInterval() const = 0; + virtual unsigned int benchmarkResamples() const = 0; + virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0; + }; +} + +#endif // CATCH_INTERFACES_CONFIG_HPP_INCLUDED + + +#ifndef CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED +#define CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED + + +#include + +namespace Catch { + + class TestCaseHandle; + struct TestCaseInfo; + class ITestCaseRegistry; + class IExceptionTranslatorRegistry; + class IExceptionTranslator; + class ReporterRegistry; + class IReporterFactory; + class ITagAliasRegistry; + class ITestInvoker; + class IMutableEnumValuesRegistry; + struct SourceLineInfo; + + class StartupExceptionRegistry; + class EventListenerFactory; + + using IReporterFactoryPtr = Detail::unique_ptr; + + class IRegistryHub { + public: + virtual ~IRegistryHub(); // = default + + virtual ReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; + virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0; + + + virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; + }; + + class IMutableRegistryHub { + public: + virtual ~IMutableRegistryHub(); // = default + virtual void registerReporter( std::string const& name, IReporterFactoryPtr factory ) = 0; + virtual void registerListener( Detail::unique_ptr factory ) = 0; + virtual void registerTest(Detail::unique_ptr&& testInfo, Detail::unique_ptr&& invoker) = 0; + virtual void registerTranslator( Detail::unique_ptr&& translator ) = 0; + virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; + virtual void registerStartupException() noexcept = 0; + virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0; + }; + + IRegistryHub const& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + +#endif // CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED + + +#ifndef CATCH_BENCHMARK_STATS_HPP_INCLUDED +#define CATCH_BENCHMARK_STATS_HPP_INCLUDED + + + +// Adapted from donated nonius code. + +#ifndef CATCH_ESTIMATE_HPP_INCLUDED +#define CATCH_ESTIMATE_HPP_INCLUDED + +namespace Catch { + namespace Benchmark { + template + struct Estimate { + Type point; + Type lower_bound; + Type upper_bound; + double confidence_interval; + }; + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_ESTIMATE_HPP_INCLUDED + + +// Adapted from donated nonius code. + +#ifndef CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED +#define CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED + +namespace Catch { + namespace Benchmark { + struct OutlierClassification { + int samples_seen = 0; + int low_severe = 0; // more than 3 times IQR below Q1 + int low_mild = 0; // 1.5 to 3 times IQR below Q1 + int high_mild = 0; // 1.5 to 3 times IQR above Q3 + int high_severe = 0; // more than 3 times IQR above Q3 + + int total() const { + return low_severe + low_mild + high_mild + high_severe; + } + }; + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_OUTLIERS_CLASSIFICATION_HPP_INCLUDED +// The fwd decl & default specialization needs to be seen by VS2017 before +// BenchmarkStats itself, or VS2017 will report compilation error. + +#include +#include + +namespace Catch { + + struct BenchmarkInfo { + std::string name; + double estimatedDuration; + int iterations; + unsigned int samples; + unsigned int resamples; + double clockResolution; + double clockCost; + }; + + // We need to keep template parameter for backwards compatibility, + // but we also do not want to use the template paraneter. + template + struct BenchmarkStats { + BenchmarkInfo info; + + std::vector samples; + Benchmark::Estimate mean; + Benchmark::Estimate standardDeviation; + Benchmark::OutlierClassification outliers; + double outlierVariance; + }; + + +} // end namespace Catch + +#endif // CATCH_BENCHMARK_STATS_HPP_INCLUDED + + +// Adapted from donated nonius code. + +#ifndef CATCH_ENVIRONMENT_HPP_INCLUDED +#define CATCH_ENVIRONMENT_HPP_INCLUDED + + +namespace Catch { + namespace Benchmark { + struct EnvironmentEstimate { + FDuration mean; + OutlierClassification outliers; + }; + struct Environment { + EnvironmentEstimate clock_resolution; + EnvironmentEstimate clock_cost; + }; + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_ENVIRONMENT_HPP_INCLUDED + + +// Adapted from donated nonius code. + +#ifndef CATCH_EXECUTION_PLAN_HPP_INCLUDED +#define CATCH_EXECUTION_PLAN_HPP_INCLUDED + + + +// Adapted from donated nonius code. + +#ifndef CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED +#define CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED + + + +// Adapted from donated nonius code. + +#ifndef CATCH_CHRONOMETER_HPP_INCLUDED +#define CATCH_CHRONOMETER_HPP_INCLUDED + + + +// Adapted from donated nonius code. + +#ifndef CATCH_OPTIMIZER_HPP_INCLUDED +#define CATCH_OPTIMIZER_HPP_INCLUDED + +#if defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__) +# include // atomic_thread_fence +#endif + + +#include + +namespace Catch { + namespace Benchmark { +#if defined(__GNUC__) || defined(__clang__) + template + inline void keep_memory(T* p) { + asm volatile("" : : "g"(p) : "memory"); + } + inline void keep_memory() { + asm volatile("" : : : "memory"); + } + + namespace Detail { + inline void optimizer_barrier() { keep_memory(); } + } // namespace Detail +#elif defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__) + +#if defined(_MSVC_VER) +#pragma optimize("", off) +#elif defined(__IAR_SYSTEMS_ICC__) +// For IAR the pragma only affects the following function +#pragma optimize=disable +#endif + template + inline void keep_memory(T* p) { + // thanks @milleniumbug + *reinterpret_cast(p) = *reinterpret_cast(p); + } + // TODO equivalent keep_memory() +#if defined(_MSVC_VER) +#pragma optimize("", on) +#endif + + namespace Detail { + inline void optimizer_barrier() { + std::atomic_thread_fence(std::memory_order_seq_cst); + } + } // namespace Detail + +#endif + + template + inline void deoptimize_value(T&& x) { + keep_memory(&x); + } + + template + inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t::value> { + deoptimize_value(CATCH_FORWARD(fn) (CATCH_FORWARD(args)...)); + } + + template + inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t::value> { + CATCH_FORWARD((fn)) (CATCH_FORWARD(args)...); + } + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_OPTIMIZER_HPP_INCLUDED + + +#ifndef CATCH_META_HPP_INCLUDED +#define CATCH_META_HPP_INCLUDED + +#include + +namespace Catch { + template + struct true_given : std::true_type {}; + + struct is_callable_tester { + template + static true_given()(std::declval()...))> test(int); + template + static std::false_type test(...); + }; + + template + struct is_callable; + + template + struct is_callable : decltype(is_callable_tester::test(0)) {}; + + +#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 + // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is + // replaced with std::invoke_result here. + template + using FunctionReturnType = std::remove_reference_t>>; +#else + template + using FunctionReturnType = std::remove_reference_t>>; +#endif + +} // namespace Catch + +namespace mpl_{ + struct na; +} + +#endif // CATCH_META_HPP_INCLUDED + +namespace Catch { + namespace Benchmark { + namespace Detail { + struct ChronometerConcept { + virtual void start() = 0; + virtual void finish() = 0; + virtual ~ChronometerConcept(); // = default; + + ChronometerConcept() = default; + ChronometerConcept(ChronometerConcept const&) = default; + ChronometerConcept& operator=(ChronometerConcept const&) = default; + }; + template + struct ChronometerModel final : public ChronometerConcept { + void start() override { started = Clock::now(); } + void finish() override { finished = Clock::now(); } + + IDuration elapsed() const { + return std::chrono::duration_cast( + finished - started ); + } + + TimePoint started; + TimePoint finished; + }; + } // namespace Detail + + struct Chronometer { + public: + template + void measure(Fun&& fun) { measure(CATCH_FORWARD(fun), is_callable()); } + + int runs() const { return repeats; } + + Chronometer(Detail::ChronometerConcept& meter, int repeats_) + : impl(&meter) + , repeats(repeats_) {} + + private: + template + void measure(Fun&& fun, std::false_type) { + measure([&fun](int) { return fun(); }, std::true_type()); + } + + template + void measure(Fun&& fun, std::true_type) { + Detail::optimizer_barrier(); + impl->start(); + for (int i = 0; i < repeats; ++i) invoke_deoptimized(fun, i); + impl->finish(); + Detail::optimizer_barrier(); + } + + Detail::ChronometerConcept* impl; + int repeats; + }; + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_CHRONOMETER_HPP_INCLUDED + +#include + +namespace Catch { + namespace Benchmark { + namespace Detail { + template + struct is_related + : std::is_same, std::decay_t> {}; + + /// We need to reinvent std::function because every piece of code that might add overhead + /// in a measurement context needs to have consistent performance characteristics so that we + /// can account for it in the measurement. + /// Implementations of std::function with optimizations that aren't always applicable, like + /// small buffer optimizations, are not uncommon. + /// This is effectively an implementation of std::function without any such optimizations; + /// it may be slow, but it is consistently slow. + struct BenchmarkFunction { + private: + struct callable { + virtual void call(Chronometer meter) const = 0; + virtual Catch::Detail::unique_ptr clone() const = 0; + virtual ~callable(); // = default; + + callable() = default; + callable(callable const&) = default; + callable& operator=(callable const&) = default; + }; + template + struct model : public callable { + model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {} + model(Fun const& fun_) : fun(fun_) {} + + Catch::Detail::unique_ptr clone() const override { + return Catch::Detail::make_unique>( *this ); + } + + void call(Chronometer meter) const override { + call(meter, is_callable()); + } + void call(Chronometer meter, std::true_type) const { + fun(meter); + } + void call(Chronometer meter, std::false_type) const { + meter.measure(fun); + } + + Fun fun; + }; + + struct do_nothing { void operator()() const {} }; + + template + BenchmarkFunction(model* c) : f(c) {} + + public: + BenchmarkFunction() + : f(new model{ {} }) {} + + template ::value, int> = 0> + BenchmarkFunction(Fun&& fun) + : f(new model>(CATCH_FORWARD(fun))) {} + + BenchmarkFunction( BenchmarkFunction&& that ) noexcept: + f( CATCH_MOVE( that.f ) ) {} + + BenchmarkFunction(BenchmarkFunction const& that) + : f(that.f->clone()) {} + + BenchmarkFunction& + operator=( BenchmarkFunction&& that ) noexcept { + f = CATCH_MOVE( that.f ); + return *this; + } + + BenchmarkFunction& operator=(BenchmarkFunction const& that) { + f = that.f->clone(); + return *this; + } + + void operator()(Chronometer meter) const { f->call(meter); } + + private: + Catch::Detail::unique_ptr f; + }; + } // namespace Detail + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED + + +// Adapted from donated nonius code. + +#ifndef CATCH_REPEAT_HPP_INCLUDED +#define CATCH_REPEAT_HPP_INCLUDED + +#include + +namespace Catch { + namespace Benchmark { + namespace Detail { + template + struct repeater { + void operator()(int k) const { + for (int i = 0; i < k; ++i) { + fun(); + } + } + Fun fun; + }; + template + repeater> repeat(Fun&& fun) { + return { CATCH_FORWARD(fun) }; + } + } // namespace Detail + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_REPEAT_HPP_INCLUDED + + +// Adapted from donated nonius code. + +#ifndef CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED +#define CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED + + + +// Adapted from donated nonius code. + +#ifndef CATCH_MEASURE_HPP_INCLUDED +#define CATCH_MEASURE_HPP_INCLUDED + + + +// Adapted from donated nonius code. + +#ifndef CATCH_COMPLETE_INVOKE_HPP_INCLUDED +#define CATCH_COMPLETE_INVOKE_HPP_INCLUDED + + +namespace Catch { + namespace Benchmark { + namespace Detail { + template + struct CompleteType { using type = T; }; + template <> + struct CompleteType { struct type {}; }; + + template + using CompleteType_t = typename CompleteType::type; + + template + struct CompleteInvoker { + template + static Result invoke(Fun&& fun, Args&&... args) { + return CATCH_FORWARD(fun)(CATCH_FORWARD(args)...); + } + }; + template <> + struct CompleteInvoker { + template + static CompleteType_t invoke(Fun&& fun, Args&&... args) { + CATCH_FORWARD(fun)(CATCH_FORWARD(args)...); + return {}; + } + }; + + // invoke and not return void :( + template + CompleteType_t> complete_invoke(Fun&& fun, Args&&... args) { + return CompleteInvoker>::invoke(CATCH_FORWARD(fun), CATCH_FORWARD(args)...); + } + + } // namespace Detail + + template + Detail::CompleteType_t> user_code(Fun&& fun) { + return Detail::complete_invoke(CATCH_FORWARD(fun)); + } + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_COMPLETE_INVOKE_HPP_INCLUDED + + +// Adapted from donated nonius code. + +#ifndef CATCH_TIMING_HPP_INCLUDED +#define CATCH_TIMING_HPP_INCLUDED + + +#include + +namespace Catch { + namespace Benchmark { + template + struct Timing { + IDuration elapsed; + Result result; + int iterations; + }; + template + using TimingOf = Timing>>; + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_TIMING_HPP_INCLUDED + +namespace Catch { + namespace Benchmark { + namespace Detail { + template + TimingOf measure(Fun&& fun, Args&&... args) { + auto start = Clock::now(); + auto&& r = Detail::complete_invoke(fun, CATCH_FORWARD(args)...); + auto end = Clock::now(); + auto delta = end - start; + return { delta, CATCH_FORWARD(r), 1 }; + } + } // namespace Detail + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_MEASURE_HPP_INCLUDED + +#include + +namespace Catch { + namespace Benchmark { + namespace Detail { + template + TimingOf measure_one(Fun&& fun, int iters, std::false_type) { + return Detail::measure(fun, iters); + } + template + TimingOf measure_one(Fun&& fun, int iters, std::true_type) { + Detail::ChronometerModel meter; + auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters)); + + return { meter.elapsed(), CATCH_MOVE(result), iters }; + } + + template + using run_for_at_least_argument_t = std::conditional_t::value, Chronometer, int>; + + + [[noreturn]] + void throw_optimized_away_error(); + + template + TimingOf> + run_for_at_least(IDuration how_long, + const int initial_iterations, + Fun&& fun) { + auto iters = initial_iterations; + while (iters < (1 << 30)) { + auto&& Timing = measure_one(fun, iters, is_callable()); + + if (Timing.elapsed >= how_long) { + return { Timing.elapsed, CATCH_MOVE(Timing.result), iters }; + } + iters *= 2; + } + throw_optimized_away_error(); + } + } // namespace Detail + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED + +#include + +namespace Catch { + namespace Benchmark { + struct ExecutionPlan { + int iterations_per_sample; + FDuration estimated_duration; + Detail::BenchmarkFunction benchmark; + FDuration warmup_time; + int warmup_iterations; + + template + std::vector run(const IConfig &cfg, Environment env) const { + // warmup a bit + Detail::run_for_at_least( + std::chrono::duration_cast( warmup_time ), + warmup_iterations, + Detail::repeat( []() { return Clock::now(); } ) + ); + + std::vector times; + const auto num_samples = cfg.benchmarkSamples(); + times.reserve( num_samples ); + for ( size_t i = 0; i < num_samples; ++i ) { + Detail::ChronometerModel model; + this->benchmark( Chronometer( model, iterations_per_sample ) ); + auto sample_time = model.elapsed() - env.clock_cost.mean; + if ( sample_time < FDuration::zero() ) { + sample_time = FDuration::zero(); + } + times.push_back(sample_time / iterations_per_sample); + } + return times; + } + }; + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_EXECUTION_PLAN_HPP_INCLUDED + + +// Adapted from donated nonius code. + +#ifndef CATCH_ESTIMATE_CLOCK_HPP_INCLUDED +#define CATCH_ESTIMATE_CLOCK_HPP_INCLUDED + + + +// Adapted from donated nonius code. + +#ifndef CATCH_STATS_HPP_INCLUDED +#define CATCH_STATS_HPP_INCLUDED + + +#include + +namespace Catch { + namespace Benchmark { + namespace Detail { + using sample = std::vector; + + double weighted_average_quantile( int k, + int q, + double* first, + double* last ); + + OutlierClassification + classify_outliers( double const* first, double const* last ); + + double mean( double const* first, double const* last ); + + double normal_cdf( double x ); + + double erfc_inv(double x); + + double normal_quantile(double p); + + Estimate + bootstrap( double confidence_level, + double* first, + double* last, + sample const& resample, + double ( *estimator )( double const*, double const* ) ); + + struct bootstrap_analysis { + Estimate mean; + Estimate standard_deviation; + double outlier_variance; + }; + + bootstrap_analysis analyse_samples(double confidence_level, + unsigned int n_resamples, + double* first, + double* last); + } // namespace Detail + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_STATS_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + namespace Benchmark { + namespace Detail { + template + std::vector resolution(int k) { + std::vector> times; + times.reserve(static_cast(k + 1)); + for ( int i = 0; i < k + 1; ++i ) { + times.push_back( Clock::now() ); + } + + std::vector deltas; + deltas.reserve(static_cast(k)); + for ( size_t idx = 1; idx < times.size(); ++idx ) { + deltas.push_back( static_cast( + ( times[idx] - times[idx - 1] ).count() ) ); + } + + return deltas; + } + + constexpr auto warmup_iterations = 10000; + constexpr auto warmup_time = std::chrono::milliseconds(100); + constexpr auto minimum_ticks = 1000; + constexpr auto warmup_seed = 10000; + constexpr auto clock_resolution_estimation_time = std::chrono::milliseconds(500); + constexpr auto clock_cost_estimation_time_limit = std::chrono::seconds(1); + constexpr auto clock_cost_estimation_tick_limit = 100000; + constexpr auto clock_cost_estimation_time = std::chrono::milliseconds(10); + constexpr auto clock_cost_estimation_iterations = 10000; + + template + int warmup() { + return run_for_at_least(warmup_time, warmup_seed, &resolution) + .iterations; + } + template + EnvironmentEstimate estimate_clock_resolution(int iterations) { + auto r = run_for_at_least(clock_resolution_estimation_time, iterations, &resolution) + .result; + return { + FDuration(mean(r.data(), r.data() + r.size())), + classify_outliers(r.data(), r.data() + r.size()), + }; + } + template + EnvironmentEstimate estimate_clock_cost(FDuration resolution) { + auto time_limit = (std::min)( + resolution * clock_cost_estimation_tick_limit, + FDuration(clock_cost_estimation_time_limit)); + auto time_clock = [](int k) { + return Detail::measure([k] { + for (int i = 0; i < k; ++i) { + volatile auto ignored = Clock::now(); + (void)ignored; + } + }).elapsed; + }; + time_clock(1); + int iters = clock_cost_estimation_iterations; + auto&& r = run_for_at_least(clock_cost_estimation_time, iters, time_clock); + std::vector times; + int nsamples = static_cast(std::ceil(time_limit / r.elapsed)); + times.reserve(static_cast(nsamples)); + for ( int s = 0; s < nsamples; ++s ) { + times.push_back( static_cast( + ( time_clock( r.iterations ) / r.iterations ) + .count() ) ); + } + return { + FDuration(mean(times.data(), times.data() + times.size())), + classify_outliers(times.data(), times.data() + times.size()), + }; + } + + template + Environment measure_environment() { +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif + static Catch::Detail::unique_ptr env; +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + if (env) { + return *env; + } + + auto iters = Detail::warmup(); + auto resolution = Detail::estimate_clock_resolution(iters); + auto cost = Detail::estimate_clock_cost(resolution.mean); + + env = Catch::Detail::make_unique( Environment{resolution, cost} ); + return *env; + } + } // namespace Detail + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_ESTIMATE_CLOCK_HPP_INCLUDED + + +// Adapted from donated nonius code. + +#ifndef CATCH_ANALYSE_HPP_INCLUDED +#define CATCH_ANALYSE_HPP_INCLUDED + + + +// Adapted from donated nonius code. + +#ifndef CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED +#define CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED + + +#include + +namespace Catch { + namespace Benchmark { + struct SampleAnalysis { + std::vector samples; + Estimate mean; + Estimate standard_deviation; + OutlierClassification outliers; + double outlier_variance; + }; + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED + + +namespace Catch { + class IConfig; + + namespace Benchmark { + namespace Detail { + SampleAnalysis analyse(const IConfig &cfg, FDuration* first, FDuration* last); + } // namespace Detail + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_ANALYSE_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace Catch { + namespace Benchmark { + struct Benchmark { + Benchmark(std::string&& benchmarkName) + : name(CATCH_MOVE(benchmarkName)) {} + + template + Benchmark(std::string&& benchmarkName , FUN &&func) + : fun(CATCH_MOVE(func)), name(CATCH_MOVE(benchmarkName)) {} + + template + ExecutionPlan prepare(const IConfig &cfg, Environment env) const { + auto min_time = env.clock_resolution.mean * Detail::minimum_ticks; + auto run_time = std::max(min_time, std::chrono::duration_cast(cfg.benchmarkWarmupTime())); + auto&& test = Detail::run_for_at_least(std::chrono::duration_cast(run_time), 1, fun); + int new_iters = static_cast(std::ceil(min_time * test.iterations / test.elapsed)); + return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast(cfg.benchmarkWarmupTime()), Detail::warmup_iterations }; + } + + template + void run() { + static_assert( Clock::is_steady, + "Benchmarking clock should be steady" ); + auto const* cfg = getCurrentContext().getConfig(); + + auto env = Detail::measure_environment(); + + getResultCapture().benchmarkPreparing(name); + CATCH_TRY{ + auto plan = user_code([&] { + return prepare(*cfg, env); + }); + + BenchmarkInfo info { + CATCH_MOVE(name), + plan.estimated_duration.count(), + plan.iterations_per_sample, + cfg->benchmarkSamples(), + cfg->benchmarkResamples(), + env.clock_resolution.mean.count(), + env.clock_cost.mean.count() + }; + + getResultCapture().benchmarkStarting(info); + + auto samples = user_code([&] { + return plan.template run(*cfg, env); + }); + + auto analysis = Detail::analyse(*cfg, samples.data(), samples.data() + samples.size()); + BenchmarkStats<> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance }; + getResultCapture().benchmarkEnded(stats); + } CATCH_CATCH_ANON (TestFailureException const&) { + getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr); + } CATCH_CATCH_ALL{ + getResultCapture().benchmarkFailed(translateActiveException()); + // We let the exception go further up so that the + // test case is marked as failed. + std::rethrow_exception(std::current_exception()); + } + } + + // sets lambda to be used in fun *and* executes benchmark! + template ::value, int> = 0> + Benchmark & operator=(Fun func) { + auto const* cfg = getCurrentContext().getConfig(); + if (!cfg->skipBenchmarks()) { + fun = Detail::BenchmarkFunction(func); + run(); + } + return *this; + } + + explicit operator bool() { + return true; + } + + private: + Detail::BenchmarkFunction fun; + std::string name; + }; + } +} // namespace Catch + +#define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1 +#define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2 + +#define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\ + if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ + BenchmarkName = [&](int benchmarkIndex) + +#define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\ + if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ + BenchmarkName = [&] + +#if defined(CATCH_CONFIG_PREFIX_ALL) + +#define CATCH_BENCHMARK(...) \ + INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) +#define CATCH_BENCHMARK_ADVANCED(name) \ + INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name) + +#else + +#define BENCHMARK(...) \ + INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) +#define BENCHMARK_ADVANCED(name) \ + INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name) + +#endif + +#endif // CATCH_BENCHMARK_HPP_INCLUDED + + +// Adapted from donated nonius code. + +#ifndef CATCH_CONSTRUCTOR_HPP_INCLUDED +#define CATCH_CONSTRUCTOR_HPP_INCLUDED + + +#include + +namespace Catch { + namespace Benchmark { + namespace Detail { + template + struct ObjectStorage + { + ObjectStorage() = default; + + ObjectStorage(const ObjectStorage& other) + { + new(&data) T(other.stored_object()); + } + + ObjectStorage(ObjectStorage&& other) + { + new(data) T(CATCH_MOVE(other.stored_object())); + } + + ~ObjectStorage() { destruct_on_exit(); } + + template + void construct(Args&&... args) + { + new (data) T(CATCH_FORWARD(args)...); + } + + template + std::enable_if_t destruct() + { + stored_object().~T(); + } + + private: + // If this is a constructor benchmark, destruct the underlying object + template + void destruct_on_exit(std::enable_if_t* = nullptr) { destruct(); } + // Otherwise, don't + template + void destruct_on_exit(std::enable_if_t* = nullptr) { } + +#if defined( __GNUC__ ) && __GNUC__ <= 6 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + T& stored_object() { return *reinterpret_cast( data ); } + + T const& stored_object() const { + return *reinterpret_cast( data ); + } +#if defined( __GNUC__ ) && __GNUC__ <= 6 +# pragma GCC diagnostic pop +#endif + + alignas( T ) unsigned char data[sizeof( T )]{}; + }; + } // namespace Detail + + template + using storage_for = Detail::ObjectStorage; + + template + using destructable_object = Detail::ObjectStorage; + } // namespace Benchmark +} // namespace Catch + +#endif // CATCH_CONSTRUCTOR_HPP_INCLUDED + +#endif // CATCH_BENCHMARK_ALL_HPP_INCLUDED + + +#ifndef CATCH_APPROX_HPP_INCLUDED +#define CATCH_APPROX_HPP_INCLUDED + + + +#ifndef CATCH_TOSTRING_HPP_INCLUDED +#define CATCH_TOSTRING_HPP_INCLUDED + + +#include +#include +#include +#include + + + + +/** \file + * Wrapper for the WCHAR configuration option + * + * We want to support platforms that do not provide `wchar_t`, so we + * sometimes have to disable providing wchar_t overloads through Catch2, + * e.g. the StringMaker specialization for `std::wstring`. + */ + +#ifndef CATCH_CONFIG_WCHAR_HPP_INCLUDED +#define CATCH_CONFIG_WCHAR_HPP_INCLUDED + + +// We assume that WCHAR should be enabled by default, and only disabled +// for a shortlist (so far only DJGPP) of compilers. + +#if defined(__DJGPP__) +# define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ + +#if !defined( CATCH_INTERNAL_CONFIG_NO_WCHAR ) && \ + !defined( CATCH_CONFIG_NO_WCHAR ) && \ + !defined( CATCH_CONFIG_WCHAR ) +# define CATCH_CONFIG_WCHAR +#endif + +#endif // CATCH_CONFIG_WCHAR_HPP_INCLUDED + + +#ifndef CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED +#define CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED + + +#include +#include +#include +#include + +namespace Catch { + + class ReusableStringStream : Detail::NonCopyable { + std::size_t m_index; + std::ostream* m_oss; + public: + ReusableStringStream(); + ~ReusableStringStream(); + + //! Returns the serialized state + std::string str() const; + //! Sets internal state to `str` + void str(std::string const& str); + +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +// Old versions of GCC do not understand -Wnonnull-compare +#pragma GCC diagnostic ignored "-Wpragmas" +// Streaming a function pointer triggers Waddress and Wnonnull-compare +// on GCC, because it implicitly converts it to bool and then decides +// that the check it uses (a? true : false) is tautological and cannot +// be null... +#pragma GCC diagnostic ignored "-Waddress" +#pragma GCC diagnostic ignored "-Wnonnull-compare" +#endif + + template + auto operator << ( T const& value ) -> ReusableStringStream& { + *m_oss << value; + return *this; + } + +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + auto get() -> std::ostream& { return *m_oss; } + }; +} + +#endif // CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED + + +#ifndef CATCH_VOID_TYPE_HPP_INCLUDED +#define CATCH_VOID_TYPE_HPP_INCLUDED + + +namespace Catch { + namespace Detail { + + template + struct make_void { using type = void; }; + + template + using void_t = typename make_void::type; + + } // namespace Detail +} // namespace Catch + + +#endif // CATCH_VOID_TYPE_HPP_INCLUDED + + +#ifndef CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED +#define CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED + + +#include + +namespace Catch { + + namespace Detail { + struct EnumInfo { + StringRef m_name; + std::vector> m_values; + + ~EnumInfo(); + + StringRef lookup( int value ) const; + }; + } // namespace Detail + + class IMutableEnumValuesRegistry { + public: + virtual ~IMutableEnumValuesRegistry(); // = default; + + virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector const& values ) = 0; + + template + Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list values ) { + static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int"); + std::vector intValues; + intValues.reserve( values.size() ); + for( auto enumValue : values ) + intValues.push_back( static_cast( enumValue ) ); + return registerEnum( enumName, allEnums, intValues ); + } + }; + +} // Catch + +#endif // CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED + +#ifdef CATCH_CONFIG_CPP17_STRING_VIEW +#include +#endif + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless +#endif + +// We need a dummy global operator<< so we can bring it into Catch namespace later +struct Catch_global_namespace_dummy{}; +std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); + +namespace Catch { + // Bring in global namespace operator<< for ADL lookup in + // `IsStreamInsertable` below. + using ::operator<<; + + namespace Detail { + + inline std::size_t catch_strnlen(const char *str, std::size_t n) { + auto ret = std::char_traits::find(str, n, '\0'); + if (ret != nullptr) { + return static_cast(ret - str); + } + return n; + } + + constexpr StringRef unprintableString = "{?}"_sr; + + //! Encases `string in quotes, and optionally escapes invisibles + std::string convertIntoString( StringRef string, bool escapeInvisibles ); + + //! Encases `string` in quotes, and escapes invisibles if user requested + //! it via CLI + std::string convertIntoString( StringRef string ); + + std::string rawMemoryToString( const void *object, std::size_t size ); + + template + std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } + + template + class IsStreamInsertable { + template + static auto test(int) + -> decltype(std::declval() << std::declval(), std::true_type()); + + template + static auto test(...)->std::false_type; + + public: + static const bool value = decltype(test(0))::value; + }; + + template + std::string convertUnknownEnumToString( E e ); + + template + std::enable_if_t< + !std::is_enum::value && !std::is_base_of::value, + std::string> convertUnstreamable( T const& ) { + return std::string(Detail::unprintableString); + } + template + std::enable_if_t< + !std::is_enum::value && std::is_base_of::value, + std::string> convertUnstreamable(T const& ex) { + return ex.what(); + } + + + template + std::enable_if_t< + std::is_enum::value, + std::string> convertUnstreamable( T const& value ) { + return convertUnknownEnumToString( value ); + } + +#if defined(_MANAGED) + //! Convert a CLR string to a utf8 std::string + template + std::string clrReferenceToString( T^ ref ) { + if (ref == nullptr) + return std::string("null"); + auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString()); + cli::pin_ptr p = &bytes[0]; + return std::string(reinterpret_cast(p), bytes->Length); + } +#endif + + } // namespace Detail + + + template + struct StringMaker { + template + static + std::enable_if_t<::Catch::Detail::IsStreamInsertable::value, std::string> + convert(const Fake& value) { + ReusableStringStream rss; + // NB: call using the function-like syntax to avoid ambiguity with + // user-defined templated operator<< under clang. + rss.operator<<(value); + return rss.str(); + } + + template + static + std::enable_if_t::value, std::string> + convert( const Fake& value ) { +#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) + return Detail::convertUnstreamable(value); +#else + return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); +#endif + } + }; + + namespace Detail { + + // This function dispatches all stringification requests inside of Catch. + // Should be preferably called fully qualified, like ::Catch::Detail::stringify + template + std::string stringify(const T& e) { + return ::Catch::StringMaker>>::convert(e); + } + + template + std::string convertUnknownEnumToString( E e ) { + return ::Catch::Detail::stringify(static_cast>(e)); + } + +#if defined(_MANAGED) + template + std::string stringify( T^ e ) { + return ::Catch::StringMaker::convert(e); + } +#endif + + } // namespace Detail + + // Some predefined specializations + + template<> + struct StringMaker { + static std::string convert(const std::string& str); + }; + +#ifdef CATCH_CONFIG_CPP17_STRING_VIEW + template<> + struct StringMaker { + static std::string convert(std::string_view str); + }; +#endif + + template<> + struct StringMaker { + static std::string convert(char const * str); + }; + template<> + struct StringMaker { + static std::string convert(char * str); + }; + +#if defined(CATCH_CONFIG_WCHAR) + template<> + struct StringMaker { + static std::string convert(const std::wstring& wstr); + }; + +# ifdef CATCH_CONFIG_CPP17_STRING_VIEW + template<> + struct StringMaker { + static std::string convert(std::wstring_view str); + }; +# endif + + template<> + struct StringMaker { + static std::string convert(wchar_t const * str); + }; + template<> + struct StringMaker { + static std::string convert(wchar_t * str); + }; +#endif // CATCH_CONFIG_WCHAR + + template + struct StringMaker { + static std::string convert(char const* str) { + return Detail::convertIntoString( + StringRef( str, Detail::catch_strnlen( str, SZ ) ) ); + } + }; + template + struct StringMaker { + static std::string convert(signed char const* str) { + auto reinterpreted = reinterpret_cast(str); + return Detail::convertIntoString( + StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ))); + } + }; + template + struct StringMaker { + static std::string convert(unsigned char const* str) { + auto reinterpreted = reinterpret_cast(str); + return Detail::convertIntoString( + StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ))); + } + }; + +#if defined(CATCH_CONFIG_CPP17_BYTE) + template<> + struct StringMaker { + static std::string convert(std::byte value); + }; +#endif // defined(CATCH_CONFIG_CPP17_BYTE) + template<> + struct StringMaker { + static std::string convert(int value); + }; + template<> + struct StringMaker { + static std::string convert(long value); + }; + template<> + struct StringMaker { + static std::string convert(long long value); + }; + template<> + struct StringMaker { + static std::string convert(unsigned int value); + }; + template<> + struct StringMaker { + static std::string convert(unsigned long value); + }; + template<> + struct StringMaker { + static std::string convert(unsigned long long value); + }; + + template<> + struct StringMaker { + static std::string convert(bool b) { + using namespace std::string_literals; + return b ? "true"s : "false"s; + } + }; + + template<> + struct StringMaker { + static std::string convert(char c); + }; + template<> + struct StringMaker { + static std::string convert(signed char value); + }; + template<> + struct StringMaker { + static std::string convert(unsigned char value); + }; + + template<> + struct StringMaker { + static std::string convert(std::nullptr_t) { + using namespace std::string_literals; + return "nullptr"s; + } + }; + + template<> + struct StringMaker { + static std::string convert(float value); + CATCH_EXPORT static int precision; + }; + + template<> + struct StringMaker { + static std::string convert(double value); + CATCH_EXPORT static int precision; + }; + + template + struct StringMaker { + template + static std::string convert(U* p) { + if (p) { + return ::Catch::Detail::rawMemoryToString(p); + } else { + return "nullptr"; + } + } + }; + + template + struct StringMaker { + static std::string convert(R C::* p) { + if (p) { + return ::Catch::Detail::rawMemoryToString(p); + } else { + return "nullptr"; + } + } + }; + +#if defined(_MANAGED) + template + struct StringMaker { + static std::string convert( T^ ref ) { + return ::Catch::Detail::clrReferenceToString(ref); + } + }; +#endif + + namespace Detail { + template + std::string rangeToString(InputIterator first, Sentinel last) { + ReusableStringStream rss; + rss << "{ "; + if (first != last) { + rss << ::Catch::Detail::stringify(*first); + for (++first; first != last; ++first) + rss << ", " << ::Catch::Detail::stringify(*first); + } + rss << " }"; + return rss.str(); + } + } + +} // namespace Catch + +////////////////////////////////////////////////////// +// Separate std-lib types stringification, so it can be selectively enabled +// This means that we do not bring in their headers + +#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) +# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER +# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER +# define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER +# define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER +#endif + +// Separate std::pair specialization +#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) +#include +namespace Catch { + template + struct StringMaker > { + static std::string convert(const std::pair& pair) { + ReusableStringStream rss; + rss << "{ " + << ::Catch::Detail::stringify(pair.first) + << ", " + << ::Catch::Detail::stringify(pair.second) + << " }"; + return rss.str(); + } + }; +} +#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER + +#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL) +#include +namespace Catch { + template + struct StringMaker > { + static std::string convert(const std::optional& optional) { + if (optional.has_value()) { + return ::Catch::Detail::stringify(*optional); + } else { + return "{ }"; + } + } + }; + template <> + struct StringMaker { + static std::string convert(const std::nullopt_t&) { + return "{ }"; + } + }; +} +#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER + +// Separate std::tuple specialization +#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) +#include +namespace Catch { + namespace Detail { + template< + typename Tuple, + std::size_t N = 0, + bool = (N < std::tuple_size::value) + > + struct TupleElementPrinter { + static void print(const Tuple& tuple, std::ostream& os) { + os << (N ? ", " : " ") + << ::Catch::Detail::stringify(std::get(tuple)); + TupleElementPrinter::print(tuple, os); + } + }; + + template< + typename Tuple, + std::size_t N + > + struct TupleElementPrinter { + static void print(const Tuple&, std::ostream&) {} + }; + + } + + + template + struct StringMaker> { + static std::string convert(const std::tuple& tuple) { + ReusableStringStream rss; + rss << '{'; + Detail::TupleElementPrinter>::print(tuple, rss.get()); + rss << " }"; + return rss.str(); + } + }; +} +#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER + +#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT) +#include +namespace Catch { + template<> + struct StringMaker { + static std::string convert(const std::monostate&) { + return "{ }"; + } + }; + + template + struct StringMaker> { + static std::string convert(const std::variant& variant) { + if (variant.valueless_by_exception()) { + return "{valueless variant}"; + } else { + return std::visit( + [](const auto& value) { + return ::Catch::Detail::stringify(value); + }, + variant + ); + } + } + }; +} +#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER + +namespace Catch { + // Import begin/ end from std here + using std::begin; + using std::end; + + namespace Detail { + template + struct is_range_impl : std::false_type {}; + + template + struct is_range_impl()))>> : std::true_type {}; + } // namespace Detail + + template + struct is_range : Detail::is_range_impl {}; + +#if defined(_MANAGED) // Managed types are never ranges + template + struct is_range { + static const bool value = false; + }; +#endif + + template + std::string rangeToString( Range const& range ) { + return ::Catch::Detail::rangeToString( begin( range ), end( range ) ); + } + + // Handle vector specially + template + std::string rangeToString( std::vector const& v ) { + ReusableStringStream rss; + rss << "{ "; + bool first = true; + for( bool b : v ) { + if( first ) + first = false; + else + rss << ", "; + rss << ::Catch::Detail::stringify( b ); + } + rss << " }"; + return rss.str(); + } + + template + struct StringMaker::value && !::Catch::Detail::IsStreamInsertable::value>> { + static std::string convert( R const& range ) { + return rangeToString( range ); + } + }; + + template + struct StringMaker { + static std::string convert(T const(&arr)[SZ]) { + return rangeToString(arr); + } + }; + + +} // namespace Catch + +// Separate std::chrono::duration specialization +#include +#include +#include + + +namespace Catch { + +template +struct ratio_string { + static std::string symbol() { + Catch::ReusableStringStream rss; + rss << '[' << Ratio::num << '/' + << Ratio::den << ']'; + return rss.str(); + } +}; + +template <> +struct ratio_string { + static char symbol() { return 'a'; } +}; +template <> +struct ratio_string { + static char symbol() { return 'f'; } +}; +template <> +struct ratio_string { + static char symbol() { return 'p'; } +}; +template <> +struct ratio_string { + static char symbol() { return 'n'; } +}; +template <> +struct ratio_string { + static char symbol() { return 'u'; } +}; +template <> +struct ratio_string { + static char symbol() { return 'm'; } +}; + + //////////// + // std::chrono::duration specializations + template + struct StringMaker> { + static std::string convert(std::chrono::duration const& duration) { + ReusableStringStream rss; + rss << duration.count() << ' ' << ratio_string::symbol() << 's'; + return rss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + ReusableStringStream rss; + rss << duration.count() << " s"; + return rss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + ReusableStringStream rss; + rss << duration.count() << " m"; + return rss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + ReusableStringStream rss; + rss << duration.count() << " h"; + return rss.str(); + } + }; + + //////////// + // std::chrono::time_point specialization + // Generic time_point cannot be specialized, only std::chrono::time_point + template + struct StringMaker> { + static std::string convert(std::chrono::time_point const& time_point) { + return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch"; + } + }; + // std::chrono::time_point specialization + template + struct StringMaker> { + static std::string convert(std::chrono::time_point const& time_point) { + auto converted = std::chrono::system_clock::to_time_t(time_point); + +#ifdef _MSC_VER + std::tm timeInfo = {}; + gmtime_s(&timeInfo, &converted); +#else + std::tm* timeInfo = std::gmtime(&converted); +#endif + + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); + char timeStamp[timeStampSize]; + const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; + +#ifdef _MSC_VER + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); +#else + std::strftime(timeStamp, timeStampSize, fmt, timeInfo); +#endif + return std::string(timeStamp, timeStampSize - 1); + } + }; +} + + +#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \ +namespace Catch { \ + template<> struct StringMaker { \ + static std::string convert( enumName value ) { \ + static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \ + return static_cast(enumInfo.lookup( static_cast( value ) )); \ + } \ + }; \ +} + +#define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ ) + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif // CATCH_TOSTRING_HPP_INCLUDED + +#include + +namespace Catch { + + class Approx { + private: + bool equalityComparisonImpl(double other) const; + // Sets and validates the new margin (margin >= 0) + void setMargin(double margin); + // Sets and validates the new epsilon (0 < epsilon < 1) + void setEpsilon(double epsilon); + + public: + explicit Approx ( double value ); + + static Approx custom(); + + Approx operator-() const; + + template ::value>> + Approx operator()( T const& value ) const { + Approx approx( static_cast(value) ); + approx.m_epsilon = m_epsilon; + approx.m_margin = m_margin; + approx.m_scale = m_scale; + return approx; + } + + template ::value>> + explicit Approx( T const& value ): Approx(static_cast(value)) + {} + + + template ::value>> + friend bool operator == ( const T& lhs, Approx const& rhs ) { + auto lhs_v = static_cast(lhs); + return rhs.equalityComparisonImpl(lhs_v); + } + + template ::value>> + friend bool operator == ( Approx const& lhs, const T& rhs ) { + return operator==( rhs, lhs ); + } + + template ::value>> + friend bool operator != ( T const& lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + template ::value>> + friend bool operator != ( Approx const& lhs, T const& rhs ) { + return !operator==( rhs, lhs ); + } + + template ::value>> + friend bool operator <= ( T const& lhs, Approx const& rhs ) { + return static_cast(lhs) < rhs.m_value || lhs == rhs; + } + + template ::value>> + friend bool operator <= ( Approx const& lhs, T const& rhs ) { + return lhs.m_value < static_cast(rhs) || lhs == rhs; + } + + template ::value>> + friend bool operator >= ( T const& lhs, Approx const& rhs ) { + return static_cast(lhs) > rhs.m_value || lhs == rhs; + } + + template ::value>> + friend bool operator >= ( Approx const& lhs, T const& rhs ) { + return lhs.m_value > static_cast(rhs) || lhs == rhs; + } + + template ::value>> + Approx& epsilon( T const& newEpsilon ) { + const auto epsilonAsDouble = static_cast(newEpsilon); + setEpsilon(epsilonAsDouble); + return *this; + } + + template ::value>> + Approx& margin( T const& newMargin ) { + const auto marginAsDouble = static_cast(newMargin); + setMargin(marginAsDouble); + return *this; + } + + template ::value>> + Approx& scale( T const& newScale ) { + m_scale = static_cast(newScale); + return *this; + } + + std::string toString() const; + + private: + double m_epsilon; + double m_margin; + double m_scale; + double m_value; + }; + +namespace literals { + Approx operator ""_a(long double val); + Approx operator ""_a(unsigned long long val); +} // end namespace literals + +template<> +struct StringMaker { + static std::string convert(Catch::Approx const& value); +}; + +} // end namespace Catch + +#endif // CATCH_APPROX_HPP_INCLUDED + + +#ifndef CATCH_ASSERTION_INFO_HPP_INCLUDED +#define CATCH_ASSERTION_INFO_HPP_INCLUDED + + + +#ifndef CATCH_SOURCE_LINE_INFO_HPP_INCLUDED +#define CATCH_SOURCE_LINE_INFO_HPP_INCLUDED + +#include +#include + +namespace Catch { + + struct SourceLineInfo { + + SourceLineInfo() = delete; + constexpr SourceLineInfo( char const* _file, std::size_t _line ) noexcept: + file( _file ), + line( _line ) + {} + + bool operator == ( SourceLineInfo const& other ) const noexcept; + bool operator < ( SourceLineInfo const& other ) const noexcept; + + char const* file; + std::size_t line; + + friend std::ostream& operator << (std::ostream& os, SourceLineInfo const& info); + }; +} + +#define CATCH_INTERNAL_LINEINFO \ + ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) + +#endif // CATCH_SOURCE_LINE_INFO_HPP_INCLUDED + +namespace Catch { + + struct AssertionInfo { + // AssertionInfo() = delete; + + StringRef macroName; + SourceLineInfo lineInfo; + StringRef capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + +} // end namespace Catch + +#endif // CATCH_ASSERTION_INFO_HPP_INCLUDED + + +#ifndef CATCH_ASSERTION_RESULT_HPP_INCLUDED +#define CATCH_ASSERTION_RESULT_HPP_INCLUDED + + + +#ifndef CATCH_LAZY_EXPR_HPP_INCLUDED +#define CATCH_LAZY_EXPR_HPP_INCLUDED + +#include + +namespace Catch { + + class ITransientExpression; + + class LazyExpression { + friend class AssertionHandler; + friend struct AssertionStats; + friend class RunContext; + + ITransientExpression const* m_transientExpression = nullptr; + bool m_isNegated; + public: + LazyExpression( bool isNegated ): + m_isNegated(isNegated) + {} + LazyExpression(LazyExpression const& other) = default; + LazyExpression& operator = ( LazyExpression const& ) = delete; + + explicit operator bool() const { + return m_transientExpression != nullptr; + } + + friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; + }; + +} // namespace Catch + +#endif // CATCH_LAZY_EXPR_HPP_INCLUDED + +#include + +namespace Catch { + + struct AssertionResultData + { + AssertionResultData() = delete; + + AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); + + std::string message; + mutable std::string reconstructedExpression; + LazyExpression lazyExpression; + ResultWas::OfType resultType; + + std::string reconstructExpression() const; + }; + + class AssertionResult { + public: + AssertionResult() = delete; + AssertionResult( AssertionInfo const& info, AssertionResultData&& data ); + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + StringRef getMessage() const; + SourceLineInfo getSourceInfo() const; + StringRef getTestMacroName() const; + + //protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +#endif // CATCH_ASSERTION_RESULT_HPP_INCLUDED + + +#ifndef CATCH_CONFIG_HPP_INCLUDED +#define CATCH_CONFIG_HPP_INCLUDED + + + +#ifndef CATCH_TEST_SPEC_HPP_INCLUDED +#define CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + + + +#ifndef CATCH_WILDCARD_PATTERN_HPP_INCLUDED +#define CATCH_WILDCARD_PATTERN_HPP_INCLUDED + + + +#ifndef CATCH_CASE_SENSITIVE_HPP_INCLUDED +#define CATCH_CASE_SENSITIVE_HPP_INCLUDED + +namespace Catch { + + enum class CaseSensitive { Yes, No }; + +} // namespace Catch + +#endif // CATCH_CASE_SENSITIVE_HPP_INCLUDED + +#include + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + WildcardPattern( std::string const& pattern, CaseSensitive caseSensitivity ); + bool matches( std::string const& str ) const; + + private: + std::string normaliseString( std::string const& str ) const; + CaseSensitive m_caseSensitivity; + WildcardPosition m_wildcard = NoWildcard; + std::string m_pattern; + }; +} + +#endif // CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + class IConfig; + struct TestCaseInfo; + class TestCaseHandle; + + class TestSpec { + + class Pattern { + public: + explicit Pattern( std::string const& name ); + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + std::string const& name() const; + private: + virtual void serializeTo( std::ostream& out ) const = 0; + // Writes string that would be reparsed into the pattern + friend std::ostream& operator<<(std::ostream& out, + Pattern const& pattern) { + pattern.serializeTo( out ); + return out; + } + + std::string const m_name; + }; + + class NamePattern : public Pattern { + public: + explicit NamePattern( std::string const& name, std::string const& filterString ); + bool matches( TestCaseInfo const& testCase ) const override; + private: + void serializeTo( std::ostream& out ) const override; + + WildcardPattern m_wildcardPattern; + }; + + class TagPattern : public Pattern { + public: + explicit TagPattern( std::string const& tag, std::string const& filterString ); + bool matches( TestCaseInfo const& testCase ) const override; + private: + void serializeTo( std::ostream& out ) const override; + + std::string m_tag; + }; + + struct Filter { + std::vector> m_required; + std::vector> m_forbidden; + + //! Serializes this filter into a string that would be parsed into + //! an equivalent filter + void serializeTo( std::ostream& out ) const; + friend std::ostream& operator<<(std::ostream& out, Filter const& f) { + f.serializeTo( out ); + return out; + } + + bool matches( TestCaseInfo const& testCase ) const; + }; + + static std::string extractFilterName( Filter const& filter ); + + public: + struct FilterMatch { + std::string name; + std::vector tests; + }; + using Matches = std::vector; + using vectorStrings = std::vector; + + bool hasFilters() const; + bool matches( TestCaseInfo const& testCase ) const; + Matches matchesByFilter( std::vector const& testCases, IConfig const& config ) const; + const vectorStrings & getInvalidSpecs() const; + + private: + std::vector m_filters; + std::vector m_invalidSpecs; + + friend class TestSpecParser; + //! Serializes this test spec into a string that would be parsed into + //! equivalent test spec + void serializeTo( std::ostream& out ) const; + friend std::ostream& operator<<(std::ostream& out, + TestSpec const& spec) { + spec.serializeTo( out ); + return out; + } + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif // CATCH_TEST_SPEC_HPP_INCLUDED + + +#ifndef CATCH_OPTIONAL_HPP_INCLUDED +#define CATCH_OPTIONAL_HPP_INCLUDED + + +#include + +namespace Catch { + + // An optional type + template + class Optional { + public: + Optional(): nullableValue( nullptr ) {} + ~Optional() { reset(); } + + Optional( T const& _value ): + nullableValue( new ( storage ) T( _value ) ) {} + Optional( T&& _value ): + nullableValue( new ( storage ) T( CATCH_MOVE( _value ) ) ) {} + + Optional& operator=( T const& _value ) { + reset(); + nullableValue = new ( storage ) T( _value ); + return *this; + } + Optional& operator=( T&& _value ) { + reset(); + nullableValue = new ( storage ) T( CATCH_MOVE( _value ) ); + return *this; + } + + Optional( Optional const& _other ): + nullableValue( _other ? new ( storage ) T( *_other ) : nullptr ) {} + Optional( Optional&& _other ): + nullableValue( _other ? new ( storage ) T( CATCH_MOVE( *_other ) ) + : nullptr ) {} + + Optional& operator=( Optional const& _other ) { + if ( &_other != this ) { + reset(); + if ( _other ) { nullableValue = new ( storage ) T( *_other ); } + } + return *this; + } + Optional& operator=( Optional&& _other ) { + if ( &_other != this ) { + reset(); + if ( _other ) { + nullableValue = new ( storage ) T( CATCH_MOVE( *_other ) ); + } + } + return *this; + } + + void reset() { + if ( nullableValue ) { nullableValue->~T(); } + nullableValue = nullptr; + } + + T& operator*() { + assert(nullableValue); + return *nullableValue; + } + T const& operator*() const { + assert(nullableValue); + return *nullableValue; + } + T* operator->() { + assert(nullableValue); + return nullableValue; + } + const T* operator->() const { + assert(nullableValue); + return nullableValue; + } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != nullptr; } + bool none() const { return nullableValue == nullptr; } + + bool operator !() const { return nullableValue == nullptr; } + explicit operator bool() const { + return some(); + } + + friend bool operator==(Optional const& a, Optional const& b) { + if (a.none() && b.none()) { + return true; + } else if (a.some() && b.some()) { + return *a == *b; + } else { + return false; + } + } + friend bool operator!=(Optional const& a, Optional const& b) { + return !( a == b ); + } + + private: + T* nullableValue; + alignas(alignof(T)) char storage[sizeof(T)]; + }; + +} // end namespace Catch + +#endif // CATCH_OPTIONAL_HPP_INCLUDED + + +#ifndef CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED +#define CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED + +#include + +namespace Catch { + + enum class GenerateFrom { + Time, + RandomDevice, + //! Currently equivalent to RandomDevice, but can change at any point + Default + }; + + std::uint32_t generateRandomSeed(GenerateFrom from); + +} // end namespace Catch + +#endif // CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED + + +#ifndef CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED +#define CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED + + +#include +#include +#include + +namespace Catch { + + enum class ColourMode : std::uint8_t; + + namespace Detail { + //! Splits the reporter spec into reporter name and kv-pair options + std::vector splitReporterSpec( StringRef reporterSpec ); + + Optional stringToColourMode( StringRef colourMode ); + } + + /** + * Structured reporter spec that a reporter can be created from + * + * Parsing has been validated, but semantics have not. This means e.g. + * that the colour mode is known to Catch2, but it might not be + * compiled into the binary, and the output filename might not be + * openable. + */ + class ReporterSpec { + std::string m_name; + Optional m_outputFileName; + Optional m_colourMode; + std::map m_customOptions; + + friend bool operator==( ReporterSpec const& lhs, + ReporterSpec const& rhs ); + friend bool operator!=( ReporterSpec const& lhs, + ReporterSpec const& rhs ) { + return !( lhs == rhs ); + } + + public: + ReporterSpec( + std::string name, + Optional outputFileName, + Optional colourMode, + std::map customOptions ); + + std::string const& name() const { return m_name; } + + Optional const& outputFile() const { + return m_outputFileName; + } + + Optional const& colourMode() const { return m_colourMode; } + + std::map const& customOptions() const { + return m_customOptions; + } + }; + + /** + * Parses provided reporter spec string into + * + * Returns empty optional on errors, e.g. + * * field that is not first and not a key+value pair + * * duplicated keys in kv pair + * * unknown catch reporter option + * * empty key/value in an custom kv pair + * * ... + */ + Optional parseReporterSpec( StringRef reporterSpec ); + +} + +#endif // CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class IStream; + + /** + * `ReporterSpec` but with the defaults filled in. + * + * Like `ReporterSpec`, the semantics are unchecked. + */ + struct ProcessedReporterSpec { + std::string name; + std::string outputFilename; + ColourMode colourMode; + std::map customOptions; + friend bool operator==( ProcessedReporterSpec const& lhs, + ProcessedReporterSpec const& rhs ); + friend bool operator!=( ProcessedReporterSpec const& lhs, + ProcessedReporterSpec const& rhs ) { + return !( lhs == rhs ); + } + }; + + struct ConfigData { + + bool listTests = false; + bool listTags = false; + bool listReporters = false; + bool listListeners = false; + + bool showSuccessfulTests = false; + bool shouldDebugBreak = false; + bool noThrow = false; + bool showHelp = false; + bool showInvisibles = false; + bool filenamesAsTags = false; + bool libIdentify = false; + bool allowZeroTests = false; + + int abortAfter = -1; + uint32_t rngSeed = generateRandomSeed(GenerateFrom::Default); + + unsigned int shardCount = 1; + unsigned int shardIndex = 0; + + bool skipBenchmarks = false; + bool benchmarkNoAnalysis = false; + unsigned int benchmarkSamples = 100; + double benchmarkConfidenceInterval = 0.95; + unsigned int benchmarkResamples = 100'000; + std::chrono::milliseconds::rep benchmarkWarmupTime = 100; + + Verbosity verbosity = Verbosity::Normal; + WarnAbout::What warnings = WarnAbout::Nothing; + ShowDurations showDurations = ShowDurations::DefaultForReporter; + double minDuration = -1; + TestRunOrder runOrder = TestRunOrder::Declared; + ColourMode defaultColourMode = ColourMode::PlatformDefault; + WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; + + std::string defaultOutputFilename; + std::string name; + std::string processName; + std::vector reporterSpecifications; + + std::vector testsOrTags; + std::vector sectionsToRun; + }; + + + class Config : public IConfig { + public: + + Config() = default; + Config( ConfigData const& data ); + ~Config() override; // = default in the cpp file + + bool listTests() const; + bool listTags() const; + bool listReporters() const; + bool listListeners() const; + + std::vector const& getReporterSpecs() const; + std::vector const& + getProcessedReporterSpecs() const; + + std::vector const& getTestsOrTags() const override; + std::vector const& getSectionsToRun() const override; + + TestSpec const& testSpec() const override; + bool hasTestFilters() const override; + + bool showHelp() const; + + // IConfig interface + bool allowThrows() const override; + StringRef name() const override; + bool includeSuccessfulResults() const override; + bool warnAboutMissingAssertions() const override; + bool warnAboutUnmatchedTestSpecs() const override; + bool zeroTestsCountAsSuccess() const override; + ShowDurations showDurations() const override; + double minDuration() const override; + TestRunOrder runOrder() const override; + uint32_t rngSeed() const override; + unsigned int shardCount() const override; + unsigned int shardIndex() const override; + ColourMode defaultColourMode() const override; + bool shouldDebugBreak() const override; + int abortAfter() const override; + bool showInvisibles() const override; + Verbosity verbosity() const override; + bool skipBenchmarks() const override; + bool benchmarkNoAnalysis() const override; + unsigned int benchmarkSamples() const override; + double benchmarkConfidenceInterval() const override; + unsigned int benchmarkResamples() const override; + std::chrono::milliseconds benchmarkWarmupTime() const override; + + private: + // Reads Bazel env vars and applies them to the config + void readBazelEnvVars(); + + ConfigData m_data; + std::vector m_processedReporterSpecs; + TestSpec m_testSpec; + bool m_hasTestFilters = false; + }; +} // end namespace Catch + +#endif // CATCH_CONFIG_HPP_INCLUDED + + +#ifndef CATCH_GET_RANDOM_SEED_HPP_INCLUDED +#define CATCH_GET_RANDOM_SEED_HPP_INCLUDED + +#include + +namespace Catch { + //! Returns Catch2's current RNG seed. + std::uint32_t getSeed(); +} + +#endif // CATCH_GET_RANDOM_SEED_HPP_INCLUDED + + +#ifndef CATCH_MESSAGE_HPP_INCLUDED +#define CATCH_MESSAGE_HPP_INCLUDED + + + + +/** \file + * Wrapper for the CATCH_CONFIG_PREFIX_MESSAGES configuration option + * + * CATCH_CONFIG_PREFIX_ALL can be used to avoid clashes with other macros + * by prepending CATCH_. This may not be desirable if the only clashes are with + * logger macros such as INFO and WARN. In this cases + * CATCH_CONFIG_PREFIX_MESSAGES can be used to only prefix a small subset + * of relevant macros. + * + */ + +#ifndef CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED +#define CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED + + +#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_PREFIX_MESSAGES) + #define CATCH_CONFIG_PREFIX_MESSAGES +#endif + +#endif // CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED + + +#ifndef CATCH_STREAM_END_STOP_HPP_INCLUDED +#define CATCH_STREAM_END_STOP_HPP_INCLUDED + + +namespace Catch { + + // Use this in variadic streaming macros to allow + // << +StreamEndStop + // as well as + // << stuff +StreamEndStop + struct StreamEndStop { + constexpr StringRef operator+() const { return StringRef(); } + + template + constexpr friend T const& operator+( T const& value, StreamEndStop ) { + return value; + } + }; + +} // namespace Catch + +#endif // CATCH_STREAM_END_STOP_HPP_INCLUDED + + +#ifndef CATCH_MESSAGE_INFO_HPP_INCLUDED +#define CATCH_MESSAGE_INFO_HPP_INCLUDED + + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( StringRef _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + StringRef macroName; + std::string message; + SourceLineInfo lineInfo; + ResultWas::OfType type; + unsigned int sequence; + + bool operator == (MessageInfo const& other) const { + return sequence == other.sequence; + } + bool operator < (MessageInfo const& other) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + +} // end namespace Catch + +#endif // CATCH_MESSAGE_INFO_HPP_INCLUDED + +#include +#include + +namespace Catch { + + struct SourceLineInfo; + class IResultCapture; + + struct MessageStream { + + template + MessageStream& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + ReusableStringStream m_stream; + }; + + struct MessageBuilder : MessageStream { + MessageBuilder( StringRef macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ): + m_info(macroName, lineInfo, type) {} + + template + MessageBuilder&& operator << ( T const& value ) && { + m_stream << value; + return CATCH_MOVE(*this); + } + + MessageInfo m_info; + }; + + class ScopedMessage { + public: + explicit ScopedMessage( MessageBuilder&& builder ); + ScopedMessage( ScopedMessage& duplicate ) = delete; + ScopedMessage( ScopedMessage&& old ) noexcept; + ~ScopedMessage(); + + MessageInfo m_info; + bool m_moved = false; + }; + + class Capturer { + std::vector m_messages; + IResultCapture& m_resultCapture; + size_t m_captured = 0; + public: + Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ); + + Capturer(Capturer const&) = delete; + Capturer& operator=(Capturer const&) = delete; + + ~Capturer(); + + void captureValue( size_t index, std::string const& value ); + + template + void captureValues( size_t index, T const& value ) { + captureValue( index, Catch::Detail::stringify( value ) ); + } + + template + void captureValues( size_t index, T const& value, Ts const&... values ) { + captureValue( index, Catch::Detail::stringify(value) ); + captureValues( index+1, values... ); + } + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ + catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( false ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ + Catch::Capturer varName( macroName##_catch_sr, \ + CATCH_INTERNAL_LINEINFO, \ + Catch::ResultWas::Info, \ + #__VA_ARGS__##_catch_sr ); \ + varName.captureValues( 0, __VA_ARGS__ ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( macroName, log ) \ + const Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \ + Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) + + +#if defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE) + + #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) + #define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg ) + #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) + #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", __VA_ARGS__ ) + +#elif defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE) + + #define CATCH_INFO( msg ) (void)(0) + #define CATCH_UNSCOPED_INFO( msg ) (void)(0) + #define CATCH_WARN( msg ) (void)(0) + #define CATCH_CAPTURE( ... ) (void)(0) + +#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE) + + #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) + #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg ) + #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) + #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", __VA_ARGS__ ) + +#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE) + + #define INFO( msg ) (void)(0) + #define UNSCOPED_INFO( msg ) (void)(0) + #define WARN( msg ) (void)(0) + #define CAPTURE( ... ) (void)(0) + +#endif // end of user facing macro declarations + + + + +#endif // CATCH_MESSAGE_HPP_INCLUDED + + +#ifndef CATCH_SECTION_INFO_HPP_INCLUDED +#define CATCH_SECTION_INFO_HPP_INCLUDED + + + +#ifndef CATCH_TOTALS_HPP_INCLUDED +#define CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct Counts { + Counts operator - ( Counts const& other ) const; + Counts& operator += ( Counts const& other ); + + std::uint64_t total() const; + bool allPassed() const; + bool allOk() const; + + std::uint64_t passed = 0; + std::uint64_t failed = 0; + std::uint64_t failedButOk = 0; + std::uint64_t skipped = 0; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const; + Totals& operator += ( Totals const& other ); + + Totals delta( Totals const& prevTotals ) const; + + Counts assertions; + Counts testCases; + }; +} + +#endif // CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct SectionInfo { + // The last argument is ignored, so that people can write + // SECTION("ShortName", "Proper description that is long") and + // still use the `-c` flag comfortably. + SectionInfo( SourceLineInfo const& _lineInfo, std::string _name, + const char* const = nullptr ): + name(CATCH_MOVE(_name)), + lineInfo(_lineInfo) + {} + + std::string name; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + +#endif // CATCH_SECTION_INFO_HPP_INCLUDED + + +#ifndef CATCH_SESSION_HPP_INCLUDED +#define CATCH_SESSION_HPP_INCLUDED + + + +#ifndef CATCH_COMMANDLINE_HPP_INCLUDED +#define CATCH_COMMANDLINE_HPP_INCLUDED + + + +#ifndef CATCH_CLARA_HPP_INCLUDED +#define CATCH_CLARA_HPP_INCLUDED + +#if defined( __clang__ ) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wweak-vtables" +# pragma clang diagnostic ignored "-Wshadow" +# pragma clang diagnostic ignored "-Wdeprecated" +#endif + +#if defined( __GNUC__ ) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + +#ifndef CLARA_CONFIG_OPTIONAL_TYPE +# ifdef __has_include +# if __has_include( ) && __cplusplus >= 201703L +# include +# define CLARA_CONFIG_OPTIONAL_TYPE std::optional +# endif +# endif +#endif + + +#include +#include +#include +#include +#include +#include +#include + +namespace Catch { + namespace Clara { + + class Args; + class Parser; + + // enum of result types from a parse + enum class ParseResultType { + Matched, + NoMatch, + ShortCircuitAll, + ShortCircuitSame + }; + + struct accept_many_t {}; + constexpr accept_many_t accept_many {}; + + namespace Detail { + struct fake_arg { + template + operator T(); + }; + + template + struct is_unary_function : std::false_type {}; + + template + struct is_unary_function< + F, + Catch::Detail::void_t()( fake_arg() ) ) + > + > : std::true_type {}; + + // Traits for extracting arg and return type of lambdas (for single + // argument lambdas) + template + struct UnaryLambdaTraits + : UnaryLambdaTraits {}; + + template + struct UnaryLambdaTraits { + static const bool isValid = false; + }; + + template + struct UnaryLambdaTraits { + static const bool isValid = true; + using ArgType = std::remove_const_t>; + using ReturnType = ReturnT; + }; + + class TokenStream; + + // Wraps a token coming from a token stream. These may not directly + // correspond to strings as a single string may encode an option + + // its argument if the : or = form is used + enum class TokenType { Option, Argument }; + struct Token { + TokenType type; + StringRef token; + }; + + // Abstracts iterators into args as a stream of tokens, with option + // arguments uniformly handled + class TokenStream { + using Iterator = std::vector::const_iterator; + Iterator it; + Iterator itEnd; + std::vector m_tokenBuffer; + void loadBuffer(); + + public: + explicit TokenStream( Args const& args ); + TokenStream( Iterator it, Iterator itEnd ); + + explicit operator bool() const { + return !m_tokenBuffer.empty() || it != itEnd; + } + + size_t count() const { + return m_tokenBuffer.size() + ( itEnd - it ); + } + + Token operator*() const { + assert( !m_tokenBuffer.empty() ); + return m_tokenBuffer.front(); + } + + Token const* operator->() const { + assert( !m_tokenBuffer.empty() ); + return &m_tokenBuffer.front(); + } + + TokenStream& operator++(); + }; + + //! Denotes type of a parsing result + enum class ResultType { + Ok, ///< No errors + LogicError, ///< Error in user-specified arguments for + ///< construction + RuntimeError ///< Error in parsing inputs + }; + + class ResultBase { + protected: + ResultBase( ResultType type ): m_type( type ) {} + virtual ~ResultBase(); // = default; + + + ResultBase(ResultBase const&) = default; + ResultBase& operator=(ResultBase const&) = default; + ResultBase(ResultBase&&) = default; + ResultBase& operator=(ResultBase&&) = default; + + virtual void enforceOk() const = 0; + + ResultType m_type; + }; + + template + class ResultValueBase : public ResultBase { + public: + T const& value() const& { + enforceOk(); + return m_value; + } + T&& value() && { + enforceOk(); + return CATCH_MOVE( m_value ); + } + + protected: + ResultValueBase( ResultType type ): ResultBase( type ) {} + + ResultValueBase( ResultValueBase const& other ): + ResultBase( other ) { + if ( m_type == ResultType::Ok ) + new ( &m_value ) T( other.m_value ); + } + ResultValueBase( ResultValueBase&& other ): + ResultBase( other ) { + if ( m_type == ResultType::Ok ) + new ( &m_value ) T( CATCH_MOVE(other.m_value) ); + } + + + ResultValueBase( ResultType, T const& value ): + ResultBase( ResultType::Ok ) { + new ( &m_value ) T( value ); + } + ResultValueBase( ResultType, T&& value ): + ResultBase( ResultType::Ok ) { + new ( &m_value ) T( CATCH_MOVE(value) ); + } + + ResultValueBase& operator=( ResultValueBase const& other ) { + if ( m_type == ResultType::Ok ) + m_value.~T(); + ResultBase::operator=( other ); + if ( m_type == ResultType::Ok ) + new ( &m_value ) T( other.m_value ); + return *this; + } + ResultValueBase& operator=( ResultValueBase&& other ) { + if ( m_type == ResultType::Ok ) m_value.~T(); + ResultBase::operator=( other ); + if ( m_type == ResultType::Ok ) + new ( &m_value ) T( CATCH_MOVE(other.m_value) ); + return *this; + } + + + ~ResultValueBase() override { + if ( m_type == ResultType::Ok ) + m_value.~T(); + } + + union { + T m_value; + }; + }; + + template <> class ResultValueBase : public ResultBase { + protected: + using ResultBase::ResultBase; + }; + + template + class BasicResult : public ResultValueBase { + public: + template + explicit BasicResult( BasicResult const& other ): + ResultValueBase( other.type() ), + m_errorMessage( other.errorMessage() ) { + assert( type() != ResultType::Ok ); + } + + template + static auto ok( U&& value ) -> BasicResult { + return { ResultType::Ok, CATCH_FORWARD(value) }; + } + static auto ok() -> BasicResult { return { ResultType::Ok }; } + static auto logicError( std::string&& message ) + -> BasicResult { + return { ResultType::LogicError, CATCH_MOVE(message) }; + } + static auto runtimeError( std::string&& message ) + -> BasicResult { + return { ResultType::RuntimeError, CATCH_MOVE(message) }; + } + + explicit operator bool() const { + return m_type == ResultType::Ok; + } + auto type() const -> ResultType { return m_type; } + auto errorMessage() const -> std::string const& { + return m_errorMessage; + } + + protected: + void enforceOk() const override { + + // Errors shouldn't reach this point, but if they do + // the actual error message will be in m_errorMessage + assert( m_type != ResultType::LogicError ); + assert( m_type != ResultType::RuntimeError ); + if ( m_type != ResultType::Ok ) + std::abort(); + } + + std::string + m_errorMessage; // Only populated if resultType is an error + + BasicResult( ResultType type, + std::string&& message ): + ResultValueBase( type ), m_errorMessage( CATCH_MOVE(message) ) { + assert( m_type != ResultType::Ok ); + } + + using ResultValueBase::ResultValueBase; + using ResultBase::m_type; + }; + + class ParseState { + public: + ParseState( ParseResultType type, + TokenStream remainingTokens ); + + ParseResultType type() const { return m_type; } + TokenStream const& remainingTokens() const& { + return m_remainingTokens; + } + TokenStream&& remainingTokens() && { + return CATCH_MOVE( m_remainingTokens ); + } + + private: + ParseResultType m_type; + TokenStream m_remainingTokens; + }; + + using Result = BasicResult; + using ParserResult = BasicResult; + using InternalParseResult = BasicResult; + + struct HelpColumns { + std::string left; + StringRef descriptions; + }; + + template + ParserResult convertInto( std::string const& source, T& target ) { + std::stringstream ss( source ); + ss >> target; + if ( ss.fail() ) { + return ParserResult::runtimeError( + "Unable to convert '" + source + + "' to destination type" ); + } else { + return ParserResult::ok( ParseResultType::Matched ); + } + } + ParserResult convertInto( std::string const& source, + std::string& target ); + ParserResult convertInto( std::string const& source, bool& target ); + +#ifdef CLARA_CONFIG_OPTIONAL_TYPE + template + auto convertInto( std::string const& source, + CLARA_CONFIG_OPTIONAL_TYPE& target ) + -> ParserResult { + T temp; + auto result = convertInto( source, temp ); + if ( result ) + target = CATCH_MOVE( temp ); + return result; + } +#endif // CLARA_CONFIG_OPTIONAL_TYPE + + struct BoundRef : Catch::Detail::NonCopyable { + virtual ~BoundRef() = default; + virtual bool isContainer() const; + virtual bool isFlag() const; + }; + struct BoundValueRefBase : BoundRef { + virtual auto setValue( std::string const& arg ) + -> ParserResult = 0; + }; + struct BoundFlagRefBase : BoundRef { + virtual auto setFlag( bool flag ) -> ParserResult = 0; + bool isFlag() const override; + }; + + template struct BoundValueRef : BoundValueRefBase { + T& m_ref; + + explicit BoundValueRef( T& ref ): m_ref( ref ) {} + + ParserResult setValue( std::string const& arg ) override { + return convertInto( arg, m_ref ); + } + }; + + template + struct BoundValueRef> : BoundValueRefBase { + std::vector& m_ref; + + explicit BoundValueRef( std::vector& ref ): m_ref( ref ) {} + + auto isContainer() const -> bool override { return true; } + + auto setValue( std::string const& arg ) + -> ParserResult override { + T temp; + auto result = convertInto( arg, temp ); + if ( result ) + m_ref.push_back( temp ); + return result; + } + }; + + struct BoundFlagRef : BoundFlagRefBase { + bool& m_ref; + + explicit BoundFlagRef( bool& ref ): m_ref( ref ) {} + + ParserResult setFlag( bool flag ) override; + }; + + template struct LambdaInvoker { + static_assert( + std::is_same::value, + "Lambda must return void or clara::ParserResult" ); + + template + static auto invoke( L const& lambda, ArgType const& arg ) + -> ParserResult { + return lambda( arg ); + } + }; + + template <> struct LambdaInvoker { + template + static auto invoke( L const& lambda, ArgType const& arg ) + -> ParserResult { + lambda( arg ); + return ParserResult::ok( ParseResultType::Matched ); + } + }; + + template + auto invokeLambda( L const& lambda, std::string const& arg ) + -> ParserResult { + ArgType temp{}; + auto result = convertInto( arg, temp ); + return !result ? result + : LambdaInvoker::ReturnType>::invoke( lambda, temp ); + } + + template struct BoundLambda : BoundValueRefBase { + L m_lambda; + + static_assert( + UnaryLambdaTraits::isValid, + "Supplied lambda must take exactly one argument" ); + explicit BoundLambda( L const& lambda ): m_lambda( lambda ) {} + + auto setValue( std::string const& arg ) + -> ParserResult override { + return invokeLambda::ArgType>( + m_lambda, arg ); + } + }; + + template struct BoundManyLambda : BoundLambda { + explicit BoundManyLambda( L const& lambda ): BoundLambda( lambda ) {} + bool isContainer() const override { return true; } + }; + + template struct BoundFlagLambda : BoundFlagRefBase { + L m_lambda; + + static_assert( + UnaryLambdaTraits::isValid, + "Supplied lambda must take exactly one argument" ); + static_assert( + std::is_same::ArgType, + bool>::value, + "flags must be boolean" ); + + explicit BoundFlagLambda( L const& lambda ): + m_lambda( lambda ) {} + + auto setFlag( bool flag ) -> ParserResult override { + return LambdaInvoker::ReturnType>::invoke( m_lambda, flag ); + } + }; + + enum class Optionality { Optional, Required }; + + class ParserBase { + public: + virtual ~ParserBase() = default; + virtual auto validate() const -> Result { return Result::ok(); } + virtual auto parse( std::string const& exeName, + TokenStream tokens ) const + -> InternalParseResult = 0; + virtual size_t cardinality() const; + + InternalParseResult parse( Args const& args ) const; + }; + + template + class ComposableParserImpl : public ParserBase { + public: + template + auto operator|( T const& other ) const -> Parser; + }; + + // Common code and state for Args and Opts + template + class ParserRefImpl : public ComposableParserImpl { + protected: + Optionality m_optionality = Optionality::Optional; + std::shared_ptr m_ref; + StringRef m_hint; + StringRef m_description; + + explicit ParserRefImpl( std::shared_ptr const& ref ): + m_ref( ref ) {} + + public: + template + ParserRefImpl( accept_many_t, + LambdaT const& ref, + StringRef hint ): + m_ref( std::make_shared>( ref ) ), + m_hint( hint ) {} + + template ::value>> + ParserRefImpl( T& ref, StringRef hint ): + m_ref( std::make_shared>( ref ) ), + m_hint( hint ) {} + + template ::value>> + ParserRefImpl( LambdaT const& ref, StringRef hint ): + m_ref( std::make_shared>( ref ) ), + m_hint( hint ) {} + + DerivedT& operator()( StringRef description ) & { + m_description = description; + return static_cast( *this ); + } + DerivedT&& operator()( StringRef description ) && { + m_description = description; + return static_cast( *this ); + } + + auto optional() -> DerivedT& { + m_optionality = Optionality::Optional; + return static_cast( *this ); + } + + auto required() -> DerivedT& { + m_optionality = Optionality::Required; + return static_cast( *this ); + } + + auto isOptional() const -> bool { + return m_optionality == Optionality::Optional; + } + + auto cardinality() const -> size_t override { + if ( m_ref->isContainer() ) + return 0; + else + return 1; + } + + StringRef hint() const { return m_hint; } + }; + + } // namespace detail + + + // A parser for arguments + class Arg : public Detail::ParserRefImpl { + public: + using ParserRefImpl::ParserRefImpl; + using ParserBase::parse; + + Detail::InternalParseResult + parse(std::string const&, + Detail::TokenStream tokens) const override; + }; + + // A parser for options + class Opt : public Detail::ParserRefImpl { + protected: + std::vector m_optNames; + + public: + template + explicit Opt(LambdaT const& ref) : + ParserRefImpl( + std::make_shared>(ref)) {} + + explicit Opt(bool& ref); + + template ::value>> + Opt( LambdaT const& ref, StringRef hint ): + ParserRefImpl( ref, hint ) {} + + template + Opt( accept_many_t, LambdaT const& ref, StringRef hint ): + ParserRefImpl( accept_many, ref, hint ) {} + + template ::value>> + Opt( T& ref, StringRef hint ): + ParserRefImpl( ref, hint ) {} + + Opt& operator[]( StringRef optName ) & { + m_optNames.push_back(optName); + return *this; + } + Opt&& operator[]( StringRef optName ) && { + m_optNames.push_back( optName ); + return CATCH_MOVE(*this); + } + + Detail::HelpColumns getHelpColumns() const; + + bool isMatch(StringRef optToken) const; + + using ParserBase::parse; + + Detail::InternalParseResult + parse(std::string const&, + Detail::TokenStream tokens) const override; + + Detail::Result validate() const override; + }; + + // Specifies the name of the executable + class ExeName : public Detail::ComposableParserImpl { + std::shared_ptr m_name; + std::shared_ptr m_ref; + + public: + ExeName(); + explicit ExeName(std::string& ref); + + template + explicit ExeName(LambdaT const& lambda) : ExeName() { + m_ref = std::make_shared>(lambda); + } + + // The exe name is not parsed out of the normal tokens, but is + // handled specially + Detail::InternalParseResult + parse(std::string const&, + Detail::TokenStream tokens) const override; + + std::string const& name() const { return *m_name; } + Detail::ParserResult set(std::string const& newName); + }; + + + // A Combined parser + class Parser : Detail::ParserBase { + mutable ExeName m_exeName; + std::vector m_options; + std::vector m_args; + + public: + + auto operator|=(ExeName const& exeName) -> Parser& { + m_exeName = exeName; + return *this; + } + + auto operator|=(Arg const& arg) -> Parser& { + m_args.push_back(arg); + return *this; + } + + friend Parser& operator|=( Parser& p, Opt const& opt ) { + p.m_options.push_back( opt ); + return p; + } + friend Parser& operator|=( Parser& p, Opt&& opt ) { + p.m_options.push_back( CATCH_MOVE(opt) ); + return p; + } + + Parser& operator|=(Parser const& other); + + template + friend Parser operator|( Parser const& p, T&& rhs ) { + Parser temp( p ); + temp |= rhs; + return temp; + } + + template + friend Parser operator|( Parser&& p, T&& rhs ) { + p |= CATCH_FORWARD(rhs); + return CATCH_MOVE(p); + } + + std::vector getHelpColumns() const; + + void writeToStream(std::ostream& os) const; + + friend auto operator<<(std::ostream& os, Parser const& parser) + -> std::ostream& { + parser.writeToStream(os); + return os; + } + + Detail::Result validate() const override; + + using ParserBase::parse; + Detail::InternalParseResult + parse(std::string const& exeName, + Detail::TokenStream tokens) const override; + }; + + /** + * Wrapper over argc + argv, assumes that the inputs outlive it + */ + class Args { + friend Detail::TokenStream; + StringRef m_exeName; + std::vector m_args; + + public: + Args(int argc, char const* const* argv); + // Helper constructor for testing + Args(std::initializer_list args); + + StringRef exeName() const { return m_exeName; } + }; + + + // Convenience wrapper for option parser that specifies the help option + struct Help : Opt { + Help(bool& showHelpFlag); + }; + + // Result type for parser operation + using Detail::ParserResult; + + namespace Detail { + template + template + Parser + ComposableParserImpl::operator|(T const& other) const { + return Parser() | static_cast(*this) | other; + } + } + + } // namespace Clara +} // namespace Catch + +#if defined( __clang__ ) +# pragma clang diagnostic pop +#endif + +#if defined( __GNUC__ ) +# pragma GCC diagnostic pop +#endif + +#endif // CATCH_CLARA_HPP_INCLUDED + +namespace Catch { + + struct ConfigData; + + Clara::Parser makeCommandLineParser( ConfigData& config ); + +} // end namespace Catch + +#endif // CATCH_COMMANDLINE_HPP_INCLUDED + +namespace Catch { + + class Session : Detail::NonCopyable { + public: + + Session(); + ~Session(); + + void showHelp() const; + void libIdentify(); + + int applyCommandLine( int argc, char const * const * argv ); + #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE) + int applyCommandLine( int argc, wchar_t const * const * argv ); + #endif + + void useConfigData( ConfigData const& configData ); + + template + int run(int argc, CharT const * const argv[]) { + if (m_startupExceptions) + return 1; + int returnCode = applyCommandLine(argc, argv); + if (returnCode == 0) + returnCode = run(); + return returnCode; + } + + int run(); + + Clara::Parser const& cli() const; + void cli( Clara::Parser const& newParser ); + ConfigData& configData(); + Config& config(); + private: + int runInternal(); + + Clara::Parser m_cli; + ConfigData m_configData; + Detail::unique_ptr m_config; + bool m_startupExceptions = false; + }; + +} // end namespace Catch + +#endif // CATCH_SESSION_HPP_INCLUDED + + +#ifndef CATCH_TAG_ALIAS_HPP_INCLUDED +#define CATCH_TAG_ALIAS_HPP_INCLUDED + + +#include + +namespace Catch { + + struct TagAlias { + TagAlias(std::string const& _tag, SourceLineInfo _lineInfo): + tag(_tag), + lineInfo(_lineInfo) + {} + + std::string tag; + SourceLineInfo lineInfo; + }; + +} // end namespace Catch + +#endif // CATCH_TAG_ALIAS_HPP_INCLUDED + + +#ifndef CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED +#define CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED + + +namespace Catch { + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + +#endif // CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED + + +#ifndef CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED +#define CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED + +// We need this suppression to leak, because it took until GCC 10 +// for the front end to handle local suppression via _Pragma properly +// inside templates (so `TEMPLATE_TEST_CASE` and co). +// **THIS IS DIFFERENT FOR STANDARD TESTS, WHERE GCC 9 IS SUFFICIENT** +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ < 10 +#pragma GCC diagnostic ignored "-Wparentheses" +#endif + + + + +#ifndef CATCH_TEST_MACROS_HPP_INCLUDED +#define CATCH_TEST_MACROS_HPP_INCLUDED + + + +#ifndef CATCH_TEST_MACRO_IMPL_HPP_INCLUDED +#define CATCH_TEST_MACRO_IMPL_HPP_INCLUDED + + + +#ifndef CATCH_ASSERTION_HANDLER_HPP_INCLUDED +#define CATCH_ASSERTION_HANDLER_HPP_INCLUDED + + + +#ifndef CATCH_DECOMPOSER_HPP_INCLUDED +#define CATCH_DECOMPOSER_HPP_INCLUDED + + + +#ifndef CATCH_COMPARE_TRAITS_HPP_INCLUDED +#define CATCH_COMPARE_TRAITS_HPP_INCLUDED + + +#include + +namespace Catch { + namespace Detail { + +#if defined( __GNUC__ ) && !defined( __clang__ ) +# pragma GCC diagnostic push + // GCC likes to complain about comparing bool with 0, in the decltype() + // that defines the comparable traits below. +# pragma GCC diagnostic ignored "-Wbool-compare" + // "ordered comparison of pointer with integer zero" same as above, + // but it does not have a separate warning flag to suppress +# pragma GCC diagnostic ignored "-Wextra" + // Did you know that comparing floats with `0` directly + // is super-duper dangerous in unevaluated context? +# pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + +#if defined( __clang__ ) +# pragma clang diagnostic push + // Did you know that comparing floats with `0` directly + // is super-duper dangerous in unevaluated context? +# pragma clang diagnostic ignored "-Wfloat-equal" +#endif + +#define CATCH_DEFINE_COMPARABLE_TRAIT( id, op ) \ + template \ + struct is_##id##_comparable : std::false_type {}; \ + template \ + struct is_##id##_comparable< \ + T, \ + U, \ + void_t() op std::declval() )>> \ + : std::true_type {}; \ + template \ + struct is_##id##_0_comparable : std::false_type {}; \ + template \ + struct is_##id##_0_comparable() op 0 )>> \ + : std::true_type {}; + + // We need all 6 pre-spaceship comparison ops: <, <=, >, >=, ==, != + CATCH_DEFINE_COMPARABLE_TRAIT( lt, < ) + CATCH_DEFINE_COMPARABLE_TRAIT( le, <= ) + CATCH_DEFINE_COMPARABLE_TRAIT( gt, > ) + CATCH_DEFINE_COMPARABLE_TRAIT( ge, >= ) + CATCH_DEFINE_COMPARABLE_TRAIT( eq, == ) + CATCH_DEFINE_COMPARABLE_TRAIT( ne, != ) + +#undef CATCH_DEFINE_COMPARABLE_TRAIT + +#if defined( __GNUC__ ) && !defined( __clang__ ) +# pragma GCC diagnostic pop +#endif +#if defined( __clang__ ) +# pragma clang diagnostic pop +#endif + + + } // namespace Detail +} // namespace Catch + +#endif // CATCH_COMPARE_TRAITS_HPP_INCLUDED + + +#ifndef CATCH_LOGICAL_TRAITS_HPP_INCLUDED +#define CATCH_LOGICAL_TRAITS_HPP_INCLUDED + +#include + +namespace Catch { +namespace Detail { + +#if defined( __cpp_lib_logical_traits ) && __cpp_lib_logical_traits >= 201510 + + using std::conjunction; + using std::disjunction; + using std::negation; + +#else + + template struct conjunction : std::true_type {}; + template struct conjunction : B1 {}; + template + struct conjunction + : std::conditional_t, B1> {}; + + template struct disjunction : std::false_type {}; + template struct disjunction : B1 {}; + template + struct disjunction + : std::conditional_t> {}; + + template + struct negation : std::integral_constant {}; + +#endif + +} // namespace Detail +} // namespace Catch + +#endif // CATCH_LOGICAL_TRAITS_HPP_INCLUDED + +#include +#include + +/** \file + * Why does decomposing look the way it does: + * + * Conceptually, decomposing is simple. We change `REQUIRE( a == b )` into + * `Decomposer{} <= a == b`, so that `Decomposer{} <= a` is evaluated first, + * and our custom operator is used for `a == b`, because `a` is transformed + * into `ExprLhs` and then into `BinaryExpr`. + * + * In practice, decomposing ends up a mess, because we have to support + * various fun things. + * + * 1) Types that are only comparable with literal 0, and they do this by + * comparing against a magic type with pointer constructor and deleted + * other constructors. Example: `REQUIRE((a <=> b) == 0)` in libstdc++ + * + * 2) Types that are only comparable with literal 0, and they do this by + * comparing against a magic type with consteval integer constructor. + * Example: `REQUIRE((a <=> b) == 0)` in current MSVC STL. + * + * 3) Types that have no linkage, and so we cannot form a reference to + * them. Example: some implementations of traits. + * + * 4) Starting with C++20, when the compiler sees `a == b`, it also uses + * `b == a` when constructing the overload set. For us this means that + * when the compiler handles `ExprLhs == b`, it also tries to resolve + * the overload set for `b == ExprLhs`. + * + * To accomodate these use cases, decomposer ended up rather complex. + * + * 1) These types are handled by adding SFINAE overloads to our comparison + * operators, checking whether `T == U` are comparable with the given + * operator, and if not, whether T (or U) are comparable with literal 0. + * If yes, the overload compares T (or U) with 0 literal inline in the + * definition. + * + * Note that for extra correctness, we check that the other type is + * either an `int` (literal 0 is captured as `int` by templates), or + * a `long` (some platforms use 0L for `NULL` and we want to support + * that for pointer comparisons). + * + * 2) For these types, `is_foo_comparable` is true, but letting + * them fall into the overload that actually does `T == int` causes + * compilation error. Handling them requires that the decomposition + * is `constexpr`, so that P2564R3 applies and the `consteval` from + * their accompanying magic type is propagated through the `constexpr` + * call stack. + * + * However this is not enough to handle these types automatically, + * because our default is to capture types by reference, to avoid + * runtime copies. While these references cannot become dangling, + * they outlive the constexpr context and thus the default capture + * path cannot be actually constexpr. + * + * The solution is to capture these types by value, by explicitly + * specializing `Catch::capture_by_value` for them. Catch2 provides + * specialization for `std::foo_ordering`s, but users can specialize + * the trait for their own types as well. + * + * 3) If a type has no linkage, we also cannot capture it by reference. + * The solution is once again to capture them by value. We handle + * the common cases by using `std::is_arithmetic` as the default + * for `Catch::capture_by_value`, but that is only a some-effort + * heuristic. But as with 2), users can specialize `capture_by_value` + * for their own types as needed. + * + * 4) To support C++20 and make the SFINAE on our decomposing operators + * work, the SFINAE has to happen in return type, rather than in + * a template type. This is due to our use of logical type traits + * (`conjunction`/`disjunction`/`negation`), that we use to workaround + * an issue in older (9-) versions of GCC. I still blame C++20 for + * this, because without the comparison order switching, the logical + * traits could still be used in template type. + * + * There are also other side concerns, e.g. supporting both `REQUIRE(a)` + * and `REQUIRE(a == b)`, or making `REQUIRE_THAT(a, IsEqual(b))` slot + * nicely into the same expression handling logic, but these are rather + * straightforward and add only a bit of complexity (e.g. common base + * class for decomposed expressions). + */ + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#pragma warning(disable:4018) // more "signed/unsigned mismatch" +#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) +#pragma warning(disable:4180) // qualifier applied to function type has no meaning +#pragma warning(disable:4800) // Forcing result to true or false +#endif + +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wsign-compare" +# pragma clang diagnostic ignored "-Wnon-virtual-dtor" +#elif defined __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wsign-compare" +# pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +#endif + +#if defined(CATCH_CPP20_OR_GREATER) && __has_include() +# include +# if defined( __cpp_lib_three_way_comparison ) && \ + __cpp_lib_three_way_comparison >= 201907L +# define CATCH_CONFIG_CPP20_COMPARE_OVERLOADS +# endif +#endif + +namespace Catch { + + namespace Detail { + // This was added in C++20, but we require only C++14 for now. + template + using RemoveCVRef_t = std::remove_cv_t>; + } + + // Note: There is nothing that stops us from extending this, + // e.g. to `std::is_scalar`, but the more encompassing + // traits are usually also more expensive. For now we + // keep this as it used to be and it can be changed later. + template + struct capture_by_value + : std::integral_constant{}> {}; + +#if defined( CATCH_CONFIG_CPP20_COMPARE_OVERLOADS ) + template <> + struct capture_by_value : std::true_type {}; + template <> + struct capture_by_value : std::true_type {}; + template <> + struct capture_by_value : std::true_type {}; +#endif + + template + struct always_false : std::false_type {}; + + class ITransientExpression { + bool m_isBinaryExpression; + bool m_result; + + public: + constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } + constexpr auto getResult() const -> bool { return m_result; } + //! This function **has** to be overriden by the derived class. + virtual void streamReconstructedExpression( std::ostream& os ) const; + + constexpr ITransientExpression( bool isBinaryExpression, bool result ) + : m_isBinaryExpression( isBinaryExpression ), + m_result( result ) + {} + + ITransientExpression() = default; + ITransientExpression(ITransientExpression const&) = default; + ITransientExpression& operator=(ITransientExpression const&) = default; + + friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) { + expr.streamReconstructedExpression(out); + return out; + } + + protected: + ~ITransientExpression() = default; + }; + + void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); + + template + class BinaryExpr : public ITransientExpression { + LhsT m_lhs; + StringRef m_op; + RhsT m_rhs; + + void streamReconstructedExpression( std::ostream &os ) const override { + formatReconstructedExpression + ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); + } + + public: + constexpr BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) + : ITransientExpression{ true, comparisonResult }, + m_lhs( lhs ), + m_op( op ), + m_rhs( rhs ) + {} + + template + auto operator && ( T ) const -> BinaryExpr const { + static_assert(always_false::value, + "chained comparisons are not supported inside assertions, " + "wrap the expression inside parentheses, or decompose it"); + } + + template + auto operator || ( T ) const -> BinaryExpr const { + static_assert(always_false::value, + "chained comparisons are not supported inside assertions, " + "wrap the expression inside parentheses, or decompose it"); + } + + template + auto operator == ( T ) const -> BinaryExpr const { + static_assert(always_false::value, + "chained comparisons are not supported inside assertions, " + "wrap the expression inside parentheses, or decompose it"); + } + + template + auto operator != ( T ) const -> BinaryExpr const { + static_assert(always_false::value, + "chained comparisons are not supported inside assertions, " + "wrap the expression inside parentheses, or decompose it"); + } + + template + auto operator > ( T ) const -> BinaryExpr const { + static_assert(always_false::value, + "chained comparisons are not supported inside assertions, " + "wrap the expression inside parentheses, or decompose it"); + } + + template + auto operator < ( T ) const -> BinaryExpr const { + static_assert(always_false::value, + "chained comparisons are not supported inside assertions, " + "wrap the expression inside parentheses, or decompose it"); + } + + template + auto operator >= ( T ) const -> BinaryExpr const { + static_assert(always_false::value, + "chained comparisons are not supported inside assertions, " + "wrap the expression inside parentheses, or decompose it"); + } + + template + auto operator <= ( T ) const -> BinaryExpr const { + static_assert(always_false::value, + "chained comparisons are not supported inside assertions, " + "wrap the expression inside parentheses, or decompose it"); + } + }; + + template + class UnaryExpr : public ITransientExpression { + LhsT m_lhs; + + void streamReconstructedExpression( std::ostream &os ) const override { + os << Catch::Detail::stringify( m_lhs ); + } + + public: + explicit constexpr UnaryExpr( LhsT lhs ) + : ITransientExpression{ false, static_cast(lhs) }, + m_lhs( lhs ) + {} + }; + + + template + class ExprLhs { + LhsT m_lhs; + public: + explicit constexpr ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} + +#define CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( id, op ) \ + template \ + constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \ + -> std::enable_if_t< \ + Detail::conjunction, \ + Detail::negation>>>::value, \ + BinaryExpr> { \ + return { \ + static_cast( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ + } \ + template \ + constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ + -> std::enable_if_t< \ + Detail::conjunction, \ + capture_by_value>::value, \ + BinaryExpr> { \ + return { \ + static_cast( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ + } \ + template \ + constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ + -> std::enable_if_t< \ + Detail::conjunction< \ + Detail::negation>, \ + Detail::is_eq_0_comparable, \ + /* We allow long because we want `ptr op NULL` to be accepted */ \ + Detail::disjunction, \ + std::is_same>>::value, \ + BinaryExpr> { \ + if ( rhs != 0 ) { throw_test_failure_exception(); } \ + return { \ + static_cast( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \ + } \ + template \ + constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ + -> std::enable_if_t< \ + Detail::conjunction< \ + Detail::negation>, \ + Detail::is_eq_0_comparable, \ + /* We allow long because we want `ptr op NULL` to be accepted */ \ + Detail::disjunction, \ + std::is_same>>::value, \ + BinaryExpr> { \ + if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); } \ + return { static_cast( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ + } + + CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( eq, == ) + CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( ne, != ) + + #undef CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR + + +#define CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( id, op ) \ + template \ + constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \ + -> std::enable_if_t< \ + Detail::conjunction, \ + Detail::negation>>>::value, \ + BinaryExpr> { \ + return { \ + static_cast( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ + } \ + template \ + constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ + -> std::enable_if_t< \ + Detail::conjunction, \ + capture_by_value>::value, \ + BinaryExpr> { \ + return { \ + static_cast( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ + } \ + template \ + constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ + -> std::enable_if_t< \ + Detail::conjunction< \ + Detail::negation>, \ + Detail::is_##id##_0_comparable, \ + std::is_same>::value, \ + BinaryExpr> { \ + if ( rhs != 0 ) { throw_test_failure_exception(); } \ + return { \ + static_cast( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \ + } \ + template \ + constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ + -> std::enable_if_t< \ + Detail::conjunction< \ + Detail::negation>, \ + Detail::is_##id##_0_comparable, \ + std::is_same>::value, \ + BinaryExpr> { \ + if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); } \ + return { static_cast( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ + } + + CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( lt, < ) + CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( le, <= ) + CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( gt, > ) + CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( ge, >= ) + + #undef CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR + + +#define CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR( op ) \ + template \ + constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \ + -> std::enable_if_t< \ + !capture_by_value>::value, \ + BinaryExpr> { \ + return { \ + static_cast( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ + } \ + template \ + constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ + -> std::enable_if_t::value, \ + BinaryExpr> { \ + return { \ + static_cast( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ + } + + CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(|) + CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(&) + CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(^) + + #undef CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR + + template + friend auto operator && ( ExprLhs &&, RhsT && ) -> BinaryExpr { + static_assert(always_false::value, + "operator&& is not supported inside assertions, " + "wrap the expression inside parentheses, or decompose it"); + } + + template + friend auto operator || ( ExprLhs &&, RhsT && ) -> BinaryExpr { + static_assert(always_false::value, + "operator|| is not supported inside assertions, " + "wrap the expression inside parentheses, or decompose it"); + } + + constexpr auto makeUnaryExpr() const -> UnaryExpr { + return UnaryExpr{ m_lhs }; + } + }; + + struct Decomposer { + template >::value, + int> = 0> + constexpr friend auto operator <= ( Decomposer &&, T && lhs ) -> ExprLhs { + return ExprLhs{ lhs }; + } + + template ::value, int> = 0> + constexpr friend auto operator <= ( Decomposer &&, T value ) -> ExprLhs { + return ExprLhs{ value }; + } + }; + +} // end namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#ifdef __clang__ +# pragma clang diagnostic pop +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + +#endif // CATCH_DECOMPOSER_HPP_INCLUDED + +#include + +namespace Catch { + + struct AssertionReaction { + bool shouldDebugBreak = false; + bool shouldThrow = false; + bool shouldSkip = false; + }; + + class AssertionHandler { + AssertionInfo m_assertionInfo; + AssertionReaction m_reaction; + bool m_completed = false; + IResultCapture& m_resultCapture; + + public: + AssertionHandler + ( StringRef macroName, + SourceLineInfo const& lineInfo, + StringRef capturedExpression, + ResultDisposition::Flags resultDisposition ); + ~AssertionHandler() { + if ( !m_completed ) { + m_resultCapture.handleIncomplete( m_assertionInfo ); + } + } + + + template + void handleExpr( ExprLhs const& expr ) { + handleExpr( expr.makeUnaryExpr() ); + } + void handleExpr( ITransientExpression const& expr ); + + void handleMessage(ResultWas::OfType resultType, StringRef message); + + void handleExceptionThrownAsExpected(); + void handleUnexpectedExceptionNotThrown(); + void handleExceptionNotThrownAsExpected(); + void handleThrowingCallSkipped(); + void handleUnexpectedInflightException(); + + void complete(); + + // query + auto allowThrows() const -> bool; + }; + + void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str ); + +} // namespace Catch + +#endif // CATCH_ASSERTION_HANDLER_HPP_INCLUDED + + +#ifndef CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED +#define CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED + + +#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) + #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__##_catch_sr +#else + #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"_catch_sr +#endif + +#endif // CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED + +// We need this suppression to leak, because it took until GCC 10 +// for the front end to handle local suppression via _Pragma properly +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ <= 9 + #pragma GCC diagnostic ignored "-Wparentheses" +#endif + +#if !defined(CATCH_CONFIG_DISABLE) + +#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) + +/////////////////////////////////////////////////////////////////////////////// +// Another way to speed-up compilation is to omit local try-catch for REQUIRE* +// macros. +#define INTERNAL_CATCH_TRY +#define INTERNAL_CATCH_CATCH( capturer ) + +#else // CATCH_CONFIG_FAST_COMPILE + +#define INTERNAL_CATCH_TRY try +#define INTERNAL_CATCH_CATCH( handler ) catch(...) { (handler).handleUnexpectedInflightException(); } + +#endif + +#define INTERNAL_CATCH_REACT( handler ) handler.complete(); + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ + do { /* NOLINT(bugprone-infinite-loop) */ \ + /* The expression should not be evaluated, but warnings should hopefully be checked */ \ + CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \ + Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ + INTERNAL_CATCH_TRY { \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); /* NOLINT(bugprone-chained-comparison) */ \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( (void)0, (false) && static_cast( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look + // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ + INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ + if( Catch::getResultCapture().lastAssertionPassed() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ + INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ + if( !Catch::getResultCapture().lastAssertionPassed() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ + try { \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ + static_cast(__VA_ARGS__); \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ + } \ + catch( ... ) { \ + catchAssertionHandler.handleUnexpectedInflightException(); \ + } \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( false ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ + if( catchAssertionHandler.allowThrows() ) \ + try { \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ + CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ + static_cast(__VA_ARGS__); \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ + } \ + catch( ... ) { \ + catchAssertionHandler.handleExceptionThrownAsExpected(); \ + } \ + else \ + catchAssertionHandler.handleThrowingCallSkipped(); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( false ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ + try { \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ + CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ + static_cast(expr); \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ + } \ + catch( exceptionType const& ) { \ + catchAssertionHandler.handleExceptionThrownAsExpected(); \ + } \ + catch( ... ) { \ + catchAssertionHandler.handleUnexpectedInflightException(); \ + } \ + else \ + catchAssertionHandler.handleThrowingCallSkipped(); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( false ) + + + +/////////////////////////////////////////////////////////////////////////////// +// Although this is matcher-based, it can be used with just a string +#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ + try { \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ + CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ + static_cast(__VA_ARGS__); \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ + } \ + catch( ... ) { \ + Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher ); \ + } \ + else \ + catchAssertionHandler.handleThrowingCallSkipped(); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( false ) + +#endif // CATCH_CONFIG_DISABLE + +#endif // CATCH_TEST_MACRO_IMPL_HPP_INCLUDED + + +#ifndef CATCH_SECTION_HPP_INCLUDED +#define CATCH_SECTION_HPP_INCLUDED + + + + +/** \file + * Wrapper for the STATIC_ANALYSIS_SUPPORT configuration option + * + * Some of Catch2's macros can be defined differently to work better with + * static analysis tools, like clang-tidy or coverity. + * Currently the main use case is to show that `SECTION`s are executed + * exclusively, and not all in one run of a `TEST_CASE`. + */ + +#ifndef CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED +#define CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED + + +#if defined(__clang_analyzer__) || defined(__COVERITY__) + #define CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT +#endif + +#if defined( CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT ) && \ + !defined( CATCH_CONFIG_NO_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT ) && \ + !defined( CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT ) +# define CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT +#endif + + +#endif // CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED + + +#ifndef CATCH_TIMER_HPP_INCLUDED +#define CATCH_TIMER_HPP_INCLUDED + +#include + +namespace Catch { + + class Timer { + uint64_t m_nanoseconds = 0; + public: + void start(); + auto getElapsedNanoseconds() const -> uint64_t; + auto getElapsedMicroseconds() const -> uint64_t; + auto getElapsedMilliseconds() const -> unsigned int; + auto getElapsedSeconds() const -> double; + }; + +} // namespace Catch + +#endif // CATCH_TIMER_HPP_INCLUDED + +namespace Catch { + + class Section : Detail::NonCopyable { + public: + Section( SectionInfo&& info ); + Section( SourceLineInfo const& _lineInfo, + StringRef _name, + const char* const = nullptr ); + ~Section(); + + // This indicates whether the section should be executed or not + explicit operator bool() const; + + private: + SectionInfo m_info; + + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT) +# define INTERNAL_CATCH_SECTION( ... ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \ + catch_internal_Section ) = \ + Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + +# define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \ + catch_internal_Section ) = \ + Catch::SectionInfo( \ + CATCH_INTERNAL_LINEINFO, \ + ( Catch::ReusableStringStream() << __VA_ARGS__ ) \ + .str() ) ) \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + +#else + +// These section definitions imply that at most one section at one level +// will be intered (because only one section's __LINE__ can be equal to +// the dummy `catchInternalSectionHint` variable from `TEST_CASE`). + +namespace Catch { + namespace Detail { + // Intentionally without linkage, as it should only be used as a dummy + // symbol for static analysis. + // The arguments are used as a dummy for checking warnings in the passed + // expressions. + int GetNewSectionHint( StringRef, const char* const = nullptr ); + } // namespace Detail +} // namespace Catch + + +# define INTERNAL_CATCH_SECTION( ... ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ + if ( [[maybe_unused]] const int catchInternalPreviousSectionHint = \ + catchInternalSectionHint, \ + catchInternalSectionHint = \ + Catch::Detail::GetNewSectionHint(__VA_ARGS__); \ + catchInternalPreviousSectionHint == __LINE__ ) \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + +# define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ + if ( [[maybe_unused]] const int catchInternalPreviousSectionHint = \ + catchInternalSectionHint, \ + catchInternalSectionHint = Catch::Detail::GetNewSectionHint( \ + ( Catch::ReusableStringStream() << __VA_ARGS__ ).str()); \ + catchInternalPreviousSectionHint == __LINE__ ) \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + +#endif + + +#endif // CATCH_SECTION_HPP_INCLUDED + + +#ifndef CATCH_TEST_REGISTRY_HPP_INCLUDED +#define CATCH_TEST_REGISTRY_HPP_INCLUDED + + + +#ifndef CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED +#define CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED + +namespace Catch { + + class ITestInvoker { + public: + virtual void invoke() const = 0; + virtual ~ITestInvoker(); // = default + }; + +} // namespace Catch + +#endif // CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED + + +#ifndef CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED +#define CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED + +#define INTERNAL_CATCH_EXPAND1( param ) INTERNAL_CATCH_EXPAND2( param ) +#define INTERNAL_CATCH_EXPAND2( ... ) INTERNAL_CATCH_NO##__VA_ARGS__ +#define INTERNAL_CATCH_DEF( ... ) INTERNAL_CATCH_DEF __VA_ARGS__ +#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF + +#define INTERNAL_CATCH_REMOVE_PARENS( ... ) \ + INTERNAL_CATCH_EXPAND1( INTERNAL_CATCH_DEF __VA_ARGS__ ) + +#endif // CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED + +// GCC 5 and older do not properly handle disabling unused-variable warning +// with a _Pragma. This means that we have to leak the suppression to the +// user code as well :-( +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5 +#pragma GCC diagnostic ignored "-Wunused-variable" +#endif + + + +namespace Catch { + +template +class TestInvokerAsMethod : public ITestInvoker { + void (C::*m_testAsMethod)(); +public: + TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {} + + void invoke() const override { + C obj; + (obj.*m_testAsMethod)(); + } +}; + +Detail::unique_ptr makeTestInvoker( void(*testAsFunction)() ); + +template +Detail::unique_ptr makeTestInvoker( void (C::*testAsMethod)() ) { + return Detail::make_unique>( testAsMethod ); +} + +struct NameAndTags { + constexpr NameAndTags( StringRef name_ = StringRef(), + StringRef tags_ = StringRef() ) noexcept: + name( name_ ), tags( tags_ ) {} + StringRef name; + StringRef tags; +}; + +struct AutoReg : Detail::NonCopyable { + AutoReg( Detail::unique_ptr invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept; +}; + +} // end namespace Catch + +#if defined(CATCH_CONFIG_DISABLE) + #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ + static inline void TestName() + #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ + namespace{ \ + struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ + void test(); \ + }; \ + } \ + void TestName::test() +#endif + + +#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ + static void TestName(); \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + namespace{ const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + static void TestName() + #define INTERNAL_CATCH_TESTCASE( ... ) \ + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__ ) + +#else // ^^ !CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT | vv CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT + + +// Dummy registrator for the dumy test case macros +namespace Catch { + namespace Detail { + struct DummyUse { + DummyUse( void ( * )( int ), Catch::NameAndTags const& ); + }; + } // namespace Detail +} // namespace Catch + +// Note that both the presence of the argument and its exact name are +// necessary for the section support. + +// We provide a shadowed variable so that a `SECTION` inside non-`TEST_CASE` +// tests can compile. The redefined `TEST_CASE` shadows this with param. +static int catchInternalSectionHint = 0; + +# define INTERNAL_CATCH_TESTCASE2( fname, ... ) \ + static void fname( int ); \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + static const Catch::Detail::DummyUse INTERNAL_CATCH_UNIQUE_NAME( \ + dummyUser )( &(fname), Catch::NameAndTags{ __VA_ARGS__ } ); \ + CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ + static void fname( [[maybe_unused]] int catchInternalSectionHint ) \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +# define INTERNAL_CATCH_TESTCASE( ... ) \ + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( dummyFunction ), __VA_ARGS__ ) + + +#endif // CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + namespace{ \ + struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ + void test(); \ + }; \ + const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \ + Catch::makeTestInvoker( &TestName::test ), \ + CATCH_INTERNAL_LINEINFO, \ + #ClassName##_catch_sr, \ + Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ + } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + void TestName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ ) + + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + namespace { \ + const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \ + Catch::makeTestInvoker( &QualifiedMethod ), \ + CATCH_INTERNAL_LINEINFO, \ + "&" #QualifiedMethod##_catch_sr, \ + Catch::NameAndTags{ __VA_ARGS__ } ); \ + } /* NOLINT */ \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ + do { \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + } while(false) + + +#endif // CATCH_TEST_REGISTRY_HPP_INCLUDED + + +// All of our user-facing macros support configuration toggle, that +// forces them to be defined prefixed with CATCH_. We also like to +// support another toggle that can minimize (disable) their implementation. +// Given this, we have 4 different configuration options below + +#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE) + + #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) + #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) + + #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) + #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) + #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) + + #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) + #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) + #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) + #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) + + #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) + #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) + #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + #define CATCH_SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ) + + + #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) + #define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ ) + #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ ) + #define CATCH_STATIC_CHECK( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ ) + #define CATCH_STATIC_CHECK_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ ) + #else + #define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ ) + #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ ) + #define CATCH_STATIC_CHECK( ... ) CATCH_CHECK( __VA_ARGS__ ) + #define CATCH_STATIC_CHECK_FALSE( ... ) CATCH_CHECK_FALSE( __VA_ARGS__ ) + #endif + + + // "BDD-style" convenience wrappers + #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) + #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) + #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) + #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) + #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) + #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) + #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) + #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) + +#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) // ^^ prefixed, implemented | vv prefixed, disabled + + #define CATCH_REQUIRE( ... ) (void)(0) + #define CATCH_REQUIRE_FALSE( ... ) (void)(0) + + #define CATCH_REQUIRE_THROWS( ... ) (void)(0) + #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) + #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) + + #define CATCH_CHECK( ... ) (void)(0) + #define CATCH_CHECK_FALSE( ... ) (void)(0) + #define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) + #define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) + #define CATCH_CHECK_NOFAIL( ... ) (void)(0) + + #define CATCH_CHECK_THROWS( ... ) (void)(0) + #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) + #define CATCH_CHECK_NOTHROW( ... ) (void)(0) + + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ )) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ )) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) + #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) + #define CATCH_SECTION( ... ) + #define CATCH_DYNAMIC_SECTION( ... ) + #define CATCH_FAIL( ... ) (void)(0) + #define CATCH_FAIL_CHECK( ... ) (void)(0) + #define CATCH_SUCCEED( ... ) (void)(0) + #define CATCH_SKIP( ... ) (void)(0) + + #define CATCH_STATIC_REQUIRE( ... ) (void)(0) + #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0) + #define CATCH_STATIC_CHECK( ... ) (void)(0) + #define CATCH_STATIC_CHECK_FALSE( ... ) (void)(0) + + // "BDD-style" convenience wrappers + #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ )) + #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), className ) + #define CATCH_GIVEN( desc ) + #define CATCH_AND_GIVEN( desc ) + #define CATCH_WHEN( desc ) + #define CATCH_AND_WHEN( desc ) + #define CATCH_THEN( desc ) + #define CATCH_AND_THEN( desc ) + +#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE) // ^^ prefixed, disabled | vv unprefixed, implemented + + #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) + #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) + + #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) + #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) + #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) + + #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) + #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) + #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) + #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) + + #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) + #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) + #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + #define SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ) + + + #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) + #define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ ) + #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" ) + #define STATIC_CHECK( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ ) + #define STATIC_CHECK_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" ) + #else + #define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ ) + #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ ) + #define STATIC_CHECK( ... ) CHECK( __VA_ARGS__ ) + #define STATIC_CHECK_FALSE( ... ) CHECK_FALSE( __VA_ARGS__ ) + #endif + + // "BDD-style" convenience wrappers + #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) + #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) + #define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) + #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) + #define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) + #define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) + #define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) + #define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) + +#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) // ^^ unprefixed, implemented | vv unprefixed, disabled + + #define REQUIRE( ... ) (void)(0) + #define REQUIRE_FALSE( ... ) (void)(0) + + #define REQUIRE_THROWS( ... ) (void)(0) + #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) + #define REQUIRE_NOTHROW( ... ) (void)(0) + + #define CHECK( ... ) (void)(0) + #define CHECK_FALSE( ... ) (void)(0) + #define CHECKED_IF( ... ) if (__VA_ARGS__) + #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) + #define CHECK_NOFAIL( ... ) (void)(0) + + #define CHECK_THROWS( ... ) (void)(0) + #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) + #define CHECK_NOTHROW( ... ) (void)(0) + + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ )) + #define METHOD_AS_TEST_CASE( method, ... ) + #define REGISTER_TEST_CASE( Function, ... ) (void)(0) + #define SECTION( ... ) + #define DYNAMIC_SECTION( ... ) + #define FAIL( ... ) (void)(0) + #define FAIL_CHECK( ... ) (void)(0) + #define SUCCEED( ... ) (void)(0) + #define SKIP( ... ) (void)(0) + + #define STATIC_REQUIRE( ... ) (void)(0) + #define STATIC_REQUIRE_FALSE( ... ) (void)(0) + #define STATIC_CHECK( ... ) (void)(0) + #define STATIC_CHECK_FALSE( ... ) (void)(0) + + // "BDD-style" convenience wrappers + #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ) ) + #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), className ) + + #define GIVEN( desc ) + #define AND_GIVEN( desc ) + #define WHEN( desc ) + #define AND_WHEN( desc ) + #define THEN( desc ) + #define AND_THEN( desc ) + +#endif // ^^ unprefixed, disabled + +// end of user facing macros + +#endif // CATCH_TEST_MACROS_HPP_INCLUDED + + +#ifndef CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED +#define CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED + + + +#ifndef CATCH_PREPROCESSOR_HPP_INCLUDED +#define CATCH_PREPROCESSOR_HPP_INCLUDED + + +#if defined(__GNUC__) +// We need to silence "empty __VA_ARGS__ warning", and using just _Pragma does not work +#pragma GCC system_header +#endif + + +#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ +#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) + +#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ +// MSVC needs more evaluations +#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) +#else +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) +#endif + +#define CATCH_REC_END(...) +#define CATCH_REC_OUT + +#define CATCH_EMPTY() +#define CATCH_DEFER(id) id CATCH_EMPTY() + +#define CATCH_REC_GET_END2() 0, CATCH_REC_END +#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 +#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 +#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT +#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) +#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) + +#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) + +#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) + +// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, +// and passes userdata as the first parameter to each invocation, +// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) +#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) +#else +// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) +#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) +#endif + +#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ +#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) + +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) +#else +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) +#endif + +#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ + CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) + +#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) +#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) +#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) +#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) +#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) +#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) +#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) +#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) +#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) + +#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N + +#define INTERNAL_CATCH_TYPE_GEN\ + template struct TypeList {};\ + template\ + constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ + template class...> struct TemplateTypeList{};\ + template class...Cs>\ + constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ + template\ + struct append;\ + template\ + struct rewrap;\ + template class, typename...>\ + struct create;\ + template class, typename>\ + struct convert;\ + \ + template \ + struct append { using type = T; };\ + template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ + struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ + template< template class L1, typename...E1, typename...Rest>\ + struct append, TypeList, Rest...> { using type = L1; };\ + \ + template< template class Container, template class List, typename...elems>\ + struct rewrap, List> { using type = TypeList>; };\ + template< template class Container, template class List, class...Elems, typename...Elements>\ + struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ + \ + template