Pārlūkot izejas kodu

HADOOP-17930. implement non-guava Precondition checkState (#3522)

Reviewed-by: Viraj Jasani <vjasani@apache.org>
Signed-off-by: Takanobu Asanuma <tasanuma@apache.org>
(cherry picked from commit c36f9402dc082a8903cf6e7fdca128658b11c59d)
Ahmed Hussein 3 gadi atpakaļ
vecāks
revīzija
2cdc6a245d

+ 92 - 0
hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Preconditions.java

@@ -46,6 +46,8 @@ public final class Preconditions {
       "The argument object is NULL";
   private static final String CHECK_ARGUMENT_EX_MESSAGE =
       "The argument expression is false";
+  private static final String CHECK_STATE_EX_MESSAGE =
+      "The state expression is false";
 
   private Preconditions() {
   }
@@ -240,6 +242,91 @@ public final class Preconditions {
     }
   }
 
+  /**
+   * Ensures the truth of an expression involving the state of the calling instance
+   * without involving any parameters to the calling method.
+   *
+   * @param expression a boolean expression
+   * @throws IllegalStateException if {@code expression} is false
+   */
+  public static void checkState(final boolean expression) {
+    if (!expression) {
+      throw new IllegalStateException();
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving the state of the calling instance
+   * without involving any parameters to the calling method.
+   *
+   * @param expression a boolean expression
+   * @param errorMessage the exception message to use if the check fails; will be converted to a
+   *     string using {@link String#valueOf(Object)}
+   * @throws IllegalStateException if {@code expression} is false
+   */
+  public static void checkState(final boolean expression, final Object errorMessage) {
+    if (!expression) {
+      throw new IllegalStateException(String.valueOf(errorMessage));
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving the state of the calling instance
+   * without involving any parameters to the calling method.
+   *
+   * <p>The message of the exception is {@code String.format(f, m)}.</p>
+   *
+   * @param expression a boolean expression
+   * @param errorMsg  the {@link String#format(String, Object...)}
+   *                 exception message if valid. Otherwise,
+   *                 the message is {@link #CHECK_STATE_EX_MESSAGE}
+   * @param errorMsgArgs the optional values for the formatted exception message.
+   * @throws IllegalStateException if {@code expression} is false
+   */
+  public static void checkState(
+      final boolean expression,
+      final String errorMsg,
+      Object... errorMsgArgs) {
+    if (!expression) {
+      String msg;
+      try {
+        msg = String.format(errorMsg, errorMsgArgs);
+      } catch (Exception e) {
+        LOG.debug("Error formatting message", e);
+        msg = CHECK_STATE_EX_MESSAGE;
+      }
+      throw new IllegalStateException(msg);
+    }
+  }
+
+  /**
+   * Preconditions that the expression involving one or more parameters to the calling method.
+   *
+   * <p>The message of the exception is {@code msgSupplier.get()}.</p>
+   *
+   * @param expression a boolean expression
+   * @param msgSupplier  the {@link Supplier#get()} set the
+   *                 exception message if valid. Otherwise,
+   *                 the message is {@link #CHECK_STATE_EX_MESSAGE}
+   * @throws IllegalStateException if {@code expression} is false
+   */
+  public static void checkState(
+      final boolean expression,
+      final Supplier<String> msgSupplier) {
+    if (!expression) {
+      String msg;
+      try {
+        // note that we can get NPE evaluating the message itself;
+        // but we do not want this to override the actual NPE.
+        msg = msgSupplier.get();
+      } catch (Exception e) {
+        LOG.debug("Error formatting message", e);
+        msg = CHECK_STATE_EX_MESSAGE;
+      }
+      throw new IllegalStateException(msg);
+    }
+  }
+
   /* @VisibleForTesting */
   static String getDefaultNullMSG() {
     return VALIDATE_IS_NOT_NULL_EX_MESSAGE;
@@ -249,4 +336,9 @@ public final class Preconditions {
   static String getDefaultCheckArgumentMSG() {
     return CHECK_ARGUMENT_EX_MESSAGE;
   }
+
+  /* @VisibleForTesting */
+  static String getDefaultCheckStateMSG() {
+    return CHECK_STATE_EX_MESSAGE;
+  }
 }

+ 100 - 0
hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestPreconditions.java

@@ -221,4 +221,104 @@ public class TestPreconditions {
         () -> Preconditions.checkArgument(false,
             () -> String.format(NULL_FORMATTER, NON_NULL_STRING)));
   }
+
+  @Test
+  public void testCheckStateWithSuccess() throws Exception {
+    // success
+    Preconditions.checkState(true);
+    // null supplier
+    Preconditions.checkState(true, null);
+    // null message
+    Preconditions.checkState(true, (String) null);
+    Preconditions.checkState(true, NON_NULL_STRING);
+    // null in string format
+    Preconditions.checkState(true, EXPECTED_ERROR_MSG_ARGS, null, null);
+    // illegalformat
+    Preconditions.checkState(true, EXPECTED_ERROR_MSG_ARGS, 1, 2);
+    // ill-formated string supplier
+    Preconditions.checkState(true, ()-> String.format("%d",
+        NON_INT_STRING));
+    // null pattern to string formatter
+    Preconditions.checkState(true, NULL_FORMATTER, null, 1);
+    // null arguments to string formatter
+    Preconditions.checkState(true, EXPECTED_ERROR_MSG_ARGS,
+        null, null);
+    // illegal format exception
+    Preconditions.checkState(true, "message %d %d",
+        NON_INT_STRING, 1);
+    // insufficient arguments
+    Preconditions.checkState(true, EXPECTED_ERROR_MSG_ARGS,
+        NON_INT_STRING);
+    // null format in string supplier
+    Preconditions.checkState(true,
+        () -> String.format(NULL_FORMATTER, NON_INT_STRING));
+  }
+
+  @Test
+  public void testCheckStateWithFailure() throws Exception {
+    // failure without message
+    LambdaTestUtils.intercept(IllegalStateException.class,
+        () -> Preconditions.checkState(false));
+    errorMessage = null;
+    // failure with Null message
+    LambdaTestUtils.intercept(IllegalStateException.class,
+        null,
+        () -> Preconditions.checkState(false, errorMessage));
+    // failure with message
+    errorMessage = EXPECTED_ERROR_MSG;
+    LambdaTestUtils.intercept(IllegalStateException.class,
+        errorMessage,
+        () -> Preconditions.checkState(false, errorMessage));
+
+    // failure with message format
+    errorMessage = EXPECTED_ERROR_MSG + " %s";
+    String arg = "IllegalStaExcep";
+    String expectedMSG = String.format(errorMessage, arg);
+    LambdaTestUtils.intercept(IllegalStateException.class,
+        expectedMSG,
+        () -> Preconditions.checkState(false, errorMessage, arg));
+
+    // failure with multiple arg message format
+    errorMessage = EXPECTED_ERROR_MSG_ARGS;
+    expectedMSG =
+        String.format(errorMessage, arg, 1);
+    LambdaTestUtils.intercept(IllegalStateException.class,
+        expectedMSG,
+        () -> Preconditions.checkState(false, errorMessage, arg, 1));
+
+    // ignore illegal format will be thrown if the case is not handled correctly
+    LambdaTestUtils.intercept(IllegalStateException.class,
+        Preconditions.getDefaultCheckStateMSG(),
+        () -> Preconditions.checkState(false,
+            errorMessage, 1, NON_INT_STRING));
+
+    // ignore illegal format will be thrown for insufficient Insufficient Args
+    LambdaTestUtils.intercept(IllegalStateException.class,
+        Preconditions.getDefaultCheckStateMSG(),
+        () -> Preconditions.checkState(false, errorMessage, NON_NULL_STRING));
+
+    // failure with Null supplier
+    final Supplier<String> nullSupplier = null;
+    LambdaTestUtils.intercept(IllegalStateException.class,
+        null,
+        () -> Preconditions.checkState(false, nullSupplier));
+
+    // ignore illegal format in supplier
+    LambdaTestUtils.intercept(IllegalStateException.class,
+        Preconditions.getDefaultCheckStateMSG(),
+        () -> Preconditions.checkState(false,
+            () -> String.format(errorMessage, 1, NON_INT_STRING)));
+
+    // ignore insufficient arguments in string Supplier
+    LambdaTestUtils.intercept(IllegalStateException.class,
+        Preconditions.getDefaultCheckStateMSG(),
+        () -> Preconditions.checkState(false,
+            () -> String.format(errorMessage, NON_NULL_STRING)));
+
+    // ignore null formatter
+    LambdaTestUtils.intercept(IllegalStateException.class,
+        Preconditions.getDefaultCheckStateMSG(),
+        () -> Preconditions.checkState(false,
+            () -> String.format(NULL_FORMATTER, NON_NULL_STRING)));
+  }
 }