-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: server-side contract tests #197
Conversation
This pull request has been linked to Shortcut Story #206687: Contract test support. |
ae5deb7
to
07e31d1
Compare
.github/workflows/server.yml
Outdated
@@ -6,11 +6,30 @@ on: | |||
paths-ignore: | |||
- '**.md' #Do not need to run CI for markdown changes. | |||
pull_request: | |||
branches: [ main, server-side ] | |||
branches: [ main, server-side, cw/sc-206686/server-build-ci ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: remove. Needed to run CI since I rebased this PR from server-side
to the server-build-ci
branch.
4a8eac0
to
f115ebb
Compare
f115ebb
to
2ddf672
Compare
@@ -0,0 +1,874 @@ | |||
evaluation/parameterized/bad attribute reference errors - tilde followed by nothing/test-flag/evaluate flag with detail |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A huge amount of these are all flags
related, since the test harness uses that method to make assertions. I've fixed that separately in #201.
* @return True if a reason exists and matches the given kind. | ||
*/ | ||
[[nodiscard]] bool ReasonKindIs(enum EvaluationReason::Kind kind) const; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found myself needing to reach into the reason and check if it was a specific kind, like:
if (detail.Reason() && detail.Reason()->Kind() == EvaluationReason::Kind::kWhatever)
I feel like this could be a reasonably common task and deserves a method, but perhaps not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose it doesn't hurt anything.
@@ -88,7 +88,7 @@ struct Flag { | |||
std::vector<Target> targets; | |||
std::vector<Target> contextTargets; | |||
std::vector<Rule> rules; | |||
std::optional<std::uint64_t> offVariation; | |||
std::optional<std::int64_t> offVariation; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our JSON specification notes that the minimum values are 0, so I used uint64_t
- but that's not the case in practice, as the test harness may send negative values.
|
||
// Object slicing on purpose; the context will be stripped out | ||
// of the ServerTrackEventParams when converted to a | ||
// TrackEventParams. | ||
out.emplace_back(std::move(event)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could maybe solve this with composition instead.
@@ -62,7 +62,7 @@ tl::expected<std::optional<DataSourceEventHandler::Put>, JsonError> tag_invoke( | |||
auto const& obj = json_value.as_object(); | |||
PARSE_FIELD(path, obj, "path"); | |||
// We don't know what to do with a path other than "/". | |||
if (path != "/") { | |||
if (!(path == "/" || path.empty())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The path may be omitted in PUT events.
@@ -138,7 +138,7 @@ EvaluationDetail<Value> Evaluator::FlagVariation( | |||
Flag const& flag, | |||
Flag::Variation variation_index, | |||
EvaluationReason reason) const { | |||
if (variation_index >= flag.variations.size()) { | |||
if (variation_index < 0 || variation_index >= flag.variations.size()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that variation_index is signed, must check for negative.
@@ -200,7 +203,21 @@ template <typename T> | |||
EvaluationDetail<T> ClientImpl::VariationInternal(Context const& ctx, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the grossness in this method that follows is fixed in a future PR (#203)
Implements the `AllFlagsState` API, which evaluates all flags and returns a serializable structure suitable for bootstrapping a client-side SDK. The method returns an `AllFlagsState` class, which has a nested `State` class representing details for a single flag. Additionally, there is an `Options` enum to control the API's behavior.
Introduces a contract test server for the server-side SDK, runs in CI, and initial (large) suppression list.
The bulk of the code is copied from the client-side, although I have made an effort to refactor the common JSON definitions into a shared library.
There is an opportunity to refactor out the "shell" (the coroutine stuff that is responsible for serving/responding to requests) into a common lib as well, but it didn't seem worth the effort.