Skip to content

Commit 536176e

Browse files
committed
test: drop GC-dependent soak test and its production helper
The pendingListDoesNotGrowUnboundedlyWhenFreshFuturesAreDropped test needed System.gc() + Thread.sleep to encourage reclamation, which is brittle. The two distinctness tests are sufficient bug-provers for the shared-instance behavior they fail on, so drop the soak test and the test-only pendingSize() helper that supported it.
1 parent 1cd29b0 commit 536176e

2 files changed

Lines changed: 0 additions & 74 deletions

File tree

lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/FDv2DataSource.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -717,25 +717,5 @@ public void close() {
717717
}
718718
}
719719
}
720-
721-
/**
722-
* Test-only: snapshot of the current pending list size after
723-
* opportunistic pruning. Used by tests to assert that the pending list
724-
* does not grow unboundedly across iterations.
725-
*/
726-
int pendingSize() {
727-
synchronized (lock) {
728-
if (pending == null) {
729-
return 0;
730-
}
731-
Iterator<WeakReference<CompletableFuture<Object>>> it = pending.iterator();
732-
while (it.hasNext()) {
733-
if (it.next().get() == null) {
734-
it.remove();
735-
}
736-
}
737-
return pending.size();
738-
}
739-
}
740720
}
741721
}

lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/FDv2DataSourceConditionsAggregateTest.java

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import java.util.concurrent.TimeUnit;
1919

2020
import static org.hamcrest.MatcherAssert.assertThat;
21-
import static org.hamcrest.Matchers.lessThanOrEqualTo;
2221
import static org.hamcrest.Matchers.not;
2322
import static org.hamcrest.Matchers.sameInstance;
2423
import static org.junit.Assert.assertNotNull;
@@ -137,59 +136,6 @@ public void getFutureAfterAggregateFiresReturnsCompletedFuture() throws Exceptio
137136
}
138137
}
139138

140-
/**
141-
* Bug-proving test for the underlying leak: repeated getFuture() calls
142-
* whose returned futures are then dropped (the run-loop pattern: each
143-
* iteration's anyOf result becomes garbage at end of iteration) must NOT
144-
* cause the pending list to grow without bound. The opportunistic prune
145-
* inside getFuture() collects entries whose WeakReference target has been
146-
* collected.
147-
*
148-
* <p>Java does not guarantee that {@link System#gc()} actually runs, but
149-
* in practice with HotSpot's default GC plus a brief sleep this is
150-
* reliable. If it ever flakes on CI, increase the iteration count or the
151-
* sleep, or migrate to a {@code -XX:+UseSerialGC} test profile.
152-
*/
153-
@Test
154-
public void pendingListDoesNotGrowUnboundedlyWhenFreshFuturesAreDropped()
155-
throws Exception {
156-
Condition fallback = new FallbackCondition(executor, 60); // never fires
157-
try (FDv2DataSource.Conditions conditions =
158-
new FDv2DataSource.Conditions(Collections.singletonList(fallback))) {
159-
int iterations = 10_000;
160-
for (int i = 0; i < iterations; i++) {
161-
CompletableFuture<Object> f = conditions.getFuture();
162-
// Simulate the run loop: race f against a fast-resolving sibling.
163-
// The anyOf result is awaited and discarded; f becomes unreachable
164-
// at end of iteration.
165-
CompletableFuture<Object> sibling = CompletableFuture.completedFuture("ok");
166-
CompletableFuture.anyOf(f, sibling).get(1, TimeUnit.SECONDS);
167-
// f goes out of scope here.
168-
169-
// Periodically encourage GC + give the cleanup path a chance.
170-
if (i % 1000 == 999) {
171-
System.gc();
172-
Thread.sleep(10);
173-
}
174-
}
175-
System.gc();
176-
Thread.sleep(50);
177-
178-
// After 10k iterations, pendingSize() should not be anywhere near
179-
// 10k. The opportunistic prune inside getFuture() runs on every
180-
// call, so any entry whose WeakReference has been collected drops
181-
// out. A small handful (< 100) of recently-added live refs is
182-
// expected because the most recent iterations may not yet have
183-
// been GC'd. Choose a generous ceiling to avoid CI flakiness while
184-
// still being orders of magnitude below the pre-fix accumulation.
185-
int finalSize = conditions.pendingSize();
186-
assertThat(
187-
"pending list size should be bounded; was " + finalSize
188-
+ " after " + iterations + " iterations",
189-
finalSize, lessThanOrEqualTo(500));
190-
}
191-
}
192-
193139
private static FDv2SourceResult makeInterruptedResult() {
194140
return FDv2SourceResult.interrupted(
195141
new DataSourceStatusProvider.ErrorInfo(

0 commit comments

Comments
 (0)