Skip to content

Commit a8a4a7b

Browse files
authored
Fix testInvalidJSON (#118398)
* Fix testInvalidJSON * CURSE YOU SPOTLESS
1 parent 5572777 commit a8a4a7b

File tree

2 files changed

+31
-41
lines changed

2 files changed

+31
-41
lines changed

muted-tests.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,6 @@ tests:
123123
- class: org.elasticsearch.xpack.downsample.ILMDownsampleDisruptionIT
124124
method: testILMDownsampleRollingRestart
125125
issue: https://github.com/elastic/elasticsearch/issues/114233
126-
- class: org.elasticsearch.reservedstate.service.FileSettingsServiceTests
127-
method: testInvalidJSON
128-
issue: https://github.com/elastic/elasticsearch/issues/116521
129126
- class: org.elasticsearch.reservedstate.service.RepositoriesFileSettingsIT
130127
method: testSettingsApplied
131128
issue: https://github.com/elastic/elasticsearch/issues/116694

server/src/test/java/org/elasticsearch/reservedstate/service/FileSettingsServiceTests.java

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,10 @@
7474
import static org.hamcrest.Matchers.hasEntry;
7575
import static org.mockito.ArgumentMatchers.any;
7676
import static org.mockito.ArgumentMatchers.argThat;
77+
import static org.mockito.ArgumentMatchers.contains;
7778
import static org.mockito.ArgumentMatchers.eq;
7879
import static org.mockito.Mockito.doAnswer;
80+
import static org.mockito.Mockito.doNothing;
7981
import static org.mockito.Mockito.mock;
8082
import static org.mockito.Mockito.spy;
8183
import static org.mockito.Mockito.times;
@@ -288,63 +290,54 @@ public void testProcessFileChanges() throws Exception {
288290
verifyNoMoreInteractions(healthIndicatorService);
289291
}
290292

291-
@SuppressWarnings("unchecked")
292293
public void testInvalidJSON() throws Exception {
293-
doAnswer((Answer<Void>) invocation -> {
294-
invocation.getArgument(1, XContentParser.class).map(); // Throw if JSON is invalid
295-
((Consumer<Exception>) invocation.getArgument(3)).accept(null);
296-
return null;
297-
}).when(controller).process(any(), any(XContentParser.class), any(), any());
298-
299-
CyclicBarrier fileChangeBarrier = new CyclicBarrier(2);
300-
fileSettingsService.addFileChangedListener(() -> awaitOrBust(fileChangeBarrier));
294+
// Chop off the functionality so we don't run too much of the actual cluster logic that we're not testing
295+
doNothing().when(controller).updateErrorState(any());
296+
doAnswer(
297+
(Answer<Void>) invocation -> { throw new AssertionError("Parse error should happen before this process method is called"); }
298+
).when(controller).process(any(), any(ReservedStateChunk.class), any(), any());
301299

300+
// Don't really care about the initial state
302301
Files.createDirectories(fileSettingsService.watchedFileDir());
303-
// contents of the JSON don't matter, we just need a file to exist
304-
writeTestFile(fileSettingsService.watchedFile(), "{}");
302+
doNothing().when(fileSettingsService).processInitialFileMissing();
303+
fileSettingsService.start();
304+
fileSettingsService.clusterChanged(new ClusterChangedEvent("test", clusterService.state(), ClusterState.EMPTY_STATE));
305305

306+
// Now break the JSON and wait
307+
CyclicBarrier fileChangeBarrier = new CyclicBarrier(2);
306308
doAnswer((Answer<?>) invocation -> {
307-
boolean returnedNormally = false;
308309
try {
309-
var result = invocation.callRealMethod();
310-
returnedNormally = true;
311-
return result;
312-
} catch (XContentParseException e) {
313-
// We're expecting a parse error. processFileChanges specifies that this is supposed to throw ExecutionException.
314-
throw new ExecutionException(e);
315-
} catch (Throwable e) {
316-
throw new AssertionError("Unexpected exception", e);
310+
return invocation.callRealMethod();
317311
} finally {
318-
if (returnedNormally == false) {
319-
// Because of the exception, listeners aren't notified, so we need to activate the barrier ourselves
320-
awaitOrBust(fileChangeBarrier);
321-
}
312+
awaitOrBust(fileChangeBarrier);
322313
}
323314
}).when(fileSettingsService).processFileChanges();
324-
325-
// Establish the initial valid JSON
326-
fileSettingsService.start();
327-
fileSettingsService.clusterChanged(new ClusterChangedEvent("test", clusterService.state(), ClusterState.EMPTY_STATE));
328-
awaitOrBust(fileChangeBarrier);
329-
330-
// Now break the JSON
331315
writeTestFile(fileSettingsService.watchedFile(), "test_invalid_JSON");
332316
awaitOrBust(fileChangeBarrier);
333317

334-
verify(fileSettingsService, times(1)).processFileOnServiceStart(); // The initial state
335-
verify(fileSettingsService, times(1)).processFileChanges(); // The changed state
336318
verify(fileSettingsService, times(1)).onProcessFileChangesException(
337-
argThat(e -> e instanceof ExecutionException && e.getCause() instanceof XContentParseException)
319+
argThat(e -> unwrapException(e) instanceof XContentParseException)
338320
);
339321

340322
// Note: the name "processFileOnServiceStart" is a bit misleading because it is not
341323
// referring to fileSettingsService.start(). Rather, it is referring to the initialization
342324
// of the watcher thread itself, which occurs asynchronously when clusterChanged is first called.
343325

344-
verify(healthIndicatorService, times(2)).changeOccurred();
345-
verify(healthIndicatorService, times(1)).successOccurred();
346-
verify(healthIndicatorService, times(1)).failureOccurred(argThat(s -> s.startsWith(IllegalArgumentException.class.getName())));
347-
verifyNoMoreInteractions(healthIndicatorService);
326+
verify(healthIndicatorService).failureOccurred(contains(XContentParseException.class.getName()));
327+
}
328+
329+
/**
330+
* Looks for the ultimate cause of {@code e} by stripping off layers of bookkeeping exception wrappers.
331+
*/
332+
private Throwable unwrapException(Throwable e) {
333+
while (e != null) {
334+
if (e instanceof ExecutionException || e instanceof IllegalStateException) {
335+
e = e.getCause();
336+
} else {
337+
break;
338+
}
339+
}
340+
return e;
348341
}
349342

350343
private static void awaitOrBust(CyclicBarrier barrier) {

0 commit comments

Comments
 (0)