Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
}
Expand Down Expand Up @@ -240,6 +242,91 @@ public static void checkArgument(
}
}

/**
* 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;
Expand All @@ -249,4 +336,9 @@ static String getDefaultNullMSG() {
static String getDefaultCheckArgumentMSG() {
return CHECK_ARGUMENT_EX_MESSAGE;
}

/* @VisibleForTesting */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, I think we can catchup on this later based on which PR goes first.

static String getDefaultCheckStateMSG() {
return CHECK_STATE_EX_MESSAGE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,4 +221,104 @@ public void testCheckArgumentWithFailure() throws Exception {
() -> 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)));
}
}