Skip to content

Commit 6ace8bc

Browse files
cpovirkGoogle Java Core Libraries
authored and
Google Java Core Libraries
committed
Expose more Java 8 APIs to Android users.
While there, remove a workaround for #1330: As discussed in cl/152418428, the problem was fixed for Java 8, and even Android has [a working implementation](https://cs.android.com/android/platform/superproject/+/android-5.0.0_r1.0.1:libcore/luni/src/main/java/java/io/FilterOutputStream.java;l=63,75;drc=eb8027492e81d5d3a0d1cd49494c59f9a03eeaa3) by 5.0.0, [aka Lollipop](https://source.android.com/docs/setup/reference/build-numbers), which is [what we target](https://guava.dev/#important-warnings). And address a few more warnings. RELNOTES=Exposed some additional Java 8 APIs to Android users. Plus: `io`: Changed `ByteSink` and `CharSink` to no longer call `flush()` in some cases before `close()`. This is a no-op for well-behaved streams, which internally flush their data as part of closing. However, we have discovered some stream implementations that have overridden `close()` to do nothing, including not to flush some buffered data. If this change causes problems, the simplest fix is usually to change the `close()` override to at least call `flush()`. PiperOrigin-RevId: 691790805
1 parent 664c80b commit 6ace8bc

File tree

22 files changed

+2448
-68
lines changed

22 files changed

+2448
-68
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2019 The Guava Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
15+
package com.google.common.collect.testing;
16+
17+
import static java.lang.annotation.ElementType.CONSTRUCTOR;
18+
import static java.lang.annotation.ElementType.METHOD;
19+
import static java.lang.annotation.ElementType.TYPE;
20+
21+
import java.lang.annotation.Target;
22+
23+
/**
24+
* Disables Animal Sniffer's checking of compatibility with older versions of Java/Android.
25+
*
26+
* <p>Each package's copy of this annotation needs to be listed in our {@code pom.xml}.
27+
*/
28+
@Target({METHOD, CONSTRUCTOR, TYPE})
29+
@ElementTypesAreNonnullByDefault
30+
@interface IgnoreJRERequirement {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,349 @@
1+
/*
2+
* Copyright (C) 2015 The Guava Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.common.collect.testing;
18+
19+
import static com.google.common.base.Preconditions.checkNotNull;
20+
import static com.google.common.collect.testing.Helpers.assertEqualIgnoringOrder;
21+
import static com.google.common.collect.testing.Helpers.assertEqualInOrder;
22+
import static com.google.common.collect.testing.Platform.format;
23+
import static java.util.Arrays.asList;
24+
import static java.util.Collections.unmodifiableSet;
25+
import static junit.framework.Assert.assertEquals;
26+
import static junit.framework.Assert.assertFalse;
27+
import static junit.framework.Assert.assertTrue;
28+
import static junit.framework.Assert.fail;
29+
30+
import com.google.common.annotations.GwtCompatible;
31+
import com.google.common.collect.ImmutableSet;
32+
import com.google.common.collect.Ordering;
33+
import com.google.common.primitives.Ints;
34+
import com.google.errorprone.annotations.CanIgnoreReturnValue;
35+
import java.util.ArrayList;
36+
import java.util.Comparator;
37+
import java.util.LinkedHashSet;
38+
import java.util.List;
39+
import java.util.Set;
40+
import java.util.Spliterator;
41+
import java.util.Spliterator.OfPrimitive;
42+
import java.util.function.Consumer;
43+
import java.util.function.Function;
44+
import java.util.function.Supplier;
45+
import org.checkerframework.checker.nullness.qual.Nullable;
46+
47+
/**
48+
* Tester for {@code Spliterator} implementations.
49+
*
50+
* @since NEXT (but since 21.0 in the JRE flavor)
51+
*/
52+
@GwtCompatible
53+
@ElementTypesAreNonnullByDefault
54+
@SuppressWarnings("Java7ApiChecker")
55+
@IgnoreJRERequirement // Users will use this only if they're already using Spliterator.
56+
public final class SpliteratorTester<E extends @Nullable Object> {
57+
/** Return type from "contains the following elements" assertions. */
58+
public interface Ordered {
59+
/**
60+
* Attests that the expected values must not just be present but must be present in the order
61+
* they were given.
62+
*/
63+
void inOrder();
64+
}
65+
66+
@IgnoreJRERequirement // *should* be redundant with the annotation on SpliteratorTester
67+
private abstract static class GeneralSpliterator<E extends @Nullable Object> {
68+
final Spliterator<E> spliterator;
69+
70+
GeneralSpliterator(Spliterator<E> spliterator) {
71+
this.spliterator = checkNotNull(spliterator);
72+
}
73+
74+
abstract void forEachRemaining(Consumer<? super E> action);
75+
76+
abstract boolean tryAdvance(Consumer<? super E> action);
77+
78+
abstract @Nullable GeneralSpliterator<E> trySplit();
79+
80+
final int characteristics() {
81+
return spliterator.characteristics();
82+
}
83+
84+
final long estimateSize() {
85+
return spliterator.estimateSize();
86+
}
87+
88+
final Comparator<? super E> getComparator() {
89+
return spliterator.getComparator();
90+
}
91+
92+
final long getExactSizeIfKnown() {
93+
return spliterator.getExactSizeIfKnown();
94+
}
95+
96+
final boolean hasCharacteristics(int characteristics) {
97+
return spliterator.hasCharacteristics(characteristics);
98+
}
99+
}
100+
101+
@IgnoreJRERequirement // *should* be redundant with the annotation on SpliteratorTester
102+
private static final class GeneralSpliteratorOfObject<E extends @Nullable Object>
103+
extends GeneralSpliterator<E> {
104+
GeneralSpliteratorOfObject(Spliterator<E> spliterator) {
105+
super(spliterator);
106+
}
107+
108+
@Override
109+
void forEachRemaining(Consumer<? super E> action) {
110+
spliterator.forEachRemaining(action);
111+
}
112+
113+
@Override
114+
boolean tryAdvance(Consumer<? super E> action) {
115+
return spliterator.tryAdvance(action);
116+
}
117+
118+
@Override
119+
@Nullable GeneralSpliterator<E> trySplit() {
120+
Spliterator<E> split = spliterator.trySplit();
121+
return split == null ? null : new GeneralSpliteratorOfObject<>(split);
122+
}
123+
}
124+
125+
@IgnoreJRERequirement // *should* be redundant with the annotation on SpliteratorTester
126+
private static final class GeneralSpliteratorOfPrimitive<
127+
E extends @Nullable Object, C, S extends Spliterator.OfPrimitive<E, C, S>>
128+
extends GeneralSpliterator<E> {
129+
final OfPrimitive<E, C, S> spliteratorOfPrimitive;
130+
final Function<Consumer<? super E>, C> consumerizer;
131+
132+
GeneralSpliteratorOfPrimitive(
133+
Spliterator.OfPrimitive<E, C, S> spliterator,
134+
Function<Consumer<? super E>, C> consumerizer) {
135+
super(spliterator);
136+
this.spliteratorOfPrimitive = spliterator;
137+
this.consumerizer = consumerizer;
138+
}
139+
140+
@Override
141+
void forEachRemaining(Consumer<? super E> action) {
142+
spliteratorOfPrimitive.forEachRemaining(consumerizer.apply(action));
143+
}
144+
145+
@Override
146+
boolean tryAdvance(Consumer<? super E> action) {
147+
return spliteratorOfPrimitive.tryAdvance(consumerizer.apply(action));
148+
}
149+
150+
@Override
151+
@Nullable GeneralSpliterator<E> trySplit() {
152+
Spliterator.OfPrimitive<E, C, ?> split = spliteratorOfPrimitive.trySplit();
153+
return split == null ? null : new GeneralSpliteratorOfPrimitive<>(split, consumerizer);
154+
}
155+
}
156+
157+
/**
158+
* Different ways of decomposing a Spliterator, all of which must produce the same elements (up to
159+
* ordering, if Spliterator.ORDERED is not present).
160+
*/
161+
@IgnoreJRERequirement // *should* be redundant with the annotation on SpliteratorTester
162+
enum SpliteratorDecompositionStrategy {
163+
NO_SPLIT_FOR_EACH_REMAINING {
164+
@Override
165+
<E extends @Nullable Object> void forEach(
166+
GeneralSpliterator<E> spliterator, Consumer<? super E> consumer) {
167+
spliterator.forEachRemaining(consumer);
168+
}
169+
},
170+
NO_SPLIT_TRY_ADVANCE {
171+
@Override
172+
<E extends @Nullable Object> void forEach(
173+
GeneralSpliterator<E> spliterator, Consumer<? super E> consumer) {
174+
while (spliterator.tryAdvance(consumer)) {
175+
// do nothing
176+
}
177+
}
178+
},
179+
MAXIMUM_SPLIT {
180+
@Override
181+
<E extends @Nullable Object> void forEach(
182+
GeneralSpliterator<E> spliterator, Consumer<? super E> consumer) {
183+
for (GeneralSpliterator<E> prefix = trySplitTestingSize(spliterator);
184+
prefix != null;
185+
prefix = trySplitTestingSize(spliterator)) {
186+
forEach(prefix, consumer);
187+
}
188+
long size = spliterator.getExactSizeIfKnown();
189+
long[] counter = {0};
190+
spliterator.forEachRemaining(
191+
e -> {
192+
consumer.accept(e);
193+
counter[0]++;
194+
});
195+
if (size >= 0) {
196+
assertEquals(size, counter[0]);
197+
}
198+
}
199+
},
200+
ALTERNATE_ADVANCE_AND_SPLIT {
201+
@Override
202+
<E extends @Nullable Object> void forEach(
203+
GeneralSpliterator<E> spliterator, Consumer<? super E> consumer) {
204+
while (spliterator.tryAdvance(consumer)) {
205+
GeneralSpliterator<E> prefix = trySplitTestingSize(spliterator);
206+
if (prefix != null) {
207+
forEach(prefix, consumer);
208+
}
209+
}
210+
}
211+
};
212+
213+
abstract <E extends @Nullable Object> void forEach(
214+
GeneralSpliterator<E> spliterator, Consumer<? super E> consumer);
215+
216+
static final Set<SpliteratorDecompositionStrategy> ALL_STRATEGIES =
217+
unmodifiableSet(new LinkedHashSet<>(asList(values())));
218+
}
219+
220+
private static <E extends @Nullable Object> @Nullable GeneralSpliterator<E> trySplitTestingSize(
221+
GeneralSpliterator<E> spliterator) {
222+
boolean subsized = spliterator.hasCharacteristics(Spliterator.SUBSIZED);
223+
long originalSize = spliterator.estimateSize();
224+
GeneralSpliterator<E> trySplit = spliterator.trySplit();
225+
if (spliterator.estimateSize() > originalSize) {
226+
fail(
227+
format(
228+
"estimated size of spliterator after trySplit (%s) is larger than original size (%s)",
229+
spliterator.estimateSize(), originalSize));
230+
}
231+
if (trySplit != null) {
232+
if (trySplit.estimateSize() > originalSize) {
233+
fail(
234+
format(
235+
"estimated size of trySplit result (%s) is larger than original size (%s)",
236+
trySplit.estimateSize(), originalSize));
237+
}
238+
}
239+
if (subsized) {
240+
if (trySplit != null) {
241+
assertEquals(
242+
"sum of estimated sizes of trySplit and original spliterator after trySplit",
243+
originalSize,
244+
trySplit.estimateSize() + spliterator.estimateSize());
245+
} else {
246+
assertEquals(
247+
"estimated size of spliterator after failed trySplit",
248+
originalSize,
249+
spliterator.estimateSize());
250+
}
251+
}
252+
return trySplit;
253+
}
254+
255+
public static <E extends @Nullable Object> SpliteratorTester<E> of(
256+
Supplier<Spliterator<E>> spliteratorSupplier) {
257+
return new SpliteratorTester<>(
258+
ImmutableSet.of(() -> new GeneralSpliteratorOfObject<>(spliteratorSupplier.get())));
259+
}
260+
261+
/**
262+
* @since NEXT (but since 28.1 in the JRE flavor)
263+
*/
264+
public static SpliteratorTester<Integer> ofInt(Supplier<Spliterator.OfInt> spliteratorSupplier) {
265+
return new SpliteratorTester<>(
266+
ImmutableSet.of(
267+
() -> new GeneralSpliteratorOfObject<>(spliteratorSupplier.get()),
268+
() -> new GeneralSpliteratorOfPrimitive<>(spliteratorSupplier.get(), c -> c::accept)));
269+
}
270+
271+
/**
272+
* @since NEXT (but since 28.1 in the JRE flavor)
273+
*/
274+
public static SpliteratorTester<Long> ofLong(Supplier<Spliterator.OfLong> spliteratorSupplier) {
275+
return new SpliteratorTester<>(
276+
ImmutableSet.of(
277+
() -> new GeneralSpliteratorOfObject<>(spliteratorSupplier.get()),
278+
() -> new GeneralSpliteratorOfPrimitive<>(spliteratorSupplier.get(), c -> c::accept)));
279+
}
280+
281+
/**
282+
* @since NEXT (but since 28.1 in the JRE flavor)
283+
*/
284+
public static SpliteratorTester<Double> ofDouble(
285+
Supplier<Spliterator.OfDouble> spliteratorSupplier) {
286+
return new SpliteratorTester<>(
287+
ImmutableSet.of(
288+
() -> new GeneralSpliteratorOfObject<>(spliteratorSupplier.get()),
289+
() -> new GeneralSpliteratorOfPrimitive<>(spliteratorSupplier.get(), c -> c::accept)));
290+
}
291+
292+
private final ImmutableSet<Supplier<GeneralSpliterator<E>>> spliteratorSuppliers;
293+
294+
private SpliteratorTester(ImmutableSet<Supplier<GeneralSpliterator<E>>> spliteratorSuppliers) {
295+
this.spliteratorSuppliers = checkNotNull(spliteratorSuppliers);
296+
}
297+
298+
@SafeVarargs
299+
@CanIgnoreReturnValue
300+
public final Ordered expect(Object... elements) {
301+
return expect(asList(elements));
302+
}
303+
304+
@CanIgnoreReturnValue
305+
public final Ordered expect(Iterable<?> elements) {
306+
List<List<E>> resultsForAllStrategies = new ArrayList<>();
307+
for (Supplier<GeneralSpliterator<E>> spliteratorSupplier : spliteratorSuppliers) {
308+
GeneralSpliterator<E> spliterator = spliteratorSupplier.get();
309+
int characteristics = spliterator.characteristics();
310+
long estimatedSize = spliterator.estimateSize();
311+
for (SpliteratorDecompositionStrategy strategy :
312+
SpliteratorDecompositionStrategy.ALL_STRATEGIES) {
313+
List<E> resultsForStrategy = new ArrayList<>();
314+
strategy.forEach(spliteratorSupplier.get(), resultsForStrategy::add);
315+
316+
// TODO(cpovirk): better failure messages
317+
if ((characteristics & Spliterator.NONNULL) != 0) {
318+
assertFalse(resultsForStrategy.contains(null));
319+
}
320+
if ((characteristics & Spliterator.SORTED) != 0) {
321+
Comparator<? super E> comparator = spliterator.getComparator();
322+
if (comparator == null) {
323+
// A sorted spliterator with no comparator is already using natural order.
324+
// (We could probably find a way to avoid rawtypes here if we wanted.)
325+
@SuppressWarnings({"unchecked", "rawtypes"})
326+
Comparator<? super E> naturalOrder =
327+
(Comparator<? super E>) Comparator.<Comparable>naturalOrder();
328+
comparator = naturalOrder;
329+
}
330+
assertTrue(Ordering.from(comparator).isOrdered(resultsForStrategy));
331+
}
332+
if ((characteristics & Spliterator.SIZED) != 0) {
333+
assertEquals(Ints.checkedCast(estimatedSize), resultsForStrategy.size());
334+
}
335+
336+
assertEqualIgnoringOrder(elements, resultsForStrategy);
337+
resultsForAllStrategies.add(resultsForStrategy);
338+
}
339+
}
340+
return new Ordered() {
341+
@Override
342+
public void inOrder() {
343+
for (List<E> resultsForStrategy : resultsForAllStrategies) {
344+
assertEqualInOrder(elements, resultsForStrategy);
345+
}
346+
}
347+
};
348+
}
349+
}

0 commit comments

Comments
 (0)