diff --git a/CHANGELOG.md b/CHANGELOG.md index f7459b47..95510d63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ Please see [CONTRIBUTING.md](https://github.com/cucumber/cucumber/blob/master/CONTRIBUTING.md) on how to contribute to Cucumber. +## In Git + +### Added + +### Changed + +### Fixed + +* Statically linking `boost_system` ([#197](https://github.com/cucumber/cucumber-cpp/pull/197) Matthieu Longo) +* Unable to `add_subdirectory(cucumber-cpp)` ([#211](https://github.com/cucumber/cucumber-cpp/pull/211) Sergey Bon) +* Warning C4265 on Visual Studio ([#195](https://github.com/cucumber/cucumber-cpp/pull/195) Matthieu Longo) +* Fix handling of optional regex captures ([#221](https://github.com/cucumber/cucumber-cpp/pull/221) Alain Martin) + ## [0.5](https://github.com/cucumber/cucumber-cpp/compare/v0.4...v0.5) (2 July 2018) ### Added diff --git a/CMakeLists.txt b/CMakeLists.txt index df364be9..ca0d7115 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,23 +5,61 @@ if(NOT CMAKE_VERSION VERSION_LESS "3.3") cmake_policy(SET CMP0063 NEW) endif() +if (NOT CMAKE_VERSION VERSION_LESS "3.13") + # CMP0077: option() honors normal variables + # https://cmake.org/cmake/help/latest/policy/CMP0077.html + cmake_policy(SET CMP0077 NEW) +endif() + project(Cucumber-Cpp) option(BUILD_SHARED_LIBS "Generate shared libraries" OFF) option(CUKE_USE_STATIC_BOOST "Statically link Boost (except boost::test)" ${WIN32}) option(CUKE_USE_STATIC_GTEST "Statically link Google Test" ON) -option(CUKE_DISABLE_BOOST_TEST "Disable boost:test" OFF) -option(CUKE_DISABLE_GTEST "Disable Google Test framework" OFF) -option(CUKE_DISABLE_UNIT_TESTS "Disable unit tests" OFF) -option(CUKE_DISABLE_E2E_TESTS "Disable end-to-end tests" OFF) -option(CUKE_ENABLE_EXAMPLES "Enable the examples" OFF) -option(CUKE_DISABLE_QT "Disable using Qt framework" OFF) -option(VALGRIND_TESTS "Run tests within Valgrind" OFF) +option(CUKE_ENABLE_BOOST_TEST "Enable Boost.Test framework" ON) +option(CUKE_ENABLE_EXAMPLES "Build examples" OFF) +option(CUKE_ENABLE_GTEST "Enable Google Test framework" ON) +option(CUKE_ENABLE_QT "Enable Qt framework" ON) +option(CUKE_TESTS_E2E "Enable end-to-end tests" ON) +option(CUKE_TESTS_UNIT "Enable unit tests" ON) +option(CUKE_TESTS_VALGRIND "Enable tests within Valgrind" OFF) set(GMOCK_SRC_DIR "" CACHE STRING "Google Mock framework sources path (otherwise downloaded)") set(GMOCK_VER "1.7.0" CACHE STRING "Google Mock framework version to be used") set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules) +# +# Option deprecation: if deprecated option is defined +# then print a warning and use its value instead +# + +function(option_depr_message old prefer) + message (DEPRECATION "${old} is deprecated in favor of ${prefer}") +endfunction() + +function(option_depr old prefer) + if(DEFINED ${old}) + option_depr_message(${old} ${prefer}) + set (${prefer} ${${old}} CACHE BOOL "Set from deprecated ${old}" FORCE) + endif() +endfunction() + +function(option_depr_invert old prefer) + if(DEFINED ${old}) + option_depr_message(${old} ${prefer}) + set (${prefer} $ CACHE BOOL "Set from deprecated ${old}" FORCE) + endif() +endfunction() + + +option_depr_invert (CUKE_DISABLE_BOOST_TEST CUKE_ENABLE_BOOST_TEST) +option_depr_invert (CUKE_DISABLE_GTEST CUKE_ENABLE_GTEST) +option_depr_invert (CUKE_DISABLE_QT CUKE_ENABLE_QT) +option_depr_invert (CUKE_DISABLE_E2E_TESTS CUKE_TESTS_E2E) +option_depr_invert (CUKE_DISABLE_UNIT_TESTS CUKE_TESTS_UNIT) +option_depr (VALGRIND_TESTS CUKE_TESTS_VALGRIND) + + # # Generic Compiler Flags # @@ -70,7 +108,7 @@ endif() set(Boost_USE_STATIC_RUNTIME OFF) set(CUKE_CORE_BOOST_LIBS thread system regex date_time program_options filesystem) -if(NOT CUKE_DISABLE_BOOST_TEST) +if(CUKE_ENABLE_BOOST_TEST) # "An external test runner utility is required to link with dynamic library" (Boost User's Guide) set(Boost_USE_STATIC_LIBS OFF) set(CMAKE_CXX_FLAGS "-DBOOST_TEST_DYN_LINK ${CMAKE_CXX_FLAGS}") @@ -112,6 +150,11 @@ if(Boost_SYSTEM_LIBRARY AND NOT TARGET Boost::system) "IMPORTED_LOCATION" "${Boost_SYSTEM_LIBRARY}" "INTERFACE_LINK_LIBRARIES" "Boost::boost" ) + if(Boost_USE_STATIC_LIBS) + set_target_properties(Boost::system PROPERTIES + "COMPILE_DEFINITIONS" BOOST_ERROR_CODE_HEADER_ONLY=1 + ) + endif() endif() if(Boost_FILESYSTEM_LIBRARY AND NOT TARGET Boost::filesystem) add_library(Boost::filesystem ${LIBRARY_TYPE} IMPORTED) @@ -153,7 +196,7 @@ endif() # GTest # -if(NOT CUKE_DISABLE_GTEST) +if(CUKE_ENABLE_GTEST) set(GTEST_USE_STATIC_LIBS ${CUKE_USE_STATIC_GTEST}) if(NOT GMOCK_ROOT) set(GMOCK_ROOT "${CMAKE_CURRENT_BINARY_DIR}/gmock") @@ -165,7 +208,7 @@ endif() # Qt # -if(NOT CUKE_DISABLE_QT) +if(CUKE_ENABLE_QT) find_package(Qt5Core) find_package(Qt5Gui) find_package(Qt5Widgets) @@ -205,7 +248,7 @@ endif() # Valgrind # -if(VALGRIND_TESTS) +if(CUKE_TESTS_VALGRIND) find_package(Valgrind REQUIRED) set(VALGRIND_ARGS --error-exitcode=2 --leak-check=full --undef-value-errors=no) if(NOT VALGRIND_VERSION_STRING VERSION_LESS 3.9) @@ -260,14 +303,14 @@ add_subdirectory(src) # Tests # -if(CUKE_DISABLE_UNIT_TESTS) - message(STATUS "Skipping unit tests") -else() +if(CUKE_TESTS_UNIT) enable_testing() add_subdirectory(tests) +else() + message(STATUS "Skipping unit tests") endif() -if(CUKE_DISABLE_E2E_TESTS) +if(NOT CUKE_TESTS_E2E) message(STATUS "Skipping end-to-end tests") else() find_program(CUCUMBER_RUBY cucumber) diff --git a/Gemfile b/Gemfile index 6a6a0374..968f8493 100644 --- a/Gemfile +++ b/Gemfile @@ -4,5 +4,7 @@ group :test do gem 'cucumber', "=2.0.0" gem 'aruba', "=0.8.0" gem 'rspec', "=3.4.0" + gem 'childprocess', "=0.5.9" + gem 'ffi', "=1.9.25" end diff --git a/README.md b/README.md index e7614182..a6055350 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,10 @@ Cucumber-Cpp uses the wire protocol at the moment, so you will need Cucumber-Ruby installed and available on the path. It is also needed to run the functional test suite. +Please mind that Cucumber-Cpp is not compatible with Cucumber-Ruby 3.x +due to a [bug in its wire protocol](https://github.com/cucumber/cucumber-ruby/issues/1183) +implementation. + To install the Ruby prerequisites: ``` diff --git a/examples/CalcQt/CMakeLists.txt b/examples/CalcQt/CMakeLists.txt index 1b3dd1a1..c09ec67c 100644 --- a/examples/CalcQt/CMakeLists.txt +++ b/examples/CalcQt/CMakeLists.txt @@ -15,10 +15,8 @@ if(TARGET Qt::Core AND TARGET Qt::Gui AND TARGET Qt::Widgets AND TARGET Qt::Test add_executable(calcqt src/CalcQt.cpp) target_link_libraries(calcqt PRIVATE libcalcqt Qt::Widgets) - if(Qt::Test) - add_executable(QtTestCalculatorQtSteps features/step_definitions/QtTestCalculatorQtSteps) - target_link_libraries(QtTestCalculatorQtSteps PRIVATE libcalcqt Qt::Test cucumber-cpp) - endif() + add_executable(QtTestCalculatorQtSteps features/step_definitions/QtTestCalculatorQtSteps) + target_link_libraries(QtTestCalculatorQtSteps PRIVATE libcalcqt Qt::Test cucumber-cpp) if(TARGET Boost::unit_test_framework) add_executable(BoostCalculatorQtSteps features/step_definitions/BoostCalculatorQtSteps.cpp) diff --git a/include/cucumber-cpp/internal/hook/HookRegistrar.hpp b/include/cucumber-cpp/internal/hook/HookRegistrar.hpp index 61d6a605..f46520d3 100644 --- a/include/cucumber-cpp/internal/hook/HookRegistrar.hpp +++ b/include/cucumber-cpp/internal/hook/HookRegistrar.hpp @@ -22,6 +22,8 @@ class CUCUMBER_CPP_EXPORT CallableStep { class CUCUMBER_CPP_EXPORT Hook { public: + virtual ~Hook() {} + void setTags(const std::string &csvTagNotation); virtual void invokeHook(Scenario *scenario, CallableStep *step); virtual void skipHook(); diff --git a/include/cucumber-cpp/internal/step/StepManager.hpp b/include/cucumber-cpp/internal/step/StepManager.hpp index 457ee899..e6e91f50 100644 --- a/include/cucumber-cpp/internal/step/StepManager.hpp +++ b/include/cucumber-cpp/internal/step/StepManager.hpp @@ -102,6 +102,9 @@ class CUCUMBER_CPP_EXPORT InvokeResult { class CUCUMBER_CPP_EXPORT StepInfo : public boost::enable_shared_from_this { public: StepInfo(const std::string &stepMatcher, const std::string source); + + virtual ~StepInfo() {} + SingleStepMatch matches(const std::string &stepDescription) const; virtual InvokeResult invokeStep(const InvokeArgs * pArgs) const = 0; @@ -115,6 +118,8 @@ class CUCUMBER_CPP_EXPORT StepInfo : public boost::enable_shared_from_this - $ + $ $/include> ) # Declaring json_spirit.header to be a direct dependency with target_link_libraries breaks installation diff --git a/src/Regex.cpp b/src/Regex.cpp index c67a4648..3ff47970 100644 --- a/src/Regex.cpp +++ b/src/Regex.cpp @@ -37,6 +37,8 @@ FindRegexMatch::FindRegexMatch(const boost::regex ®exImpl, const std::string if (i->matched) { RegexSubmatch s = {*i, i->first - expression.begin()}; submatches.push_back(s); + } else { + submatches.push_back(RegexSubmatch()); } } } diff --git a/tests/unit/RegexTest.cpp b/tests/unit/RegexTest.cpp index 8fa97d61..a618ba16 100644 --- a/tests/unit/RegexTest.cpp +++ b/tests/unit/RegexTest.cpp @@ -46,6 +46,22 @@ TEST(RegexTest, matchesRegexWithSubmatches) { EXPECT_EQ("69", match->getSubmatches()[1].value); } +TEST(RegexTest, matchesRegexWithOptionalSubmatches) { + Regex sum("^(\\d+)\\+(\\d+)(?:\\+(\\d+))?=(\\d+)$"); + + shared_ptr match(sum.find("1+2+3=6")); + EXPECT_TRUE(match->matches()); + ASSERT_EQ(4, match->getSubmatches().size()); + + match = shared_ptr(sum.find("42+27=69")); + EXPECT_TRUE(match->matches()); + ASSERT_EQ(4, match->getSubmatches().size()); + EXPECT_EQ("42", match->getSubmatches()[0].value); + EXPECT_EQ("27", match->getSubmatches()[1].value); + EXPECT_EQ("", match->getSubmatches()[2].value); + EXPECT_EQ("69", match->getSubmatches()[3].value); +} + TEST(RegexTest, findAllDoesNotMatchIfNoTokens) { Regex sum("([^,]+)(?:,|$)"); shared_ptr match(sum.findAll("")); diff --git a/travis.sh b/travis.sh index 0a3ed509..ebfdf0bc 100755 --- a/travis.sh +++ b/travis.sh @@ -70,7 +70,9 @@ cmake --build build cmake --build build --target test cmake --build build --target features -startXvfb # Start virtual X display server +# +# Execute Calc examples +# for TEST in \ build/examples/Calc/GTestCalculatorSteps \ @@ -78,20 +80,24 @@ for TEST in \ build/examples/Calc/BoostCalculatorSteps \ build/examples/Calc/FuncArgsCalculatorSteps \ ; do - if [ -f "${TEST}" ]; then - "${TEST}" > /dev/null & - sleep 1 - cucumber examples/Calc - wait % - fi + "${TEST}" > /dev/null & + sleep 1 + cucumber examples/Calc + wait % done +# +# Execute QtCalc examples +# + +startXvfb # Start virtual X display server + for TEST in \ build/examples/CalcQt/GTestCalculatorQtSteps \ build/examples/CalcQt/QtTestCalculatorQtSteps \ build/examples/CalcQt/BoostCalculatorQtSteps \ ; do - if [ -f "${TEST}" -a -n "${DISPLAY:-}" ]; then + if [ -n "${DISPLAY:-}" ]; then "${TEST}" 2> /dev/null & sleep 1 cucumber examples/CalcQt @@ -99,16 +105,18 @@ for TEST in \ fi done -# Test unix sockets +killXvfb + +# +# Execute feature showcase on Unix socket +# + SOCK=cucumber.wire.sock TEST=build/examples/FeatureShowcase/FeatureShowcaseSteps -if [ -f "${TEST}" ]; then - echo "unix: ${SOCK}" > examples/FeatureShowcase/features/step_definitions/cucumber.wire - "${TEST}" --unix "${SOCK}" > /dev/null & - cucumber examples/FeatureShowcase - wait % -fi +echo "unix: ${SOCK}" > examples/FeatureShowcase/features/step_definitions/cucumber.wire +"${TEST}" --unix "${SOCK}" > /dev/null & +cucumber examples/FeatureShowcase +wait % -killXvfb cmake --build build --target install