From 40df3fb040a909ba2c108cc1c64df90b01dd9990 Mon Sep 17 00:00:00 2001 From: NeaguGeorgiana23 Date: Fri, 13 Mar 2026 11:36:17 +0000 Subject: [PATCH 1/8] change test framework from cucumber-cpp to cwt-cucumber Signed-off-by: NeaguGeorgiana23 --- BUILD | 4 +- Gemfile | 3 - Gemfile.lock | 56 ------- MODULE.bazel | 24 +-- test/e2e/BUILD | 10 +- test/e2e/context_storing_provider.cpp | 2 - test/e2e/cwt_extension.bzl | 38 +++++ test/e2e/steps/BUILD | 7 +- test/e2e/steps/minimal_steps.cpp | 226 ++++++++++++-------------- 9 files changed, 152 insertions(+), 218 deletions(-) delete mode 100644 Gemfile delete mode 100644 Gemfile.lock create mode 100644 test/e2e/cwt_extension.bzl diff --git a/BUILD b/BUILD index 6066694..4e6278d 100644 --- a/BUILD +++ b/BUILD @@ -1,8 +1,6 @@ -load("@rules_gherkin//gherkin:defs.bzl", "gherkin_library") - package(default_visibility = ["//visibility:public"]) -gherkin_library( +filegroup( name = "openfeature_gherkin_spec_features", srcs = glob(["spec/specification/assets/gherkin/evaluation.feature"]), ) \ No newline at end of file diff --git a/Gemfile b/Gemfile deleted file mode 100644 index c0128f5..0000000 --- a/Gemfile +++ /dev/null @@ -1,3 +0,0 @@ -source 'https://rubygems.org' -gem 'cucumber', '~> 10.2.0' -gem 'cucumber-wire', '~> 8.0.0' \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index a0f4b35..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,56 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - base64 (0.3.0) - bigdecimal (4.0.1) - bigdecimal (4.0.1-java) - builder (3.3.0) - cucumber (10.2.0) - base64 (~> 0.2) - builder (~> 3.2) - cucumber-ci-environment (> 9, < 12) - cucumber-core (> 15, < 17) - cucumber-cucumber-expressions (> 17, < 20) - cucumber-html-formatter (> 21, < 23) - diff-lcs (~> 1.5) - logger (~> 1.6) - mini_mime (~> 1.1) - multi_test (~> 1.1) - sys-uname (~> 1.3) - cucumber-ci-environment (11.0.0) - cucumber-core (15.4.0) - cucumber-gherkin (> 27, < 40) - cucumber-messages (> 26, < 33) - cucumber-tag-expressions (> 5, < 9) - cucumber-cucumber-expressions (19.0.0) - bigdecimal - cucumber-gherkin (38.0.0) - cucumber-messages (>= 31, < 33) - cucumber-html-formatter (22.3.0) - cucumber-messages (> 23, < 33) - cucumber-messages (32.0.1) - cucumber-tag-expressions (8.1.0) - cucumber-wire (8.0.0) - cucumber-core (> 11, < 16) - cucumber-cucumber-expressions (> 14, < 20) - diff-lcs (1.6.2) - ffi (1.17.3-java) - ffi (1.17.3-x86_64-linux-gnu) - logger (1.7.0) - memoist3 (1.0.0) - mini_mime (1.1.5) - multi_test (1.1.0) - sys-uname (1.5.0) - ffi (~> 1.1) - memoist3 (~> 1.0.0) - -PLATFORMS - universal-java-11 - x86_64-linux - -DEPENDENCIES - cucumber (~> 10.2.0) - cucumber-wire (~> 8.0.0) - -BUNDLED WITH - 2.4.19 diff --git a/MODULE.bazel b/MODULE.bazel index 45d26b2..d871b9f 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -3,26 +3,6 @@ module(name = "openfeature_cpp_sdk") bazel_dep(name = "googletest", version = "1.17.0.bcr.2") bazel_dep(name = "abseil-cpp", version = "20250814.2") bazel_dep(name = "rules_cc", version = "0.2.17") -bazel_dep(name = "cucumber-cpp", version = "0.8.0.bcr.1") - -bazel_dep(name = "rules_gherkin", version = "0.2.0") -bazel_dep(name = "rules_ruby", version = "0.23.1") - -# Hermetic Ruby Toolchain Configuration -ruby = use_extension("@rules_ruby//ruby:extensions.bzl", "ruby") -ruby.toolchain( - name = "ruby", - version = "3.2.2", # JRuby or standard MRI version suitable for execution -) - -# Cucumber Gem provisioning via Bundler integration -ruby.bundle_fetch( - name = "cucumber", - gemfile = "//:Gemfile", - gemfile_lock = "//:Gemfile.lock", -) -use_repo(ruby, "cucumber", "ruby", "ruby_toolchains") -register_toolchains("@ruby_toolchains//:all") # Hedron's Compile Commands Extractor for Bazel # https://github.com/hedronvision/bazel-compile-commands-extractor @@ -34,3 +14,7 @@ git_override( # https://github.com/hedronvision/bazel-compile-commands-extractor/pull/219 commit = "02d15621b528efd877f5d5657c4b738523a0eb17", ) + +# Fetch cwt-cucumber directly from GitHub +cwt_ext = use_extension("//test/e2e:cwt_extension.bzl", "cwt_ext") +use_repo(cwt_ext, "cwt_cucumber") \ No newline at end of file diff --git a/test/e2e/BUILD b/test/e2e/BUILD index 9a3ef3b..d819f0f 100644 --- a/test/e2e/BUILD +++ b/test/e2e/BUILD @@ -1,5 +1,4 @@ load("@rules_cc//cc:defs.bzl", "cc_library") -load("@rules_gherkin//gherkin:defs.bzl", "gherkin_test") package( default_visibility = ["//visibility:public"], @@ -22,7 +21,6 @@ cc_library( "//openfeature:reason", "//openfeature:value", "//openfeature:resolution_details", - "@cucumber-cpp//:cucumber-cpp", "@googletest//:gtest", ], ) @@ -51,10 +49,12 @@ cc_library( ], ) -gherkin_test( +cc_test( name = "openfeature_gherkin_e2e_tests", - steps = "//test/e2e/steps:gherkin_step_definitions", + data = ["//:openfeature_gherkin_spec_features"], + args =["$(locations //:openfeature_gherkin_spec_features)"], deps = [ - "//:openfeature_gherkin_spec_features", + "//test/e2e/steps:gherkin_step_definitions", + "@cwt_cucumber//:cwt-cucumber", ], ) diff --git a/test/e2e/context_storing_provider.cpp b/test/e2e/context_storing_provider.cpp index c07e110..1ae625f 100644 --- a/test/e2e/context_storing_provider.cpp +++ b/test/e2e/context_storing_provider.cpp @@ -2,14 +2,12 @@ #include -#include #include #include "openfeature/flag_metadata.h" #include "openfeature/reason.h" #include "openfeature/value.h" -using cucumber::ScenarioScope; namespace openfeature_e2e { diff --git a/test/e2e/cwt_extension.bzl b/test/e2e/cwt_extension.bzl new file mode 100644 index 0000000..1ed3aca --- /dev/null +++ b/test/e2e/cwt_extension.bzl @@ -0,0 +1,38 @@ +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +def _cwt_ext_impl(ctx): + http_archive( + name = "cwt_cucumber", + # Use the latest stable release (e.g., v2.8) + urls =["https://github.com/ThoSe1990/cwt-cucumber/archive/refs/tags/2.8.tar.gz"], + strip_prefix = "cwt-cucumber-2.8", + # Inject a BUILD file to compile it on the fly + build_file_content = """ +load("@rules_cc//cc:defs.bzl", "cc_library") + +# Generate the version file from the template +genrule( + name = "generate_version_file", + srcs =["src/version.template"], + outs = ["src/version.hpp"], + cmd = "sed 's/@PROJECT_VERSION@/2.8/g' $< > $@", +) + +cc_library( + name = "cwt-cucumber", + srcs = glob([ + "src/**/*.cpp", + ]), + hdrs = glob([ + "src/**/*.hpp", + ]) +[ + "src/version.hpp", + ], + strip_include_prefix = "src", + copts =["-std=c++20"], + visibility = ["//visibility:public"], +) +""", + ) + +cwt_ext = module_extension(implementation = _cwt_ext_impl) \ No newline at end of file diff --git a/test/e2e/steps/BUILD b/test/e2e/steps/BUILD index b8a6204..e624154 100644 --- a/test/e2e/steps/BUILD +++ b/test/e2e/steps/BUILD @@ -1,10 +1,11 @@ -load("@rules_gherkin//gherkin:defs.bzl", "cc_gherkin_steps") +load("@rules_cc//cc:defs.bzl", "cc_library") package(default_visibility = ["//visibility:public"]) -cc_gherkin_steps( +cc_library( name = "gherkin_step_definitions", srcs = ["minimal_steps.cpp"], + copts = ["-std=c++20"], deps = [ "//openfeature:evaluation_context", "//openfeature:openfeature_api", @@ -13,7 +14,7 @@ cc_gherkin_steps( "//test/e2e:context_storing_provider", "//test/e2e:state", "//test:mock_feature_provider", - "@cucumber-cpp//:cucumber-cpp", + "@cwt_cucumber//:cwt-cucumber", "@googletest//:gtest", ], visibility = ["//test/e2e:__subpackages__"], diff --git a/test/e2e/steps/minimal_steps.cpp b/test/e2e/steps/minimal_steps.cpp index bcdf998..f73b0b5 100644 --- a/test/e2e/steps/minimal_steps.cpp +++ b/test/e2e/steps/minimal_steps.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include @@ -18,7 +18,6 @@ #include "test/e2e/state.h" #include "test/mocks/mock_feature_provider.h" -using ::cucumber::ScenarioScope; using ::testing::_; using ::testing::Return; @@ -92,34 +91,30 @@ std::shared_ptr CreateMockNotReadyProvider() { return mock; } -GIVEN("^a (.*) provider$") { - REGEX_PARAM(std::string, status_type); - ScenarioScope state; +GIVEN(provider_setup, "a {word} provider") { + std::string status_type = CUKE_ARG(1); + openfeature_e2e::State& state = cuke::context(); if (status_type == "stable" || status_type == "ready") { - state->provider = CreateStableProvider(); - openfeature::OpenFeatureAPI::GetInstance().SetProviderAndWait( - state->provider); + state.provider = CreateStableProvider(); + openfeature::OpenFeatureAPI::GetInstance().SetProviderAndWait(state.provider); } else if (status_type == "error") { - state->provider = CreateMockErrorProvider(); - openfeature::OpenFeatureAPI::GetInstance().SetProviderAndWait( - state->provider); + state.provider = CreateMockErrorProvider(); + openfeature::OpenFeatureAPI::GetInstance().SetProviderAndWait(state.provider); } else if (status_type == "not ready") { - state->provider = CreateMockNotReadyProvider(); - openfeature::OpenFeatureAPI::GetInstance().SetProvider(state->provider); + state.provider = CreateMockNotReadyProvider(); + openfeature::OpenFeatureAPI::GetInstance().SetProvider(state.provider); } - state->client = openfeature::OpenFeatureAPI::GetInstance().GetClient(); + state.client = openfeature::OpenFeatureAPI::GetInstance().GetClient(); } -THEN("^the provider status should be \"([^\"]*)\"$") { - REGEX_PARAM(std::string, expected_status_str); - ScenarioScope state; +THEN(check_provider_status, "the provider status should be {string}") { + std::string expected_status_str = CUKE_ARG(1); + openfeature_e2e::State& state = cuke::context(); - openfeature::ProviderStatus actual_status = - state->client->GetProviderStatus(); - openfeature::ProviderStatus expected_status = - openfeature::ProviderStatus::kReady; + openfeature::ProviderStatus actual_status = state.client->GetProviderStatus(); + openfeature::ProviderStatus expected_status = openfeature::ProviderStatus::kReady; if (expected_status_str == "READY") { expected_status = openfeature::ProviderStatus::kReady; @@ -136,100 +131,86 @@ THEN("^the provider status should be \"([^\"]*)\"$") { EXPECT_EQ(actual_status, expected_status); } -WHEN( - "^a boolean flag with key \"([^\"]*)\" is evaluated with default value " - "\"([^\"]*)\"$") { - REGEX_PARAM(std::string, key); - REGEX_PARAM(std::string, default_val_str); - ScenarioScope state; +WHEN(eval_boolean_flag, "a boolean flag with key {string} is evaluated with default value {string}") { + std::string key = CUKE_ARG(1); + std::string default_val_str = CUKE_ARG(2); + openfeature_e2e::State& state = cuke::context(); bool default_val = (default_val_str == "true"); - state->last_evaluation_value = - openfeature::Value(state->client->GetBooleanValue(key, default_val)); + state.last_evaluation_value = + openfeature::Value(state.client->GetBooleanValue(key, default_val)); } -THEN("^the resolved boolean value should be \"([^\"]*)\"$") { - REGEX_PARAM(std::string, expected_str); - ScenarioScope state; +THEN(check_resolved_boolean, "the resolved boolean value should be {string}") { + std::string expected_str = CUKE_ARG(1); + openfeature_e2e::State& state = cuke::context(); + bool expected = (expected_str == "true"); - EXPECT_EQ(state->last_evaluation_value.AsBool().value(), expected); + EXPECT_EQ(state.last_evaluation_value.AsBool().value(), expected); } -WHEN( - "^a string flag with key \"([^\"]*)\" is evaluated with default value " - "\"([^\"]*)\"$") { - REGEX_PARAM(std::string, key); - REGEX_PARAM(std::string, default_val); - ScenarioScope state; +WHEN(eval_string_flag, "a string flag with key {string} is evaluated with default value {string}") { + std::string key = CUKE_ARG(1); + std::string default_val = CUKE_ARG(2); + openfeature_e2e::State& state = cuke::context(); - state->last_evaluation_value = - openfeature::Value(state->client->GetStringValue(key, default_val)); + state.last_evaluation_value = + openfeature::Value(state.client->GetStringValue(key, default_val)); } -THEN("^the resolved string value should be \"([^\"]*)\"$") { - REGEX_PARAM(std::string, expected); - ScenarioScope state; - EXPECT_EQ(state->last_evaluation_value.AsString().value(), expected); +THEN(check_resolved_string, "the resolved string value should be {string}") { + std::string expected = CUKE_ARG(1); + openfeature_e2e::State& state = cuke::context(); + EXPECT_EQ(state.last_evaluation_value.AsString().value(), expected); } -WHEN( - "^an integer flag with key \"([^\"]*)\" is evaluated with default value " - "(\\d+)$") { - REGEX_PARAM(std::string, key); - REGEX_PARAM(int64_t, default_val); - ScenarioScope state; +WHEN(eval_integer_flag, "an integer flag with key {string} is evaluated with default value {int}") { + std::string key = CUKE_ARG(1); + int64_t default_val = CUKE_ARG(2); + openfeature_e2e::State& state = cuke::context(); - state->last_evaluation_value = - openfeature::Value(state->client->GetIntegerValue(key, default_val)); + state.last_evaluation_value = + openfeature::Value(state.client->GetIntegerValue(key, default_val)); } -THEN("^the resolved integer value should be (\\d+)$") { - REGEX_PARAM(int64_t, expected); - ScenarioScope state; - EXPECT_EQ(state->last_evaluation_value.AsInt().value(), expected); +THEN(check_resolved_integer, "the resolved integer value should be {int}") { + int64_t expected = CUKE_ARG(1); + openfeature_e2e::State& state = cuke::context(); + EXPECT_EQ(state.last_evaluation_value.AsInt().value(), expected); } -WHEN( - "^a float flag with key \"([^\"]*)\" is evaluated with default value " - "([\\d\\.]+)$") { - REGEX_PARAM(std::string, key); - REGEX_PARAM(double, default_val); - ScenarioScope state; +WHEN(eval_float_flag, "a float flag with key {string} is evaluated with default value {double}") { + std::string key = CUKE_ARG(1); + double default_val = CUKE_ARG(2); + openfeature_e2e::State& state = cuke::context(); - state->last_evaluation_value = - openfeature::Value(state->client->GetDoubleValue(key, default_val)); + state.last_evaluation_value = + openfeature::Value(state.client->GetDoubleValue(key, default_val)); } -THEN("^the resolved float value should be ([\\d\\.]+)$") { - REGEX_PARAM(double, expected); - ScenarioScope state; - EXPECT_DOUBLE_EQ(state->last_evaluation_value.AsDouble().value(), expected); +THEN(check_resolved_float, "the resolved float value should be {double}") { + double expected = CUKE_ARG(1); + openfeature_e2e::State& state = cuke::context(); + EXPECT_DOUBLE_EQ(state.last_evaluation_value.AsDouble().value(), expected); } -WHEN( - "^an object flag with key \"([^\"]*)\" is evaluated with a null default " - "value$") { - REGEX_PARAM(std::string, key); - ScenarioScope state; +WHEN(eval_object_flag_null, "an object flag with key {string} is evaluated with a null default value") { + std::string key = CUKE_ARG(1); + openfeature_e2e::State& state = cuke::context(); - state->last_evaluation_value = - state->client->GetObjectValue(key, openfeature::Value()); + state.last_evaluation_value = state.client->GetObjectValue(key, openfeature::Value()); } -THEN( - "^the resolved object value should be contain fields \"([^\"]*)\", " - "\"([^\"]*)\", and \"([^\"]*)\", with values \"([^\"]*)\", \"([^\"]*)\" " - "and (\\d+), respectively$") { - REGEX_PARAM(std::string, f1); - REGEX_PARAM(std::string, f2); - REGEX_PARAM(std::string, f3); - REGEX_PARAM(std::string, v1_str); - REGEX_PARAM(std::string, v2); - REGEX_PARAM(int64_t, v3); - ScenarioScope state; - - const std::map* structure = - state->last_evaluation_value.AsStructure(); +THEN(check_resolved_object, "the resolved object value should be contain fields {string}, {string}, and {string}, with values {string}, {string} and {int}, respectively") { + std::string f1 = CUKE_ARG(1); + std::string f2 = CUKE_ARG(2); + std::string f3 = CUKE_ARG(3); + std::string v1_str = CUKE_ARG(4); + std::string v2 = CUKE_ARG(5); + int64_t v3 = CUKE_ARG(6); + openfeature_e2e::State& state = cuke::context(); + + const std::map* structure = state.last_evaluation_value.AsStructure(); ASSERT_NE(structure, nullptr); EXPECT_EQ(structure->at(f1).AsBool().value(), (v1_str == "true")); @@ -237,19 +218,16 @@ THEN( EXPECT_EQ(structure->at(f3).AsInt().value(), v3); } -WHEN( - "^context contains keys \"([^\"]*)\", \"([^\"]*)\", \"([^\"]*)\", " - "\"([^\"]*)\" with values \"([^\"]*)\", \"([^\"]*)\", (\\d+), " - "\"([^\"]*)\"$") { - REGEX_PARAM(std::string, k1); - REGEX_PARAM(std::string, k2); - REGEX_PARAM(std::string, k3); - REGEX_PARAM(std::string, k4); - REGEX_PARAM(std::string, v1); - REGEX_PARAM(std::string, v2); - REGEX_PARAM(int64_t, v3); - REGEX_PARAM(std::string, v4); - ScenarioScope state; +WHEN(setup_context, "context contains keys {string}, {string}, {string}, {string} with values {string}, {string}, {int}, {string}") { + std::string k1 = CUKE_ARG(1); + std::string k2 = CUKE_ARG(2); + std::string k3 = CUKE_ARG(3); + std::string k4 = CUKE_ARG(4); + std::string v1 = CUKE_ARG(5); + std::string v2 = CUKE_ARG(6); + int64_t v3 = CUKE_ARG(7); + std::string v4 = CUKE_ARG(8); + openfeature_e2e::State& state = cuke::context(); openfeature::EvaluationContext ctx = openfeature::EvaluationContext::Builder() .WithAttribute(k1, v1) @@ -258,42 +236,38 @@ WHEN( .WithAttribute(k4, v4) .build(); - state->context = std::make_unique(ctx); + state.context = std::make_unique(ctx); } -WHEN( - "^a flag with key \"([^\"]*)\" is evaluated with default value " - "\"([^\"]*)\"$") { - REGEX_PARAM(std::string, key); - REGEX_PARAM(std::string, default_val); - ScenarioScope state; - - // Evaluate using the context built in the previous step. - if (state->context) { - state->last_evaluation_value = openfeature::Value( - state->client->GetStringValue(key, default_val, *state->context)); +WHEN(eval_flag_with_context, "a flag with key {string} is evaluated with default value {string}") { + std::string key = CUKE_ARG(1); + std::string default_val = CUKE_ARG(2); + openfeature_e2e::State& state = cuke::context(); + + if (state.context) { + state.last_evaluation_value = openfeature::Value( + state.client->GetStringValue(key, default_val, *state.context)); } else { - state->last_evaluation_value = - openfeature::Value(state->client->GetStringValue(key, default_val)); + state.last_evaluation_value = + openfeature::Value(state.client->GetStringValue(key, default_val)); } } -THEN("^the resolved string response should be \"([^\"]*)\"$") { - REGEX_PARAM(std::string, expected); - ScenarioScope state; +THEN(check_resolved_string_response, "the resolved string response should be {string}") { + std::string expected = CUKE_ARG(1); + openfeature_e2e::State& state = cuke::context(); - EXPECT_EQ(state->last_evaluation_value.AsString().value(), expected); + EXPECT_EQ(state.last_evaluation_value.AsString().value(), expected); } -THEN("^the resolved flag value is \"([^\"]*)\" when the context is empty$") { - REGEX_PARAM(std::string, expected); - ScenarioScope state; +THEN(check_resolved_flag_empty_ctx, "the resolved flag value is {string} when the context is empty") { + std::string expected = CUKE_ARG(1); + openfeature_e2e::State& state = cuke::context(); - // Evaluate context-aware flag with an empty context. openfeature::EvaluationContext empty_ctx = openfeature::EvaluationContext::Builder().build(); std::string actual = - state->client->GetStringValue("context-aware", "EXTERNAL", empty_ctx); + state.client->GetStringValue("context-aware", "EXTERNAL", empty_ctx); EXPECT_EQ(actual, expected); } From 1ea3f5ca6cad5a4e555e2a5b13130492a88acd4c Mon Sep 17 00:00:00 2001 From: NeaguGeorgiana23 Date: Fri, 13 Mar 2026 11:47:05 +0000 Subject: [PATCH 2/8] format files Signed-off-by: NeaguGeorgiana23 --- test/e2e/context_storing_provider.cpp | 1 - test/e2e/cwt_extension.bzl | 10 ++--- test/e2e/steps/minimal_steps.cpp | 54 +++++++++++++++++++-------- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/test/e2e/context_storing_provider.cpp b/test/e2e/context_storing_provider.cpp index 1ae625f..f9e7496 100644 --- a/test/e2e/context_storing_provider.cpp +++ b/test/e2e/context_storing_provider.cpp @@ -8,7 +8,6 @@ #include "openfeature/reason.h" #include "openfeature/value.h" - namespace openfeature_e2e { openfeature::Metadata ContextStoringProvider::GetMetadata() const { diff --git a/test/e2e/cwt_extension.bzl b/test/e2e/cwt_extension.bzl index 1ed3aca..1206d40 100644 --- a/test/e2e/cwt_extension.bzl +++ b/test/e2e/cwt_extension.bzl @@ -3,14 +3,14 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") def _cwt_ext_impl(ctx): http_archive( name = "cwt_cucumber", - # Use the latest stable release (e.g., v2.8) +#Use the latest stable release(e.g., v2.8) urls =["https://github.com/ThoSe1990/cwt-cucumber/archive/refs/tags/2.8.tar.gz"], strip_prefix = "cwt-cucumber-2.8", - # Inject a BUILD file to compile it on the fly +#Inject a BUILD file to compile it on the fly build_file_content = """ load("@rules_cc//cc:defs.bzl", "cc_library") -# Generate the version file from the template +#Generate the version file from the template genrule( name = "generate_version_file", srcs =["src/version.template"], @@ -20,9 +20,7 @@ genrule( cc_library( name = "cwt-cucumber", - srcs = glob([ - "src/**/*.cpp", - ]), + srcs = glob(["src/**/*.cpp"]), hdrs = glob([ "src/**/*.hpp", ]) +[ diff --git a/test/e2e/steps/minimal_steps.cpp b/test/e2e/steps/minimal_steps.cpp index f73b0b5..e49248e 100644 --- a/test/e2e/steps/minimal_steps.cpp +++ b/test/e2e/steps/minimal_steps.cpp @@ -97,10 +97,12 @@ GIVEN(provider_setup, "a {word} provider") { if (status_type == "stable" || status_type == "ready") { state.provider = CreateStableProvider(); - openfeature::OpenFeatureAPI::GetInstance().SetProviderAndWait(state.provider); + openfeature::OpenFeatureAPI::GetInstance().SetProviderAndWait( + state.provider); } else if (status_type == "error") { state.provider = CreateMockErrorProvider(); - openfeature::OpenFeatureAPI::GetInstance().SetProviderAndWait(state.provider); + openfeature::OpenFeatureAPI::GetInstance().SetProviderAndWait( + state.provider); } else if (status_type == "not ready") { state.provider = CreateMockNotReadyProvider(); openfeature::OpenFeatureAPI::GetInstance().SetProvider(state.provider); @@ -114,7 +116,8 @@ THEN(check_provider_status, "the provider status should be {string}") { openfeature_e2e::State& state = cuke::context(); openfeature::ProviderStatus actual_status = state.client->GetProviderStatus(); - openfeature::ProviderStatus expected_status = openfeature::ProviderStatus::kReady; + openfeature::ProviderStatus expected_status = + openfeature::ProviderStatus::kReady; if (expected_status_str == "READY") { expected_status = openfeature::ProviderStatus::kReady; @@ -131,7 +134,9 @@ THEN(check_provider_status, "the provider status should be {string}") { EXPECT_EQ(actual_status, expected_status); } -WHEN(eval_boolean_flag, "a boolean flag with key {string} is evaluated with default value {string}") { +WHEN(eval_boolean_flag, + "a boolean flag with key {string} is evaluated with default value " + "{string}") { std::string key = CUKE_ARG(1); std::string default_val_str = CUKE_ARG(2); openfeature_e2e::State& state = cuke::context(); @@ -144,12 +149,14 @@ WHEN(eval_boolean_flag, "a boolean flag with key {string} is evaluated with defa THEN(check_resolved_boolean, "the resolved boolean value should be {string}") { std::string expected_str = CUKE_ARG(1); openfeature_e2e::State& state = cuke::context(); - + bool expected = (expected_str == "true"); EXPECT_EQ(state.last_evaluation_value.AsBool().value(), expected); } -WHEN(eval_string_flag, "a string flag with key {string} is evaluated with default value {string}") { +WHEN(eval_string_flag, + "a string flag with key {string} is evaluated with default value " + "{string}") { std::string key = CUKE_ARG(1); std::string default_val = CUKE_ARG(2); openfeature_e2e::State& state = cuke::context(); @@ -164,7 +171,9 @@ THEN(check_resolved_string, "the resolved string value should be {string}") { EXPECT_EQ(state.last_evaluation_value.AsString().value(), expected); } -WHEN(eval_integer_flag, "an integer flag with key {string} is evaluated with default value {int}") { +WHEN( + eval_integer_flag, + "an integer flag with key {string} is evaluated with default value {int}") { std::string key = CUKE_ARG(1); int64_t default_val = CUKE_ARG(2); openfeature_e2e::State& state = cuke::context(); @@ -179,7 +188,9 @@ THEN(check_resolved_integer, "the resolved integer value should be {int}") { EXPECT_EQ(state.last_evaluation_value.AsInt().value(), expected); } -WHEN(eval_float_flag, "a float flag with key {string} is evaluated with default value {double}") { +WHEN( + eval_float_flag, + "a float flag with key {string} is evaluated with default value {double}") { std::string key = CUKE_ARG(1); double default_val = CUKE_ARG(2); openfeature_e2e::State& state = cuke::context(); @@ -194,14 +205,19 @@ THEN(check_resolved_float, "the resolved float value should be {double}") { EXPECT_DOUBLE_EQ(state.last_evaluation_value.AsDouble().value(), expected); } -WHEN(eval_object_flag_null, "an object flag with key {string} is evaluated with a null default value") { +WHEN( + eval_object_flag_null, + "an object flag with key {string} is evaluated with a null default value") { std::string key = CUKE_ARG(1); openfeature_e2e::State& state = cuke::context(); - state.last_evaluation_value = state.client->GetObjectValue(key, openfeature::Value()); + state.last_evaluation_value = + state.client->GetObjectValue(key, openfeature::Value()); } -THEN(check_resolved_object, "the resolved object value should be contain fields {string}, {string}, and {string}, with values {string}, {string} and {int}, respectively") { +THEN(check_resolved_object, + "the resolved object value should be contain fields {string}, {string}, " + "and {string}, with values {string}, {string} and {int}, respectively") { std::string f1 = CUKE_ARG(1); std::string f2 = CUKE_ARG(2); std::string f3 = CUKE_ARG(3); @@ -210,7 +226,8 @@ THEN(check_resolved_object, "the resolved object value should be contain fields int64_t v3 = CUKE_ARG(6); openfeature_e2e::State& state = cuke::context(); - const std::map* structure = state.last_evaluation_value.AsStructure(); + const std::map* structure = + state.last_evaluation_value.AsStructure(); ASSERT_NE(structure, nullptr); EXPECT_EQ(structure->at(f1).AsBool().value(), (v1_str == "true")); @@ -218,7 +235,9 @@ THEN(check_resolved_object, "the resolved object value should be contain fields EXPECT_EQ(structure->at(f3).AsInt().value(), v3); } -WHEN(setup_context, "context contains keys {string}, {string}, {string}, {string} with values {string}, {string}, {int}, {string}") { +WHEN(setup_context, + "context contains keys {string}, {string}, {string}, {string} with values " + "{string}, {string}, {int}, {string}") { std::string k1 = CUKE_ARG(1); std::string k2 = CUKE_ARG(2); std::string k3 = CUKE_ARG(3); @@ -239,7 +258,8 @@ WHEN(setup_context, "context contains keys {string}, {string}, {string}, {string state.context = std::make_unique(ctx); } -WHEN(eval_flag_with_context, "a flag with key {string} is evaluated with default value {string}") { +WHEN(eval_flag_with_context, + "a flag with key {string} is evaluated with default value {string}") { std::string key = CUKE_ARG(1); std::string default_val = CUKE_ARG(2); openfeature_e2e::State& state = cuke::context(); @@ -253,14 +273,16 @@ WHEN(eval_flag_with_context, "a flag with key {string} is evaluated with default } } -THEN(check_resolved_string_response, "the resolved string response should be {string}") { +THEN(check_resolved_string_response, + "the resolved string response should be {string}") { std::string expected = CUKE_ARG(1); openfeature_e2e::State& state = cuke::context(); EXPECT_EQ(state.last_evaluation_value.AsString().value(), expected); } -THEN(check_resolved_flag_empty_ctx, "the resolved flag value is {string} when the context is empty") { +THEN(check_resolved_flag_empty_ctx, + "the resolved flag value is {string} when the context is empty") { std::string expected = CUKE_ARG(1); openfeature_e2e::State& state = cuke::context(); From 818f25894b5b5d26787e6ac7b43da1ea29ca85cb Mon Sep 17 00:00:00 2001 From: NeaguGeorgiana23 Date: Fri, 13 Mar 2026 13:34:20 +0000 Subject: [PATCH 3/8] apply gemini suggestions Signed-off-by: NeaguGeorgiana23 --- test/e2e/cwt_extension.bzl | 10 ++++--- test/e2e/steps/minimal_steps.cpp | 45 ++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/test/e2e/cwt_extension.bzl b/test/e2e/cwt_extension.bzl index 1206d40..bde5e6c 100644 --- a/test/e2e/cwt_extension.bzl +++ b/test/e2e/cwt_extension.bzl @@ -1,11 +1,13 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") def _cwt_ext_impl(ctx): + version = "2.8" http_archive( name = "cwt_cucumber", + sha256 = "30576a39a9ce2c4a915ed8f0e46f3f0ef149febf995989dfb02a05866ff38f57", #Use the latest stable release(e.g., v2.8) - urls =["https://github.com/ThoSe1990/cwt-cucumber/archive/refs/tags/2.8.tar.gz"], - strip_prefix = "cwt-cucumber-2.8", + urls = ["https://github.com/ThoSe1990/cwt-cucumber/archive/refs/tags/" + version + ".tar.gz"], + strip_prefix = "cwt-cucumber-" + version, #Inject a BUILD file to compile it on the fly build_file_content = """ load("@rules_cc//cc:defs.bzl", "cc_library") @@ -15,7 +17,7 @@ genrule( name = "generate_version_file", srcs =["src/version.template"], outs = ["src/version.hpp"], - cmd = "sed 's/@PROJECT_VERSION@/2.8/g' $< > $@", + cmd = "sed 's/@PROJECT_VERSION@/{version}/g' $< > $@", ) cc_library( @@ -30,7 +32,7 @@ cc_library( copts =["-std=c++20"], visibility = ["//visibility:public"], ) -""", +""".replace("{version}", version), ) cwt_ext = module_extension(implementation = _cwt_ext_impl) \ No newline at end of file diff --git a/test/e2e/steps/minimal_steps.cpp b/test/e2e/steps/minimal_steps.cpp index e49248e..cb684b2 100644 --- a/test/e2e/steps/minimal_steps.cpp +++ b/test/e2e/steps/minimal_steps.cpp @@ -21,6 +21,11 @@ using ::testing::_; using ::testing::Return; +constexpr int64_t kDefaultIntegerFlagValue = 10; +constexpr double kDefaultFloatFlagValue = 0.5; +constexpr int64_t kImagesPerPageValue = 100; +constexpr auto kProviderInitDelay = std::chrono::milliseconds(200); + // Helper to create simple static flags for the InMemoryProvider. template openfeature::Flag CreateStaticFlag(T value) { @@ -37,14 +42,14 @@ std::shared_ptr CreateStableProvider() { // Set up the static flags expected by the basic evaluation tests. flags["boolean-flag"] = CreateStaticFlag(true); flags["string-flag"] = CreateStaticFlag("hi"); - flags["integer-flag"] = CreateStaticFlag(10); - flags["float-flag"] = CreateStaticFlag(0.5); + flags["integer-flag"] = CreateStaticFlag(kDefaultIntegerFlagValue); + flags["float-flag"] = CreateStaticFlag(kDefaultFloatFlagValue); // Object flag setup. std::map obj_map; obj_map["showImages"] = openfeature::Value(true); obj_map["title"] = openfeature::Value("Check out these pics!"); - obj_map["imagesPerPage"] = openfeature::Value(100); + obj_map["imagesPerPage"] = openfeature::Value(kImagesPerPageValue); flags["object-flag"] = CreateStaticFlag(openfeature::Value(obj_map)); @@ -85,7 +90,7 @@ std::shared_ptr CreateMockNotReadyProvider() { EXPECT_CALL(*mock, Shutdown()).WillRepeatedly(Return(absl::OkStatus())); EXPECT_CALL(*mock, Init(_)) .WillOnce(testing::Invoke([](const openfeature::EvaluationContext&) { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); + std::this_thread::sleep_for(kProviderInitDelay); return absl::OkStatus(); })); return mock; @@ -93,7 +98,7 @@ std::shared_ptr CreateMockNotReadyProvider() { GIVEN(provider_setup, "a {word} provider") { std::string status_type = CUKE_ARG(1); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); if (status_type == "stable" || status_type == "ready") { state.provider = CreateStableProvider(); @@ -113,7 +118,7 @@ GIVEN(provider_setup, "a {word} provider") { THEN(check_provider_status, "the provider status should be {string}") { std::string expected_status_str = CUKE_ARG(1); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); openfeature::ProviderStatus actual_status = state.client->GetProviderStatus(); openfeature::ProviderStatus expected_status = @@ -139,7 +144,7 @@ WHEN(eval_boolean_flag, "{string}") { std::string key = CUKE_ARG(1); std::string default_val_str = CUKE_ARG(2); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); bool default_val = (default_val_str == "true"); state.last_evaluation_value = @@ -148,7 +153,7 @@ WHEN(eval_boolean_flag, THEN(check_resolved_boolean, "the resolved boolean value should be {string}") { std::string expected_str = CUKE_ARG(1); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); bool expected = (expected_str == "true"); EXPECT_EQ(state.last_evaluation_value.AsBool().value(), expected); @@ -159,7 +164,7 @@ WHEN(eval_string_flag, "{string}") { std::string key = CUKE_ARG(1); std::string default_val = CUKE_ARG(2); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); state.last_evaluation_value = openfeature::Value(state.client->GetStringValue(key, default_val)); @@ -167,7 +172,7 @@ WHEN(eval_string_flag, THEN(check_resolved_string, "the resolved string value should be {string}") { std::string expected = CUKE_ARG(1); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); EXPECT_EQ(state.last_evaluation_value.AsString().value(), expected); } @@ -176,7 +181,7 @@ WHEN( "an integer flag with key {string} is evaluated with default value {int}") { std::string key = CUKE_ARG(1); int64_t default_val = CUKE_ARG(2); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); state.last_evaluation_value = openfeature::Value(state.client->GetIntegerValue(key, default_val)); @@ -184,7 +189,7 @@ WHEN( THEN(check_resolved_integer, "the resolved integer value should be {int}") { int64_t expected = CUKE_ARG(1); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); EXPECT_EQ(state.last_evaluation_value.AsInt().value(), expected); } @@ -193,7 +198,7 @@ WHEN( "a float flag with key {string} is evaluated with default value {double}") { std::string key = CUKE_ARG(1); double default_val = CUKE_ARG(2); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); state.last_evaluation_value = openfeature::Value(state.client->GetDoubleValue(key, default_val)); @@ -201,7 +206,7 @@ WHEN( THEN(check_resolved_float, "the resolved float value should be {double}") { double expected = CUKE_ARG(1); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); EXPECT_DOUBLE_EQ(state.last_evaluation_value.AsDouble().value(), expected); } @@ -209,7 +214,7 @@ WHEN( eval_object_flag_null, "an object flag with key {string} is evaluated with a null default value") { std::string key = CUKE_ARG(1); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); state.last_evaluation_value = state.client->GetObjectValue(key, openfeature::Value()); @@ -224,7 +229,7 @@ THEN(check_resolved_object, std::string v1_str = CUKE_ARG(4); std::string v2 = CUKE_ARG(5); int64_t v3 = CUKE_ARG(6); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); const std::map* structure = state.last_evaluation_value.AsStructure(); @@ -246,7 +251,7 @@ WHEN(setup_context, std::string v2 = CUKE_ARG(6); int64_t v3 = CUKE_ARG(7); std::string v4 = CUKE_ARG(8); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); openfeature::EvaluationContext ctx = openfeature::EvaluationContext::Builder() .WithAttribute(k1, v1) @@ -262,7 +267,7 @@ WHEN(eval_flag_with_context, "a flag with key {string} is evaluated with default value {string}") { std::string key = CUKE_ARG(1); std::string default_val = CUKE_ARG(2); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); if (state.context) { state.last_evaluation_value = openfeature::Value( @@ -276,7 +281,7 @@ WHEN(eval_flag_with_context, THEN(check_resolved_string_response, "the resolved string response should be {string}") { std::string expected = CUKE_ARG(1); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); EXPECT_EQ(state.last_evaluation_value.AsString().value(), expected); } @@ -284,7 +289,7 @@ THEN(check_resolved_string_response, THEN(check_resolved_flag_empty_ctx, "the resolved flag value is {string} when the context is empty") { std::string expected = CUKE_ARG(1); - openfeature_e2e::State& state = cuke::context(); + auto& state = cuke::context(); openfeature::EvaluationContext empty_ctx = openfeature::EvaluationContext::Builder().build(); From f664b237def335e64c54864d24a6f1576d138e3e Mon Sep 17 00:00:00 2001 From: NeaguGeorgiana23 Date: Fri, 13 Mar 2026 13:50:55 +0000 Subject: [PATCH 4/8] Don't throw FAILED message when we have UNDEFINED scenarios. Signed-off-by: NeaguGeorgiana23 --- test/e2e/cwt_extension.bzl | 5 ++++- test/e2e/steps/minimal_steps.cpp | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/test/e2e/cwt_extension.bzl b/test/e2e/cwt_extension.bzl index bde5e6c..84af9e6 100644 --- a/test/e2e/cwt_extension.bzl +++ b/test/e2e/cwt_extension.bzl @@ -22,7 +22,10 @@ genrule( cc_library( name = "cwt-cucumber", - srcs = glob(["src/**/*.cpp"]), + srcs = glob( + ["src/**/*.cpp"], + exclude =["src/main.cpp"] + ), hdrs = glob([ "src/**/*.hpp", ]) +[ diff --git a/test/e2e/steps/minimal_steps.cpp b/test/e2e/steps/minimal_steps.cpp index cb684b2..1e6e264 100644 --- a/test/e2e/steps/minimal_steps.cpp +++ b/test/e2e/steps/minimal_steps.cpp @@ -299,5 +299,24 @@ THEN(check_resolved_flag_empty_ctx, EXPECT_EQ(actual, expected); } +// This function helps the test not to fail if we have an "UNDEFINED" scenario. +// It should be deleted when we are able to write steps for all scenarios. +int main(int argc, char* argv[]) { + GTEST_FLAG_SET(throw_on_failure, true); + ::testing::InitGoogleMock(&argc, argv); + + cuke::cwt_cucumber cucumber(argc, const_cast(argv)); + + cucumber.run_tests(); + + cucumber.print_results(); + + if (::testing::UnitTest::GetInstance()->failed_test_count() > 0) { + return 1; + } + + return 0; +} + // TODO: Enable more Gherkin scenarios as the SDK functionality expands, e.g. // around event hooks, detailed evaluation, etc. \ No newline at end of file From 020e9817e3ec0b1b4717d2d9a66aa159b3b4e0a5 Mon Sep 17 00:00:00 2001 From: NeaguGeorgiana23 Date: Mon, 16 Mar 2026 08:30:00 +0000 Subject: [PATCH 5/8] fix ci-format-test-lint Signed-off-by: NeaguGeorgiana23 --- test/e2e/steps/minimal_steps.cpp | 42 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/test/e2e/steps/minimal_steps.cpp b/test/e2e/steps/minimal_steps.cpp index 1e6e264..6bd120b 100644 --- a/test/e2e/steps/minimal_steps.cpp +++ b/test/e2e/steps/minimal_steps.cpp @@ -223,41 +223,41 @@ WHEN( THEN(check_resolved_object, "the resolved object value should be contain fields {string}, {string}, " "and {string}, with values {string}, {string} and {int}, respectively") { - std::string f1 = CUKE_ARG(1); - std::string f2 = CUKE_ARG(2); - std::string f3 = CUKE_ARG(3); - std::string v1_str = CUKE_ARG(4); - std::string v2 = CUKE_ARG(5); - int64_t v3 = CUKE_ARG(6); + std::string boolField = CUKE_ARG(1); + std::string stringField = CUKE_ARG(2); + std::string intField = CUKE_ARG(3); + std::string boolValue = CUKE_ARG(4); + std::string stringValue = CUKE_ARG(5); + int64_t intValue = CUKE_ARG(6); auto& state = cuke::context(); const std::map* structure = state.last_evaluation_value.AsStructure(); ASSERT_NE(structure, nullptr); - EXPECT_EQ(structure->at(f1).AsBool().value(), (v1_str == "true")); - EXPECT_EQ(structure->at(f2).AsString().value(), v2); - EXPECT_EQ(structure->at(f3).AsInt().value(), v3); + EXPECT_EQ(structure->at(boolField).AsBool().value(), (boolValue == "true")); + EXPECT_EQ(structure->at(stringField).AsString().value(), stringValue); + EXPECT_EQ(structure->at(intField).AsInt().value(), intValue); } WHEN(setup_context, "context contains keys {string}, {string}, {string}, {string} with values " "{string}, {string}, {int}, {string}") { - std::string k1 = CUKE_ARG(1); - std::string k2 = CUKE_ARG(2); - std::string k3 = CUKE_ARG(3); - std::string k4 = CUKE_ARG(4); - std::string v1 = CUKE_ARG(5); - std::string v2 = CUKE_ARG(6); - int64_t v3 = CUKE_ARG(7); - std::string v4 = CUKE_ARG(8); + std::string field1 = CUKE_ARG(1); + std::string field2 = CUKE_ARG(2); + std::string field3 = CUKE_ARG(3); + std::string field4 = CUKE_ARG(4); + std::string value1 = CUKE_ARG(5); + std::string value2 = CUKE_ARG(6); + int64_t value3 = CUKE_ARG(7); + std::string value4 = CUKE_ARG(8); auto& state = cuke::context(); openfeature::EvaluationContext ctx = openfeature::EvaluationContext::Builder() - .WithAttribute(k1, v1) - .WithAttribute(k2, v2) - .WithAttribute(k3, v3) - .WithAttribute(k4, v4) + .WithAttribute(field1, value1) + .WithAttribute(field2, value2) + .WithAttribute(field3, value3) + .WithAttribute(field4, value4) .build(); state.context = std::make_unique(ctx); From 372fc9943f39aa7c7d43e34780d8f2448a032c21 Mon Sep 17 00:00:00 2001 From: NeaguGeorgiana23 Date: Mon, 16 Mar 2026 08:37:01 +0000 Subject: [PATCH 6/8] fix ci-format-test-lint Signed-off-by: NeaguGeorgiana23 --- test/e2e/steps/minimal_steps.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/e2e/steps/minimal_steps.cpp b/test/e2e/steps/minimal_steps.cpp index 6bd120b..8b4f2b8 100644 --- a/test/e2e/steps/minimal_steps.cpp +++ b/test/e2e/steps/minimal_steps.cpp @@ -223,21 +223,21 @@ WHEN( THEN(check_resolved_object, "the resolved object value should be contain fields {string}, {string}, " "and {string}, with values {string}, {string} and {int}, respectively") { - std::string boolField = CUKE_ARG(1); - std::string stringField = CUKE_ARG(2); - std::string intField = CUKE_ARG(3); - std::string boolValue = CUKE_ARG(4); - std::string stringValue = CUKE_ARG(5); - int64_t intValue = CUKE_ARG(6); + std::string bool_field = CUKE_ARG(1); + std::string string_field = CUKE_ARG(2); + std::string int_field = CUKE_ARG(3); + std::string bool_value = CUKE_ARG(4); + std::string string_value = CUKE_ARG(5); + int64_t int_value = CUKE_ARG(6); auto& state = cuke::context(); const std::map* structure = state.last_evaluation_value.AsStructure(); ASSERT_NE(structure, nullptr); - EXPECT_EQ(structure->at(boolField).AsBool().value(), (boolValue == "true")); - EXPECT_EQ(structure->at(stringField).AsString().value(), stringValue); - EXPECT_EQ(structure->at(intField).AsInt().value(), intValue); + EXPECT_EQ(structure->at(bool_field).AsBool().value(), (bool_value == "true")); + EXPECT_EQ(structure->at(string_field).AsString().value(), string_value); + EXPECT_EQ(structure->at(int_field).AsInt().value(), int_value); } WHEN(setup_context, From 1dce26e9ea3a1956e8b332ae31f17de9841c5721 Mon Sep 17 00:00:00 2001 From: NeaguGeorgiana23 Date: Tue, 24 Mar 2026 08:20:03 +0000 Subject: [PATCH 7/8] rezolve comments Signed-off-by: NeaguGeorgiana23 --- MODULE.bazel | 10 +++++++-- test/e2e/BUILD | 2 ++ test/e2e/cwt_cucumber.BUILD | 31 ++++++++++++++++++++++++++++ test/e2e/cwt_extension.bzl | 41 ------------------------------------- 4 files changed, 41 insertions(+), 43 deletions(-) create mode 100644 test/e2e/cwt_cucumber.BUILD delete mode 100644 test/e2e/cwt_extension.bzl diff --git a/MODULE.bazel b/MODULE.bazel index d871b9f..ffc50cb 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -15,6 +15,12 @@ git_override( commit = "02d15621b528efd877f5d5657c4b738523a0eb17", ) +git_repository = use_repo_rule("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") + # Fetch cwt-cucumber directly from GitHub -cwt_ext = use_extension("//test/e2e:cwt_extension.bzl", "cwt_ext") -use_repo(cwt_ext, "cwt_cucumber") \ No newline at end of file +git_repository( + name = "cwt_cucumber", + build_file = "//test/e2e:cwt_cucumber.BUILD", + remote = "https://github.com/ThoSe1990/cwt-cucumber.git", + tag = "2.8", +) \ No newline at end of file diff --git a/test/e2e/BUILD b/test/e2e/BUILD index d819f0f..b9696d0 100644 --- a/test/e2e/BUILD +++ b/test/e2e/BUILD @@ -4,6 +4,8 @@ package( default_visibility = ["//visibility:public"], ) +exports_files(["cwt-cucumber.BUILD"]) + cc_library( name = "context_storing_provider", srcs = [ diff --git a/test/e2e/cwt_cucumber.BUILD b/test/e2e/cwt_cucumber.BUILD new file mode 100644 index 0000000..87c497b --- /dev/null +++ b/test/e2e/cwt_cucumber.BUILD @@ -0,0 +1,31 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") + +# Generate the version file from the template by extracting the version from CMakeLists.txt +genrule( + name = "generate_version_file", + srcs = [ + "CMakeLists.txt", + "src/version.template", + ], + outs = ["src/version.hpp"], + cmd = """ + VERSION=$$(grep 'project(cwt-cucumber VERSION' $(location CMakeLists.txt) | sed 's/.*VERSION \\([0-9.]*\\).*/\\1/'); + sed "s/@PROJECT_VERSION@/$$VERSION/g" $(location src/version.template) > $@ + """, +) + +cc_library( + name = "cwt-cucumber", + srcs = glob( + ["src/**/*.cpp"], + exclude = ["src/main.cpp"], + ), + hdrs = glob([ + "src/**/*.hpp", + ]) + [ + "src/version.hpp", + ], + copts = ["-std=c++20"], + strip_include_prefix = "src", + visibility = ["//visibility:public"], +) diff --git a/test/e2e/cwt_extension.bzl b/test/e2e/cwt_extension.bzl deleted file mode 100644 index 84af9e6..0000000 --- a/test/e2e/cwt_extension.bzl +++ /dev/null @@ -1,41 +0,0 @@ -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -def _cwt_ext_impl(ctx): - version = "2.8" - http_archive( - name = "cwt_cucumber", - sha256 = "30576a39a9ce2c4a915ed8f0e46f3f0ef149febf995989dfb02a05866ff38f57", -#Use the latest stable release(e.g., v2.8) - urls = ["https://github.com/ThoSe1990/cwt-cucumber/archive/refs/tags/" + version + ".tar.gz"], - strip_prefix = "cwt-cucumber-" + version, -#Inject a BUILD file to compile it on the fly - build_file_content = """ -load("@rules_cc//cc:defs.bzl", "cc_library") - -#Generate the version file from the template -genrule( - name = "generate_version_file", - srcs =["src/version.template"], - outs = ["src/version.hpp"], - cmd = "sed 's/@PROJECT_VERSION@/{version}/g' $< > $@", -) - -cc_library( - name = "cwt-cucumber", - srcs = glob( - ["src/**/*.cpp"], - exclude =["src/main.cpp"] - ), - hdrs = glob([ - "src/**/*.hpp", - ]) +[ - "src/version.hpp", - ], - strip_include_prefix = "src", - copts =["-std=c++20"], - visibility = ["//visibility:public"], -) -""".replace("{version}", version), - ) - -cwt_ext = module_extension(implementation = _cwt_ext_impl) \ No newline at end of file From 087f397ba70cd5b787e1f604b6f2a497ffcba57c Mon Sep 17 00:00:00 2001 From: NeaguGeorgiana23 Date: Thu, 26 Mar 2026 08:13:06 +0000 Subject: [PATCH 8/8] remove Spec submodule. Signed-off-by: NeaguGeorgiana23 --- .gitmodules | 3 --- BUILD | 5 ----- MODULE.bazel | 27 ++++++++++++++++++++++----- spec | 1 - test/e2e/BUILD | 4 ++-- 5 files changed, 24 insertions(+), 16 deletions(-) delete mode 100644 .gitmodules delete mode 160000 spec diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 85115b5..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "spec"] - path = spec - url = https://github.com/open-feature/spec.git diff --git a/BUILD b/BUILD index 4e6278d..ffd0fb0 100644 --- a/BUILD +++ b/BUILD @@ -1,6 +1 @@ package(default_visibility = ["//visibility:public"]) - -filegroup( - name = "openfeature_gherkin_spec_features", - srcs = glob(["spec/specification/assets/gherkin/evaluation.feature"]), -) \ No newline at end of file diff --git a/MODULE.bazel b/MODULE.bazel index ffc50cb..67bbd96 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -4,23 +4,40 @@ bazel_dep(name = "googletest", version = "1.17.0.bcr.2") bazel_dep(name = "abseil-cpp", version = "20250814.2") bazel_dep(name = "rules_cc", version = "0.2.17") -# Hedron's Compile Commands Extractor for Bazel -# https://github.com/hedronvision/bazel-compile-commands-extractor +#Hedron's Compile Commands Extractor for Bazel +#https: // github.com/hedronvision/bazel-compile-commands-extractor bazel_dep(name = "hedron_compile_commands", dev_dependency = True) git_override( module_name = "hedron_compile_commands", remote = "https://github.com/hedronvision/bazel-compile-commands-extractor.git", - # Not official but well established fork with a fix to header only libraries - # https://github.com/hedronvision/bazel-compile-commands-extractor/pull/219 +#Not official but well established fork with a fix to header only libraries +#https: // github.com/hedronvision/bazel-compile-commands-extractor/pull/219 commit = "02d15621b528efd877f5d5657c4b738523a0eb17", ) git_repository = use_repo_rule("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") -# Fetch cwt-cucumber directly from GitHub +#Fetch cwt - cucumber directly from GitHub git_repository( name = "cwt_cucumber", build_file = "//test/e2e:cwt_cucumber.BUILD", remote = "https://github.com/ThoSe1990/cwt-cucumber.git", tag = "2.8", +) + +#Fetch OpenFeature spec for Gherkin scenarios +git_repository( + name = "openfeature_spec", + remote = "https://github.com/open-feature/spec.git", + branch = "main", + build_file_content = """ +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "gherkin_features", +#TODO : Once the SDK is finished, \ + the source should be changed to "specification/assets/gherkin/*.feature" + srcs = glob(["specification/assets/gherkin/evaluation.feature"]), +) +""", ) \ No newline at end of file diff --git a/spec b/spec deleted file mode 160000 index eefdf43..0000000 --- a/spec +++ /dev/null @@ -1 +0,0 @@ -Subproject commit eefdf439c5a5b69ccde036c3c6959a4a6c17e08c diff --git a/test/e2e/BUILD b/test/e2e/BUILD index b9696d0..64b4272 100644 --- a/test/e2e/BUILD +++ b/test/e2e/BUILD @@ -53,8 +53,8 @@ cc_library( cc_test( name = "openfeature_gherkin_e2e_tests", - data = ["//:openfeature_gherkin_spec_features"], - args =["$(locations //:openfeature_gherkin_spec_features)"], + data = ["@openfeature_spec//:gherkin_features"], + args =["$(locations @openfeature_spec//:gherkin_features)"], deps = [ "//test/e2e/steps:gherkin_step_definitions", "@cwt_cucumber//:cwt-cucumber",