ElasticsearchUncaughtExceptionHandlerTests.java 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * Licensed to Elasticsearch under one or more contributor
  3. * license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright
  5. * ownership. Elasticsearch licenses this file to you under
  6. * the Apache License, Version 2.0 (the "License"); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. package org.elasticsearch.bootstrap;
  20. import org.elasticsearch.test.ESTestCase;
  21. import org.junit.Before;
  22. import java.io.IOError;
  23. import java.io.IOException;
  24. import java.io.UncheckedIOException;
  25. import java.util.Collections;
  26. import java.util.HashMap;
  27. import java.util.Map;
  28. import java.util.concurrent.atomic.AtomicBoolean;
  29. import java.util.concurrent.atomic.AtomicInteger;
  30. import java.util.concurrent.atomic.AtomicReference;
  31. import static org.hamcrest.CoreMatchers.equalTo;
  32. public class ElasticsearchUncaughtExceptionHandlerTests extends ESTestCase {
  33. private Map<Class<? extends Error>, Integer> expectedStatus;
  34. @Before
  35. public void setUp() throws Exception {
  36. super.setUp();
  37. Map<Class<? extends Error>, Integer> expectedStatus = new HashMap<>();
  38. expectedStatus.put(InternalError.class, 128);
  39. expectedStatus.put(OutOfMemoryError.class, 127);
  40. expectedStatus.put(StackOverflowError.class, 126);
  41. expectedStatus.put(UnknownError.class, 125);
  42. expectedStatus.put(IOError.class, 124);
  43. this.expectedStatus = Collections.unmodifiableMap(expectedStatus);
  44. }
  45. public void testUncaughtError() throws InterruptedException {
  46. final Error error = randomFrom(
  47. new InternalError(),
  48. new OutOfMemoryError(),
  49. new StackOverflowError(),
  50. new UnknownError(),
  51. new IOError(new IOException("fatal")),
  52. new Error() {});
  53. final Thread thread = new Thread(() -> { throw error; });
  54. final String name = randomAlphaOfLength(10);
  55. thread.setName(name);
  56. final AtomicBoolean halt = new AtomicBoolean();
  57. final AtomicInteger observedStatus = new AtomicInteger();
  58. final AtomicReference<String> threadNameReference = new AtomicReference<>();
  59. final AtomicReference<Throwable> throwableReference = new AtomicReference<>();
  60. thread.setUncaughtExceptionHandler(new ElasticsearchUncaughtExceptionHandler() {
  61. @Override
  62. void halt(int status) {
  63. halt.set(true);
  64. observedStatus.set(status);
  65. }
  66. @Override
  67. void onFatalUncaught(String threadName, Throwable t) {
  68. threadNameReference.set(threadName);
  69. throwableReference.set(t);
  70. }
  71. @Override
  72. void onNonFatalUncaught(String threadName, Throwable t) {
  73. fail();
  74. }
  75. });
  76. thread.start();
  77. thread.join();
  78. assertTrue(halt.get());
  79. final int status;
  80. if (expectedStatus.containsKey(error.getClass())) {
  81. status = expectedStatus.get(error.getClass());
  82. } else {
  83. status = 1;
  84. }
  85. assertThat(observedStatus.get(), equalTo(status));
  86. assertThat(threadNameReference.get(), equalTo(name));
  87. assertThat(throwableReference.get(), equalTo(error));
  88. }
  89. public void testUncaughtException() throws InterruptedException {
  90. final RuntimeException e = new RuntimeException("boom");
  91. final Thread thread = new Thread(() -> { throw e; });
  92. final String name = randomAlphaOfLength(10);
  93. thread.setName(name);
  94. final AtomicReference<String> threadNameReference = new AtomicReference<>();
  95. final AtomicReference<Throwable> throwableReference = new AtomicReference<>();
  96. thread.setUncaughtExceptionHandler(new ElasticsearchUncaughtExceptionHandler() {
  97. @Override
  98. void halt(int status) {
  99. fail();
  100. }
  101. @Override
  102. void onFatalUncaught(String threadName, Throwable t) {
  103. fail();
  104. }
  105. @Override
  106. void onNonFatalUncaught(String threadName, Throwable t) {
  107. threadNameReference.set(threadName);
  108. throwableReference.set(t);
  109. }
  110. });
  111. thread.start();
  112. thread.join();
  113. assertThat(threadNameReference.get(), equalTo(name));
  114. assertThat(throwableReference.get(), equalTo(e));
  115. }
  116. public void testIsFatalCause() {
  117. assertFatal(new OutOfMemoryError());
  118. assertFatal(new StackOverflowError());
  119. assertFatal(new InternalError());
  120. assertFatal(new UnknownError());
  121. assertFatal(new IOError(new IOException()));
  122. assertNonFatal(new RuntimeException());
  123. assertNonFatal(new UncheckedIOException(new IOException()));
  124. }
  125. private void assertFatal(Throwable cause) {
  126. assertTrue(ElasticsearchUncaughtExceptionHandler.isFatalUncaught(cause));
  127. }
  128. private void assertNonFatal(Throwable cause) {
  129. assertFalse(ElasticsearchUncaughtExceptionHandler.isFatalUncaught(cause));
  130. }
  131. }