Skip to content
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: add client-side C binding for fetching data source state #442

Merged
merged 1 commit into from
Oct 1, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -501,9 +501,23 @@ enum LDDataSourceStatus_State {
* SDK key will never become valid), or because the SDK client was
* explicitly shut down.
*/
LD_DATASOURCESTATUS_STATE_SHUTDOWN = 4
LD_DATASOURCESTATUS_STATE_SHUTDOWN = 4,

LD_DATASOURCESTATUS_STATE_UNUSED_MAXVALUE =
INT32_MAX /* Used to ensure the underlying type is
* at least 32 bits. */
};

/**
* @param state The state to convert to a string.
* @param default_if_unknown The default string to return if the state is not
* recognized.
* @return Returns the name of the given LDDataSourceStatus_State.
*/
LD_EXPORT(char const*)
LDDataSourceStatus_State_Name(enum LDDataSourceStatus_State state,
char const* default_if_unknown);

/**
* Get an enumerated value representing the overall current state of the data
* source.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <chrono>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <optional>
Expand All @@ -15,7 +16,7 @@ namespace launchdarkly::client_side::data_sources {
/**
* Enumeration of possible data source states.
*/
enum class DataSourceState {
enum class DataSourceState : std::int32_t {
/**
* The initial state of the data source when the SDK is being
* initialized.
Expand Down Expand Up @@ -62,15 +63,17 @@ enum class DataSourceState {
* SDK key will never become valid), or because the SDK client was
* explicitly shut down.
*/
kShutdown = 4,

// BackgroundDisabled,

// TODO: A plugin of sorts would likely be required to implement
// network availability.
// kNetworkUnavailable,
kShutdown = 4
};

/**
*
* @return Returns the name of the given DataSourceState as a string. If
* the enum value is not recognized, the default string value is returned.
*/
char const* GetDataSourceStateName(DataSourceState state,
char const* default_if_unknown);

using DataSourceStatus =
common::data_sources::DataSourceStatusBase<DataSourceState>;

Expand Down
8 changes: 8 additions & 0 deletions libs/client-sdk/src/bindings/c/sdk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,14 @@ LDDataSourceStatus_GetState(LDDataSourceStatus status) {
TO_DATASOURCESTATUS(status)->State());
}

LD_EXPORT(char const*)
LDDataSourceStatus_State_Name(enum LDDataSourceStatus_State state,
char const* default_if_unknown) {
return GetDataSourceStateName(
static_cast<data_sources::DataSourceStatus::DataSourceState>(state),
default_if_unknown);
}

LD_EXPORT(LDDataSourceStatus_ErrorInfo)
LDDataSourceStatus_GetLastError(LDDataSourceStatus status) {
LD_ASSERT_NOT_NULL(status);
Expand Down
25 changes: 13 additions & 12 deletions libs/client-sdk/src/data_sources/data_source_status.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@

namespace launchdarkly::client_side::data_sources {

std::ostream& operator<<(std::ostream& out,
DataSourceStatus::DataSourceState const& state) {
char const* GetDataSourceStateName(DataSourceState state,
char const* default_if_unknown) {
switch (state) {
case DataSourceStatus::DataSourceState::kInitializing:
out << "INITIALIZING";
break;
return "INITIALIZING";
case DataSourceStatus::DataSourceState::kValid:
out << "VALID";
break;
return "VALID";
case DataSourceStatus::DataSourceState::kInterrupted:
out << "INTERRUPTED";
break;
return "INTERRUPTED";
case DataSourceStatus::DataSourceState::kSetOffline:
out << "OFFLINE";
break;
return "OFFLINE";
case DataSourceStatus::DataSourceState::kShutdown:
out << "SHUTDOWN";
break;
return "SHUTDOWN";
default:
return default_if_unknown;
}
}

std::ostream& operator<<(std::ostream& out,
DataSourceStatus::DataSourceState const& state) {
out << GetDataSourceStateName(state, "UNKNOWN");
return out;
}

Expand All @@ -33,7 +34,7 @@
out << "Status(" << status.State() << ", Since("
<< std::put_time(std::gmtime(&as_time_t), "%Y-%m-%d %H:%M:%S") << ")";
if (status.LastError()) {
out << ", " << status.LastError().value();

Check warning on line 37 in libs/client-sdk/src/data_sources/data_source_status.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/libs/client-sdk/src/data_sources/data_source_status.cpp:37:24 [bugprone-unchecked-optional-access]

unchecked access to optional value
}
out << ")";
return out;
Expand Down
21 changes: 21 additions & 0 deletions libs/client-sdk/tests/client_c_bindings_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
TEST(ClientBindings, MinimalInstantiation) {
LDClientConfigBuilder cfg_builder = LDClientConfigBuilder_New("sdk-123");

LDClientConfig config;

Check warning on line 17 in libs/client-sdk/tests/client_c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/libs/client-sdk/tests/client_c_bindings_test.cpp:17:20 [cppcoreguidelines-init-variables]

variable 'config' is not initialized
LDStatus status = LDClientConfigBuilder_Build(cfg_builder, &config);
ASSERT_TRUE(LDStatus_Ok(status));

Expand All @@ -33,7 +33,7 @@
}

void FlagListenerFunction(char const* flag_key,
LDValue new_value,

Check warning on line 36 in libs/client-sdk/tests/client_c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/libs/client-sdk/tests/client_c_bindings_test.cpp:36:27 [bugprone-easily-swappable-parameters]

2 adjacent parameters of 'FlagListenerFunction' of similar type ('LDValue') are easily swapped by mistake
LDValue old_value,
bool deleted,
void* user_data) {}
Expand All @@ -44,7 +44,7 @@
LDClientConfigBuilder cfg_builder = LDClientConfigBuilder_New("sdk-123");
LDClientConfigBuilder_Offline(cfg_builder, true);

LDClientConfig config;

Check warning on line 47 in libs/client-sdk/tests/client_c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/libs/client-sdk/tests/client_c_bindings_test.cpp:47:20 [cppcoreguidelines-init-variables]

variable 'config' is not initialized
LDStatus status = LDClientConfigBuilder_Build(cfg_builder, &config);
ASSERT_TRUE(LDStatus_Ok(status));

Expand All @@ -56,19 +56,19 @@
LDClientSDK sdk = LDClientSDK_New(config, context);

bool success = false;
LDClientSDK_Start(sdk, 3000, &success);

Check warning on line 59 in libs/client-sdk/tests/client_c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/libs/client-sdk/tests/client_c_bindings_test.cpp:59:28 [cppcoreguidelines-avoid-magic-numbers

3000 is a magic number; consider replacing it with a named constant
EXPECT_TRUE(success);

struct LDFlagListener listener {
reinterpret_cast<FlagChangedCallbackFn>(0x123),

Check warning on line 63 in libs/client-sdk/tests/client_c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/libs/client-sdk/tests/client_c_bindings_test.cpp:63:9 [cppcoreguidelines-pro-type-reinterpret-cast]

do not use reinterpret_cast

Check warning on line 63 in libs/client-sdk/tests/client_c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/libs/client-sdk/tests/client_c_bindings_test.cpp:63:49 [cppcoreguidelines-avoid-magic-numbers

0x123 is a magic number; consider replacing it with a named constant
reinterpret_cast<void*>(0x456)

Check warning on line 64 in libs/client-sdk/tests/client_c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/libs/client-sdk/tests/client_c_bindings_test.cpp:64:13 [cppcoreguidelines-pro-type-reinterpret-cast]

do not use reinterpret_cast

Check warning on line 64 in libs/client-sdk/tests/client_c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/libs/client-sdk/tests/client_c_bindings_test.cpp:64:37 [cppcoreguidelines-avoid-magic-numbers

0x456 is a magic number; consider replacing it with a named constant
};

LDFlagListener_Init(&listener);
ASSERT_EQ(listener.FlagChanged, nullptr);
ASSERT_EQ(listener.UserData, nullptr);

listener.UserData = const_cast<char*>("Potato");

Check warning on line 71 in libs/client-sdk/tests/client_c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

/libs/client-sdk/tests/client_c_bindings_test.cpp:71:25 [cppcoreguidelines-pro-type-const-cast]

do not use const_cast
listener.FlagChanged = FlagListenerFunction;

LDListenerConnection connection =
Expand Down Expand Up @@ -194,3 +194,24 @@

LDDataSourceStatus_ErrorInfo_Free(info);
}

TEST(ClientBindings, TestDataSourceStatusStateName) {
ASSERT_STREQ(LDDataSourceStatus_State_Name(LD_DATASOURCESTATUS_STATE_VALID,
"unknown"),
"VALID");
ASSERT_STREQ(LDDataSourceStatus_State_Name(
LD_DATASOURCESTATUS_STATE_OFFLINE, "unknown"),
"OFFLINE");
ASSERT_STREQ(LDDataSourceStatus_State_Name(
LD_DATASOURCESTATUS_STATE_INITIALIZING, "unknown"),
"INITIALIZING");
ASSERT_STREQ(LDDataSourceStatus_State_Name(
LD_DATASOURCESTATUS_STATE_SHUTDOWN, "unknown"),
"SHUTDOWN");
ASSERT_STREQ(LDDataSourceStatus_State_Name(
LD_DATASOURCESTATUS_STATE_INTERRUPTED, "unknown"),
"INTERRUPTED");
ASSERT_STREQ(LDDataSourceStatus_State_Name(
LD_DATASOURCESTATUS_STATE_UNUSED_MAXVALUE, "unknown"),
"unknown");
}
Loading