Skip to content

Commit 388dd04

Browse files
tanderson-lddmvk
andauthored
feat: Introduce TestData#delete to simplify testing of flag deletion. (#21)
This is migrating a [PR from the java-server-sdk repo](launchdarkly/java-server-sdk@c8bdd2d). The java-server-sdk repo will be archived after this is merged. Co-authored-by: David Moravek <[email protected]>
1 parent 28f702d commit 388dd04

File tree

3 files changed

+79
-4
lines changed

3 files changed

+79
-4
lines changed

lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/integrations/TestData.java

+31-2
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,36 @@ public FlagBuilder flag(String key) {
110110
}
111111
return new FlagBuilder(key).booleanFlag();
112112
}
113-
113+
114+
/**
115+
* Deletes a specific flag from the test data by create a versioned tombstone.
116+
* <p>
117+
* This has the same effect as if a flag were removed on the LaunchDarkly dashboard.
118+
* It immediately propagates the flag change to any {@code LDClient} instance(s) that you have
119+
* already configured to use this {@code TestData}. If no {@code LDClient} has been started yet,
120+
* it simply adds tombstone to the test data which will be provided to any {@code LDClient} that
121+
* you subsequently configure.
122+
*
123+
* @param key the flag key
124+
* @return a flag configuration builder
125+
*/
126+
public TestData delete(String key) {
127+
final ItemDescriptor tombstoneItem;
128+
synchronized (lock) {
129+
final ItemDescriptor oldItem = currentFlags.get(key);
130+
final int oldVersion = oldItem == null ? 0 : oldItem.getVersion();
131+
tombstoneItem = ItemDescriptor.deletedItem(oldVersion + 1);
132+
currentFlags.put(key, tombstoneItem);
133+
currentBuilders.remove(key);
134+
}
135+
136+
for (DataSourceImpl instance: instances) {
137+
instance.updates.upsert(DataModel.FEATURES, key, tombstoneItem);
138+
}
139+
140+
return this;
141+
}
142+
114143
/**
115144
* Updates the test data with the specified flag configuration.
116145
* <p>
@@ -146,7 +175,7 @@ public TestData update(FlagBuilder flagBuilder) {
146175

147176
return this;
148177
}
149-
178+
150179
/**
151180
* Simulates a change in the data source status.
152181
* <p>

lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/TestDataTest.java

+29-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import static org.hamcrest.Matchers.is;
3434
import static org.hamcrest.Matchers.iterableWithSize;
3535
import static org.hamcrest.Matchers.not;
36+
import static org.hamcrest.Matchers.notNullValue;
3637
import static org.hamcrest.Matchers.nullValue;
3738

3839
@SuppressWarnings("javadoc")
@@ -151,7 +152,34 @@ public void updatesFlag() throws Exception {
151152
expectedFlag.on(true).version(2);
152153
assertJsonEquals(flagJson(expectedFlag, 2), flagJson(flag1));
153154
}
154-
155+
156+
@Test
157+
public void deletesFlag() throws Exception {
158+
final TestData td = TestData.dataSource();
159+
160+
try (final DataSource ds = td.build(clientContext("", new LDConfig.Builder().build(), updates))) {
161+
final Future<Void> started = ds.start();
162+
assertThat(started.isDone(), is(true));
163+
assertThat(updates.valid, is(true));
164+
165+
td.update(td.flag("foo").on(false).valueForAll(LDValue.of("bar")));
166+
td.delete("foo");
167+
168+
assertThat(updates.upserts.size(), equalTo(2));
169+
UpsertParams up = updates.upserts.take();
170+
assertThat(up.kind, is(DataModel.FEATURES));
171+
assertThat(up.key, equalTo("foo"));
172+
assertThat(up.item.getVersion(), equalTo(1));
173+
assertThat(up.item.getItem(), notNullValue());
174+
175+
up = updates.upserts.take();
176+
assertThat(up.kind, is(DataModel.FEATURES));
177+
assertThat(up.key, equalTo("foo"));
178+
assertThat(up.item.getVersion(), equalTo(2));
179+
assertThat(up.item.getItem(), nullValue());
180+
}
181+
}
182+
155183
@Test
156184
public void flagConfigSimpleBoolean() throws Exception {
157185
Function<ModelBuilders.FlagBuilder, ModelBuilders.FlagBuilder> expectedBooleanFlag = fb ->

lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/integrations/TestDataWithClientTest.java

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.launchdarkly.sdk.server.integrations;
22

3+
import com.launchdarkly.sdk.EvaluationDetail;
4+
import com.launchdarkly.sdk.EvaluationReason;
35
import com.launchdarkly.sdk.LDContext;
46
import com.launchdarkly.sdk.LDValue;
57
import com.launchdarkly.sdk.server.Components;
@@ -52,7 +54,23 @@ public void updatesFlag() throws Exception {
5254
assertThat(client.boolVariation("flag", LDContext.create("user"), false), is(true));
5355
}
5456
}
55-
57+
58+
@Test
59+
public void deletesFlag() throws Exception {
60+
td.update(td.flag("flag").on(true));
61+
62+
try (LDClient client = new LDClient(SDK_KEY, config)) {
63+
assertThat(client.boolVariation("flag", LDContext.create("user"), false), is(true));
64+
65+
td.delete("flag");
66+
67+
final EvaluationDetail<Boolean> detail = client.boolVariationDetail("flag", LDContext.create("user"), false);
68+
assertThat(detail.getValue(), is(false));
69+
assertThat(detail.isDefaultValue(), is(true));
70+
assertThat(detail.getReason().getErrorKind(), is(EvaluationReason.ErrorKind.FLAG_NOT_FOUND));
71+
}
72+
}
73+
5674
@Test
5775
public void usesTargets() throws Exception {
5876
td.update(td.flag("flag").fallthroughVariation(false).variationForUser("user1", true));

0 commit comments

Comments
 (0)