android13/external/guava/guava-tests/test/com/google/common/base/PreconditionsTest.java

588 lines
19 KiB
Java

/*
* Copyright (C) 2006 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.base;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.testing.ArbitraryInstances;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
/**
* Unit test for {@link Preconditions}.
*
* @author Kevin Bourrillion
* @author Jared Levy
*/
@GwtCompatible(emulated = true)
public class PreconditionsTest extends TestCase {
public void testCheckArgument_simple_success() {
Preconditions.checkArgument(true);
}
public void testCheckArgument_simple_failure() {
try {
Preconditions.checkArgument(false);
fail("no exception thrown");
} catch (IllegalArgumentException expected) {
}
}
public void testCheckArgument_simpleMessage_success() {
Preconditions.checkArgument(true, IGNORE_ME);
}
public void testCheckArgument_simpleMessage_failure() {
try {
Preconditions.checkArgument(false, new Message());
fail("no exception thrown");
} catch (IllegalArgumentException expected) {
verifySimpleMessage(expected);
}
}
public void testCheckArgument_nullMessage_failure() {
try {
Preconditions.checkArgument(false, null);
fail("no exception thrown");
} catch (IllegalArgumentException expected) {
assertThat(expected).hasMessageThat().isEqualTo("null");
}
}
public void testCheckArgument_nullMessageWithArgs_failure() {
try {
Preconditions.checkArgument(false, null, "b", "d");
fail("no exception thrown");
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("null [b, d]");
}
}
public void testCheckArgument_nullArgs_failure() {
try {
Preconditions.checkArgument(false, "A %s C %s E", null, null);
fail("no exception thrown");
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("A null C null E");
}
}
public void testCheckArgument_notEnoughArgs_failure() {
try {
Preconditions.checkArgument(false, "A %s C %s E", "b");
fail("no exception thrown");
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("A b C %s E");
}
}
public void testCheckArgument_tooManyArgs_failure() {
try {
Preconditions.checkArgument(false, "A %s C %s E", "b", "d", "f");
fail("no exception thrown");
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("A b C d E [f]");
}
}
public void testCheckArgument_singleNullArg_failure() {
try {
Preconditions.checkArgument(false, "A %s C", (Object) null);
fail("no exception thrown");
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("A null C");
}
}
public void testCheckArgument_singleNullArray_failure() {
try {
Preconditions.checkArgument(false, "A %s C", (Object[]) null);
fail("no exception thrown");
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("A (Object[])null C");
}
}
public void testCheckArgument_complexMessage_success() {
Preconditions.checkArgument(true, "%s", IGNORE_ME);
}
public void testCheckArgument_complexMessage_failure() {
try {
Preconditions.checkArgument(false, FORMAT, 5);
fail("no exception thrown");
} catch (IllegalArgumentException expected) {
verifyComplexMessage(expected);
}
}
public void testCheckState_simple_success() {
Preconditions.checkState(true);
}
public void testCheckState_simple_failure() {
try {
Preconditions.checkState(false);
fail("no exception thrown");
} catch (IllegalStateException expected) {
}
}
public void testCheckState_simpleMessage_success() {
Preconditions.checkState(true, IGNORE_ME);
}
public void testCheckState_simpleMessage_failure() {
try {
Preconditions.checkState(false, new Message());
fail("no exception thrown");
} catch (IllegalStateException expected) {
verifySimpleMessage(expected);
}
}
public void testCheckState_nullMessage_failure() {
try {
Preconditions.checkState(false, null);
fail("no exception thrown");
} catch (IllegalStateException expected) {
assertThat(expected).hasMessageThat().isEqualTo("null");
}
}
public void testCheckState_complexMessage_success() {
Preconditions.checkState(true, "%s", IGNORE_ME);
}
public void testCheckState_complexMessage_failure() {
try {
Preconditions.checkState(false, FORMAT, 5);
fail("no exception thrown");
} catch (IllegalStateException expected) {
verifyComplexMessage(expected);
}
}
private static final String NON_NULL_STRING = "foo";
public void testCheckNotNull_simple_success() {
String result = Preconditions.checkNotNull(NON_NULL_STRING);
assertSame(NON_NULL_STRING, result);
}
public void testCheckNotNull_simple_failure() {
try {
Preconditions.checkNotNull(null);
fail("no exception thrown");
} catch (NullPointerException expected) {
}
}
public void testCheckNotNull_simpleMessage_success() {
String result = Preconditions.checkNotNull(NON_NULL_STRING, IGNORE_ME);
assertSame(NON_NULL_STRING, result);
}
public void testCheckNotNull_simpleMessage_failure() {
try {
Preconditions.checkNotNull(null, new Message());
fail("no exception thrown");
} catch (NullPointerException expected) {
verifySimpleMessage(expected);
}
}
public void testCheckNotNull_complexMessage_success() {
String result = Preconditions.checkNotNull(NON_NULL_STRING, "%s", IGNORE_ME);
assertSame(NON_NULL_STRING, result);
}
public void testCheckNotNull_complexMessage_failure() {
try {
Preconditions.checkNotNull(null, FORMAT, 5);
fail("no exception thrown");
} catch (NullPointerException expected) {
verifyComplexMessage(expected);
}
}
public void testCheckElementIndex_ok() {
assertEquals(0, Preconditions.checkElementIndex(0, 1));
assertEquals(0, Preconditions.checkElementIndex(0, 2));
assertEquals(1, Preconditions.checkElementIndex(1, 2));
}
public void testCheckElementIndex_badSize() {
try {
Preconditions.checkElementIndex(1, -1);
fail();
} catch (IllegalArgumentException expected) {
// don't care what the message text is, as this is an invalid usage of
// the Preconditions class, unlike all the other exceptions it throws
}
}
public void testCheckElementIndex_negative() {
try {
Preconditions.checkElementIndex(-1, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
assertThat(expected).hasMessageThat().isEqualTo("index (-1) must not be negative");
}
}
public void testCheckElementIndex_tooHigh() {
try {
Preconditions.checkElementIndex(1, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
assertThat(expected).hasMessageThat().isEqualTo("index (1) must be less than size (1)");
}
}
public void testCheckElementIndex_withDesc_negative() {
try {
Preconditions.checkElementIndex(-1, 1, "foo");
fail();
} catch (IndexOutOfBoundsException expected) {
assertThat(expected).hasMessageThat().isEqualTo("foo (-1) must not be negative");
}
}
public void testCheckElementIndex_withDesc_tooHigh() {
try {
Preconditions.checkElementIndex(1, 1, "foo");
fail();
} catch (IndexOutOfBoundsException expected) {
assertThat(expected).hasMessageThat().isEqualTo("foo (1) must be less than size (1)");
}
}
public void testCheckPositionIndex_ok() {
assertEquals(0, Preconditions.checkPositionIndex(0, 0));
assertEquals(0, Preconditions.checkPositionIndex(0, 1));
assertEquals(1, Preconditions.checkPositionIndex(1, 1));
}
public void testCheckPositionIndex_badSize() {
try {
Preconditions.checkPositionIndex(1, -1);
fail();
} catch (IllegalArgumentException expected) {
// don't care what the message text is, as this is an invalid usage of
// the Preconditions class, unlike all the other exceptions it throws
}
}
public void testCheckPositionIndex_negative() {
try {
Preconditions.checkPositionIndex(-1, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
assertThat(expected).hasMessageThat().isEqualTo("index (-1) must not be negative");
}
}
public void testCheckPositionIndex_tooHigh() {
try {
Preconditions.checkPositionIndex(2, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
assertThat(expected)
.hasMessageThat()
.isEqualTo("index (2) must not be greater than size (1)");
}
}
public void testCheckPositionIndex_withDesc_negative() {
try {
Preconditions.checkPositionIndex(-1, 1, "foo");
fail();
} catch (IndexOutOfBoundsException expected) {
assertThat(expected).hasMessageThat().isEqualTo("foo (-1) must not be negative");
}
}
public void testCheckPositionIndex_withDesc_tooHigh() {
try {
Preconditions.checkPositionIndex(2, 1, "foo");
fail();
} catch (IndexOutOfBoundsException expected) {
assertThat(expected).hasMessageThat().isEqualTo("foo (2) must not be greater than size (1)");
}
}
public void testCheckPositionIndexes_ok() {
Preconditions.checkPositionIndexes(0, 0, 0);
Preconditions.checkPositionIndexes(0, 0, 1);
Preconditions.checkPositionIndexes(0, 1, 1);
Preconditions.checkPositionIndexes(1, 1, 1);
}
public void testCheckPositionIndexes_badSize() {
try {
Preconditions.checkPositionIndexes(1, 1, -1);
fail();
} catch (IllegalArgumentException expected) {
}
}
public void testCheckPositionIndex_startNegative() {
try {
Preconditions.checkPositionIndexes(-1, 1, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
assertThat(expected).hasMessageThat().isEqualTo("start index (-1) must not be negative");
}
}
public void testCheckPositionIndexes_endTooHigh() {
try {
Preconditions.checkPositionIndexes(0, 2, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
assertThat(expected)
.hasMessageThat()
.isEqualTo("end index (2) must not be greater than size (1)");
}
}
public void testCheckPositionIndexes_reversed() {
try {
Preconditions.checkPositionIndexes(1, 0, 1);
fail();
} catch (IndexOutOfBoundsException expected) {
assertThat(expected)
.hasMessageThat()
.isEqualTo("end index (0) must not be less than start index (1)");
}
}
@GwtIncompatible("Reflection")
public void testAllOverloads_checkArgument() throws Exception {
for (ImmutableList<Class<?>> sig : allSignatures(boolean.class)) {
Method checkArgumentMethod =
Preconditions.class.getMethod("checkArgument", sig.toArray(new Class<?>[] {}));
checkArgumentMethod.invoke(null /* static method */, getParametersForSignature(true, sig));
Object[] failingParams = getParametersForSignature(false, sig);
try {
checkArgumentMethod.invoke(null /* static method */, failingParams);
fail();
} catch (InvocationTargetException ite) {
assertFailureCause(ite.getCause(), IllegalArgumentException.class, failingParams);
}
}
}
@GwtIncompatible("Reflection")
public void testAllOverloads_checkState() throws Exception {
for (ImmutableList<Class<?>> sig : allSignatures(boolean.class)) {
Method checkArgumentMethod =
Preconditions.class.getMethod("checkState", sig.toArray(new Class<?>[] {}));
checkArgumentMethod.invoke(null /* static method */, getParametersForSignature(true, sig));
Object[] failingParams = getParametersForSignature(false, sig);
try {
checkArgumentMethod.invoke(null /* static method */, failingParams);
fail();
} catch (InvocationTargetException ite) {
assertFailureCause(ite.getCause(), IllegalStateException.class, failingParams);
}
}
}
@GwtIncompatible("Reflection")
public void testAllOverloads_checkNotNull() throws Exception {
for (ImmutableList<Class<?>> sig : allSignatures(Object.class)) {
Method checkArgumentMethod =
Preconditions.class.getMethod("checkNotNull", sig.toArray(new Class<?>[] {}));
checkArgumentMethod.invoke(
null /* static method */, getParametersForSignature(new Object(), sig));
Object[] failingParams = getParametersForSignature(null, sig);
try {
checkArgumentMethod.invoke(null /* static method */, failingParams);
fail();
} catch (InvocationTargetException ite) {
assertFailureCause(ite.getCause(), NullPointerException.class, failingParams);
}
}
}
/**
* Asserts that the given throwable has the given class and then asserts on the message as using
* the full set of method parameters.
*/
private void assertFailureCause(
Throwable throwable, Class<? extends Throwable> clazz, Object[] params) {
assertThat(throwable).isInstanceOf(clazz);
if (params.length == 1) {
assertThat(throwable).hasMessageThat().isNull();
} else if (params.length == 2) {
assertThat(throwable).hasMessageThat().isEmpty();
} else {
assertThat(throwable)
.hasMessageThat()
.isEqualTo(Strings.lenientFormat("", Arrays.copyOfRange(params, 2, params.length)));
}
}
/**
* Returns an array containing parameters for invoking a checkArgument, checkNotNull or checkState
* method reflectively
*
* @param firstParam The first parameter
* @param sig The method signature
*/
@GwtIncompatible("ArbitraryInstances")
private Object[] getParametersForSignature(Object firstParam, ImmutableList<Class<?>> sig) {
Object[] params = new Object[sig.size()];
params[0] = firstParam;
if (params.length > 1) {
params[1] = "";
if (params.length > 2) {
// fill in the rest of the array with arbitrary instances
for (int i = 2; i < params.length; i++) {
params[i] = ArbitraryInstances.get(sig.get(i));
}
}
}
return params;
}
private static final ImmutableList<Class<?>> possibleParamTypes =
ImmutableList.of(char.class, int.class, long.class, Object.class);
/**
* Returns a list of parameters for invoking an overload of checkState, checkArgument or
* checkNotNull
*
* @param predicateType The first parameter to the method (boolean or Object)
*/
private static ImmutableList<ImmutableList<Class<?>>> allSignatures(Class<?> predicateType) {
ImmutableSet.Builder<ImmutableList<Class<?>>> allOverloads = ImmutableSet.builder();
// The first two are for the overloads that don't take formatting args, e.g.
// checkArgument(boolean) and checkArgument(boolean, Object)
allOverloads.add(ImmutableList.<Class<?>>of(predicateType));
allOverloads.add(ImmutableList.<Class<?>>of(predicateType, Object.class));
List<List<Class<?>>> typesLists = new ArrayList<>();
for (int i = 0; i < 2; i++) {
typesLists.add(possibleParamTypes);
for (List<Class<?>> curr : Lists.cartesianProduct(typesLists)) {
allOverloads.add(
ImmutableList.<Class<?>>builder()
.add(predicateType)
.add(String.class) // the format string
.addAll(curr)
.build());
}
}
return allOverloads.build().asList();
}
// 'test' to demonstrate some potentially ambiguous overloads. This 'test' is kind of strange,
// but essentially each line will be a call to a Preconditions method that, but for a documented
// change would be a compiler error.
// See http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2 for the spec on
// how javac selects overloads
@SuppressWarnings("null")
public void overloadSelection() {
Boolean boxedBoolean = null;
boolean aBoolean = true;
Long boxedLong = null;
int anInt = 1;
// With a boxed predicate, no overloads can be selected in phase 1
// ambiguous without the call to .booleanValue to unbox the Boolean
Preconditions.checkState(boxedBoolean.booleanValue(), "", 1);
// ambiguous without the cast to Object because the boxed predicate prevents any overload from
// being selected in phase 1
Preconditions.checkState(boxedBoolean, "", (Object) boxedLong);
// ternaries introduce their own problems. because of the ternary (which requires a boxing
// operation) no overload can be selected in phase 1. and in phase 2 it is ambiguous since it
// matches with the second parameter being boxed and without it being boxed. The cast to Object
// avoids this.
Preconditions.checkState(aBoolean, "", aBoolean ? "" : anInt, (Object) anInt);
// ambiguous without the .booleanValue() call since the boxing forces us into phase 2 resolution
short s = 2;
Preconditions.checkState(boxedBoolean.booleanValue(), "", s);
}
@GwtIncompatible // NullPointerTester
public void testNullPointers() {
/*
* Don't bother testing: Preconditions defines a bunch of methods that accept a template (or
* even entire message) that simultaneously:
*
* - _shouldn't_ be null, so we don't annotate it with @Nullable
*
* - _can_ be null without causing a runtime failure (because we don't want the interesting
* details of precondition failure to be hidden by an exception we throw about an unexpectedly
* null _failure message_)
*
* That combination upsets NullPointerTester, which wants any call that passes null for a
* non-@Nullable parameter to trigger a NullPointerException.
*
* (We still define this empty method to keep PackageSanityTests from generating its own
* automated nullness tests, which would fail.)
*/
}
private static final Object IGNORE_ME =
new Object() {
@Override
public String toString() {
throw new AssertionFailedError();
}
};
private static class Message {
boolean invoked;
@Override
public String toString() {
assertFalse(invoked);
invoked = true;
return "A message";
}
}
private static final String FORMAT = "I ate %s pies.";
private static void verifySimpleMessage(Exception e) {
assertThat(e).hasMessageThat().isEqualTo("A message");
}
private static void verifyComplexMessage(Exception e) {
assertThat(e).hasMessageThat().isEqualTo("I ate 5 pies.");
}
}