Skip to content
Merged
2 changes: 1 addition & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
CheckOptions:
- { key: readability-identifier-length.IgnoredParameterNames, value: 'i|j|k|c|os|it' }
- { key: readability-identifier-length.IgnoredVariableNames, value: 'ec' }
- { key: readability-identifier-length.IgnoredVariableNames, value: 'ec|id' }
- { key: readability-identifier-length.IgnoredLoopCounterNames, value: 'i|j|k|c|os|it' }
22 changes: 11 additions & 11 deletions apps/sdk-contract-tests/include/client_entity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,24 @@ class ClientEntity {

private:
tl::expected<nlohmann::json, std::string> Evaluate(
EvaluateFlagParams params);
EvaluateFlagParams const&);

tl::expected<nlohmann::json, std::string> EvaluateDetail(
EvaluateFlagParams);
EvaluateFlagParams const&);

tl::expected<nlohmann::json, std::string> EvaluateAll(
EvaluateAllFlagParams params);
EvaluateAllFlagParams const&);

tl::expected<nlohmann::json, std::string> Identify(
IdentifyEventParams params);
IdentifyEventParams const&);

tl::expected<nlohmann::json, std::string> Custom(CustomEventParams params);

tl::expected<nlohmann::json, std::string> ContextBuild(
ContextBuildParams params);

tl::expected<nlohmann::json, std::string> ContextConvert(
ContextConvertParams params);
tl::expected<nlohmann::json, std::string> Custom(CustomEventParams const&);

std::unique_ptr<launchdarkly::client_side::Client> client_;
};

static tl::expected<nlohmann::json, std::string> ContextConvert(
ContextConvertParams const&);

static tl::expected<nlohmann::json, std::string> ContextBuild(
ContextBuildParams const&);
7 changes: 4 additions & 3 deletions apps/sdk-contract-tests/include/entity_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,15 @@ class EntityManager {
* @return An ID representing the entity, or none if the entity couldn't
* be created.
*/
std::optional<std::string> create(ConfigParams params);
std::optional<std::string> create(ConfigParams const& params);
/**
* Destroy an entity with the given ID.
* @param id ID of the entity.
* @return True if the entity was found and destroyed.
*/
bool destroy(std::string const& id);

tl::expected<nlohmann::json, std::string> command(std::string const& id,
CommandParams params);
tl::expected<nlohmann::json, std::string> command(
std::string const& id,
CommandParams const& params);
};
45 changes: 34 additions & 11 deletions apps/sdk-contract-tests/src/client_entity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,36 @@
#include <launchdarkly/serialization/json_value.hpp>
#include <launchdarkly/value.hpp>

#include <chrono>
#include <future>

ClientEntity::ClientEntity(
std::unique_ptr<launchdarkly::client_side::Client> client)
: client_(std::move(client)) {}

tl::expected<nlohmann::json, std::string> ClientEntity::Identify(
IdentifyEventParams params) {
return tl::make_unexpected("identify not yet supported");
IdentifyEventParams const& params) {
boost::system::error_code ec;
auto json_value = boost::json::parse(params.context.dump(), ec);
if (ec) {
return tl::make_unexpected(ec.what());
}

auto maybe_ctx = boost::json::value_to<
tl::expected<launchdarkly::Context, launchdarkly::JsonError>>(
json_value);

if (!maybe_ctx) {
return tl::make_unexpected(
launchdarkly::ErrorToString(maybe_ctx.error()));
}

if (!maybe_ctx->valid()) {
return tl::make_unexpected(maybe_ctx->errors());
}

client_->IdentifyAsync(*maybe_ctx).wait();
return nlohmann::json{};
Copy link
Contributor Author

@cwaldren-ld cwaldren-ld May 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This blocks the thread serving the request, but that's fine since the the contract tests execute serially (and correct, since the contract tests assume it will happen synchronously.)

}

static void BuildContextFromParams(launchdarkly::ContextBuilder& builder,
Expand All @@ -38,8 +61,8 @@ static void BuildContextFromParams(launchdarkly::ContextBuilder& builder,
}
}

tl::expected<nlohmann::json, std::string> ClientEntity::ContextBuild(
ContextBuildParams params) {
tl::expected<nlohmann::json, std::string> ContextBuild(
ContextBuildParams const& params) {
ContextResponse resp{};

auto builder = launchdarkly::ContextBuilder();
Expand All @@ -62,8 +85,8 @@ tl::expected<nlohmann::json, std::string> ClientEntity::ContextBuild(
return resp;
}

tl::expected<nlohmann::json, std::string> ClientEntity::ContextConvert(
ContextConvertParams params) {
tl::expected<nlohmann::json, std::string> ContextConvert(
ContextConvertParams const& params) {
ContextResponse resp{};

boost::system::error_code ec;
Expand Down Expand Up @@ -92,7 +115,7 @@ tl::expected<nlohmann::json, std::string> ClientEntity::ContextConvert(
}

tl::expected<nlohmann::json, std::string> ClientEntity::Custom(
CustomEventParams params) {
CustomEventParams const& params) {
auto data = params.data ? boost::json::value_to<launchdarkly::Value>(
boost::json::parse(params.data->dump()))
: launchdarkly::Value::Null();
Expand All @@ -113,7 +136,7 @@ tl::expected<nlohmann::json, std::string> ClientEntity::Custom(
}

tl::expected<nlohmann::json, std::string> ClientEntity::EvaluateAll(
EvaluateAllFlagParams params) {
EvaluateAllFlagParams const& params) {
EvaluateAllFlagsResponse resp{};

boost::ignore_unused(params);
Expand All @@ -127,7 +150,7 @@ tl::expected<nlohmann::json, std::string> ClientEntity::EvaluateAll(
}

tl::expected<nlohmann::json, std::string> ClientEntity::EvaluateDetail(
EvaluateFlagParams params) {
EvaluateFlagParams const& params) {
auto const& key = params.flagKey;

auto const& defaultVal = params.defaultValue;
Expand Down Expand Up @@ -202,7 +225,7 @@ tl::expected<nlohmann::json, std::string> ClientEntity::EvaluateDetail(
return result;
}
tl::expected<nlohmann::json, std::string> ClientEntity::Evaluate(
EvaluateFlagParams params) {
EvaluateFlagParams const& params) {
if (params.detail) {
return EvaluateDetail(params);
}
Expand Down Expand Up @@ -279,7 +302,7 @@ tl::expected<nlohmann::json, std::string> ClientEntity::Command(
}
return Custom(*params.customEvent);
case Command::FlushEvents:
client_->AsyncFlush();
client_->FlushAsync();
return nlohmann::json{};
case Command::ContextBuild:
if (!params.contextBuild) {
Expand Down
4 changes: 2 additions & 2 deletions apps/sdk-contract-tests/src/entity_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ ParseContext(nlohmann::json value) {
boost_json_val);
}

std::optional<std::string> EntityManager::create(ConfigParams in) {
std::optional<std::string> EntityManager::create(ConfigParams const& in) {
std::string id = std::to_string(counter_++);

auto config_builder = ConfigBuilder(in.credential);
Expand Down Expand Up @@ -159,7 +159,7 @@ bool EntityManager::destroy(std::string const& id) {

tl::expected<nlohmann::json, std::string> EntityManager::command(
std::string const& id,
CommandParams params) {
CommandParams const& params) {
auto it = entities_.find(id);
if (it == entities_.end()) {
return tl::make_unexpected("entity not found");
Expand Down
50 changes: 2 additions & 48 deletions apps/sdk-contract-tests/test-suppressions.txt
Original file line number Diff line number Diff line change
@@ -1,56 +1,10 @@
events/summary events/basic counter behavior
events/summary events/context kinds
events/summary events/reset after each flush
events/identify events/basic properties/single kind default
events/identify events/basic properties/single kind non-default
events/identify events/basic properties/multi-kind
events/custom events/basic properties/single kind default
events/custom events/basic properties/single kind non-default
events/custom events/basic properties/multi-kind
events/context properties/single-kind minimal/debug event
events/context properties/single-kind minimal/identify event
events/context properties/multi-kind minimal/debug event
events/context properties/multi-kind minimal/identify event
events/context properties/single-kind with attributes, nothing private/debug event
events/context properties/single-kind with attributes, nothing private/identify event
events/context properties/single-kind, allAttributesPrivate/debug event
events/context properties/single-kind, allAttributesPrivate/identify event
events/context properties/single-kind, specific private attributes/debug event
events/context properties/single-kind, specific private attributes/identify event
events/context properties/single-kind, private attribute nested property/debug event
events/context properties/single-kind, private attribute nested property/identify event
events/context properties/custom attribute with value false/debug event
events/context properties/custom attribute with value false/identify event
events/context properties/custom attribute with value true/debug event
events/context properties/custom attribute with value true/identify event
events/context properties/custom attribute with value -1000/debug event
events/context properties/custom attribute with value -1000/identify event
events/context properties/custom attribute with value 0/debug event
events/context properties/custom attribute with value 0/identify event
events/context properties/custom attribute with value 1000/debug event
events/context properties/custom attribute with value 1000/identify event
events/context properties/custom attribute with value -1000.5/debug event
events/context properties/custom attribute with value -1000.5/identify event
events/context properties/custom attribute with value 1000.5/debug event
events/context properties/custom attribute with value 1000.5/identify event
events/context properties/custom attribute with value ""/debug event
events/context properties/custom attribute with value ""/identify event
events/context properties/custom attribute with value "abc"/debug event
events/context properties/custom attribute with value "abc"/identify event
events/context properties/custom attribute with value "has \"escaped\" characters"/debug event
events/context properties/custom attribute with value "has \"escaped\" characters"/identify event
events/context properties/custom attribute with value []/debug event
events/context properties/custom attribute with value []/identify event
events/context properties/custom attribute with value ["a","b"]/debug event
events/context properties/custom attribute with value ["a","b"]/identify event
events/context properties/custom attribute with value {}/debug event
events/context properties/custom attribute with value {}/identify event
events/context properties/custom attribute with value {"a":1}/debug event
events/context properties/custom attribute with value {"a":1}/identify event
events/disabling/identify event
streaming/requests/query parameters/evaluationReasons set to true/GET
streaming/requests/query parameters/evaluationReasons set to true/REPORT
tags/disallowed characters

# The Client doesn't need to know how to deserialize users.
context type/convert/old user to context/{"key": ""}
context type/convert/old user to context/{"key": "a"}
context type/convert/old user to context/{"key": "a"}
Expand Down
2 changes: 1 addition & 1 deletion apps/sse-contract-tests/include/entity_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class EntityManager {
* @return An ID representing the entity, or none if the entity couldn't
* be created.
*/
std::optional<std::string> create(ConfigParams params);
std::optional<std::string> create(ConfigParams const& params);
/**
* Destroy an entity with the given ID.
* @param id ID of the entity.
Expand Down
13 changes: 5 additions & 8 deletions apps/sse-contract-tests/src/entity_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@ using launchdarkly::LogLevel;

EntityManager::EntityManager(boost::asio::any_io_executor executor,
launchdarkly::Logger& logger)
: entities_(),
counter_{0},
executor_{std::move(executor)},
logger_{logger} {}
: counter_{0}, executor_{std::move(executor)}, logger_{logger} {}

std::optional<std::string> EntityManager::create(ConfigParams params) {
std::optional<std::string> EntityManager::create(ConfigParams const& params) {
std::string id = std::to_string(counter_++);

auto poster = std::make_shared<EventOutbox>(executor_, params.callbackUrl);
Expand All @@ -20,8 +17,8 @@ std::optional<std::string> EntityManager::create(ConfigParams params) {
launchdarkly::sse::Builder(executor_, params.streamUrl);

if (params.headers) {
for (auto const& h : *params.headers) {
client_builder.header(h.first, h.second);
for (auto const& header : *params.headers) {
client_builder.header(header.first, header.second);
}
}

Expand Down Expand Up @@ -65,7 +62,7 @@ bool EntityManager::destroy(std::string const& id) {
return false;
}

it->second.first->close();
it->second.first->async_shutdown(nullptr);
it->second.second->stop();

entities_.erase(it);
Expand Down
18 changes: 13 additions & 5 deletions libs/client-sdk/include/launchdarkly/client_side/client.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <chrono>
#include <future>
#include <memory>
#include <string>
#include <unordered_map>
Expand Down Expand Up @@ -87,16 +88,23 @@ class IClient {
* Tells the client that all pending analytics events (if any) should be
* delivered as soon as possible.
*/
virtual void AsyncFlush() = 0;
virtual void FlushAsync() = 0;

/**
* Changes the current evaluation context, requests flags for that context
* from LaunchDarkly if we are online, and generates an analytics event to
* tell LaunchDarkly about the context.
*
* Only one IdentifyAsync can be in progress at once; calling it
* concurrently is undefined behavior.
*
* To block until the identify operation is complete, call wait() on
* the returned future.
*
* @param context The new evaluation context.
*/
virtual void AsyncIdentify(Context context) = 0;

virtual std::future<void> IdentifyAsync(Context context) = 0;

/**
* Returns the boolean value of a feature flag for a given flag key.
Expand Down Expand Up @@ -265,9 +273,9 @@ class Client : public IClient {

void Track(std::string event_name) override;

void AsyncFlush() override;
void FlushAsync() override;

void AsyncIdentify(Context context) override;
std::future<void> IdentifyAsync(Context context) override;

bool BoolVariation(FlagKey const& key, bool default_value) override;

Expand Down Expand Up @@ -307,4 +315,4 @@ class Client : public IClient {
std::unique_ptr<IClient> client;
};

} // namespace launchdarkly::client_side
} // namespace launchdarkly::client_side
8 changes: 4 additions & 4 deletions libs/client-sdk/src/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ void Client::Track(std::string event_name) {
client->Track(std::move(event_name));
}

void Client::AsyncFlush() {
client->AsyncFlush();
void Client::FlushAsync() {
client->FlushAsync();
}

void Client::AsyncIdentify(Context context) {
client->AsyncIdentify(std::move(context));
std::future<void> Client::IdentifyAsync(Context context) {
return client->IdentifyAsync(std::move(context));
}

bool Client::BoolVariation(FlagKey const& key, bool default_value) {
Expand Down
Loading