Skip to content

Commit 1337405

Browse files
cpovirkGoogle Java Core Libraries
authored andcommitted
Use addSuppressed in AbstractExecutionThreadService, and otherwise update/clarify code pinned to "Java 7" / old versions of Android.
RELNOTES=n/a PiperOrigin-RevId: 686882751
1 parent 0e2fa3e commit 1337405

File tree

23 files changed

+131
-116
lines changed

23 files changed

+131
-116
lines changed

android/guava-testlib/src/com/google/common/testing/ForwardingWrapperTester.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ public <T> void testForwarding(
8484
Method[] methods = getMostConcreteMethods(interfaceType);
8585
AccessibleObject.setAccessible(methods, true);
8686
for (Method method : methods) {
87-
// Under java 8, interfaces can have default methods that aren't abstract.
87+
// Interfaces can have default methods that aren't abstract.
8888
// No need to verify them.
89-
// Can't check isDefault() for JDK 7 compatibility.
89+
// Can't check isDefault() for Android compatibility.
9090
if (!Modifier.isAbstract(method.getModifiers())) {
9191
continue;
9292
}

android/guava-testlib/test/com/google/common/collect/testing/OpenJdk6MapTests.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,7 @@
4040
*
4141
* @author Kevin Bourrillion
4242
*/
43-
/*
44-
* TODO(cpovirk): consider renaming this class in light of our now running it
45-
* under JDK7
46-
*/
43+
// TODO(cpovirk): consider renaming this class in light of our now running it under newer JDKs.
4744
public class OpenJdk6MapTests extends TestsForMapsInJavaUtil {
4845
public static Test suite() {
4946
return new OpenJdk6MapTests().allTests();

android/guava-tests/test/com/google/common/base/Utf8Test.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public class Utf8Test extends TestCase {
6060
ILL_FORMED_STRINGS = builder.build();
6161
}
6262

63+
// We can't use Character.isSurrogate(c) because of GWT.
64+
6365
public void testEncodedLength_validStrings() {
6466
assertEquals(0, Utf8.encodedLength(""));
6567
assertEquals(11, Utf8.encodedLength("Hello world"));

android/guava-tests/test/com/google/common/collect/ForwardingMapTest.java

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@
2929
import com.google.common.collect.testing.features.CollectionFeature;
3030
import com.google.common.collect.testing.features.CollectionSize;
3131
import com.google.common.collect.testing.features.MapFeature;
32-
import com.google.common.reflect.AbstractInvocationHandler;
3332
import com.google.common.reflect.Parameter;
34-
import com.google.common.reflect.Reflection;
3533
import com.google.common.reflect.TypeToken;
3634
import com.google.common.testing.ArbitraryInstances;
3735
import com.google.common.testing.EqualsTester;
@@ -44,6 +42,9 @@
4442
import java.util.Map;
4543
import java.util.Map.Entry;
4644
import java.util.Set;
45+
import java.util.function.Consumer;
46+
import java.util.function.IntFunction;
47+
import java.util.function.Predicate;
4748
import junit.framework.Test;
4849
import junit.framework.TestCase;
4950
import junit.framework.TestSuite;
@@ -330,38 +331,25 @@ protected Map<K, V> delegate() {
330331
};
331332
}
332333

333-
private static final ImmutableMap<String, String> JUF_METHODS =
334-
ImmutableMap.of(
335-
"java.util.function.Predicate", "test",
336-
"java.util.function.Consumer", "accept",
337-
"java.util.function.IntFunction", "apply");
338-
339334
private static @Nullable Object getDefaultValue(final TypeToken<?> type) {
340335
Class<?> rawType = type.getRawType();
341336
Object defaultValue = ArbitraryInstances.get(rawType);
342337
if (defaultValue != null) {
343338
return defaultValue;
344339
}
345340

346-
final String typeName = rawType.getCanonicalName();
347-
if (JUF_METHODS.containsKey(typeName)) {
348-
// Generally, methods that accept java.util.function.* instances
349-
// don't like to get null values. We generate them dynamically
350-
// using Proxy so that we can have Java 7 compliant code.
351-
return Reflection.newProxy(
352-
rawType,
353-
new AbstractInvocationHandler() {
354-
@Override
355-
public Object handleInvocation(Object proxy, Method method, Object[] args) {
356-
// Crude, but acceptable until we can use Java 8. Other
357-
// methods have default implementations, and it is hard to
358-
// distinguish.
359-
if (method.getName().equals(JUF_METHODS.get(typeName))) {
360-
return getDefaultValue(type.method(method).getReturnType());
361-
}
362-
throw new IllegalStateException("Unexpected " + method + " invoked on " + proxy);
363-
}
364-
});
341+
// TODO(cpovirk): Support these types in ArbitraryInstances itself?
342+
if (rawType.equals(Predicate.class)) {
343+
return (Predicate<Object>) v -> (boolean) getDefaultValue(TypeToken.of(boolean.class));
344+
} else if (rawType.equals(IntFunction.class)) {
345+
try {
346+
Method method = IntFunction.class.getMethod("apply", int.class);
347+
return (IntFunction<Object>) v -> getDefaultValue(type.method(method).getReturnType());
348+
} catch (NoSuchMethodException e) {
349+
throw newLinkageError(e);
350+
}
351+
} else if (rawType.equals(Consumer.class)) {
352+
return (Consumer<Object>) v -> {};
365353
} else {
366354
return null;
367355
}
@@ -393,4 +381,8 @@ private static <T> void callAllPublicMethods(TypeToken<T> type, T object)
393381
}
394382
}
395383
}
384+
385+
private static LinkageError newLinkageError(Throwable cause) {
386+
return new LinkageError(cause.toString(), cause);
387+
}
396388
}

android/guava-tests/test/com/google/common/reflect/InvokableTest.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.lang.annotation.RetentionPolicy;
2929
import java.lang.reflect.AccessibleObject;
3030
import java.lang.reflect.Constructor;
31+
import java.lang.reflect.GenericDeclaration;
3132
import java.lang.reflect.Method;
3233
import java.lang.reflect.Modifier;
3334
import java.lang.reflect.ParameterizedType;
@@ -53,15 +54,9 @@ public void testApiCompatibleWithAccessibleObject() {
5354
ImmutableSet<String> accessibleObjectMethods =
5455
publicMethodSignatures(AccessibleObject.class, ImmutableSet.of("canAccess"));
5556
assertThat(invokableMethods).containsAtLeastElementsIn(accessibleObjectMethods);
56-
Class<?> genericDeclaration;
57-
try {
58-
genericDeclaration = Class.forName("java.lang.reflect.GenericDeclaration");
59-
ImmutableSet<String> genericDeclarationMethods =
60-
publicMethodSignatures(genericDeclaration, ImmutableSet.<String>of());
61-
assertThat(invokableMethods).containsAtLeastElementsIn(genericDeclarationMethods);
62-
} catch (ClassNotFoundException e) {
63-
// OK: we're on Java 7, which doesn't have this class
64-
}
57+
ImmutableSet<String> genericDeclarationMethods =
58+
publicMethodSignatures(GenericDeclaration.class, ImmutableSet.<String>of());
59+
assertThat(invokableMethods).containsAtLeastElementsIn(genericDeclarationMethods);
6560
}
6661

6762
private static ImmutableSet<String> publicMethodSignatures(

android/guava-tests/test/com/google/common/util/concurrent/AbstractExecutionThreadServiceTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ public void testServiceThrowOnRunAndThenAgainOnShutDown() throws Exception {
231231
assertThat(expected).hasCauseThat().hasMessageThat().isEqualTo("kaboom!");
232232
assertTrue(service.shutDownCalled);
233233
assertEquals(Service.State.FAILED, service.state());
234+
assertThat(expected.getCause().getSuppressed()[0]).hasMessageThat().isEqualTo("double kaboom!");
234235
}
235236

236237
private class ThrowOnRunService extends AbstractExecutionThreadService {

android/guava-tests/test/com/google/common/util/concurrent/ServiceManagerTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import com.google.common.collect.ImmutableMap;
2828
import com.google.common.collect.ImmutableSet;
29+
import com.google.common.collect.Iterables;
2930
import com.google.common.collect.Lists;
3031
import com.google.common.collect.Sets;
3132
import com.google.common.testing.NullPointerTester;
@@ -417,6 +418,36 @@ public String format(LogRecord record) {
417418
}
418419
}
419420

421+
public void testStartupFailureOutput() {
422+
Logger logger = Logger.getLogger(ServiceManager.class.getName());
423+
logger.setLevel(Level.SEVERE);
424+
TestLogHandler logHandler = new TestLogHandler();
425+
logger.addHandler(logHandler);
426+
ServiceManager manager =
427+
new ServiceManager(Arrays.<Service>asList(new FailRunService(), new FailStartService()));
428+
// Due to the implementation of the two services we know that both are now failed. So the
429+
// following awaitHealthy call is just to get the exception.
430+
manager.startAsync();
431+
assertThat(manager.servicesByState().get(State.FAILED)).hasSize(2);
432+
IllegalStateException e =
433+
assertThrows(IllegalStateException.class, () -> manager.awaitHealthy());
434+
assertThat(e.getMessage())
435+
.contains(
436+
"Expected to be healthy after starting. The following services are not " + "running:");
437+
438+
Throwable[] suppressed = e.getSuppressed();
439+
assertThat(suppressed).hasLength(2);
440+
assertThat(suppressed[0]).hasCauseThat().isInstanceOf(IllegalStateException.class);
441+
assertThat(suppressed[0]).hasCauseThat().hasMessageThat().isEqualTo("run failure");
442+
443+
assertThat(suppressed[1]).hasCauseThat().isInstanceOf(IllegalStateException.class);
444+
assertThat(suppressed[1]).hasCauseThat().hasMessageThat().isEqualTo("start failure");
445+
LogRecord record = Iterables.getOnlyElement(logHandler.getStoredLogRecords());
446+
// We log failures that occur after startup
447+
assertThat(record.getMessage())
448+
.contains("Service FailRunService [FAILED] has failed in the RUNNING state");
449+
}
450+
420451
/**
421452
* Tests that a ServiceManager can be fully shut down if one of its failure listeners is slow or
422453
* even permanently blocked.

android/guava/src/com/google/common/base/CharMatcher.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,8 @@ protected CharMatcher() {}
368368
// Non-static factories
369369

370370
/** Returns a matcher that matches any character not matched by this matcher. */
371-
// @Override under Java 8 but not under Java 7
371+
// This is not an override in java7, where Guava's Predicate does not extend the JDK's Predicate.
372+
@SuppressWarnings("MissingOverride")
372373
public CharMatcher negate() {
373374
return new Negated(this);
374375
}

android/guava/src/com/google/common/base/Utf8.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ private static int encodedLengthGeneral(CharSequence sequence, int start) {
8585
utf8Length += (0x7f - c) >>> 31; // branch free!
8686
} else {
8787
utf8Length += 2;
88-
// jdk7+: if (Character.isSurrogate(c)) {
88+
// We can't use Character.isSurrogate(c) here and below because of GWT.
8989
if (MIN_SURROGATE <= c && c <= MAX_SURROGATE) {
9090
// Check that we have a well-formed surrogate pair.
9191
if (Character.codePointAt(sequence, i) == c) {

android/guava/src/com/google/common/collect/ImmutableMap.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ public boolean containsValue(@CheckForNull Object value) {
893893
* Note, however, that Java 8+ users can call this method with any version and flavor of
894894
* Guava.
895895
*/
896-
// @Override under Java 8 / API Level 24
896+
@Override
897897
@CheckForNull
898898
public final V getOrDefault(@CheckForNull Object key, @CheckForNull V defaultValue) {
899899
/*

0 commit comments

Comments
 (0)