Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions contract-tests/server-contract-tests/test-suppressions.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# SC-214431
evaluation/parameterized/bad attribute reference errors - clause with no attribute/test-flag/evaluate flag with detail
evaluation/parameterized/bad attribute reference errors - empty path component/test-flag/evaluate flag with detail
evaluation/parameterized/bad attribute reference errors - tilde followed by invalid escape character/test-flag/evaluate flag with detail
Expand Down Expand Up @@ -60,12 +61,8 @@ evaluation/parameterized/prerequisites/prerequisite cycle is detected at top lev
evaluation/parameterized/prerequisites/prerequisite cycle is detected at top level, recursion stops/prerequisite cycle is detected at top level, recursion stops/evaluate all flags
evaluation/parameterized/prerequisites/prerequisite cycle is detected at deeper level, recursion stops/prerequisite cycle is detected at deeper level, recursion stops/evaluate flag with detail
evaluation/parameterized/prerequisites/prerequisite cycle is detected at deeper level, recursion stops/prerequisite cycle is detected at deeper level, recursion stops/evaluate all flags
evaluation/parameterized/rollout or experiment - error for empty variations list in rollout/fallthrough rollout/fallthrough rollout/evaluate flag without detail
evaluation/parameterized/rollout or experiment - error for empty variations list in rollout/fallthrough rollout/fallthrough rollout/evaluate flag with detail
evaluation/parameterized/rollout or experiment - error for empty variations list in rollout/fallthrough rollout/fallthrough rollout/evaluate all flags
evaluation/parameterized/rollout or experiment - error for empty variations list in rollout/rule rollout/rule rollout/evaluate flag without detail
evaluation/parameterized/rollout or experiment - error for empty variations list in rollout/rule rollout/rule rollout/evaluate flag with detail
evaluation/parameterized/rollout or experiment - error for empty variations list in rollout/rule rollout/rule rollout/evaluate all flags
evaluation/parameterized/segment recursion/cycle is detected at top level, recursion stops/cycle is detected at top level, recursion stops/evaluate flag with detail
evaluation/parameterized/segment recursion/cycle is detected below top level, recursion stops/cycle is detected below top level, recursion stops/evaluate flag with detail
events/summary events/prerequisites
Expand Down
2 changes: 1 addition & 1 deletion libs/internal/include/launchdarkly/data_model/flag.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct Flag {
explicit Rollout(std::vector<WeightedVariation>);
};

using VariationOrRollout = std::variant<Variation, Rollout>;
using VariationOrRollout = std::variant<std::optional<Variation>, Rollout>;

struct Prerequisite {
std::string key;
Expand Down
21 changes: 12 additions & 9 deletions libs/internal/src/serialization/json_flag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,13 @@ tag_invoke(boost::json::value_to_tag<
return std::make_optional(*rollout);
}

data_model::Flag::Variation variation{};
/* If there's no rollout, this must be a variation. If there's no
* data at all, we must treat it as variation 0 (since upstream encoders may
* omit 0.) */
PARSE_FIELD_DEFAULT(variation, obj, "variation", 0);
std::optional<data_model::Flag::Variation> variation;

return std::make_optional(variation);
/* If there's no rollout, this must be a variation. If there's no variation,
* then this will be detected as a malformed flag at evaluation time. */
PARSE_CONDITIONAL_FIELD(variation, obj, "variation");

return variation;
}

namespace data_model {
Expand Down Expand Up @@ -264,9 +264,12 @@ void tag_invoke(
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, data_model::Flag::Rollout>) {
obj.emplace("rollout", boost::json::value_from(arg));
} else if constexpr (std::is_same_v<T,
data_model::Flag::Variation>) {
obj.emplace("variation", arg);
} else if constexpr (std::is_same_v<
T, std::optional<
data_model::Flag::Variation>>) {
if (arg) {
obj.emplace("variation", *arg);
}
}
},
variation_or_rollout);
Expand Down
6 changes: 4 additions & 2 deletions libs/internal/tests/data_model_serialization_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,8 @@ TEST(FlagRuleTests, DeserializesMinimumValid) {
ASSERT_FALSE(result->trackEvents);
ASSERT_TRUE(result->clauses.empty());
ASSERT_FALSE(result->id);
ASSERT_EQ(std::get<data_model::Flag::Variation>(result->variationOrRollout),
ASSERT_EQ(std::get<std::optional<data_model::Flag::Variation>>(
result->variationOrRollout),
data_model::Flag::Variation(123));
}

Expand All @@ -348,7 +349,8 @@ TEST(FlagRuleTests, DeserializesAllFields) {
ASSERT_TRUE(result->trackEvents);
ASSERT_TRUE(result->clauses.empty());
ASSERT_EQ(result->id, "foo");
ASSERT_EQ(std::get<data_model::Flag::Variation>(result->variationOrRollout),
ASSERT_EQ(std::get<std::optional<data_model::Flag::Variation>>(
result->variationOrRollout),
data_model::Flag::Variation(123));
}

Expand Down
8 changes: 6 additions & 2 deletions libs/server-sdk/src/evaluation/bucketing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,12 @@ tl::expected<BucketResult, Error> Variation(
return std::visit(
[&](auto&& arg) -> tl::expected<BucketResult, Error> {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, Flag::Variation>) {
return BucketResult(arg);
if constexpr (std::is_same_v<T, std::optional<Flag::Variation>>) {
if (!arg) {
return tl::make_unexpected(
Error::RolloutMissingVariations());
}
return BucketResult(*arg);
} else if constexpr (std::is_same_v<T, Flag::Rollout>) {
if (arg.variations.empty()) {
return tl::make_unexpected(
Expand Down