From e59d4ad9a8e2da987961d26559cf32b3bf909ad8 Mon Sep 17 00:00:00 2001 From: Paolo Calao Date: Mon, 2 Nov 2020 16:59:23 +0100 Subject: [PATCH 1/8] [WIP] Add unit test workflow based on https://github.com/arduino/cpp-test-action/pull/2 --- .github/workflows/unit-tests.yml | 45 ++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 .github/workflows/unit-tests.yml diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml new file mode 100644 index 00000000..b889c771 --- /dev/null +++ b/.github/workflows/unit-tests.yml @@ -0,0 +1,45 @@ +name: Unit Tests + +on: + pull_request: + paths: + - ".github/workflows/unit-tests.yml" + - 'extras/test/**' + - 'src/**' + + push: + paths: + - ".github/workflows/unit-tests.yml" + - 'extras/test/**' + - 'src/**' + +jobs: + test: + name: Run unit tests + runs-on: ubuntu-latest + + env: + COVERAGE_DATA_PATH: extras/coverage-data/coverage.info + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - uses: arduino/cpp-test-action@main + with: + runtime-paths: | + - extras/test/build/bin/TEST_TARGET_UUID + - extras/test/build/bin/TEST_TARGET_DISC_DEVICE + - extras/test/build/bin/TEST_TARGET_ADVERTISING_DATA + coverage-exclude-paths: | + - '*/extras/test/*' + - '/usr/*' + coverage-data-path: ${{ env.COVERAGE_DATA_PATH }} + + - name: Upload coverage report to Codecov + uses: codecov/codecov-action@v1 + with: + file: "${{ env.COVERAGE_DATA_PATH }}" + fail_ci_if_error: true + + From 1340d09238cc5d08c6f7aa33aa93720f8bc77e76 Mon Sep 17 00:00:00 2001 From: Paolo Calao Date: Tue, 3 Nov 2020 11:35:54 +0100 Subject: [PATCH 2/8] [CI] Fix uninitialized checked variable --- extras/test/src/test_advertising_data/test_advertising_data.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extras/test/src/test_advertising_data/test_advertising_data.cpp b/extras/test/src/test_advertising_data/test_advertising_data.cpp index 67fa1d25..005ab51d 100644 --- a/extras/test/src/test_advertising_data/test_advertising_data.cpp +++ b/extras/test/src/test_advertising_data/test_advertising_data.cpp @@ -142,7 +142,7 @@ TEST_CASE("BLE test raw data", "[ArduinoBLE::BLEAdvertisingData]") uint8_t data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }; - advData.setRawData(data, sizeof(data)); + retVal = advData.setRawData(data, sizeof(data)); REQUIRE(!retVal); advData.clear(); } From 8035af8ad3ae2ef27e051bf42effd17f6280e527 Mon Sep 17 00:00:00 2001 From: Paolo Calao Date: Wed, 11 Nov 2020 15:47:13 +0100 Subject: [PATCH 3/8] [CI] Improve unit tests - improve test failures readability - add const qualifiers to golden data for improving safety --- .../test_advertising_data.cpp | 58 ++++++++----- .../test_advertising_data/test_local_name.cpp | 43 ++++++---- .../test_manufacturer.cpp | 81 ++++++++++++------- .../test_advertising_data/test_service.cpp | 55 ++++++++----- extras/test/src/test_uuid/test_uuid.cpp | 2 +- 5 files changed, 157 insertions(+), 82 deletions(-) diff --git a/extras/test/src/test_advertising_data/test_advertising_data.cpp b/extras/test/src/test_advertising_data/test_advertising_data.cpp index 005ab51d..5c4902d8 100644 --- a/extras/test/src/test_advertising_data/test_advertising_data.cpp +++ b/extras/test/src/test_advertising_data/test_advertising_data.cpp @@ -30,8 +30,8 @@ TEST_CASE("Test flags override", "[ArduinoBLE::BLEAdvertisingData]") // Mocking advertisement packet BLEAdvertisingData advData; // Expected results - uint8_t defaultData[] = {0x02, BLEFieldFlags, 0x06}; - uint8_t goldenFlags[] = {0x02, 0x01, BLEFlagsBREDRNotSupported}; + const uint8_t defaultData[] = {0x02, BLEFieldFlags, 0x06}; + const uint8_t goldenFlags[] = {0x02, 0x01, BLEFlagsBREDRNotSupported}; WHEN("Default options for flags") { @@ -74,9 +74,9 @@ TEST_CASE("Set default flags in an already full advertising data packet", "[Ardu const uint8_t manufacturerData[24] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}; - uint8_t defaultFlags[3] = {0x02, 0x01, 0x06}; + const uint8_t defaultFlags[3] = {0x02, 0x01, 0x06}; - uint8_t goldenData[31] = { + const uint8_t goldenData[31] = { (sizeof(manufacturerData) + 1), BLEFieldManufacturerData, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, ((uint8_t)(strlen(name) + 1)), BLEFieldCompleteLocalName, 't', 'e', 's' @@ -109,22 +109,36 @@ TEST_CASE("BLE overwrite a full internal advertising data with an external built BLE.setLocalName("test"); BLE.setAdvertisedServiceUuid("1818"); BLE.advertise(); - //WARN("data length: " << BLE.getAdvertisingData().dataLength()); - verify = (BLE.getAdvertisingData().dataLength() == (3 + (2+2))); - REQUIRE(verify); - verify = (BLE.getScanResponseData().dataLength() == (4+2)); - REQUIRE(verify); + THEN("Check that BLE advertising data has been set") + { + verify = (BLE.getAdvertisingData().dataLength() == (3 + (2+2))); + REQUIRE(verify); + } + + THEN("Check that BLE scan response data has been set") + { + verify = (BLE.getScanResponseData().dataLength() == (4+2)); + REQUIRE(verify); + } + + // Copy external empty adv data into advertising data BLE.setAdvertisingData(advData); BLE.advertise(); - //WARN(BLE.getAdvertisingData().dataLength()); - verify = (BLE.getAdvertisingData().dataLength() == 3); - REQUIRE(verify); + THEN("BLE advertising data should be erased") + { + verify = (BLE.getAdvertisingData().dataLength() == 3); + REQUIRE(verify); + } + // Copy external empty adv data into scan response data BLE.setScanResponseData(advData); BLE.advertise(); - verify = (BLE.getScanResponseData().dataLength() == 0); - REQUIRE(verify); + THEN("BLE scan response data should be erased") + { + verify = (BLE.getScanResponseData().dataLength() == 0); + REQUIRE(verify); + } } // Clear BLE advertising data @@ -139,21 +153,27 @@ TEST_CASE("BLE test raw data", "[ArduinoBLE::BLEAdvertisingData]") WHEN("Set too large raw data") { - uint8_t data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + const uint8_t data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }; retVal = advData.setRawData(data, sizeof(data)); - REQUIRE(!retVal); + THEN("Set raw data should return false. The parameter should not be set") + { + REQUIRE(!retVal); + } advData.clear(); } WHEN("Set correct raw data") { - uint8_t data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + const uint8_t data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; retVal = advData.setRawData(data, sizeof(data)); - REQUIRE(retVal); + THEN("Set raw data should return true. The parameter should be correctly set") + { + REQUIRE(retVal); + } advData.updateData(); REQUIRE( 0 == memcmp(data, advData.data(), sizeof(data)) ); advData.clear(); @@ -161,7 +181,7 @@ TEST_CASE("BLE test raw data", "[ArduinoBLE::BLEAdvertisingData]") WHEN("Hide other parameters by setting raw data") { - uint8_t data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + const uint8_t data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; advData.setLocalName("test"); advData.setRawData(data, sizeof(data)); diff --git a/extras/test/src/test_advertising_data/test_local_name.cpp b/extras/test/src/test_advertising_data/test_local_name.cpp index 947224cc..a0b4e19d 100644 --- a/extras/test/src/test_advertising_data/test_local_name.cpp +++ b/extras/test/src/test_advertising_data/test_local_name.cpp @@ -35,8 +35,15 @@ TEST_CASE("Test local name setting", "[ArduinoBLE::BLEAdvertisingData]") { const char* name = "test"; retVal = advData.setLocalName(name); - REQUIRE(retVal); - REQUIRE( (strlen(name) + 2) == (oldRemainingLength - advData.remainingLength()) ); + THEN("Set local name should return true. The name parameter should be correctly set") + { + REQUIRE(retVal); + } + + THEN("Check the exact number of bytes occupied by the name just set") + { + REQUIRE( (strlen(name) + 2) == (oldRemainingLength - advData.remainingLength()) ); + } oldRemainingLength = advData.remainingLength(); advData.updateData(); @@ -47,30 +54,36 @@ TEST_CASE("Test local name setting", "[ArduinoBLE::BLEAdvertisingData]") { const char* name = "way too long local name (len 32)"; retVal = advData.setLocalName(name); - REQUIRE(!retVal); - REQUIRE( oldRemainingLength == advData.remainingLength() ); - advData.updateData(); - REQUIRE( advData.dataLength() == (MAX_AD_DATA_LENGTH - oldRemainingLength) ); + THEN("Set local name should return false. The name parameter should not be set") + { + REQUIRE(!retVal); + REQUIRE( oldRemainingLength == advData.remainingLength() ); + advData.updateData(); + REQUIRE( advData.dataLength() == (MAX_AD_DATA_LENGTH - oldRemainingLength) ); + } } WHEN("Overwrite local name with a name as long as max data length") { const char* name = "local name with full length "; retVal = advData.setLocalName(name); - REQUIRE(retVal); - REQUIRE( (strlen(name) + 2) == (oldRemainingLength - advData.remainingLength()) ); - oldRemainingLength = advData.remainingLength(); + THEN("The name parameter should be correctly overwritten. The remaining length should be 0") + { + REQUIRE(retVal); + REQUIRE( (strlen(name) + 2) == (oldRemainingLength - advData.remainingLength()) ); + oldRemainingLength = advData.remainingLength(); - advData.updateData(); - REQUIRE(advData.dataLength() == (strlen(name) + 2)); - // advData should be full now - REQUIRE( 0 == advData.remainingLength() ); - REQUIRE( 0 == advData.availableForWrite() ); + advData.updateData(); + REQUIRE(advData.dataLength() == (strlen(name) + 2)); + // advData should be full now + REQUIRE( 0 == advData.remainingLength() ); + REQUIRE( 0 == advData.availableForWrite() ); + } } WHEN("Check consistency when setting the external advertising data") { - auto goldenData = advData.data(); + const auto goldenData = advData.data(); BLE.setAdvertisingData(advData); BLE.advertise(); REQUIRE( 0 == memcmp(goldenData, BLE.getAdvertisingData().data(), advData.dataLength()) ); diff --git a/extras/test/src/test_advertising_data/test_manufacturer.cpp b/extras/test/src/test_advertising_data/test_manufacturer.cpp index 39f7e955..7c23d26c 100644 --- a/extras/test/src/test_advertising_data/test_manufacturer.cpp +++ b/extras/test/src/test_advertising_data/test_manufacturer.cpp @@ -29,7 +29,7 @@ TEST_CASE("Test manufacturer data setting", "[ArduinoBLE::BLEAdvertisingData]") { BLEAdvertisingData advData; int oldRemainingLength = advData.remainingLength(); - uint16_t companyId = 0x1100; + const uint16_t companyId = 0x1100; bool retVal; WHEN("Set correct manufacturer data without id") @@ -38,8 +38,11 @@ TEST_CASE("Test manufacturer data setting", "[ArduinoBLE::BLEAdvertisingData]") const uint8_t goldenData[] = {(sizeof(data) + 1), BLEFieldManufacturerData, 0x00, 0x11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; retVal = advData.setManufacturerData(data, sizeof(data)); - REQUIRE(retVal); - REQUIRE( (sizeof(data) + 2) == (oldRemainingLength - advData.remainingLength()) ); + THEN("Check that the manufacturer data has been correctly set") + { + REQUIRE(retVal); + REQUIRE( (sizeof(data) + 2) == (oldRemainingLength - advData.remainingLength()) ); + } oldRemainingLength = advData.remainingLength(); advData.updateData(); @@ -53,8 +56,11 @@ TEST_CASE("Test manufacturer data setting", "[ArduinoBLE::BLEAdvertisingData]") const uint8_t goldenData[] = {(sizeof(data) + sizeof(companyId) + 1), BLEFieldManufacturerData, 0x00, 0x11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; retVal = advData.setManufacturerData(companyId, data, sizeof(data)); - REQUIRE(retVal); - REQUIRE( (sizeof(data) + sizeof(companyId) + 2) == (oldRemainingLength - advData.remainingLength()) ); + THEN("Check that the manufacturer data has been correctly set") + { + REQUIRE(retVal); + REQUIRE( (sizeof(data) + sizeof(companyId) + 2) == (oldRemainingLength - advData.remainingLength()) ); + } oldRemainingLength = advData.remainingLength(); advData.updateData(); @@ -68,8 +74,11 @@ TEST_CASE("Test manufacturer data setting", "[ArduinoBLE::BLEAdvertisingData]") const uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}; retVal = advData.setManufacturerData(companyId, data, sizeof(data)); - REQUIRE(!retVal); - REQUIRE( oldRemainingLength == advData.remainingLength() ); + THEN("Manufacturer data was too long, check that it has not been set") + { + REQUIRE(!retVal); + REQUIRE( oldRemainingLength == advData.remainingLength() ); + } advData.updateData(); REQUIRE( advData.dataLength() == (MAX_AD_DATA_LENGTH - oldRemainingLength) ); } @@ -80,8 +89,11 @@ TEST_CASE("Test manufacturer data setting", "[ArduinoBLE::BLEAdvertisingData]") const uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}; retVal = advData.setManufacturerData(data, sizeof(data)); - REQUIRE(!retVal); - REQUIRE( oldRemainingLength == advData.remainingLength() ); + THEN("Manufacturer data was too long, check that it has not been set") + { + REQUIRE(!retVal); + REQUIRE( oldRemainingLength == advData.remainingLength() ); + } advData.updateData(); REQUIRE( advData.dataLength() == (MAX_AD_DATA_LENGTH - oldRemainingLength) ); } @@ -93,13 +105,19 @@ TEST_CASE("Test manufacturer data setting", "[ArduinoBLE::BLEAdvertisingData]") 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}; const uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28}; - retVal = advData.setManufacturerData(companyId, dataGivenId, sizeof(dataGivenId)); - REQUIRE(retVal); - retVal = advData.setManufacturerData(data, sizeof(data)); - REQUIRE(retVal); - REQUIRE( 0 == advData.remainingLength() ); - advData.updateData(); - REQUIRE( advData.dataLength() == (MAX_AD_DATA_LENGTH) ); + THEN("Check that first insertion of manufacturer data given id is correctly done") + { + retVal = advData.setManufacturerData(companyId, dataGivenId, sizeof(dataGivenId)); + REQUIRE(retVal); + } + THEN("Check that the insertion of manufacturer data without after one with id is correctly done") + { + retVal = advData.setManufacturerData(data, sizeof(data)); + REQUIRE(retVal); + REQUIRE( 0 == advData.remainingLength() ); + advData.updateData(); + REQUIRE( advData.dataLength() == (MAX_AD_DATA_LENGTH) ); + } } WHEN("Set manufacturer data given id after setting manufacturer data without id") @@ -110,10 +128,16 @@ TEST_CASE("Test manufacturer data setting", "[ArduinoBLE::BLEAdvertisingData]") 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}; const uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28}; - retVal = advData.setManufacturerData(data, sizeof(data)); - REQUIRE(retVal); - retVal = advData.setManufacturerData(companyId, dataGivenId, sizeof(dataGivenId)); - REQUIRE(!retVal); + THEN("Check that first insertion of manufacturer data WITHOUT id is correctly done") + { + retVal = advData.setManufacturerData(data, sizeof(data)); + REQUIRE(retVal); + } + THEN("Check that the insertion of manufacturer data given id after one without id is correctly done") + { + retVal = advData.setManufacturerData(companyId, dataGivenId, sizeof(dataGivenId)); + REQUIRE(!retVal); + } } WHEN("Overwrite manufacturer data with one as long as max data length") @@ -124,17 +148,20 @@ TEST_CASE("Test manufacturer data setting", "[ArduinoBLE::BLEAdvertisingData]") 0x00, 0x11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}; retVal = advData.setManufacturerData(companyId, data, sizeof(data)); - REQUIRE(retVal); - - advData.updateData(); - REQUIRE( 0 == advData.remainingLength() ); - REQUIRE( 0 == advData.availableForWrite() ); - REQUIRE( 0 == memcmp(goldenData, advData.data(), sizeof(goldenData)) ); + THEN("Manufacturer data should be set correctly") + { + REQUIRE(retVal); + + advData.updateData(); + REQUIRE( 0 == advData.remainingLength() ); + REQUIRE( 0 == advData.availableForWrite() ); + REQUIRE( 0 == memcmp(goldenData, advData.data(), sizeof(goldenData)) ); + } } WHEN("Check consistency when setting the external advertising data") { - auto goldenData = advData.data(); + const auto goldenData = advData.data(); BLE.setAdvertisingData(advData); BLE.advertise(); REQUIRE( 0 == memcmp(goldenData, BLE.getAdvertisingData().data(), advData.dataLength()) ); diff --git a/extras/test/src/test_advertising_data/test_service.cpp b/extras/test/src/test_advertising_data/test_service.cpp index 5c212c1f..66b1689f 100644 --- a/extras/test/src/test_advertising_data/test_service.cpp +++ b/extras/test/src/test_advertising_data/test_service.cpp @@ -50,12 +50,13 @@ TEST_CASE("Test advertised service id setting", "[ArduinoBLE::BLEAdvertisingData const char* service = "00112233445566770011223344556677"; advData.setLocalName(name); oldRemainingLength = advData.remainingLength(); - retVal = advData.setAdvertisedServiceUuid(service); - REQUIRE(!retVal); - - REQUIRE( oldRemainingLength == advData.remainingLength() ); - advData.updateData(); - REQUIRE( advData.dataLength() == (MAX_AD_DATA_LENGTH - oldRemainingLength) ); + THEN("Check that the too long parameter has not been set") + { + REQUIRE(!advData.setAdvertisedServiceUuid(service)); + REQUIRE( oldRemainingLength == advData.remainingLength() ); + advData.updateData(); + REQUIRE( advData.dataLength() == (MAX_AD_DATA_LENGTH - oldRemainingLength) ); + } } WHEN("Fill to maximum an advertising packet with a service id") @@ -64,8 +65,7 @@ TEST_CASE("Test advertised service id setting", "[ArduinoBLE::BLEAdvertisingData const char* name = "11 char str"; const char* service = "00112233445566770011223344556677"; advData.setLocalName(name); - retVal = advData.setAdvertisedServiceUuid(service); - REQUIRE(retVal); + REQUIRE(advData.setAdvertisedServiceUuid(service)); advData.updateData(); REQUIRE(advData.dataLength() == (MAX_AD_DATA_LENGTH)); @@ -76,7 +76,7 @@ TEST_CASE("Test advertised service id setting", "[ArduinoBLE::BLEAdvertisingData WHEN("Check consistency when setting the external advertising data") { - auto goldenData = advData.data(); + const auto goldenData = advData.data(); BLE.setAdvertisingData(advData); BLE.advertise(); REQUIRE( 0 == memcmp(goldenData, BLE.getAdvertisingData().data(), advData.dataLength()) ); @@ -91,7 +91,7 @@ TEST_CASE("Test service data setting", "[ArduinoBLE::BLEAdvertisingData]") { BLEAdvertisingData advData; int oldRemainingLength = advData.remainingLength(); - uint16_t uuid = 0x1100; + const uint16_t uuid = 0x1100; bool retVal; WHEN("Set correct service data") @@ -100,14 +100,20 @@ TEST_CASE("Test service data setting", "[ArduinoBLE::BLEAdvertisingData]") const uint8_t goldenData[] = {(sizeof(data) + sizeof(uuid) + 1), BLEFieldServiceData, 0x00, 0x11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; retVal = advData.setAdvertisedServiceData(uuid, data, sizeof(data)); - REQUIRE(retVal); - REQUIRE( (sizeof(data) + 2 + sizeof(uuid)) == (oldRemainingLength - advData.remainingLength()) ); + THEN("Correctly set parameter") + { + REQUIRE(retVal); + REQUIRE( (sizeof(data) + 2 + sizeof(uuid)) == (oldRemainingLength - advData.remainingLength()) ); + } oldRemainingLength = advData.remainingLength(); advData.updateData(); - REQUIRE(advData.dataLength() == (sizeof(data) + 2 + sizeof(uuid))); - REQUIRE(advData.dataLength() == sizeof(goldenData)); - REQUIRE( 0 == memcmp(goldenData, advData.data(), sizeof(goldenData)) ); + THEN("Check parameter analyzing advertising raw data") + { + REQUIRE(advData.dataLength() == (sizeof(data) + 2 + sizeof(uuid))); + REQUIRE(advData.dataLength() == sizeof(goldenData)); + REQUIRE( 0 == memcmp(goldenData, advData.data(), sizeof(goldenData)) ); + } } WHEN("Set too long service data") @@ -116,7 +122,10 @@ TEST_CASE("Test service data setting", "[ArduinoBLE::BLEAdvertisingData]") const uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}; retVal = advData.setAdvertisedServiceData(uuid, data, sizeof(data)); - REQUIRE(!retVal); + THEN("Check that the too long parameter has not been set") + { + REQUIRE(!retVal); + } REQUIRE( oldRemainingLength == advData.remainingLength() ); advData.updateData(); REQUIRE( advData.dataLength() == (MAX_AD_DATA_LENGTH - oldRemainingLength) ); @@ -127,17 +136,23 @@ TEST_CASE("Test service data setting", "[ArduinoBLE::BLEAdvertisingData]") const uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}; retVal = advData.setAdvertisedServiceData(uuid, data, sizeof(data)); - REQUIRE(retVal); + THEN("Check correctly set parameter") + { + REQUIRE(retVal); + } advData.updateData(); // advData should be full now - REQUIRE( 0 == advData.remainingLength() ); - REQUIRE( 0 == advData.availableForWrite() ); + THEN("advData should be full now") + { + REQUIRE( 0 == advData.remainingLength() ); + REQUIRE( 0 == advData.availableForWrite() ); + } } WHEN("Check consistency when setting the external advertising data") { - auto goldenData = advData.data(); + const auto goldenData = advData.data(); BLE.setAdvertisingData(advData); BLE.advertise(); REQUIRE( 0 == memcmp(goldenData, BLE.getAdvertisingData().data(), advData.dataLength()) ); diff --git a/extras/test/src/test_uuid/test_uuid.cpp b/extras/test/src/test_uuid/test_uuid.cpp index 13b655e6..1832c741 100644 --- a/extras/test/src/test_uuid/test_uuid.cpp +++ b/extras/test/src/test_uuid/test_uuid.cpp @@ -47,6 +47,6 @@ TEST_CASE("BLE uuid test", "[ArduinoBLE::BLEUuid]") REQUIRE(verify); // print the uuid - WARN("test: " << testUuid << ", golden: " << goldenUuid); + //WARN("test: " << testUuid << ", golden: " << goldenUuid); } } \ No newline at end of file From 6fa01914ae14237c3afb1498140791e8be961e2a Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 8 Apr 2025 09:04:47 +0200 Subject: [PATCH 4/8] [CI] use codecov token --- .github/workflows/unit-tests.yml | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index b889c771..2a96b8a5 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - uses: arduino/cpp-test-action@main with: @@ -36,10 +36,23 @@ jobs: - '/usr/*' coverage-data-path: ${{ env.COVERAGE_DATA_PATH }} + # A token is used to avoid intermittent spurious job failures caused by rate limiting. + - name: Set up Codecov upload token + run: | + if [[ "${{ github.repository }}" == "arduino-libraries/ArduinoBLE" ]]; then + # In order to avoid uploads of data from forks, only use the token for runs in the parent repo. + # Token is intentionally exposed. + # See: https://community.codecov.com/t/upload-issues-unable-to-locate-build-via-github-actions-api/3954 + CODECOV_TOKEN="8118de48-b2af-48b4-a66a-26026847bfc5" + else + # codecov/codecov-action does unauthenticated upload if empty string is passed via the `token` input. + CODECOV_TOKEN="" + fi + echo "CODECOV_TOKEN=$CODECOV_TOKEN" >> "$GITHUB_ENV" + - name: Upload coverage report to Codecov - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v3 with: file: "${{ env.COVERAGE_DATA_PATH }}" fail_ci_if_error: true - - + token: ${{ env.CODECOV_TOKEN }} From c5bed5560455486c92f2ded02e18e8c6e72dbed4 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 8 Apr 2025 11:36:21 +0200 Subject: [PATCH 5/8] [CI] modernize cmake build --- extras/test/.gitignore | 18 +- extras/test/CMakeLists.txt | 20 +- .../external/catch/v2.12.1/include/catch.hpp | 17698 ---------------- .../test_advertising_data.cpp | 2 +- .../test_advertising_data/test_local_name.cpp | 2 +- .../test_manufacturer.cpp | 2 +- .../test_advertising_data/test_service.cpp | 2 +- .../test_discovered_device.cpp | 2 +- extras/test/src/test_main.cpp | 2 +- extras/test/src/test_uuid/test_uuid.cpp | 2 +- 10 files changed, 42 insertions(+), 17708 deletions(-) delete mode 100644 extras/test/external/catch/v2.12.1/include/catch.hpp diff --git a/extras/test/.gitignore b/extras/test/.gitignore index c795b054..7e9215ee 100644 --- a/extras/test/.gitignore +++ b/extras/test/.gitignore @@ -1 +1,17 @@ -build \ No newline at end of file +build +### CMake ### +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +### CMake Patch ### +# External projects +*-prefix/ \ No newline at end of file diff --git a/extras/test/CMakeLists.txt b/extras/test/CMakeLists.txt index bbba16ca..84603cd3 100644 --- a/extras/test/CMakeLists.txt +++ b/extras/test/CMakeLists.txt @@ -1,12 +1,22 @@ ########################################################################## set(CMAKE_VERBOSE_MAKEFILE ON) -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.5) ########################################################################## project(testArduinoBLE) +Include(FetchContent) + +FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v3.4.0 +) + +FetchContent_MakeAvailable(Catch2) + ########################################################################## set(CMAKE_CXX_STANDARD 11) @@ -35,6 +45,9 @@ set(DUT_SRCS ../../src/utility/HCI.cpp ../../src/utility/GATT.cpp ../../src/utility/L2CAPSignaling.cpp + ../../src/utility/keyDistribution.cpp + ../../src/utility/bitDescriptions.cpp + ../../src/utility/btct.cpp ../../src/local/BLELocalAttribute.cpp ../../src/local/BLELocalCharacteristic.cpp ../../src/local/BLELocalDescriptor.cpp @@ -102,7 +115,6 @@ include_directories(../../src) include_directories(../../src/local) include_directories(../../src/remote) include_directories(../../src/utility) -include_directories(external/catch/v2.12.1/include) target_include_directories(TEST_TARGET_DISC_DEVICE PUBLIC include/test_discovered_device) target_include_directories(TEST_TARGET_ADVERTISING_DATA PUBLIC include/test_advertising_data) @@ -124,3 +136,7 @@ add_custom_command(TARGET TEST_TARGET_DISC_DEVICE POST_BUILD add_custom_command(TARGET TEST_TARGET_ADVERTISING_DATA POST_BUILD COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/TEST_TARGET_ADVERTISING_DATA ) + +target_link_libraries( TEST_TARGET_UUID Catch2WithMain ) +target_link_libraries( TEST_TARGET_DISC_DEVICE Catch2WithMain ) +target_link_libraries( TEST_TARGET_ADVERTISING_DATA Catch2WithMain ) diff --git a/extras/test/external/catch/v2.12.1/include/catch.hpp b/extras/test/external/catch/v2.12.1/include/catch.hpp deleted file mode 100644 index 1d2c9bb6..00000000 --- a/extras/test/external/catch/v2.12.1/include/catch.hpp +++ /dev/null @@ -1,17698 +0,0 @@ -/* - * Catch v2.12.1 - * Generated: 2020-04-21 19:29:20.964532 - * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved. - * - * Distributed under the Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - */ -#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -// start catch.hpp - - -#define CATCH_VERSION_MAJOR 2 -#define CATCH_VERSION_MINOR 12 -#define CATCH_VERSION_PATCH 1 - -#ifdef __clang__ -# pragma clang system_header -#elif defined __GNUC__ -# pragma GCC system_header -#endif - -// start catch_suppress_warnings.h - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(push) -# pragma warning(disable: 161 1682) -# else // __ICC -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wswitch-enum" -# pragma clang diagnostic ignored "-Wcovered-switch-default" -# endif -#elif defined __GNUC__ - // Because REQUIREs trigger GCC's -Wparentheses, and because still - // supported version of g++ have only buggy support for _Pragmas, - // Wparentheses have to be suppressed globally. -# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details - -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic ignored "-Wpadded" -#endif -// end catch_suppress_warnings.h -#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) -# define CATCH_IMPL -# define CATCH_CONFIG_ALL_PARTS -#endif - -// In the impl file, we want to have access to all parts of the headers -// Can also be used to sanely support PCHs -#if defined(CATCH_CONFIG_ALL_PARTS) -# define CATCH_CONFIG_EXTERNAL_INTERFACES -# if defined(CATCH_CONFIG_DISABLE_MATCHERS) -# undef CATCH_CONFIG_DISABLE_MATCHERS -# endif -# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) -# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER -# endif -#endif - -#if !defined(CATCH_CONFIG_IMPL_ONLY) -// start catch_platform.h - -#ifdef __APPLE__ -# include -# if TARGET_OS_OSX == 1 -# define CATCH_PLATFORM_MAC -# elif TARGET_OS_IPHONE == 1 -# define CATCH_PLATFORM_IPHONE -# endif - -#elif defined(linux) || defined(__linux) || defined(__linux__) -# define CATCH_PLATFORM_LINUX - -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) -# define CATCH_PLATFORM_WINDOWS -#endif - -// end catch_platform.h - -#ifdef CATCH_IMPL -# ifndef CLARA_CONFIG_MAIN -# define CLARA_CONFIG_MAIN_NOT_DEFINED -# define CLARA_CONFIG_MAIN -# endif -#endif - -// start catch_user_interfaces.h - -namespace Catch { - unsigned int rngSeed(); -} - -// end catch_user_interfaces.h -// start catch_tag_alias_autoregistrar.h - -// start catch_common.h - -// start catch_compiler_capabilities.h - -// Detect a number of compiler features - by compiler -// The following features are defined: -// -// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? -// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? -// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? -// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? -// **************** -// Note to maintainers: if new toggles are added please document them -// in configuration.md, too -// **************** - -// In general each macro has a _NO_ form -// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. -// Many features, at point of detection, define an _INTERNAL_ macro, so they -// can be combined, en-mass, with the _NO_ forms later. - -#ifdef __cplusplus - -# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) -# define CATCH_CPP14_OR_GREATER -# endif - -# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) -# define CATCH_CPP17_OR_GREATER -# endif - -#endif - -#if defined(__cpp_lib_uncaught_exceptions) -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -#endif - -// We have to avoid both ICC and Clang, because they try to mask themselves -// as gcc, and we want only GCC in this block -#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) - -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) - -#endif - -#if defined(__clang__) - -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) - -// 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") -// ``` -// -// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. -# if !defined(__ibmxl__) -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-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_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\"" ) - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// Assume that non-Windows platforms support posix signals by default -#if !defined(CATCH_PLATFORM_WINDOWS) - #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS -#endif - -//////////////////////////////////////////////////////////////////////////////// -// We know some environments not to support full POSIX signals -#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) - #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -#endif - -#ifdef __OS400__ -# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -# define CATCH_CONFIG_COLOUR_NONE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Android somehow still does not support std::to_string -#if defined(__ANDROID__) -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING -# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE -#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) - -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) - -# if _MSC_VER >= 1900 // Visual Studio 2015 or newer -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -# endif - -// Universal Windows platform does not support SEH -// Or console colours (or console at all...) -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) -# define CATCH_CONFIG_COLOUR_NONE -# else -# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH -# endif - -// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ -// _MSVC_TRADITIONAL == 0 means new conformant preprocessor -// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor -# if !defined(__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 - -//////////////////////////////////////////////////////////////////////////////// -// DJGPP -#ifdef __DJGPP__ -# define CATCH_INTERNAL_CONFIG_NO_WCHAR -#endif // __DJGPP__ - -//////////////////////////////////////////////////////////////////////////////// -// Embarcadero C++Build -#if defined(__BORLANDC__) - #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// Use of __COUNTER__ is suppressed during code analysis in -// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly -// handled by it. -// Otherwise all supported compilers support COUNTER macro, -// but user still might want to turn it off -#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) - #define CATCH_INTERNAL_CONFIG_COUNTER -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// 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_CONFIG_COLOUR_NONE -#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) - # define CATCH_INTERNAL_CONFIG_CPP17_BYTE - # 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_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) -# define CATCH_CONFIG_COUNTER -#endif -#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) -# define CATCH_CONFIG_WINDOWS_SEH -#endif -// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. -#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) -# define CATCH_CONFIG_POSIX_SIGNALS -#endif -// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. -#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) -# define CATCH_CONFIG_WCHAR -#endif - -#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) -# define CATCH_CONFIG_CPP11_TO_STRING -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) -# define CATCH_CONFIG_CPP17_OPTIONAL -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) -# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) -# define CATCH_CONFIG_CPP17_STRING_VIEW -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) -# define CATCH_CONFIG_CPP17_VARIANT -#endif - -#if defined(CATCH_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) -# 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_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) -# define CATCH_CONFIG_ANDROID_LOGWRITE -#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_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_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_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) -# define 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 - -// end catch_compiler_capabilities.h -#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line -#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) -#ifdef CATCH_CONFIG_COUNTER -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) -#else -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) -#endif - -#include -#include -#include - -// We need a dummy global operator<< so we can bring it into Catch namespace later -struct Catch_global_namespace_dummy {}; -std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); - -namespace Catch { - - struct CaseSensitive { enum Choice { - Yes, - No - }; }; - - class NonCopyable { - NonCopyable( NonCopyable const& ) = delete; - NonCopyable( NonCopyable && ) = delete; - NonCopyable& operator = ( NonCopyable const& ) = delete; - NonCopyable& operator = ( NonCopyable && ) = delete; - - protected: - NonCopyable(); - virtual ~NonCopyable(); - }; - - struct SourceLineInfo { - - SourceLineInfo() = delete; - SourceLineInfo( char const* _file, std::size_t _line ) noexcept - : file( _file ), - line( _line ) - {} - - SourceLineInfo( SourceLineInfo const& other ) = default; - SourceLineInfo& operator = ( SourceLineInfo const& ) = default; - SourceLineInfo( SourceLineInfo&& ) noexcept = default; - SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; - - bool empty() const noexcept { return file[0] == '\0'; } - bool operator == ( SourceLineInfo const& other ) const noexcept; - bool operator < ( SourceLineInfo const& other ) const noexcept; - - char const* file; - std::size_t line; - }; - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); - - // Bring in operator<< from global namespace into Catch namespace - // This is necessary because the overload of operator<< above makes - // lookup stop at namespace Catch - using ::operator<<; - - // Use this in variadic streaming macros to allow - // >> +StreamEndStop - // as well as - // >> stuff +StreamEndStop - struct StreamEndStop { - std::string operator+() const; - }; - template - T const& operator + ( T const& value, StreamEndStop ) { - return value; - } -} - -#define CATCH_INTERNAL_LINEINFO \ - ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) - -// end catch_common.h -namespace Catch { - - struct RegistrarForTagAliases { - RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); - }; - -} // end namespace Catch - -#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ - CATCH_INTERNAL_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 - -// end catch_tag_alias_autoregistrar.h -// start catch_test_registry.h - -// start catch_interfaces_testcase.h - -#include - -namespace Catch { - - class TestSpec; - - struct ITestInvoker { - virtual void invoke () const = 0; - virtual ~ITestInvoker(); - }; - - class TestCase; - struct IConfig; - - struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual std::vector const& getAllTests() const = 0; - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; - }; - - bool isThrowSafe( TestCase const& testCase, IConfig const& config ); - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); - std::vector const& getAllTestCasesSorted( IConfig const& config ); - -} - -// end catch_interfaces_testcase.h -// start catch_stringref.h - -#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*; - - 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 const& other ) const noexcept -> bool; - auto operator != (StringRef const& other) const noexcept -> bool { - return !(*this == other); - } - - auto operator[] ( size_type index ) const noexcept -> char { - assert(index < m_size); - return m_start[index]; - } - - public: // named queries - constexpr auto empty() const noexcept -> bool { - return m_size == 0; - } - constexpr auto size() const noexcept -> size_type { - return m_size; - } - - // Returns the current start pointer. If the StringRef is not - // null-terminated, throws std::domain_exception - auto c_str() const -> char const*; - - public: // substrings and searches - // 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. - auto substr( size_type start, size_type length ) const noexcept -> StringRef; - - // Returns the current start pointer. May not be null-terminated. - auto data() const noexcept -> char const*; - - constexpr auto isNullTerminated() const noexcept -> bool { - return m_start[m_size] == '\0'; - } - - public: // iterators - constexpr const_iterator begin() const { return m_start; } - constexpr const_iterator end() const { return m_start + m_size; } - }; - - auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; - auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; - - 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 ); -} - -// end catch_stringref.h -// start catch_preprocessor.hpp - - -#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ -#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) - -#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ -// MSVC needs more evaluations -#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) -#else -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) -#endif - -#define CATCH_REC_END(...) -#define CATCH_REC_OUT - -#define CATCH_EMPTY() -#define CATCH_DEFER(id) id CATCH_EMPTY() - -#define CATCH_REC_GET_END2() 0, CATCH_REC_END -#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 -#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 -#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT -#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) -#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) - -#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) - -#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) - -// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, -// and passes userdata as the first parameter to each invocation, -// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) -#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) - -#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) - -#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) -#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ -#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ -#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF -#define INTERNAL_CATCH_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) - -#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) - -#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, _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