Skip to content

Commit 94f52de

Browse files
committed
Add requested test
1 parent 1734d9c commit 94f52de

File tree

6 files changed

+104
-13
lines changed

6 files changed

+104
-13
lines changed

contract-tests/src/command_params.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ pub struct EvaluateAllFlagsResponse {
6363
pub state: FlagDetail,
6464
}
6565

66+
#[allow(dead_code)]
6667
#[derive(Deserialize, Debug)]
6768
#[serde(rename_all = "camelCase")]
6869
pub struct CustomEventParams {

launchdarkly-server-sdk/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ mockito = "1.2.0"
5050
assert-json-diff = "2.0.2"
5151
async-std = "1.12.0"
5252
reqwest = { version = "0.12.4", features = ["json"] }
53+
testing_logger = "0.1.1"
5354

5455
[features]
5556
default = ["rustls"]

launchdarkly-server-sdk/src/client.rs

Lines changed: 99 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,9 @@ impl Client {
331331
pub fn close(&self) {
332332
self.event_processor.close();
333333

334-
// If the system is in offline mode, no receiver will be listening to this broadcast
335-
// channel, so sending on it would always result in an error.
336-
if !self.offline {
334+
// If the system is in offline mode or daemon mode, no receiver will be listening to this
335+
// broadcast channel, so sending on it would always result in an error.
336+
if !self.offline && !self.daemon_mode {
337337
if let Err(e) = self.shutdown_broadcast.send(()) {
338338
error!("Failed to shutdown client appropriately: {}", e);
339339
}
@@ -850,7 +850,8 @@ mod tests {
850850
use eval::{ContextBuilder, MultiContextBuilder};
851851
use futures::FutureExt;
852852
use hyper::client::HttpConnector;
853-
use launchdarkly_server_sdk_evaluation::Reason;
853+
use launchdarkly_server_sdk_evaluation::{Flag, Reason, Segment};
854+
use maplit::hashmap;
854855
use std::collections::HashMap;
855856
use tokio::time::Instant;
856857

@@ -859,13 +860,19 @@ mod tests {
859860
use crate::events::create_event_sender;
860861
use crate::events::event::{OutputEvent, VariationKey};
861862
use crate::events::processor_builders::EventProcessorBuilder;
863+
use crate::stores::persistent_store::tests::InMemoryPersistentDataStore;
862864
use crate::stores::store_types::{PatchTarget, StorageItem};
863865
use crate::test_common::{
864866
self, basic_flag, basic_flag_with_prereq, basic_flag_with_prereqs_and_visibility,
865867
basic_flag_with_visibility, basic_int_flag, basic_migration_flag, basic_off_flag,
866868
};
867-
use crate::{ConfigBuilder, MigratorBuilder, Operation, Origin};
869+
use crate::{
870+
AllData, ConfigBuilder, MigratorBuilder, NullEventProcessorBuilder, Operation, Origin,
871+
PersistentDataStore, PersistentDataStoreBuilder, PersistentDataStoreFactory,
872+
SerializedItem,
873+
};
868874
use test_case::test_case;
875+
869876

870877
use super::*;
871878

@@ -1415,28 +1422,109 @@ mod tests {
14151422
assert_eq!(event_rx.iter().count(), 0);
14161423
}
14171424

1425+
struct InMemoryPersistentDataStoreFactory {
1426+
data: AllData<Flag, Segment>,
1427+
initialized: bool,
1428+
}
1429+
1430+
impl PersistentDataStoreFactory for InMemoryPersistentDataStoreFactory {
1431+
fn create_persistent_data_store(
1432+
&self,
1433+
) -> Result<Box<(dyn PersistentDataStore + 'static)>, std::io::Error> {
1434+
let serialized_data =
1435+
AllData::<SerializedItem, SerializedItem>::try_from(self.data.clone())?;
1436+
Ok(Box::new(InMemoryPersistentDataStore {
1437+
data: serialized_data,
1438+
initialized: self.initialized,
1439+
}))
1440+
}
1441+
}
1442+
14181443
#[test]
14191444
fn variation_detail_handles_daemon_mode() {
1420-
let (client, event_rx) = make_mocked_client_with_delay(1000, false, true);
1445+
testing_logger::setup();
1446+
let factory = InMemoryPersistentDataStoreFactory {
1447+
data: AllData {
1448+
flags: hashmap!["flag".into() => basic_flag("flag")],
1449+
segments: HashMap::new(),
1450+
},
1451+
initialized: true,
1452+
};
1453+
let builder = PersistentDataStoreBuilder::new(Arc::new(factory));
1454+
1455+
let config = ConfigBuilder::new("sdk-key")
1456+
.daemon_mode(true)
1457+
.data_store(&builder)
1458+
.event_processor(&NullEventProcessorBuilder::new())
1459+
.build()
1460+
.expect("config should build");
1461+
1462+
let client = Client::build(config).expect("Should be built.");
1463+
14211464
client.start_with_default_executor();
14221465

14231466
let context = ContextBuilder::new("bob")
14241467
.build()
14251468
.expect("Failed to create context");
14261469

1427-
let detail = client.variation_detail(&context, "myFlag", FlagValue::Bool(false));
1470+
let detail = client.variation_detail(&context, "flag", FlagValue::Bool(false));
14281471

1429-
assert!(!detail.value.unwrap().as_bool().unwrap());
1472+
assert!(detail.value.unwrap().as_bool().unwrap());
14301473
assert!(matches!(
14311474
detail.reason,
1432-
Reason::Error {
1433-
error: eval::Error::FlagNotFound
1475+
Reason::Fallthrough {
1476+
in_experiment: false
14341477
}
14351478
));
14361479
client.flush();
14371480
client.close();
14381481

1439-
assert_eq!(event_rx.iter().count(), 2);
1482+
testing_logger::validate(|captured_logs| {
1483+
assert_eq!(captured_logs.len(), 1);
1484+
assert_eq!(
1485+
captured_logs[0].body,
1486+
"Started LaunchDarkly Client in daemon mode"
1487+
);
1488+
});
1489+
}
1490+
1491+
#[test]
1492+
fn daemon_mode_is_quiet_if_store_is_not_initialized() {
1493+
testing_logger::setup();
1494+
1495+
let factory = InMemoryPersistentDataStoreFactory {
1496+
data: AllData {
1497+
flags: HashMap::new(),
1498+
segments: HashMap::new(),
1499+
},
1500+
initialized: false,
1501+
};
1502+
let builder = PersistentDataStoreBuilder::new(Arc::new(factory));
1503+
1504+
let config = ConfigBuilder::new("sdk-key")
1505+
.daemon_mode(true)
1506+
.data_store(&builder)
1507+
.event_processor(&NullEventProcessorBuilder::new())
1508+
.build()
1509+
.expect("config should build");
1510+
1511+
let client = Client::build(config).expect("Should be built.");
1512+
1513+
client.start_with_default_executor();
1514+
1515+
let context = ContextBuilder::new("bob")
1516+
.build()
1517+
.expect("Failed to create context");
1518+
1519+
client.variation_detail(&context, "flag", FlagValue::Bool(false));
1520+
1521+
testing_logger::validate(|captured_logs| {
1522+
assert_eq!(captured_logs.len(), 1);
1523+
assert_eq!(
1524+
captured_logs[0].body,
1525+
"Started LaunchDarkly Client in daemon mode"
1526+
);
1527+
});
14401528
}
14411529

14421530
#[test]

launchdarkly-server-sdk/src/events/event.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ impl OutputEvent {
422422
}
423423
}
424424

425+
#[allow(clippy::large_enum_variant)]
425426
#[derive(Clone, Debug, Serialize)]
426427
pub enum InputEvent {
427428
FeatureRequest(FeatureRequestEvent),

launchdarkly-server-sdk/src/migrations/migrator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ where
452452
payload: &'a P,
453453
}
454454

455-
impl<'a, P, T, F> Executor<'a, P, T, F>
455+
impl<P, T, F> Executor<'_, P, T, F>
456456
where
457457
P: Send + Sync,
458458
T: Send + Sync,

launchdarkly-server-sdk/src/stores/persistent_store.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ pub trait PersistentDataStore: Send + Sync {
9494
}
9595

9696
#[cfg(test)]
97-
pub(super) mod tests {
97+
pub(crate) mod tests {
9898
use crate::stores::persistent_store::PersistentDataStore;
9999
use crate::stores::store_types::{AllData, DataKind, SerializedItem};
100100
use std::collections::HashMap;

0 commit comments

Comments
 (0)