Skip to content

Commit 98e1271

Browse files
Hendrik MuhsAjeetNathawat
andauthored
[Transform] Adding null check to fix potential NPE (#96785) (#97002)
Co-authored-by: AjeetNathawat <[email protected]>
1 parent 96cd571 commit 98e1271

File tree

3 files changed

+106
-1
lines changed

3 files changed

+106
-1
lines changed

docs/changelog/96785.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 96785
2+
summary: Adding null check to fix potential NPE
3+
area: Transform
4+
type: enhancement
5+
issues:
6+
- 96781

x-pack/plugin/transform/src/main/java/org/elasticsearch/xpack/transform/transforms/common/AbstractCompositeAggFunction.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.elasticsearch.xpack.transform.transforms.Function;
3434
import org.elasticsearch.xpack.transform.transforms.pivot.AggregationResultUtils;
3535

36+
import java.util.Collections;
3637
import java.util.List;
3738
import java.util.Map;
3839
import java.util.stream.Collectors;
@@ -88,9 +89,13 @@ public void preview(
8889
return;
8990
}
9091
final CompositeAggregation agg = aggregations.get(COMPOSITE_AGGREGATION_NAME);
92+
if (agg == null || agg.getBuckets().isEmpty()) {
93+
listener.onResponse(Collections.emptyList());
94+
return;
95+
}
96+
9197
TransformIndexerStats stats = new TransformIndexerStats();
9298
TransformProgress progress = new TransformProgress();
93-
9499
List<Map<String, Object>> docs = extractResults(agg, fieldTypeMap, stats, progress).map(
95100
this::documentTransformationFunction
96101
).collect(Collectors.toList());

x-pack/plugin/transform/src/test/java/org/elasticsearch/xpack/transform/transforms/pivot/PivotTests.java

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import java.io.IOException;
5757
import java.util.ArrayList;
5858
import java.util.Collections;
59+
import java.util.HashMap;
5960
import java.util.List;
6061
import java.util.Map;
6162
import java.util.Set;
@@ -70,6 +71,7 @@
7071
import static org.hamcrest.CoreMatchers.is;
7172
import static org.hamcrest.Matchers.contains;
7273
import static org.hamcrest.Matchers.containsString;
74+
import static org.hamcrest.Matchers.empty;
7375
import static org.hamcrest.Matchers.equalTo;
7476
import static org.hamcrest.Matchers.notNullValue;
7577
import static org.hamcrest.Matchers.nullValue;
@@ -265,6 +267,60 @@ public void testProcessSearchResponse() {
265267
assertThat(pivot.processSearchResponse(searchResponseFromAggs(aggs), null, null, null, null, null), is(nullValue()));
266268
}
267269

270+
public void testPreviewForEmptyAggregation() throws Exception {
271+
Function pivot = new Pivot(
272+
PivotConfigTests.randomPivotConfig(),
273+
SettingsConfigTests.randomSettingsConfig(),
274+
Version.CURRENT,
275+
Collections.emptySet()
276+
);
277+
278+
CountDownLatch latch = new CountDownLatch(1);
279+
final AtomicReference<Exception> exceptionHolder = new AtomicReference<>();
280+
final AtomicReference<List<Map<String, Object>>> responseHolder = new AtomicReference<>();
281+
282+
Client emptyAggregationClient = new MyMockClientWithEmptyAggregation("empty aggregation test for preview");
283+
pivot.preview(emptyAggregationClient, null, new HashMap<>(), new SourceConfig("test"), null, 1, ActionListener.wrap(r -> {
284+
responseHolder.set(r);
285+
latch.countDown();
286+
}, e -> {
287+
exceptionHolder.set(e);
288+
latch.countDown();
289+
}));
290+
assertTrue(latch.await(100, TimeUnit.MILLISECONDS));
291+
emptyAggregationClient.close();
292+
293+
assertThat(exceptionHolder.get(), is(nullValue()));
294+
assertThat(responseHolder.get(), is(empty()));
295+
}
296+
297+
public void testPreviewForCompositeAggregation() throws Exception {
298+
Function pivot = new Pivot(
299+
PivotConfigTests.randomPivotConfig(),
300+
SettingsConfigTests.randomSettingsConfig(),
301+
Version.CURRENT,
302+
Collections.emptySet()
303+
);
304+
305+
CountDownLatch latch = new CountDownLatch(1);
306+
final AtomicReference<Exception> exceptionHolder = new AtomicReference<>();
307+
final AtomicReference<List<Map<String, Object>>> responseHolder = new AtomicReference<>();
308+
309+
Client compositeAggregationClient = new MyMockClientWithCompositeAggregation("composite aggregation test for preview");
310+
pivot.preview(compositeAggregationClient, null, new HashMap<>(), new SourceConfig("test"), null, 1, ActionListener.wrap(r -> {
311+
responseHolder.set(r);
312+
latch.countDown();
313+
}, e -> {
314+
exceptionHolder.set(e);
315+
latch.countDown();
316+
}));
317+
assertTrue(latch.await(100, TimeUnit.MILLISECONDS));
318+
compositeAggregationClient.close();
319+
320+
assertThat(exceptionHolder.get(), is(nullValue()));
321+
assertThat(responseHolder.get(), is(empty()));
322+
}
323+
268324
private static SearchResponse searchResponseFromAggs(Aggregations aggs) {
269325
SearchResponseSections sections = new SearchResponseSections(null, aggs, null, false, null, null, 1);
270326
SearchResponse searchResponse = new SearchResponse(sections, null, 10, 5, 0, 0, new ShardSearchFailure[0], null);
@@ -326,6 +382,44 @@ protected <Request extends ActionRequest, Response extends ActionResponse> void
326382
}
327383
}
328384

385+
private class MyMockClientWithEmptyAggregation extends NoOpClient {
386+
MyMockClientWithEmptyAggregation(String testName) {
387+
super(testName);
388+
}
389+
390+
@SuppressWarnings("unchecked")
391+
@Override
392+
protected <Request extends ActionRequest, Response extends ActionResponse> void doExecute(
393+
ActionType<Response> action,
394+
Request request,
395+
ActionListener<Response> listener
396+
) {
397+
SearchResponse response = mock(SearchResponse.class);
398+
when(response.getAggregations()).thenReturn(new Aggregations(List.of()));
399+
listener.onResponse((Response) response);
400+
}
401+
}
402+
403+
private class MyMockClientWithCompositeAggregation extends NoOpClient {
404+
MyMockClientWithCompositeAggregation(String testName) {
405+
super(testName);
406+
}
407+
408+
@SuppressWarnings("unchecked")
409+
@Override
410+
protected <Request extends ActionRequest, Response extends ActionResponse> void doExecute(
411+
ActionType<Response> action,
412+
Request request,
413+
ActionListener<Response> listener
414+
) {
415+
SearchResponse response = mock(SearchResponse.class);
416+
CompositeAggregation compositeAggregation = mock(CompositeAggregation.class);
417+
when(response.getAggregations()).thenReturn(new Aggregations(List.of(compositeAggregation)));
418+
when(compositeAggregation.getBuckets()).thenReturn(new ArrayList<>());
419+
listener.onResponse((Response) response);
420+
}
421+
}
422+
329423
private PivotConfig getValidPivotConfig() throws IOException {
330424
return new PivotConfig(GroupConfigTests.randomGroupConfig(), getValidAggregationConfig(), null);
331425
}

0 commit comments

Comments
 (0)