New upstream version 23.3
Emmanuel Bourg
4 years ago
17 | 17 | |
18 | 18 | ## Latest release |
19 | 19 | |
20 | The most recent release is [Guava 23.1][current release], released September 27, | |
20 | The most recent release is [Guava 23.2][current release], released October 11, | |
21 | 21 | 2017. |
22 | 22 | |
23 | 23 | The Maven group ID is `com.google.guava`, and the artifact ID is `guava`. Use |
24 | version `23.1-jre` for the JRE flavor, or `23.1-android` for the Android flavor. | |
24 | version `23.2-jre` for the JRE flavor, or `23.2-android` for the Android flavor. | |
25 | 25 | |
26 | 26 | To add a dependency on Guava using Maven, use the following: |
27 | 27 | |
29 | 29 | <dependency> |
30 | 30 | <groupId>com.google.guava</groupId> |
31 | 31 | <artifactId>guava</artifactId> |
32 | <version>23.1-jre</version> | |
32 | <version>23.2-jre</version> | |
33 | 33 | <!-- or, for Android: --> |
34 | <version>23.1-android</version> | |
34 | <version>23.2-android</version> | |
35 | 35 | </dependency> |
36 | 36 | ``` |
37 | 37 | |
39 | 39 | |
40 | 40 | ``` |
41 | 41 | dependencies { |
42 | compile 'com.google.guava:guava:23.1-jre' | |
42 | compile 'com.google.guava:guava:23.2-jre' | |
43 | 43 | // or, for Android: |
44 | compile 'com.google.guava:guava:23.1-android' | |
44 | compile 'com.google.guava:guava:23.2-android' | |
45 | 45 | } |
46 | 46 | ``` |
47 | 47 | |
94 | 94 | correctly in other environments. For the Android flavor, our unit tests run on |
95 | 95 | API level 15 (Ice Cream Sandwich). |
96 | 96 | |
97 | [current release]: https://github.com/google/guava/releases/tag/v23.1 | |
97 | [current release]: https://github.com/google/guava/releases/tag/v23.2 | |
98 | 98 | [guava-snapshot-api-docs]: http://google.github.io/guava/releases/snapshot-jre/api/docs/ |
99 | 99 | [guava-snapshot-api-diffs]: http://google.github.io/guava/releases/snapshot-jre/api/diffs/ |
100 | 100 | [Guava Explained]: https://github.com/google/guava/wiki/Home |
4 | 4 | <parent> |
5 | 5 | <groupId>com.google.guava</groupId> |
6 | 6 | <artifactId>guava-parent</artifactId> |
7 | <version>23.2-android</version> | |
7 | <version>23.3-android</version> | |
8 | 8 | </parent> |
9 | 9 | <artifactId>guava</artifactId> |
10 | 10 | <packaging>bundle</packaging> |
1497 | 1497 | |
1498 | 1498 | /** Implementation of {@link #digit()}. */ |
1499 | 1499 | private static final class Digit extends RangesMatcher { |
1500 | // Plug the following UnicodeSet pattern into | |
1501 | // https://unicode.org/cldr/utility/list-unicodeset.jsp | |
1502 | // [[:Nd:]&[:nv=0:]&[\u0000-\uFFFF]] | |
1503 | // and get the zeroes from there. | |
1500 | 1504 | |
1501 | 1505 | // Must be in ascending order. |
1502 | 1506 | private static final String ZEROES = |
1503 | "0\u0660\u06f0\u07c0\u0966\u09e6\u0a66\u0ae6\u0b66" | |
1504 | + "\u0be6\u0c66\u0ce6\u0d66\u0e50\u0ed0\u0f20\u1040\u1090\u17e0\u1810" | |
1505 | + "\u1946\u19d0\u1b50\u1bb0\u1c40\u1c50\ua620\ua8d0\ua900\uaa50\uff10"; | |
1507 | "0\u0660\u06f0\u07c0\u0966\u09e6\u0a66\u0ae6\u0b66\u0be6\u0c66\u0ce6\u0d66\u0de6" | |
1508 | + "\u0e50\u0ed0\u0f20\u1040\u1090\u17e0\u1810\u1946\u19d0\u1a80\u1a90\u1b50\u1bb0" | |
1509 | + "\u1c40\u1c50\ua620\ua8d0\ua900\ua9d0\ua9f0\uaa50\uabf0\uff10"; | |
1506 | 1510 | |
1507 | 1511 | private static char[] zeroes() { |
1508 | 1512 | return ZEROES.toCharArray(); |
1620 | 1624 | |
1621 | 1625 | /** Implementation of {@link #invisible()}. */ |
1622 | 1626 | private static final class Invisible extends RangesMatcher { |
1623 | ||
1627 | // Plug the following UnicodeSet pattern into | |
1628 | // https://unicode.org/cldr/utility/list-unicodeset.jsp | |
1629 | // [[[:Zs:][:Zl:][:Zp:][:Cc:][:Cf:][:Cs:][:Co:]]&[\u0000-\uFFFF]] | |
1630 | // with the "Abbreviate" option, and get the ranges from there. | |
1624 | 1631 | private static final String RANGE_STARTS = |
1625 | "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f\u1680\u180e\u2000\u2028\u205f\u2066\u2067" | |
1626 | + "\u2068\u2069\u206a\u3000\ud800\ufeff\ufff9\ufffa"; | |
1627 | private static final String RANGE_ENDS = | |
1628 | "\u0020\u00a0\u00ad\u0604\u061c\u06dd\u070f\u1680\u180e\u200f\u202f\u2064\u2066\u2067" | |
1629 | + "\u2068\u2069\u206f\u3000\uf8ff\ufeff\ufff9\ufffb"; | |
1632 | "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f\u08e2\u1680\u180e\u2000\u2028\u205f\u2066" | |
1633 | + "\u3000\ud800\ufeff\ufff9"; | |
1634 | private static final String RANGE_ENDS = // inclusive ends | |
1635 | "\u0020\u00a0\u00ad\u0605\u061c\u06dd\u070f\u08e2\u1680\u180e\u200f\u202f\u2064\u206f" | |
1636 | + "\u3000\uf8ff\ufeff\ufffb"; | |
1630 | 1637 | |
1631 | 1638 | static final Invisible INSTANCE = new Invisible(); |
1632 | 1639 |
31 | 31 | * |
32 | 32 | * @author Louis Wasserman |
33 | 33 | * @since 15.0 |
34 | * @deprecated Use {@link com.google.common.graph.Traverser} instead. All instance methods except | |
35 | * for {@link #inOrderTraversal} have their equivalent on the result of {@code | |
36 | * Traverser.forTree(tree)} where {@code tree} implements {@code SuccessorsFunction}, which has | |
37 | * a similar API as {@link #children}. | |
38 | * <p>This class is scheduled to be removed in January 2018. | |
34 | 39 | */ |
40 | @Deprecated | |
35 | 41 | @Beta |
36 | 42 | @GwtCompatible |
37 | 43 | public abstract class BinaryTreeTraverser<T> extends TreeTraverser<T> { |
62 | 62 | * |
63 | 63 | * @author Louis Wasserman |
64 | 64 | * @since 15.0 |
65 | * @deprecated Use {@link com.google.common.graph.Traverser} instead. All instance methods have | |
66 | * their equivalent on the result of {@code Traverser.forTree(tree)} where {@code tree} | |
67 | * implements {@code SuccessorsFunction}, which has a similar API as {@link #children} or can be | |
68 | * the same lambda function as passed into {@link #using(Function)}. | |
69 | * <p>This class is scheduled to be removed in January 2018. | |
65 | 70 | */ |
71 | @Deprecated | |
66 | 72 | @Beta |
67 | 73 | @GwtCompatible |
68 | 74 | public abstract class TreeTraverser<T> { |
74 | 80 | * {@code TreeTraverser} and implement its {@link #children} method directly. |
75 | 81 | * |
76 | 82 | * @since 20.0 |
77 | */ | |
83 | * @deprecated Use {@link com.google.common.graph.Traverser#forTree} instead. If you are using a | |
84 | * lambda, these methods have exactly the same signature. | |
85 | */ | |
86 | @Deprecated | |
78 | 87 | public static <T> TreeTraverser<T> using( |
79 | 88 | final Function<T, ? extends Iterable<T>> nodeToChildrenFunction) { |
80 | 89 | checkNotNull(nodeToChildrenFunction); |
92 | 101 | public abstract Iterable<T> children(T root); |
93 | 102 | |
94 | 103 | /** |
95 | * Returns an unmodifiable iterable over the nodes in a tree structure, using pre-order | |
96 | * traversal. That is, each node's subtrees are traversed after the node itself is returned. | |
97 | * | |
98 | * <p>No guarantees are made about the behavior of the traversal when nodes change while | |
99 | * iteration is in progress or when the iterators generated by {@link #children} are advanced. | |
100 | */ | |
104 | * Returns an unmodifiable iterable over the nodes in a tree structure, using pre-order traversal. | |
105 | * That is, each node's subtrees are traversed after the node itself is returned. | |
106 | * | |
107 | * <p>No guarantees are made about the behavior of the traversal when nodes change while iteration | |
108 | * is in progress or when the iterators generated by {@link #children} are advanced. | |
109 | * | |
110 | * @deprecated Use {@link com.google.common.graph.Traverser#depthFirstPreOrder} instead, which has | |
111 | * the same behavior. | |
112 | */ | |
113 | @Deprecated | |
101 | 114 | public final FluentIterable<T> preOrderTraversal(final T root) { |
102 | 115 | checkNotNull(root); |
103 | 116 | return new FluentIterable<T>() { |
145 | 158 | * Returns an unmodifiable iterable over the nodes in a tree structure, using post-order |
146 | 159 | * traversal. That is, each node's subtrees are traversed before the node itself is returned. |
147 | 160 | * |
148 | * <p>No guarantees are made about the behavior of the traversal when nodes change while | |
149 | * iteration is in progress or when the iterators generated by {@link #children} are advanced. | |
150 | */ | |
161 | * <p>No guarantees are made about the behavior of the traversal when nodes change while iteration | |
162 | * is in progress or when the iterators generated by {@link #children} are advanced. | |
163 | * | |
164 | * @deprecated Use {@link com.google.common.graph.Traverser#depthFirstPostOrder} instead, which | |
165 | * has the same behavior. | |
166 | */ | |
167 | @Deprecated | |
151 | 168 | public final FluentIterable<T> postOrderTraversal(final T root) { |
152 | 169 | checkNotNull(root); |
153 | 170 | return new FluentIterable<T>() { |
205 | 222 | * Returns an unmodifiable iterable over the nodes in a tree structure, using breadth-first |
206 | 223 | * traversal. That is, all the nodes of depth 0 are returned, then depth 1, then 2, and so on. |
207 | 224 | * |
208 | * <p>No guarantees are made about the behavior of the traversal when nodes change while | |
209 | * iteration is in progress or when the iterators generated by {@link #children} are advanced. | |
210 | */ | |
225 | * <p>No guarantees are made about the behavior of the traversal when nodes change while iteration | |
226 | * is in progress or when the iterators generated by {@link #children} are advanced. | |
227 | * | |
228 | * @deprecated Use {@link com.google.common.graph.Traverser#breadthFirst} instead, which has the | |
229 | * same behavior. | |
230 | */ | |
231 | @Deprecated | |
211 | 232 | public final FluentIterable<T> breadthFirstTraversal(final T root) { |
212 | 233 | checkNotNull(root); |
213 | 234 | return new FluentIterable<T>() { |
167 | 167 | * |
168 | 168 | * <p>See <a href="https://en.wikipedia.org/wiki/Breadth-first_search">Wikipedia</a> for more |
169 | 169 | * info. |
170 | * | |
171 | * @throws IllegalArgumentException if {@code startNode} is not an element of the graph | |
170 | 172 | */ |
171 | 173 | public abstract Iterable<N> breadthFirst(N startNode); |
172 | 174 | |
198 | 200 | * }</pre> |
199 | 201 | * |
200 | 202 | * <p>See <a href="https://en.wikipedia.org/wiki/Depth-first_search">Wikipedia</a> for more info. |
203 | * | |
204 | * @throws IllegalArgumentException if {@code startNode} is not an element of the graph | |
201 | 205 | */ |
202 | 206 | public abstract Iterable<N> depthFirstPreOrder(N startNode); |
203 | 207 | |
229 | 233 | * }</pre> |
230 | 234 | * |
231 | 235 | * <p>See <a href="https://en.wikipedia.org/wiki/Depth-first_search">Wikipedia</a> for more info. |
236 | * | |
237 | * @throws IllegalArgumentException if {@code startNode} is not an element of the graph | |
232 | 238 | */ |
233 | 239 | public abstract Iterable<N> depthFirstPostOrder(N startNode); |
234 | 240 | |
241 | 247 | |
242 | 248 | @Override |
243 | 249 | public Iterable<N> breadthFirst(final N startNode) { |
250 | checkNotNull(startNode); | |
251 | checkThatNodeIsInGraph(startNode); | |
244 | 252 | return new Iterable<N>() { |
245 | 253 | @Override |
246 | 254 | public Iterator<N> iterator() { |
251 | 259 | |
252 | 260 | @Override |
253 | 261 | public Iterable<N> depthFirstPreOrder(final N startNode) { |
262 | checkNotNull(startNode); | |
263 | checkThatNodeIsInGraph(startNode); | |
254 | 264 | return new Iterable<N>() { |
255 | 265 | @Override |
256 | 266 | public Iterator<N> iterator() { |
261 | 271 | |
262 | 272 | @Override |
263 | 273 | public Iterable<N> depthFirstPostOrder(final N startNode) { |
274 | checkNotNull(startNode); | |
275 | checkThatNodeIsInGraph(startNode); | |
264 | 276 | return new Iterable<N>() { |
265 | 277 | @Override |
266 | 278 | public Iterator<N> iterator() { |
267 | 279 | return new DepthFirstIterator(startNode, Order.POSTORDER); |
268 | 280 | } |
269 | 281 | }; |
282 | } | |
283 | ||
284 | @SuppressWarnings("CheckReturnValue") | |
285 | private void checkThatNodeIsInGraph(N startNode) { | |
286 | // successors() throws an IllegalArgumentException for nodes that are not an element of the | |
287 | // graph. | |
288 | graph.successors(startNode); | |
270 | 289 | } |
271 | 290 | |
272 | 291 | private final class BreadthFirstIterator extends UnmodifiableIterator<N> { |
359 | 378 | |
360 | 379 | @Override |
361 | 380 | public Iterable<N> breadthFirst(final N startNode) { |
381 | checkNotNull(startNode); | |
382 | checkThatNodeIsInTree(startNode); | |
362 | 383 | return new Iterable<N>() { |
363 | 384 | @Override |
364 | 385 | public Iterator<N> iterator() { |
369 | 390 | |
370 | 391 | @Override |
371 | 392 | public Iterable<N> depthFirstPreOrder(final N startNode) { |
393 | checkNotNull(startNode); | |
394 | checkThatNodeIsInTree(startNode); | |
372 | 395 | return new Iterable<N>() { |
373 | 396 | @Override |
374 | 397 | public Iterator<N> iterator() { |
379 | 402 | |
380 | 403 | @Override |
381 | 404 | public Iterable<N> depthFirstPostOrder(final N startNode) { |
405 | checkNotNull(startNode); | |
406 | checkThatNodeIsInTree(startNode); | |
382 | 407 | return new Iterable<N>() { |
383 | 408 | @Override |
384 | 409 | public Iterator<N> iterator() { |
385 | 410 | return new DepthFirstPostOrderIterator(startNode); |
386 | 411 | } |
387 | 412 | }; |
413 | } | |
414 | ||
415 | @SuppressWarnings("CheckReturnValue") | |
416 | private void checkThatNodeIsInTree(N startNode) { | |
417 | // successors() throws an IllegalArgumentException for nodes that are not an element of the | |
418 | // graph. | |
419 | tree.successors(startNode); | |
388 | 420 | } |
389 | 421 | |
390 | 422 | private final class BreadthFirstIterator extends UnmodifiableIterator<N> { |
22 | 22 | import com.google.common.base.Ascii; |
23 | 23 | import com.google.common.base.CharMatcher; |
24 | 24 | import com.google.common.base.Joiner; |
25 | import com.google.common.base.Optional; | |
25 | 26 | import com.google.common.base.Splitter; |
26 | 27 | import com.google.common.collect.ImmutableList; |
27 | 28 | import com.google.thirdparty.publicsuffix.PublicSuffixPatterns; |
29 | import com.google.thirdparty.publicsuffix.PublicSuffixType; | |
28 | 30 | import java.util.List; |
29 | 31 | import javax.annotation.Nullable; |
30 | 32 | |
31 | 33 | /** |
32 | * An immutable well-formed internet domain name, such as {@code com} or {@code | |
33 | * foo.co.uk}. Only syntactic analysis is performed; no DNS lookups or other network interactions | |
34 | * take place. Thus there is no guarantee that the domain actually exists on the internet. | |
34 | * An immutable well-formed internet domain name, such as {@code com} or {@code foo.co.uk}. Only | |
35 | * syntactic analysis is performed; no DNS lookups or other network interactions take place. Thus | |
36 | * there is no guarantee that the domain actually exists on the internet. | |
35 | 37 | * |
36 | 38 | * <p>One common use of this class is to determine whether a given string is likely to represent an |
37 | 39 | * addressable domain on the web -- that is, for a candidate string {@code "xxx"}, might browsing to |
39 | 41 | * done by determining whether the domain ended with a {@linkplain #isPublicSuffix() public suffix} |
40 | 42 | * but was not itself a public suffix. However, this test is no longer accurate. There are many |
41 | 43 | * domains which are both public suffixes and addressable as hosts; {@code "uk.com"} is one example. |
42 | * As a result, the only useful test to determine if a domain is a plausible web host is | |
43 | * {@link #hasPublicSuffix()}. This will return {@code true} for many domains which (currently) are | |
44 | * not hosts, such as {@code "com"}, but given that any public suffix may become a host without | |
45 | * warning, it is better to err on the side of permissiveness and thus avoid spurious rejection of | |
46 | * valid sites. | |
44 | * Using the subset of public suffixes that are {@linkplain #isRegistrySuffix() registry suffixes}, | |
45 | * one can get a better result, as only a few registry suffixes are addressable. However, the most | |
46 | * useful test to determine if a domain is a plausible web host is {@link #hasPublicSuffix()}. This | |
47 | * will return {@code true} for many domains which (currently) are not hosts, such as {@code "com"}, | |
48 | * but given that any public suffix may become a host without warning, it is better to err on the | |
49 | * side of permissiveness and thus avoid spurious rejection of valid sites. Of course, to actually | |
50 | * determine addressability of any host, clients of this class will need to perform their own DNS | |
51 | * lookups. | |
47 | 52 | * |
48 | 53 | * <p>During construction, names are normalized in two ways: |
49 | 54 | * |
50 | 55 | * <ol> |
51 | * <li>ASCII uppercase characters are converted to lowercase. | |
52 | * <li>Unicode dot separators other than the ASCII period ({@code '.'}) are converted to the ASCII | |
53 | * period. | |
56 | * <li>ASCII uppercase characters are converted to lowercase. | |
57 | * <li>Unicode dot separators other than the ASCII period ({@code '.'}) are converted to the ASCII | |
58 | * period. | |
54 | 59 | * </ol> |
55 | 60 | * |
56 | 61 | * <p>The normalized values will be returned from {@link #toString()} and {@link #parts()}, and will |
57 | 62 | * be reflected in the result of {@link #equals(Object)}. |
58 | 63 | * |
59 | 64 | * <p><a href="http://en.wikipedia.org/wiki/Internationalized_domain_name">Internationalized domain |
60 | * names</a> such as {@code 网络.cn} are supported, as are the equivalent | |
61 | * <a href="http://en.wikipedia.org/wiki/Internationalized_domain_name">IDNA Punycode-encoded</a> | |
65 | * names</a> such as {@code 网络.cn} are supported, as are the equivalent <a | |
66 | * href="http://en.wikipedia.org/wiki/Internationalized_domain_name">IDNA Punycode-encoded</a> | |
62 | 67 | * versions. |
63 | 68 | * |
64 | 69 | * @author Craig Berry |
73 | 78 | private static final Joiner DOT_JOINER = Joiner.on('.'); |
74 | 79 | |
75 | 80 | /** |
76 | * Value of {@link #publicSuffixIndex} which indicates that no public suffix was found. | |
77 | */ | |
78 | private static final int NO_PUBLIC_SUFFIX_FOUND = -1; | |
81 | * Value of {@link #publicSuffixIndex} or {@link #registrySuffixIndex} which indicates that no | |
82 | * relevant suffix was found. | |
83 | */ | |
84 | private static final int NO_SUFFIX_FOUND = -1; | |
79 | 85 | |
80 | 86 | private static final String DOT_REGEX = "\\."; |
81 | 87 | |
111 | 117 | |
112 | 118 | /** |
113 | 119 | * The index in the {@link #parts()} list at which the public suffix begins. For example, for the |
114 | * domain name {@code www.google.co.uk}, the value would be 2 (the index of the {@code co} part). | |
115 | * The value is negative (specifically, {@link #NO_PUBLIC_SUFFIX_FOUND}) if no public suffix was | |
116 | * found. | |
120 | * domain name {@code myblog.blogspot.co.uk}, the value would be 1 (the index of the {@code | |
121 | * blogspot} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no public | |
122 | * suffix was found. | |
117 | 123 | */ |
118 | 124 | private final int publicSuffixIndex; |
125 | ||
126 | /** | |
127 | * The index in the {@link #parts()} list at which the registry suffix begins. For example, for | |
128 | * the domain name {@code myblog.blogspot.co.uk}, the value would be 2 (the index of the {@code | |
129 | * co} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no registry suffix | |
130 | * was found. | |
131 | */ | |
132 | private final int registrySuffixIndex; | |
119 | 133 | |
120 | 134 | /** |
121 | 135 | * Constructor used to implement {@link #from(String)}, and from subclasses. |
139 | 153 | checkArgument(parts.size() <= MAX_PARTS, "Domain has too many parts: '%s'", name); |
140 | 154 | checkArgument(validateSyntax(parts), "Not a valid domain name: '%s'", name); |
141 | 155 | |
142 | this.publicSuffixIndex = findPublicSuffix(); | |
143 | } | |
144 | ||
145 | /** | |
146 | * Returns the index of the leftmost part of the public suffix, or -1 if not found. Note that the | |
147 | * value defined as the "public suffix" may not be a public suffix according to | |
148 | * {@link #isPublicSuffix()} if the domain ends with an excluded domain pattern such as | |
149 | * {@code "nhs.uk"}. | |
150 | */ | |
151 | private int findPublicSuffix() { | |
156 | this.publicSuffixIndex = findSuffixOfType(Optional.<PublicSuffixType>absent()); | |
157 | this.registrySuffixIndex = findSuffixOfType(Optional.of(PublicSuffixType.REGISTRY)); | |
158 | } | |
159 | ||
160 | /** | |
161 | * Returns the index of the leftmost part of the suffix, or -1 if not found. Note that the value | |
162 | * defined as a suffix may not produce {@code true} results from {@link #isPublicSuffix()} or | |
163 | * {@link #isRegistrySuffix()} if the domain ends with an excluded domain pattern such as {@code | |
164 | * "nhs.uk"}. | |
165 | * | |
166 | * <p>If a {@code desiredType} is specified, this method only finds suffixes of the given type. | |
167 | * Otherwise, it finds the first suffix of any type. | |
168 | */ | |
169 | private int findSuffixOfType(Optional<PublicSuffixType> desiredType) { | |
152 | 170 | final int partsSize = parts.size(); |
153 | 171 | |
154 | 172 | for (int i = 0; i < partsSize; i++) { |
155 | 173 | String ancestorName = DOT_JOINER.join(parts.subList(i, partsSize)); |
156 | 174 | |
157 | if (PublicSuffixPatterns.EXACT.containsKey(ancestorName)) { | |
175 | if (matchesType( | |
176 | desiredType, Optional.fromNullable(PublicSuffixPatterns.EXACT.get(ancestorName)))) { | |
158 | 177 | return i; |
159 | 178 | } |
160 | 179 | |
165 | 184 | return i + 1; |
166 | 185 | } |
167 | 186 | |
168 | if (matchesWildcardPublicSuffix(ancestorName)) { | |
187 | if (matchesWildcardSuffixType(desiredType, ancestorName)) { | |
169 | 188 | return i; |
170 | 189 | } |
171 | 190 | } |
172 | 191 | |
173 | return NO_PUBLIC_SUFFIX_FOUND; | |
192 | return NO_SUFFIX_FOUND; | |
174 | 193 | } |
175 | 194 | |
176 | 195 | /** |
177 | 196 | * Returns an instance of {@link InternetDomainName} after lenient validation. Specifically, |
178 | 197 | * validation against <a href="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</a> |
179 | * ("Internationalizing Domain Names in Applications") is skipped, while validation against | |
180 | * <a href="http://www.ietf.org/rfc/rfc1035.txt">RFC 1035</a> is relaxed in the following ways: | |
198 | * ("Internationalizing Domain Names in Applications") is skipped, while validation against <a | |
199 | * href="http://www.ietf.org/rfc/rfc1035.txt">RFC 1035</a> is relaxed in the following ways: | |
200 | * | |
181 | 201 | * <ul> |
182 | * <li>Any part containing non-ASCII characters is considered valid. | |
183 | * <li>Underscores ('_') are permitted wherever dashes ('-') are permitted. | |
184 | * <li>Parts other than the final part may start with a digit, as mandated by | |
185 | * <a href="https://tools.ietf.org/html/rfc1123#section-2">RFC 1123</a>. | |
202 | * <li>Any part containing non-ASCII characters is considered valid. | |
203 | * <li>Underscores ('_') are permitted wherever dashes ('-') are permitted. | |
204 | * <li>Parts other than the final part may start with a digit, as mandated by <a | |
205 | * href="https://tools.ietf.org/html/rfc1123#section-2">RFC 1123</a>. | |
186 | 206 | * </ul> |
187 | 207 | * |
188 | 208 | * |
189 | 209 | * @param domain A domain name (not IP address) |
190 | * @throws IllegalArgumentException if {@code name} is not syntactically valid according to | |
191 | * {@link #isValid} | |
210 | * @throws IllegalArgumentException if {@code name} is not syntactically valid according to {@link | |
211 | * #isValid} | |
192 | 212 | * @since 10.0 (previously named {@code fromLenient}) |
193 | 213 | */ |
194 | 214 | public static InternetDomainName from(String domain) { |
291 | 311 | /** |
292 | 312 | * Indicates whether this domain name represents a <i>public suffix</i>, as defined by the Mozilla |
293 | 313 | * Foundation's <a href="http://publicsuffix.org/">Public Suffix List</a> (PSL). A public suffix |
294 | * is one under which Internet users can directly register names, such as {@code com}, | |
295 | * {@code co.uk} or {@code pvt.k12.wy.us}. Examples of domain names that are <i>not</i> public | |
296 | * suffixes include {@code google}, {@code google.com} and {@code foo.co.uk}. | |
314 | * is one under which Internet users can directly register names, such as {@code com}, {@code | |
315 | * co.uk} or {@code pvt.k12.wy.us}. Examples of domain names that are <i>not</i> public suffixes | |
316 | * include {@code google.com}, {@code foo.co.uk}, and {@code myblog.blogspot.com}. | |
317 | * | |
318 | * <p>Public suffixes are a proper superset of {@linkplain #isRegistrySuffix() registry suffixes}. | |
319 | * The list of public suffixes additionally contains privately owned domain names under which | |
320 | * Internet users can register subdomains. An example of a public suffix that is not a registry | |
321 | * suffix is {@code blogspot.com}. Note that it is true that all public suffixes <i>have</i> | |
322 | * registry suffixes, since domain name registries collectively control all internet domain names. | |
323 | * | |
324 | * <p>For considerations on whether the public suffix or registry suffix designation is more | |
325 | * suitable for your application, see <a | |
326 | * href="https://github.com/google/guava/wiki/InternetDomainNameExplained">this article</a>. | |
297 | 327 | * |
298 | 328 | * @return {@code true} if this domain name appears exactly on the public suffix list |
299 | 329 | * @since 6.0 |
304 | 334 | |
305 | 335 | /** |
306 | 336 | * Indicates whether this domain name ends in a {@linkplain #isPublicSuffix() public suffix}, |
307 | * including if it is a public suffix itself. For example, returns {@code true} for | |
308 | * {@code www.google.com}, {@code foo.co.uk} and {@code com}, but not for {@code google} or | |
309 | * {@code google.foo}. This is the recommended method for determining whether a domain is | |
310 | * potentially an addressable host. | |
337 | * including if it is a public suffix itself. For example, returns {@code true} for {@code | |
338 | * www.google.com}, {@code foo.co.uk} and {@code com}, but not for {@code invalid} or {@code | |
339 | * google.invalid}. This is the recommended method for determining whether a domain is potentially | |
340 | * an addressable host. | |
341 | * | |
342 | * <p>Note that this method is equivalent to {@link #hasRegistrySuffix()} because all registry | |
343 | * suffixes are public suffixes <i>and</i> all public suffixes have registry suffixes. | |
311 | 344 | * |
312 | 345 | * @since 6.0 |
313 | 346 | */ |
314 | 347 | public boolean hasPublicSuffix() { |
315 | return publicSuffixIndex != NO_PUBLIC_SUFFIX_FOUND; | |
348 | return publicSuffixIndex != NO_SUFFIX_FOUND; | |
316 | 349 | } |
317 | 350 | |
318 | 351 | /** |
327 | 360 | |
328 | 361 | /** |
329 | 362 | * Indicates whether this domain name ends in a {@linkplain #isPublicSuffix() public suffix}, |
330 | * while not being a public suffix itself. For example, returns {@code true} for | |
331 | * {@code www.google.com}, {@code foo.co.uk} and {@code bar.ca.us}, but not for {@code google}, | |
332 | * {@code com}, or {@code | |
333 | * google.foo}. | |
334 | * | |
335 | * <p><b>Warning:</b> a {@code false} result from this method does not imply that the domain does | |
336 | * not represent an addressable host, as many public suffixes are also addressable hosts. Use | |
337 | * {@link #hasPublicSuffix()} for that test. | |
363 | * while not being a public suffix itself. For example, returns {@code true} for {@code | |
364 | * www.google.com}, {@code foo.co.uk} and {@code myblog.blogspot.com}, but not for {@code com}, | |
365 | * {@code co.uk}, {@code google.invalid}, or {@code blogspot.com}. | |
338 | 366 | * |
339 | 367 | * <p>This method can be used to determine whether it will probably be possible to set cookies on |
340 | 368 | * the domain, though even that depends on individual browsers' implementations of cookie |
348 | 376 | |
349 | 377 | /** |
350 | 378 | * Indicates whether this domain name is composed of exactly one subdomain component followed by a |
351 | * {@linkplain #isPublicSuffix() public suffix}. For example, returns {@code true} for | |
352 | * {@code google.com} and {@code foo.co.uk}, but not for {@code www.google.com} or {@code co.uk}. | |
353 | * | |
354 | * <p><b>Warning:</b> A {@code true} result from this method does not imply that the domain is at | |
355 | * the highest level which is addressable as a host, as many public suffixes are also addressable | |
356 | * hosts. For example, the domain {@code bar.uk.com} has a public suffix of {@code uk.com}, so it | |
357 | * would return {@code true} from this method. But {@code uk.com} is itself an addressable host. | |
379 | * {@linkplain #isPublicSuffix() public suffix}. For example, returns {@code true} for {@code | |
380 | * google.com} {@code foo.co.uk}, and {@code myblog.blogspot.com}, but not for {@code | |
381 | * www.google.com}, {@code co.uk}, or {@code blogspot.com}. | |
358 | 382 | * |
359 | 383 | * <p>This method can be used to determine whether a domain is probably the highest level for |
360 | 384 | * which cookies may be set, though even that depends on individual browsers' implementations of |
367 | 391 | } |
368 | 392 | |
369 | 393 | /** |
370 | * Returns the portion of this domain name that is one level beneath the public suffix. For | |
371 | * example, for {@code x.adwords.google.co.uk} it returns {@code google.co.uk}, since | |
372 | * {@code co.uk} is a public suffix. | |
394 | * Returns the portion of this domain name that is one level beneath the {@linkplain | |
395 | * #isPublicSuffix() public suffix}. For example, for {@code x.adwords.google.co.uk} it returns | |
396 | * {@code google.co.uk}, since {@code co.uk} is a public suffix. Similarly, for {@code | |
397 | * myblog.blogspot.com} it returns the same domain, {@code myblog.blogspot.com}, since {@code | |
398 | * blogspot.com} is a public suffix. | |
373 | 399 | * |
374 | 400 | * <p>If {@link #isTopPrivateDomain()} is true, the current domain name instance is returned. |
375 | * | |
376 | * <p>This method should not be used to determine the topmost parent domain which is addressable | |
377 | * as a host, as many public suffixes are also addressable hosts. For example, the domain | |
378 | * {@code foo.bar.uk.com} has a public suffix of {@code uk.com}, so it would return | |
379 | * {@code bar.uk.com} from this method. But {@code uk.com} is itself an addressable host. | |
380 | 401 | * |
381 | 402 | * <p>This method can be used to determine the probable highest level parent domain for which |
382 | 403 | * cookies may be set, though even that depends on individual browsers' implementations of cookie |
391 | 412 | } |
392 | 413 | checkState(isUnderPublicSuffix(), "Not under a public suffix: %s", name); |
393 | 414 | return ancestor(publicSuffixIndex - 1); |
415 | } | |
416 | ||
417 | /** | |
418 | * Indicates whether this domain name represents a <i>registry suffix</i>, as defined by a subset | |
419 | * of the Mozilla Foundation's <a href="http://publicsuffix.org/">Public Suffix List</a> (PSL). A | |
420 | * registry suffix is one under which Internet users can directly register names via a domain name | |
421 | * registrar, and have such registrations lawfully protected by internet-governing bodies such as | |
422 | * ICANN. Examples of registry suffixes include {@code com}, {@code co.uk}, and {@code | |
423 | * pvt.k12.wy.us}. Examples of domain names that are <i>not</i> registry suffixes include {@code | |
424 | * google.com} and {@code foo.co.uk}. | |
425 | * | |
426 | * <p>Registry suffixes are a proper subset of {@linkplain #isPublicSuffix() public suffixes}. The | |
427 | * list of public suffixes additionally contains privately owned domain names under which Internet | |
428 | * users can register subdomains. An example of a public suffix that is not a registry suffix is | |
429 | * {@code blogspot.com}. Note that it is true that all public suffixes <i>have</i> registry | |
430 | * suffixes, since domain name registries collectively control all internet domain names. | |
431 | * | |
432 | * <p>For considerations on whether the public suffix or registry suffix designation is more | |
433 | * suitable for your application, see <a | |
434 | * href="https://github.com/google/guava/wiki/InternetDomainNameExplained">this article</a>. | |
435 | * | |
436 | * @return {@code true} if this domain name appears exactly on the public suffix list as part of | |
437 | * the registry suffix section (labelled "ICANN"). | |
438 | * @since 23.3 | |
439 | */ | |
440 | public boolean isRegistrySuffix() { | |
441 | return registrySuffixIndex == 0; | |
442 | } | |
443 | ||
444 | /** | |
445 | * Indicates whether this domain name ends in a {@linkplain #isRegistrySuffix() registry suffix}, | |
446 | * including if it is a registry suffix itself. For example, returns {@code true} for {@code | |
447 | * www.google.com}, {@code foo.co.uk} and {@code com}, but not for {@code invalid} or {@code | |
448 | * google.invalid}. | |
449 | * | |
450 | * <p>Note that this method is equivalent to {@link #hasPublicSuffix()} because all registry | |
451 | * suffixes are public suffixes <i>and</i> all public suffixes have registry suffixes. | |
452 | * | |
453 | * @since 23.3 | |
454 | */ | |
455 | public boolean hasRegistrySuffix() { | |
456 | return registrySuffixIndex != NO_SUFFIX_FOUND; | |
457 | } | |
458 | ||
459 | /** | |
460 | * Returns the {@linkplain #isRegistrySuffix() registry suffix} portion of the domain name, or | |
461 | * {@code null} if no registry suffix is present. | |
462 | * | |
463 | * @since 23.3 | |
464 | */ | |
465 | public InternetDomainName registrySuffix() { | |
466 | return hasRegistrySuffix() ? ancestor(registrySuffixIndex) : null; | |
467 | } | |
468 | ||
469 | /** | |
470 | * Indicates whether this domain name ends in a {@linkplain #isRegistrySuffix() registry suffix}, | |
471 | * while not being a registry suffix itself. For example, returns {@code true} for {@code | |
472 | * www.google.com}, {@code foo.co.uk} and {@code blogspot.com}, but not for {@code com}, {@code | |
473 | * co.uk}, or {@code google.invalid}. | |
474 | * | |
475 | * @since 23.3 | |
476 | */ | |
477 | public boolean isUnderRegistrySuffix() { | |
478 | return registrySuffixIndex > 0; | |
479 | } | |
480 | ||
481 | /** | |
482 | * Indicates whether this domain name is composed of exactly one subdomain component followed by a | |
483 | * {@linkplain #isRegistrySuffix() registry suffix}. For example, returns {@code true} for {@code | |
484 | * google.com}, {@code foo.co.uk}, and {@code blogspot.com}, but not for {@code www.google.com}, | |
485 | * {@code co.uk}, or {@code myblog.blogspot.com}. | |
486 | * | |
487 | * <p><b>Warning:</b> This method should not be used to determine the probable highest level | |
488 | * parent domain for which cookies may be set. Use {@link #topPrivateDomain()} for that purpose. | |
489 | * | |
490 | * @since 23.3 | |
491 | */ | |
492 | public boolean isTopDomainUnderRegistrySuffix() { | |
493 | return registrySuffixIndex == 1; | |
494 | } | |
495 | ||
496 | /** | |
497 | * Returns the portion of this domain name that is one level beneath the {@linkplain | |
498 | * #isRegistrySuffix() registry suffix}. For example, for {@code x.adwords.google.co.uk} it | |
499 | * returns {@code google.co.uk}, since {@code co.uk} is a registry suffix. Similarly, for {@code | |
500 | * myblog.blogspot.com} it returns {@code blogspot.com}, since {@code com} is a registry suffix. | |
501 | * | |
502 | * <p>If {@link #isTopDomainUnderRegistrySuffix()} is true, the current domain name instance is | |
503 | * returned. | |
504 | * | |
505 | * <p><b>Warning:</b> This method should not be used to determine whether a domain is probably the | |
506 | * highest level for which cookies may be set. Use {@link #isTopPrivateDomain()} for that purpose. | |
507 | * | |
508 | * @throws IllegalStateException if this domain does not end with a registry suffix | |
509 | * @since 23.3 | |
510 | */ | |
511 | public InternetDomainName topDomainUnderRegistrySuffix() { | |
512 | if (isTopDomainUnderRegistrySuffix()) { | |
513 | return this; | |
514 | } | |
515 | checkState(isUnderRegistrySuffix(), "Not under a registry suffix: %s", name); | |
516 | return ancestor(registrySuffixIndex - 1); | |
394 | 517 | } |
395 | 518 | |
396 | 519 | /** |
468 | 591 | } |
469 | 592 | |
470 | 593 | /** |
471 | * Does the domain name match one of the "wildcard" patterns (e.g. {@code "*.ar"})? | |
472 | */ | |
473 | private static boolean matchesWildcardPublicSuffix(String domain) { | |
594 | * Does the domain name match one of the "wildcard" patterns (e.g. {@code "*.ar"})? If a {@code | |
595 | * desiredType} is specified, the wildcard pattern must also match that type. | |
596 | */ | |
597 | private static boolean matchesWildcardSuffixType( | |
598 | Optional<PublicSuffixType> desiredType, String domain) { | |
474 | 599 | final String[] pieces = domain.split(DOT_REGEX, 2); |
475 | return pieces.length == 2 && PublicSuffixPatterns.UNDER.containsKey(pieces[1]); | |
600 | return pieces.length == 2 | |
601 | && matchesType( | |
602 | desiredType, Optional.fromNullable(PublicSuffixPatterns.UNDER.get(pieces[1]))); | |
603 | } | |
604 | ||
605 | /** | |
606 | * If a {@code desiredType} is specified, returns true only if the {@code actualType} is | |
607 | * identical. Otherwise, returns true as long as {@code actualType} is present. | |
608 | */ | |
609 | private static boolean matchesType( | |
610 | Optional<PublicSuffixType> desiredType, Optional<PublicSuffixType> actualType) { | |
611 | return desiredType.isPresent() ? desiredType.equals(actualType) : actualType.isPresent(); | |
476 | 612 | } |
477 | 613 | |
478 | 614 | /** |
8 | 8 | * Source: |
9 | 9 | * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/extra/AtomicDouble.java?revision=1.13 |
10 | 10 | * (Modified to adapt to guava coding conventions and |
11 | * to use AtomicLongFieldUpdater instead of sun.misc.Unsafe) | |
11 | * to use AtomicLong instead of sun.misc.Unsafe) | |
12 | 12 | */ |
13 | 13 | |
14 | 14 | package com.google.common.util.concurrent; |
16 | 16 | import static java.lang.Double.doubleToRawLongBits; |
17 | 17 | import static java.lang.Double.longBitsToDouble; |
18 | 18 | |
19 | import com.google.common.annotations.GwtIncompatible; | |
20 | 19 | import com.google.errorprone.annotations.CanIgnoreReturnValue; |
21 | import com.google.j2objc.annotations.ReflectionSupport; | |
22 | import java.util.concurrent.atomic.AtomicLongFieldUpdater; | |
20 | import java.util.concurrent.atomic.AtomicLong; | |
23 | 21 | |
24 | 22 | /** |
25 | 23 | * A {@code double} value that may be updated atomically. See the {@link |
52 | 50 | * @author Martin Buchholz |
53 | 51 | * @since 11.0 |
54 | 52 | */ |
55 | @GwtIncompatible | |
56 | @ReflectionSupport(value = ReflectionSupport.Level.FULL) | |
57 | 53 | public class AtomicDouble extends Number implements java.io.Serializable { |
58 | 54 | private static final long serialVersionUID = 0L; |
59 | 55 | |
60 | private transient volatile long value; | |
61 | ||
62 | private static final AtomicLongFieldUpdater<AtomicDouble> updater = | |
63 | AtomicLongFieldUpdater.newUpdater(AtomicDouble.class, "value"); | |
56 | // We would use AtomicLongFieldUpdater, but it has issues on some Android devices. | |
57 | private transient AtomicLong value; | |
64 | 58 | |
65 | 59 | /** |
66 | 60 | * Creates a new {@code AtomicDouble} with the given initial value. |
68 | 62 | * @param initialValue the initial value |
69 | 63 | */ |
70 | 64 | public AtomicDouble(double initialValue) { |
71 | value = doubleToRawLongBits(initialValue); | |
65 | value = new AtomicLong(doubleToRawLongBits(initialValue)); | |
72 | 66 | } |
73 | 67 | |
74 | 68 | /** |
75 | 69 | * Creates a new {@code AtomicDouble} with initial value {@code 0.0}. |
76 | 70 | */ |
77 | 71 | public AtomicDouble() { |
78 | // assert doubleToRawLongBits(0.0) == 0L; | |
72 | this(0.0); | |
79 | 73 | } |
80 | 74 | |
81 | 75 | /** |
84 | 78 | * @return the current value |
85 | 79 | */ |
86 | 80 | public final double get() { |
87 | return longBitsToDouble(value); | |
81 | return longBitsToDouble(value.get()); | |
88 | 82 | } |
89 | 83 | |
90 | 84 | /** |
94 | 88 | */ |
95 | 89 | public final void set(double newValue) { |
96 | 90 | long next = doubleToRawLongBits(newValue); |
97 | value = next; | |
91 | value.set(next); | |
98 | 92 | } |
99 | 93 | |
100 | 94 | /** |
104 | 98 | */ |
105 | 99 | public final void lazySet(double newValue) { |
106 | 100 | long next = doubleToRawLongBits(newValue); |
107 | updater.lazySet(this, next); | |
101 | value.lazySet(next); | |
108 | 102 | } |
109 | 103 | |
110 | 104 | /** |
115 | 109 | */ |
116 | 110 | public final double getAndSet(double newValue) { |
117 | 111 | long next = doubleToRawLongBits(newValue); |
118 | return longBitsToDouble(updater.getAndSet(this, next)); | |
112 | return longBitsToDouble(value.getAndSet(next)); | |
119 | 113 | } |
120 | 114 | |
121 | 115 | /** |
129 | 123 | * the actual value was not bitwise equal to the expected value. |
130 | 124 | */ |
131 | 125 | public final boolean compareAndSet(double expect, double update) { |
132 | return updater.compareAndSet(this, | |
126 | return value.compareAndSet( | |
133 | 127 | doubleToRawLongBits(expect), |
134 | 128 | doubleToRawLongBits(update)); |
135 | 129 | } |
150 | 144 | * @return {@code true} if successful |
151 | 145 | */ |
152 | 146 | public final boolean weakCompareAndSet(double expect, double update) { |
153 | return updater.weakCompareAndSet(this, | |
147 | return value.weakCompareAndSet( | |
154 | 148 | doubleToRawLongBits(expect), |
155 | 149 | doubleToRawLongBits(update)); |
156 | 150 | } |
164 | 158 | @CanIgnoreReturnValue |
165 | 159 | public final double getAndAdd(double delta) { |
166 | 160 | while (true) { |
167 | long current = value; | |
161 | long current = value.get(); | |
168 | 162 | double currentVal = longBitsToDouble(current); |
169 | 163 | double nextVal = currentVal + delta; |
170 | 164 | long next = doubleToRawLongBits(nextVal); |
171 | if (updater.compareAndSet(this, current, next)) { | |
165 | if (value.compareAndSet(current, next)) { | |
172 | 166 | return currentVal; |
173 | 167 | } |
174 | 168 | } |
183 | 177 | @CanIgnoreReturnValue |
184 | 178 | public final double addAndGet(double delta) { |
185 | 179 | while (true) { |
186 | long current = value; | |
180 | long current = value.get(); | |
187 | 181 | double currentVal = longBitsToDouble(current); |
188 | 182 | double nextVal = currentVal + delta; |
189 | 183 | long next = doubleToRawLongBits(nextVal); |
190 | if (updater.compareAndSet(this, current, next)) { | |
184 | if (value.compareAndSet(current, next)) { | |
191 | 185 | return nextVal; |
192 | 186 | } |
193 | 187 | } |
250 | 244 | private void readObject(java.io.ObjectInputStream s) |
251 | 245 | throws java.io.IOException, ClassNotFoundException { |
252 | 246 | s.defaultReadObject(); |
253 | ||
247 | value = new AtomicLong(); | |
254 | 248 | set(s.readDouble()); |
255 | 249 | } |
256 | 250 | } |
0 | /* | |
1 | * Copyright (C) 2017 The Guava Authors | |
2 | * | |
3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except | |
4 | * in compliance with the License. You may obtain a copy of the License at | |
5 | * | |
6 | * http://www.apache.org/licenses/LICENSE-2.0 | |
7 | * | |
8 | * Unless required by applicable law or agreed to in writing, software distributed under the License | |
9 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express | |
10 | * or implied. See the License for the specific language governing permissions and limitations under | |
11 | * the License. | |
12 | */ | |
13 | ||
14 | package com.google.common.util.concurrent; | |
15 | ||
16 | import java.util.Date; | |
17 | import java.util.concurrent.TimeUnit; | |
18 | import java.util.concurrent.locks.Condition; | |
19 | ||
20 | /** Forwarding wrapper around a {@code Condition}. */ | |
21 | abstract class ForwardingCondition implements Condition { | |
22 | abstract Condition delegate(); | |
23 | ||
24 | @Override | |
25 | public void await() throws InterruptedException { | |
26 | delegate().await(); | |
27 | } | |
28 | ||
29 | @Override | |
30 | public void awaitUninterruptibly() { | |
31 | delegate().awaitUninterruptibly(); | |
32 | } | |
33 | ||
34 | @Override | |
35 | public long awaitNanos(long nanosTimeout) throws InterruptedException { | |
36 | return delegate().awaitNanos(nanosTimeout); | |
37 | } | |
38 | ||
39 | @Override | |
40 | public boolean await(long time, TimeUnit unit) throws InterruptedException { | |
41 | return delegate().await(time, unit); | |
42 | } | |
43 | ||
44 | @Override | |
45 | public boolean awaitUntil(Date deadline) throws InterruptedException { | |
46 | return delegate().awaitUntil(deadline); | |
47 | } | |
48 | ||
49 | @Override | |
50 | public void signal() { | |
51 | delegate().signal(); | |
52 | } | |
53 | ||
54 | @Override | |
55 | public void signalAll() { | |
56 | delegate().signalAll(); | |
57 | } | |
58 | } |
0 | /* | |
1 | * Copyright (C) 2017 The Guava Authors | |
2 | * | |
3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except | |
4 | * in compliance with the License. You may obtain a copy of the License at | |
5 | * | |
6 | * http://www.apache.org/licenses/LICENSE-2.0 | |
7 | * | |
8 | * Unless required by applicable law or agreed to in writing, software distributed under the License | |
9 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express | |
10 | * or implied. See the License for the specific language governing permissions and limitations under | |
11 | * the License. | |
12 | */ | |
13 | ||
14 | package com.google.common.util.concurrent; | |
15 | ||
16 | import java.util.concurrent.TimeUnit; | |
17 | import java.util.concurrent.locks.Condition; | |
18 | import java.util.concurrent.locks.Lock; | |
19 | ||
20 | /** Forwarding wrapper around a {@code Lock}. */ | |
21 | abstract class ForwardingLock implements Lock { | |
22 | abstract Lock delegate(); | |
23 | ||
24 | @Override | |
25 | public void lock() { | |
26 | delegate().lock(); | |
27 | } | |
28 | ||
29 | @Override | |
30 | public void lockInterruptibly() throws InterruptedException { | |
31 | delegate().lockInterruptibly(); | |
32 | } | |
33 | ||
34 | @Override | |
35 | public boolean tryLock() { | |
36 | return delegate().tryLock(); | |
37 | } | |
38 | ||
39 | @Override | |
40 | public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { | |
41 | return delegate().tryLock(time, unit); | |
42 | } | |
43 | ||
44 | @Override | |
45 | public void unlock() { | |
46 | delegate().unlock(); | |
47 | } | |
48 | ||
49 | @Override | |
50 | public Condition newCondition() { | |
51 | return delegate().newCondition(); | |
52 | } | |
53 | } |
61 | 61 | Collections.synchronizedList(new ArrayList<PerListenerQueue<L>>()); |
62 | 62 | |
63 | 63 | /** Method reference-compatible listener event. */ |
64 | public interface Event<L> { | |
64 | interface Event<L> { | |
65 | 65 | /** Call a method on the listener. */ |
66 | 66 | void call(L listener); |
67 | 67 | } |
420 | 420 | * trucking. If an {@code Error} is thrown, the error will propagate and execution will stop until |
421 | 421 | * the next time a task is submitted. |
422 | 422 | * |
423 | * @deprecated Use {@link #newSequentialExecutor}. This method is scheduled for removal in | |
424 | * January 2018. | |
423 | 425 | * @since 23.1 |
426 | */ | |
427 | @Beta | |
428 | @Deprecated | |
429 | @GwtIncompatible | |
430 | public static Executor sequentialExecutor(Executor delegate) { | |
431 | return new SequentialExecutor(delegate); | |
432 | } | |
433 | ||
434 | /** | |
435 | * Returns an {@link Executor} that runs each task executed sequentially, such that no two tasks | |
436 | * are running concurrently. | |
437 | * | |
438 | * <p>The executor uses {@code delegate} in order to {@link Executor#execute execute} each task in | |
439 | * turn, and does not create any threads of its own. | |
440 | * | |
441 | * <p>After execution starts on the {@code delegate} {@link Executor}, tasks are polled and | |
442 | * executed from the queue until there are no more tasks. The thread will not be released until | |
443 | * there are no more tasks to run. | |
444 | * | |
445 | * <p>If a task is {@linkplain Thread#interrupt interrupted}, execution of subsequent tasks | |
446 | * continues. {@code RuntimeException}s thrown by tasks are simply logged and the executor keeps | |
447 | * trucking. If an {@code Error} is thrown, the error will propagate and execution will stop until | |
448 | * the next time a task is submitted. | |
449 | * | |
450 | * @since 23.3 (since 23.1 as {@link #sequentialExecutor(Executor)}) | |
424 | 451 | */ |
425 | 452 | @Beta |
426 | 453 | @GwtIncompatible |
427 | public static Executor sequentialExecutor(Executor delegate) { | |
454 | public static Executor newSequentialExecutor(Executor delegate) { | |
428 | 455 | return new SequentialExecutor(delegate); |
429 | 456 | } |
430 | 457 |
50 | 50 | |
51 | 51 | private final QueueWorker worker = new QueueWorker(); |
52 | 52 | |
53 | /** Use {@link MoreExecutors#sequentialExecutor} */ | |
53 | /** Use {@link MoreExecutors#newSequentialExecutor} */ | |
54 | 54 | SequentialExecutor(Executor executor) { |
55 | 55 | this.executor = Preconditions.checkNotNull(executor); |
56 | 56 | } |
34 | 34 | import java.util.concurrent.ConcurrentMap; |
35 | 35 | import java.util.concurrent.Semaphore; |
36 | 36 | import java.util.concurrent.atomic.AtomicReferenceArray; |
37 | import java.util.concurrent.locks.Condition; | |
37 | 38 | import java.util.concurrent.locks.Lock; |
38 | 39 | import java.util.concurrent.locks.ReadWriteLock; |
39 | 40 | import java.util.concurrent.locks.ReentrantLock; |
50 | 51 | * <p>The guarantee provided by this class is that equal keys lead to the same lock (or semaphore), |
51 | 52 | * i.e. {@code if (key1.equals(key2))} then {@code striped.get(key1) == striped.get(key2)} (assuming |
52 | 53 | * {@link Object#hashCode()} is correctly implemented for the keys). Note that if {@code key1} is |
53 | * <strong>not</strong> equal to {@code key2}, it is <strong>not</strong> guaranteed that | |
54 | * {@code striped.get(key1) != striped.get(key2)}; the elements might nevertheless be mapped to the | |
55 | * same lock. The lower the number of stripes, the higher the probability of this happening. | |
54 | * <strong>not</strong> equal to {@code key2}, it is <strong>not</strong> guaranteed that {@code | |
55 | * striped.get(key1) != striped.get(key2)}; the elements might nevertheless be mapped to the same | |
56 | * lock. The lower the number of stripes, the higher the probability of this happening. | |
56 | 57 | * |
57 | 58 | * <p>There are three flavors of this class: {@code Striped<Lock>}, {@code Striped<Semaphore>}, and |
58 | * {@code Striped<ReadWriteLock>}. For each type, two implementations are offered: | |
59 | * {@linkplain #lock(int) strong} and {@linkplain #lazyWeakLock(int) weak} {@code Striped<Lock>}, | |
60 | * {@linkplain #semaphore(int, int) strong} and {@linkplain #lazyWeakSemaphore(int, int) weak} | |
61 | * {@code Striped<Semaphore>}, and {@linkplain #readWriteLock(int) strong} and | |
62 | * {@linkplain #lazyWeakReadWriteLock(int) weak} {@code Striped<ReadWriteLock>}. <i>Strong</i> means | |
63 | * that all stripes (locks/semaphores) are initialized eagerly, and are not reclaimed unless | |
64 | * {@code Striped} itself is reclaimable. <i>Weak</i> means that locks/semaphores are created | |
65 | * lazily, and they are allowed to be reclaimed if nobody is holding on to them. This is useful, for | |
66 | * example, if one wants to create a {@code | |
67 | * Striped<Lock>} of many locks, but worries that in most cases only a small portion of these would | |
68 | * be in use. | |
59 | * {@code Striped<ReadWriteLock>}. For each type, two implementations are offered: {@linkplain | |
60 | * #lock(int) strong} and {@linkplain #lazyWeakLock(int) weak} {@code Striped<Lock>}, {@linkplain | |
61 | * #semaphore(int, int) strong} and {@linkplain #lazyWeakSemaphore(int, int) weak} {@code | |
62 | * Striped<Semaphore>}, and {@linkplain #readWriteLock(int) strong} and {@linkplain | |
63 | * #lazyWeakReadWriteLock(int) weak} {@code Striped<ReadWriteLock>}. <i>Strong</i> means that all | |
64 | * stripes (locks/semaphores) are initialized eagerly, and are not reclaimed unless {@code Striped} | |
65 | * itself is reclaimable. <i>Weak</i> means that locks/semaphores are created lazily, and they are | |
66 | * allowed to be reclaimed if nobody is holding on to them. This is useful, for example, if one | |
67 | * wants to create a {@code Striped<Lock>} of many locks, but worries that in most cases only a | |
68 | * small portion of these would be in use. | |
69 | 69 | * |
70 | 70 | * <p>Prior to this class, one might be tempted to use {@code Map<K, Lock>}, where {@code K} |
71 | 71 | * represents the task. This maximizes concurrency by having each unique key mapped to a unique |
92 | 92 | private Striped() {} |
93 | 93 | |
94 | 94 | /** |
95 | * Returns the stripe that corresponds to the passed key. It is always guaranteed that if | |
96 | * {@code key1.equals(key2)}, then {@code get(key1) == get(key2)}. | |
95 | * Returns the stripe that corresponds to the passed key. It is always guaranteed that if {@code | |
96 | * key1.equals(key2)}, then {@code get(key1) == get(key2)}. | |
97 | 97 | * |
98 | 98 | * @param key an arbitrary, non-null key |
99 | 99 | * @return the stripe that the passed key corresponds to |
114 | 114 | */ |
115 | 115 | abstract int indexFor(Object key); |
116 | 116 | |
117 | /** | |
118 | * Returns the total number of stripes in this instance. | |
119 | */ | |
117 | /** Returns the total number of stripes in this instance. */ | |
120 | 118 | public abstract int size(); |
121 | 119 | |
122 | 120 | /** |
123 | * Returns the stripes that correspond to the passed objects, in ascending (as per | |
124 | * {@link #getAt(int)}) order. Thus, threads that use the stripes in the order returned by this | |
125 | * method are guaranteed to not deadlock each other. | |
126 | * | |
127 | * <p>It should be noted that using a {@code Striped<L>} with relatively few stripes, and | |
128 | * {@code bulkGet(keys)} with a relative large number of keys can cause an excessive number of | |
129 | * shared stripes (much like the birthday paradox, where much fewer than anticipated birthdays are | |
130 | * needed for a pair of them to match). Please consider carefully the implications of the number | |
131 | * of stripes, the intended concurrency level, and the typical number of keys used in a | |
132 | * {@code bulkGet(keys)} operation. See <a href="http://www.mathpages.com/home/kmath199.htm">Balls | |
133 | * in Bins model</a> for mathematical formulas that can be used to estimate the probability of | |
121 | * Returns the stripes that correspond to the passed objects, in ascending (as per {@link | |
122 | * #getAt(int)}) order. Thus, threads that use the stripes in the order returned by this method | |
123 | * are guaranteed to not deadlock each other. | |
124 | * | |
125 | * <p>It should be noted that using a {@code Striped<L>} with relatively few stripes, and {@code | |
126 | * bulkGet(keys)} with a relative large number of keys can cause an excessive number of shared | |
127 | * stripes (much like the birthday paradox, where much fewer than anticipated birthdays are needed | |
128 | * for a pair of them to match). Please consider carefully the implications of the number of | |
129 | * stripes, the intended concurrency level, and the typical number of keys used in a {@code | |
130 | * bulkGet(keys)} operation. See <a href="http://www.mathpages.com/home/kmath199.htm">Balls in | |
131 | * Bins model</a> for mathematical formulas that can be used to estimate the probability of | |
134 | 132 | * collisions. |
135 | 133 | * |
136 | 134 | * @param keys arbitrary non-null keys |
283 | 281 | * @return a new {@code Striped<ReadWriteLock>} |
284 | 282 | */ |
285 | 283 | public static Striped<ReadWriteLock> lazyWeakReadWriteLock(int stripes) { |
286 | return lazy(stripes, READ_WRITE_LOCK_SUPPLIER); | |
287 | } | |
288 | ||
289 | // ReentrantReadWriteLock is large enough to make padding probably unnecessary | |
284 | return lazy(stripes, WEAK_SAFE_READ_WRITE_LOCK_SUPPLIER); | |
285 | } | |
286 | ||
290 | 287 | private static final Supplier<ReadWriteLock> READ_WRITE_LOCK_SUPPLIER = |
291 | 288 | new Supplier<ReadWriteLock>() { |
292 | 289 | @Override |
294 | 291 | return new ReentrantReadWriteLock(); |
295 | 292 | } |
296 | 293 | }; |
294 | ||
295 | private static final Supplier<ReadWriteLock> WEAK_SAFE_READ_WRITE_LOCK_SUPPLIER = | |
296 | new Supplier<ReadWriteLock>() { | |
297 | @Override | |
298 | public ReadWriteLock get() { | |
299 | return new WeakSafeReadWriteLock(); | |
300 | } | |
301 | }; | |
302 | ||
303 | /** | |
304 | * ReadWriteLock implementation whose read and write locks retain a reference back to this lock. | |
305 | * Otherwise, a reference to just the read lock or just the write lock would not suffice to ensure | |
306 | * the {@code ReadWriteLock} is retained. | |
307 | */ | |
308 | private static final class WeakSafeReadWriteLock implements ReadWriteLock { | |
309 | private final ReadWriteLock delegate; | |
310 | ||
311 | WeakSafeReadWriteLock() { | |
312 | this.delegate = new ReentrantReadWriteLock(); | |
313 | } | |
314 | ||
315 | @Override | |
316 | public Lock readLock() { | |
317 | return new WeakSafeLock(delegate.readLock(), this); | |
318 | } | |
319 | ||
320 | @Override | |
321 | public Lock writeLock() { | |
322 | return new WeakSafeLock(delegate.writeLock(), this); | |
323 | } | |
324 | } | |
325 | ||
326 | /** Lock object that ensures a strong reference is retained to a specified object. */ | |
327 | private static final class WeakSafeLock extends ForwardingLock { | |
328 | private final Lock delegate; | |
329 | ||
330 | @SuppressWarnings("unused") | |
331 | private final WeakSafeReadWriteLock strongReference; | |
332 | ||
333 | WeakSafeLock(Lock delegate, WeakSafeReadWriteLock strongReference) { | |
334 | this.delegate = delegate; | |
335 | this.strongReference = strongReference; | |
336 | } | |
337 | ||
338 | @Override | |
339 | Lock delegate() { | |
340 | return delegate; | |
341 | } | |
342 | ||
343 | @Override | |
344 | public Condition newCondition() { | |
345 | return new WeakSafeCondition(delegate.newCondition(), strongReference); | |
346 | } | |
347 | } | |
348 | ||
349 | /** Condition object that ensures a strong reference is retained to a specified object. */ | |
350 | private static final class WeakSafeCondition extends ForwardingCondition { | |
351 | private final Condition delegate; | |
352 | ||
353 | @SuppressWarnings("unused") | |
354 | private final WeakSafeReadWriteLock strongReference; | |
355 | ||
356 | WeakSafeCondition(Condition delegate, WeakSafeReadWriteLock strongReference) { | |
357 | this.delegate = delegate; | |
358 | this.strongReference = strongReference; | |
359 | } | |
360 | ||
361 | @Override | |
362 | Condition delegate() { | |
363 | return delegate; | |
364 | } | |
365 | } | |
297 | 366 | |
298 | 367 | private abstract static class PowerOfTwoStriped<L> extends Striped<L> { |
299 | 368 | /** Capacity (power of two) minus one, for fast mod evaluation */ |
456 | 525 | } |
457 | 526 | } |
458 | 527 | |
459 | /** | |
460 | * A bit mask were all bits are set. | |
461 | */ | |
528 | /** A bit mask were all bits are set. */ | |
462 | 529 | private static final int ALL_SET = ~0; |
463 | 530 | |
464 | 531 | private static int ceilToPowerOfTwo(int x) { |
13 | 13 | |
14 | 14 | package com.google.thirdparty.publicsuffix; |
15 | 15 | |
16 | import com.google.common.annotations.Beta; | |
16 | 17 | import com.google.common.annotations.GwtCompatible; |
17 | 18 | |
18 | 19 | /** |
19 | * Specifies the type of a top-level domain definition. | |
20 | * <b>Do not use this class directly. For access to public-suffix information, | |
21 | * use {@link com.google.common.net.InternetDomainName}.</b> | |
22 | * | |
23 | * <p>Specifies the type of a top-level domain definition. | |
24 | * | |
25 | * @since 23.3 | |
20 | 26 | */ |
27 | @Beta | |
21 | 28 | @GwtCompatible |
22 | enum PublicSuffixType { | |
29 | public enum PublicSuffixType { | |
23 | 30 | |
24 | /** private definition of a top-level domain */ | |
31 | /** Public suffix that is provided by a private company, e.g. "blogspot.com" */ | |
25 | 32 | PRIVATE(':', ','), |
26 | /** ICANN definition of a top-level domain */ | |
27 | ICANN('!', '?'); | |
33 | /** Public suffix that is backed by an ICANN-style domain name registry */ | |
34 | REGISTRY('!', '?'); | |
28 | 35 | |
29 | 36 | /** The character used for an inner node in the trie encoding */ |
30 | 37 | private final char innerNodeCode; |
56 | 63 | } |
57 | 64 | |
58 | 65 | static PublicSuffixType fromIsPrivate(boolean isPrivate) { |
59 | return isPrivate ? PRIVATE : ICANN; | |
66 | return isPrivate ? PRIVATE : REGISTRY; | |
60 | 67 | } |
61 | 68 | } |
17 | 17 | import com.google.common.base.Joiner; |
18 | 18 | import com.google.common.collect.ImmutableMap; |
19 | 19 | import com.google.common.collect.Lists; |
20 | ||
21 | 20 | import java.util.List; |
22 | 21 | |
23 | 22 | /** |
73 | 72 | stack.add(0, reverse(encoded.subSequence(0, idx))); |
74 | 73 | |
75 | 74 | if (c == '!' || c == '?' || c == ':' || c == ',') { |
76 | // '!' represents an interior node that represents an ICANN entry in the map. | |
77 | // '?' represents a leaf node, which represents an ICANN entry in map. | |
75 | // '!' represents an interior node that represents a REGISTRY entry in the map. | |
76 | // '?' represents a leaf node, which represents a REGISTRY entry in map. | |
78 | 77 | // ':' represents an interior node that represents a private entry in the map |
79 | 78 | // ',' represents a leaf node, which represents a private entry in the map. |
80 | 79 | String domain = PREFIX_JOINER.join(stack); |
4 | 4 | <parent> |
5 | 5 | <groupId>com.google.guava</groupId> |
6 | 6 | <artifactId>guava-parent</artifactId> |
7 | <version>23.2-android</version> | |
7 | <version>23.3-android</version> | |
8 | 8 | </parent> |
9 | 9 | <artifactId>guava-testlib</artifactId> |
10 | 10 | <name>Guava Testing Library</name> |
4 | 4 | <parent> |
5 | 5 | <groupId>com.google.guava</groupId> |
6 | 6 | <artifactId>guava-parent</artifactId> |
7 | <version>23.2-android</version> | |
7 | <version>23.3-android</version> | |
8 | 8 | </parent> |
9 | 9 | <artifactId>guava-tests</artifactId> |
10 | 10 | <name>Guava Unit Tests</name> |
149 | 149 | assertNotNull(getClass().getResource("internal/Finalizer.class")); |
150 | 150 | } |
151 | 151 | |
152 | public void testFinalizeClassHasNoNestedClases() throws Exception { | |
152 | public void testFinalizeClassHasNoNestedClasses() throws Exception { | |
153 | 153 | // Ensure that the Finalizer class has no nested classes. |
154 | 154 | // See https://code.google.com/p/guava-libraries/issues/detail?id=1505 |
155 | 155 | assertEquals(Collections.emptyList(), Arrays.asList(Finalizer.class.getDeclaredClasses())); |
99 | 99 | assertThat(letters).containsExactly("", "a", "b", "c").inOrder(); |
100 | 100 | } |
101 | 101 | |
102 | public void testCharacterSplitWithMultitpleLetters() { | |
102 | public void testCharacterSplitWithMultipleLetters() { | |
103 | 103 | Iterable<String> testCharacteringMotto = Splitter.on('-').split( |
104 | 104 | "Testing-rocks-Debugging-sucks"); |
105 | 105 | assertThat(testCharacteringMotto) |
114 | 114 | createDirectedGraph("hd", "he", "hg", "da", "db", "dc", "gf"); |
115 | 115 | |
116 | 116 | /** |
117 | * Two disjoint tree-shaped graphs that look as follows (all edges are directed facing downwards): | |
118 | * | |
119 | * <pre>{@code | |
120 | * a c | |
121 | * | | | |
122 | * | | | |
123 | * b d | |
124 | * }</pre> | |
125 | */ | |
126 | private static final SuccessorsFunction<Character> TWO_TREES = createDirectedGraph("ab", "cd"); | |
127 | ||
128 | /** | |
129 | * A graph consisting of a single root {@code a}: | |
130 | * | |
131 | * <pre>{@code | |
132 | * a | |
133 | * }</pre> | |
134 | */ | |
135 | private static final SuccessorsFunction<Character> SINGLE_ROOT = createSingleRootGraph(); | |
136 | ||
137 | /** | |
117 | 138 | * A graph that is not a tree (for example, it has two antiparallel edge between {@code e} and |
118 | 139 | * {@code f} and thus has a cycle) but is a valid input to {@link Traverser#forTree} when starting |
119 | 140 | * e.g. at node {@code a} (all edges without an arrow are directed facing downwards): |
198 | 219 | assertEqualCharNodes(traverser.breadthFirst('a'), "a"); |
199 | 220 | } |
200 | 221 | |
222 | @Test | |
223 | public void forGraph_breadthFirst_twoTrees() { | |
224 | Iterable<Character> result = Traverser.forGraph(TWO_TREES).breadthFirst('a'); | |
225 | ||
226 | assertEqualCharNodes(result, "ab"); | |
227 | } | |
228 | ||
229 | @Test | |
230 | public void forGraph_breadthFirst_singleRoot() { | |
231 | Iterable<Character> result = Traverser.forGraph(SINGLE_ROOT).breadthFirst('a'); | |
232 | ||
233 | assertEqualCharNodes(result, "a"); | |
234 | } | |
235 | ||
236 | @Test | |
237 | public void forGraph_breadthFirst_emptyGraph() { | |
238 | try { | |
239 | Traverser.forGraph(createDirectedGraph()).breadthFirst('a'); | |
240 | fail("Expected IllegalArgumentException"); | |
241 | } catch (IllegalArgumentException expected) { | |
242 | } | |
243 | } | |
244 | ||
201 | 245 | /** |
202 | 246 | * Checks that the elements of the iterable are calculated on the fly. Concretely, that means that |
203 | 247 | * {@link SuccessorsFunction#successors(Object)} can only be called for a subset of all nodes. |
208 | 252 | Iterable<Character> result = Traverser.forGraph(graph).breadthFirst('a'); |
209 | 253 | |
210 | 254 | assertEqualCharNodes(Iterables.limit(result, 2), "ab"); |
211 | assertThat(graph.requestedNodes).containsExactly('a', 'b'); | |
255 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'b'); | |
212 | 256 | |
213 | 257 | // Iterate again to see if calculation is done again |
214 | 258 | assertEqualCharNodes(Iterables.limit(result, 2), "ab"); |
215 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'b', 'b'); | |
259 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'a', 'b', 'b'); | |
216 | 260 | } |
217 | 261 | |
218 | 262 | @Test |
269 | 313 | } |
270 | 314 | |
271 | 315 | @Test |
316 | public void forGraph_depthFirstPreOrder_twoTrees() { | |
317 | Iterable<Character> result = Traverser.forGraph(TWO_TREES).depthFirstPreOrder('a'); | |
318 | ||
319 | assertEqualCharNodes(result, "ab"); | |
320 | } | |
321 | ||
322 | @Test | |
323 | public void forGraph_depthFirstPreOrder_singleRoot() { | |
324 | Iterable<Character> result = Traverser.forGraph(SINGLE_ROOT).depthFirstPreOrder('a'); | |
325 | ||
326 | assertEqualCharNodes(result, "a"); | |
327 | } | |
328 | ||
329 | @Test | |
330 | public void forGraph_depthFirstPreOrder_emptyGraph() { | |
331 | try { | |
332 | Traverser.forGraph(createDirectedGraph()).depthFirstPreOrder('a'); | |
333 | fail("Expected IllegalArgumentException"); | |
334 | } catch (IllegalArgumentException expected) { | |
335 | } | |
336 | } | |
337 | ||
338 | @Test | |
272 | 339 | public void forGraph_depthFirstPreOrder_iterableIsLazy() { |
273 | 340 | RequestSavingGraph graph = new RequestSavingGraph(DIAMOND_GRAPH); |
274 | 341 | Iterable<Character> result = Traverser.forGraph(graph).depthFirstPreOrder('a'); |
275 | 342 | |
276 | 343 | assertEqualCharNodes(Iterables.limit(result, 2), "ab"); |
277 | assertThat(graph.requestedNodes).containsExactly('a', 'b', 'd'); | |
344 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'b', 'd'); | |
278 | 345 | |
279 | 346 | // Iterate again to see if calculation is done again |
280 | 347 | assertEqualCharNodes(Iterables.limit(result, 2), "ab"); |
281 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'b', 'b', 'd', 'd'); | |
348 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'a', 'b', 'b', 'd', 'd'); | |
282 | 349 | } |
283 | 350 | |
284 | 351 | @Test |
334 | 401 | } |
335 | 402 | |
336 | 403 | @Test |
404 | public void forGraph_depthFirstPostOrder_twoTrees() { | |
405 | Iterable<Character> result = Traverser.forGraph(TWO_TREES).depthFirstPostOrder('a'); | |
406 | ||
407 | assertEqualCharNodes(result, "ba"); | |
408 | } | |
409 | ||
410 | @Test | |
411 | public void forGraph_depthFirstPostOrder_singleRoot() { | |
412 | Iterable<Character> result = Traverser.forGraph(SINGLE_ROOT).depthFirstPostOrder('a'); | |
413 | ||
414 | assertEqualCharNodes(result, "a"); | |
415 | } | |
416 | ||
417 | @Test | |
418 | public void forGraph_depthFirstPostOrder_emptyGraph() { | |
419 | try { | |
420 | Traverser.forGraph(createDirectedGraph()).depthFirstPostOrder('a'); | |
421 | fail("Expected IllegalArgumentException"); | |
422 | } catch (IllegalArgumentException expected) { | |
423 | } | |
424 | } | |
425 | ||
426 | @Test | |
337 | 427 | public void forGraph_depthFirstPostOrder_iterableIsLazy() { |
338 | 428 | RequestSavingGraph graph = new RequestSavingGraph(DIAMOND_GRAPH); |
339 | 429 | Iterable<Character> result = Traverser.forGraph(graph).depthFirstPostOrder('a'); |
340 | 430 | |
341 | 431 | assertEqualCharNodes(Iterables.limit(result, 2), "db"); |
342 | assertThat(graph.requestedNodes).containsExactly('a', 'b', 'd'); | |
432 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'b', 'd'); | |
343 | 433 | |
344 | 434 | // Iterate again to see if calculation is done again |
345 | 435 | assertEqualCharNodes(Iterables.limit(result, 2), "db"); |
346 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'b', 'b', 'd', 'd'); | |
436 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'a', 'b', 'b', 'd', 'd'); | |
347 | 437 | } |
348 | 438 | |
349 | 439 | @Test |
437 | 527 | } |
438 | 528 | |
439 | 529 | @Test |
530 | public void forTree_breadthFirst_twoTrees() { | |
531 | Iterable<Character> result = Traverser.forTree(TWO_TREES).breadthFirst('a'); | |
532 | ||
533 | assertEqualCharNodes(result, "ab"); | |
534 | } | |
535 | ||
536 | @Test | |
537 | public void forTree_breadthFirst_singleRoot() { | |
538 | Iterable<Character> result = Traverser.forTree(SINGLE_ROOT).breadthFirst('a'); | |
539 | ||
540 | assertEqualCharNodes(result, "a"); | |
541 | } | |
542 | ||
543 | @Test | |
544 | public void forTree_breadthFirst_emptyGraph() { | |
545 | try { | |
546 | Traverser.forTree(createDirectedGraph()).breadthFirst('a'); | |
547 | fail("Expected IllegalArgumentException"); | |
548 | } catch (IllegalArgumentException expected) { | |
549 | } | |
550 | } | |
551 | ||
552 | @Test | |
440 | 553 | public void forTree_breadthFirst_iterableIsLazy() { |
441 | 554 | RequestSavingGraph graph = new RequestSavingGraph(TREE); |
442 | 555 | Iterable<Character> result = Traverser.forGraph(graph).breadthFirst('h'); |
443 | 556 | |
444 | 557 | assertEqualCharNodes(Iterables.limit(result, 2), "hd"); |
445 | assertThat(graph.requestedNodes).containsExactly('h', 'd'); | |
558 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'd'); | |
446 | 559 | |
447 | 560 | // Iterate again to see if calculation is done again |
448 | 561 | assertEqualCharNodes(Iterables.limit(result, 2), "hd"); |
449 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'd', 'd'); | |
562 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'h', 'd', 'd'); | |
450 | 563 | } |
451 | 564 | |
452 | 565 | @Test |
477 | 590 | } |
478 | 591 | |
479 | 592 | @Test |
593 | public void forTree_depthFirstPreOrder_twoTrees() { | |
594 | Iterable<Character> result = Traverser.forTree(TWO_TREES).depthFirstPreOrder('a'); | |
595 | ||
596 | assertEqualCharNodes(result, "ab"); | |
597 | } | |
598 | ||
599 | @Test | |
600 | public void forTree_depthFirstPreOrder_singleRoot() { | |
601 | Iterable<Character> result = Traverser.forTree(SINGLE_ROOT).depthFirstPreOrder('a'); | |
602 | ||
603 | assertEqualCharNodes(result, "a"); | |
604 | } | |
605 | ||
606 | @Test | |
607 | public void forTree_depthFirstPreOrder_emptyGraph() { | |
608 | try { | |
609 | Traverser.forTree(createDirectedGraph()).depthFirstPreOrder('a'); | |
610 | fail("Expected IllegalArgumentException"); | |
611 | } catch (IllegalArgumentException expected) { | |
612 | } | |
613 | } | |
614 | ||
615 | @Test | |
480 | 616 | public void forTree_depthFirstPreOrder_iterableIsLazy() { |
481 | 617 | RequestSavingGraph graph = new RequestSavingGraph(TREE); |
482 | 618 | Iterable<Character> result = Traverser.forGraph(graph).depthFirstPreOrder('h'); |
483 | 619 | |
484 | 620 | assertEqualCharNodes(Iterables.limit(result, 2), "hd"); |
485 | assertThat(graph.requestedNodes).containsExactly('h', 'd', 'a'); | |
621 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'd', 'a'); | |
486 | 622 | |
487 | 623 | // Iterate again to see if calculation is done again |
488 | 624 | assertEqualCharNodes(Iterables.limit(result, 2), "hd"); |
489 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'd', 'd', 'a', 'a'); | |
625 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'h', 'd', 'd', 'a', 'a'); | |
490 | 626 | } |
491 | 627 | |
492 | 628 | @Test |
517 | 653 | } |
518 | 654 | |
519 | 655 | @Test |
656 | public void forTree_depthFirstPostOrder_twoTrees() { | |
657 | Iterable<Character> result = Traverser.forTree(TWO_TREES).depthFirstPostOrder('a'); | |
658 | ||
659 | assertEqualCharNodes(result, "ba"); | |
660 | } | |
661 | ||
662 | @Test | |
663 | public void forTree_depthFirstPostOrder_singleRoot() { | |
664 | Iterable<Character> result = Traverser.forTree(SINGLE_ROOT).depthFirstPostOrder('a'); | |
665 | ||
666 | assertEqualCharNodes(result, "a"); | |
667 | } | |
668 | ||
669 | @Test | |
670 | public void forTree_depthFirstPostOrder_emptyGraph() { | |
671 | try { | |
672 | Traverser.forTree(createDirectedGraph()).depthFirstPostOrder('a'); | |
673 | fail("Expected IllegalArgumentException"); | |
674 | } catch (IllegalArgumentException expected) { | |
675 | } | |
676 | } | |
677 | ||
678 | @Test | |
520 | 679 | public void forTree_depthFirstPostOrder_iterableIsLazy() { |
521 | 680 | RequestSavingGraph graph = new RequestSavingGraph(TREE); |
522 | 681 | Iterable<Character> result = Traverser.forGraph(graph).depthFirstPostOrder('h'); |
523 | 682 | |
524 | 683 | assertEqualCharNodes(Iterables.limit(result, 2), "ab"); |
525 | assertThat(graph.requestedNodes).containsExactly('h', 'd', 'a', 'b'); | |
684 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'd', 'a', 'b'); | |
526 | 685 | |
527 | 686 | // Iterate again to see if calculation is done again |
528 | 687 | assertEqualCharNodes(Iterables.limit(result, 2), "ab"); |
529 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'd', 'd', 'a', 'a', 'b', 'b'); | |
688 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'h', 'd', 'd', 'a', 'a', 'b', 'b'); | |
530 | 689 | } |
531 | 690 | |
532 | 691 | private static SuccessorsFunction<Character> createDirectedGraph(String... edges) { |
560 | 719 | return new SuccessorsFunction<Character>() { |
561 | 720 | @Override |
562 | 721 | public Iterable<? extends Character> successors(Character node) { |
722 | checkArgument( | |
723 | graphMap.containsKey(node) || graphMap.containsValue(node), | |
724 | "Node %s is not an element of this graph", | |
725 | node); | |
563 | 726 | return Ordering.natural().immutableSortedCopy(graphMap.get(node)); |
564 | 727 | } |
565 | 728 | }; |
729 | } | |
730 | ||
731 | private static ImmutableGraph<Character> createSingleRootGraph() { | |
732 | MutableGraph<Character> graph = GraphBuilder.directed().build(); | |
733 | graph.addNode('a'); | |
734 | return ImmutableGraph.copyOf(graph); | |
566 | 735 | } |
567 | 736 | |
568 | 737 | private static void assertEqualCharNodes(Iterable<Character> result, String expectedCharacters) { |
58 | 58 | assertCrc(0x113fdb5c, descending); |
59 | 59 | } |
60 | 60 | |
61 | public void testScsiReadCommad() { | |
61 | public void testScsiReadCommand() { | |
62 | 62 | // Test SCSI read command. |
63 | 63 | byte[] scsiReadCommand = new byte[] { |
64 | 64 | 0x01, (byte) 0xc0, 0x00, 0x00, |
19 | 19 | import static com.google.common.math.MathTesting.FINITE_DOUBLE_CANDIDATES; |
20 | 20 | import static com.google.common.math.MathTesting.POSITIVE_FINITE_DOUBLE_CANDIDATES; |
21 | 21 | |
22 | import java.lang.reflect.Method; | |
22 | 23 | import java.math.BigInteger; |
23 | 24 | import junit.framework.TestCase; |
24 | import sun.misc.FpUtils; | |
25 | 25 | |
26 | 26 | /** |
27 | 27 | * Tests for {@link DoubleUtils}. |
29 | 29 | * @author Louis Wasserman |
30 | 30 | */ |
31 | 31 | public class DoubleUtilsTest extends TestCase { |
32 | @AndroidIncompatible // no FpUtils | |
33 | public void testNextDown() { | |
32 | @AndroidIncompatible // no FpUtils and no Math.nextDown in old versions | |
33 | public void testNextDown() throws Exception { | |
34 | Method jdkNextDown = getJdkNextDown(); | |
34 | 35 | for (double d : FINITE_DOUBLE_CANDIDATES) { |
35 | assertEquals(FpUtils.nextDown(d), DoubleUtils.nextDown(d)); | |
36 | assertEquals(jdkNextDown.invoke(null, d), DoubleUtils.nextDown(d)); | |
37 | } | |
38 | } | |
39 | ||
40 | private static Method getJdkNextDown() throws Exception { | |
41 | try { | |
42 | return Math.class.getMethod("nextDown", double.class); | |
43 | } catch (NoSuchMethodException expectedBeforeJava8) { | |
44 | return Class.forName("sun.misc.FpUtils").getMethod("nextDown", double.class); | |
36 | 45 | } |
37 | 46 | } |
38 | 47 |
95 | 95 | ALMOST_TOO_MANY_LEVELS + "com", |
96 | 96 | ALMOST_TOO_LONG + ".c"); |
97 | 97 | |
98 | private static final ImmutableSet<String> PS = ImmutableSet.of( | |
99 | "com", | |
100 | "co.uk", | |
101 | "foo.bd", | |
102 | "xxxxxx.bd", | |
103 | "org.mK", | |
104 | "us", | |
105 | "uk\uFF61com.", // Alternate dot character | |
106 | "\u7f51\u7edc.Cn", // "网络.Cn" | |
107 | "j\u00f8rpeland.no", // "jorpeland.no" (first o slashed) | |
108 | "xn--jrpeland-54a.no" // IDNA (punycode) encoding of above | |
109 | ); | |
98 | private static final ImmutableSet<String> RS = | |
99 | ImmutableSet.of( | |
100 | "com", | |
101 | "co.uk", | |
102 | "foo.bd", | |
103 | "xxxxxx.bd", | |
104 | "org.mK", | |
105 | "us", | |
106 | "co.uk.", // Trailing dot | |
107 | "co\uFF61uk", // Alternate dot character | |
108 | "\u7f51\u7edc.Cn", // "网络.Cn" | |
109 | "j\u00f8rpeland.no", // "jorpeland.no" (first o slashed) | |
110 | "xn--jrpeland-54a.no"); // IDNA (punycode) encoding of above | |
111 | ||
112 | private static final ImmutableSet<String> PS_NOT_RS = | |
113 | ImmutableSet.of("blogspot.com", "blogspot.co.uk", "uk.com"); | |
114 | ||
115 | private static final ImmutableSet<String> PS = | |
116 | ImmutableSet.<String>builder().addAll(RS).addAll(PS_NOT_RS).build(); | |
110 | 117 | |
111 | 118 | private static final ImmutableSet<String> NO_PS = ImmutableSet.of( |
112 | 119 | "www", "foo.ihopethiswillneverbeapublicsuffix", "x.y.z"); |
113 | 120 | |
114 | private static final ImmutableSet<String> NON_PS = ImmutableSet.of( | |
115 | "foo.bar.com", "foo.ca", "foo.bar.ca", | |
116 | "foo.bar.co.il", "state.CA.us", "www.state.pa.us", "pvt.k12.ca.us", | |
117 | "www.google.com", "www4.yahoo.co.uk", "home.netscape.com", | |
118 | "web.MIT.edu", "foo.eDu.au", "utenti.blah.IT", "dominio.com.co"); | |
121 | /** | |
122 | * Having a public suffix is equivalent to having a registry suffix, because all registry suffixes | |
123 | * are public suffixes, and all public suffixes have registry suffixes. | |
124 | */ | |
125 | private static final ImmutableSet<String> NO_RS = NO_PS; | |
126 | ||
127 | private static final ImmutableSet<String> NON_PS = | |
128 | ImmutableSet.of( | |
129 | "foo.bar.com", | |
130 | "foo.ca", | |
131 | "foo.bar.ca", | |
132 | "foo.blogspot.com", | |
133 | "foo.blogspot.co.uk", | |
134 | "foo.uk.com", | |
135 | "foo.bar.co.il", | |
136 | "state.CA.us", | |
137 | "www.state.pa.us", | |
138 | "pvt.k12.ca.us", | |
139 | "www.google.com", | |
140 | "www4.yahoo.co.uk", | |
141 | "home.netscape.com", | |
142 | "web.MIT.edu", | |
143 | "foo.eDu.au", | |
144 | "utenti.blah.IT", | |
145 | "dominio.com.co"); | |
146 | ||
147 | private static final ImmutableSet<String> NON_RS = | |
148 | ImmutableSet.<String>builder().addAll(NON_PS).addAll(PS_NOT_RS).build(); | |
149 | ||
150 | private static final ImmutableSet<String> TOP_UNDER_REGISTRY_SUFFIX = | |
151 | ImmutableSet.of("google.com", "foo.Co.uk", "foo.ca.us."); | |
119 | 152 | |
120 | 153 | private static final ImmutableSet<String> TOP_PRIVATE_DOMAIN = |
121 | ImmutableSet.of("google.com", "foo.Co.uk", "foo.ca.us."); | |
154 | ImmutableSet.of("google.com", "foo.Co.uk", "foo.ca.us.", "foo.blogspot.com"); | |
155 | ||
156 | private static final ImmutableSet<String> UNDER_TOP_UNDER_REGISTRY_SUFFIX = | |
157 | ImmutableSet.of("foo.bar.google.com", "a.b.co.uk", "x.y.ca.us"); | |
122 | 158 | |
123 | 159 | private static final ImmutableSet<String> UNDER_PRIVATE_DOMAIN = |
124 | ImmutableSet.of("foo.bar.google.com", "a.b.co.uk", "x.y.ca.us"); | |
160 | ImmutableSet.of("foo.bar.google.com", "a.b.co.uk", "x.y.ca.us", "a.b.blogspot.com"); | |
125 | 161 | |
126 | 162 | private static final ImmutableSet<String> VALID_IP_ADDRS = ImmutableSet.of( |
127 | 163 | "1.2.3.4", "127.0.0.1", "::1", "2001:db8::1"); |
191 | 227 | "a\u7f51\u7edcA.\u7f51\u7edc.Cn" // "a网络A.网络.Cn" |
192 | 228 | ); |
193 | 229 | |
230 | private static final ImmutableSet<String> SOMEWHERE_UNDER_RS = | |
231 | ImmutableSet.<String>builder().addAll(SOMEWHERE_UNDER_PS).addAll(PS_NOT_RS).build(); | |
232 | ||
194 | 233 | public void testValid() { |
195 | 234 | for (String name : VALID_NAME) { |
196 | 235 | InternetDomainName.from(name); |
261 | 300 | assertTrue(name, domain.hasPublicSuffix()); |
262 | 301 | assertTrue(name, domain.isUnderPublicSuffix()); |
263 | 302 | assertFalse(name, domain.isTopPrivateDomain()); |
303 | } | |
304 | } | |
305 | ||
306 | public void testRegistrySuffix() { | |
307 | for (String name : RS) { | |
308 | final InternetDomainName domain = InternetDomainName.from(name); | |
309 | assertTrue(name, domain.isRegistrySuffix()); | |
310 | assertTrue(name, domain.hasRegistrySuffix()); | |
311 | assertFalse(name, domain.isUnderRegistrySuffix()); | |
312 | assertFalse(name, domain.isTopDomainUnderRegistrySuffix()); | |
313 | assertEquals(domain, domain.registrySuffix()); | |
314 | } | |
315 | ||
316 | for (String name : NO_RS) { | |
317 | final InternetDomainName domain = InternetDomainName.from(name); | |
318 | assertFalse(name, domain.isRegistrySuffix()); | |
319 | assertFalse(name, domain.hasRegistrySuffix()); | |
320 | assertFalse(name, domain.isUnderRegistrySuffix()); | |
321 | assertFalse(name, domain.isTopDomainUnderRegistrySuffix()); | |
322 | assertNull(domain.registrySuffix()); | |
323 | } | |
324 | ||
325 | for (String name : NON_RS) { | |
326 | final InternetDomainName domain = InternetDomainName.from(name); | |
327 | assertFalse(name, domain.isRegistrySuffix()); | |
328 | assertTrue(name, domain.hasRegistrySuffix()); | |
329 | assertTrue(name, domain.isUnderRegistrySuffix()); | |
330 | } | |
331 | } | |
332 | ||
333 | public void testUnderRegistrySuffix() { | |
334 | for (String name : SOMEWHERE_UNDER_RS) { | |
335 | final InternetDomainName domain = InternetDomainName.from(name); | |
336 | assertFalse(name, domain.isRegistrySuffix()); | |
337 | assertTrue(name, domain.hasRegistrySuffix()); | |
338 | assertTrue(name, domain.isUnderRegistrySuffix()); | |
339 | } | |
340 | } | |
341 | ||
342 | public void testTopDomainUnderRegistrySuffix() { | |
343 | for (String name : TOP_UNDER_REGISTRY_SUFFIX) { | |
344 | final InternetDomainName domain = InternetDomainName.from(name); | |
345 | assertFalse(name, domain.isRegistrySuffix()); | |
346 | assertTrue(name, domain.hasRegistrySuffix()); | |
347 | assertTrue(name, domain.isUnderRegistrySuffix()); | |
348 | assertTrue(name, domain.isTopDomainUnderRegistrySuffix()); | |
349 | assertEquals(domain.parent(), domain.registrySuffix()); | |
350 | } | |
351 | } | |
352 | ||
353 | public void testUnderTopDomainUnderRegistrySuffix() { | |
354 | for (String name : UNDER_TOP_UNDER_REGISTRY_SUFFIX) { | |
355 | final InternetDomainName domain = InternetDomainName.from(name); | |
356 | assertFalse(name, domain.isRegistrySuffix()); | |
357 | assertTrue(name, domain.hasRegistrySuffix()); | |
358 | assertTrue(name, domain.isUnderRegistrySuffix()); | |
359 | assertFalse(name, domain.isTopDomainUnderRegistrySuffix()); | |
264 | 360 | } |
265 | 361 | } |
266 | 362 | |
362 | 458 | } |
363 | 459 | } |
364 | 460 | |
365 | public void testExclusion() { | |
461 | public void testPublicSuffixExclusion() { | |
366 | 462 | InternetDomainName domain = InternetDomainName.from("foo.city.yokohama.jp"); |
367 | 463 | assertTrue(domain.hasPublicSuffix()); |
368 | 464 | assertEquals("yokohama.jp", domain.publicSuffix().toString()); |
371 | 467 | assertFalse(domain.publicSuffix().isPublicSuffix()); |
372 | 468 | } |
373 | 469 | |
374 | public void testMultipleUnders() { | |
470 | public void testPublicSuffixMultipleUnders() { | |
375 | 471 | // PSL has both *.uk and *.sch.uk; the latter should win. |
376 | 472 | // See http://code.google.com/p/guava-libraries/issues/detail?id=1176 |
377 | 473 | |
379 | 475 | assertTrue(domain.hasPublicSuffix()); |
380 | 476 | assertEquals("essex.sch.uk", domain.publicSuffix().toString()); |
381 | 477 | assertEquals("www.essex.sch.uk", domain.topPrivateDomain().toString()); |
478 | } | |
479 | ||
480 | public void testRegistrySuffixExclusion() { | |
481 | InternetDomainName domain = InternetDomainName.from("foo.city.yokohama.jp"); | |
482 | assertTrue(domain.hasRegistrySuffix()); | |
483 | assertEquals("yokohama.jp", domain.registrySuffix().toString()); | |
484 | ||
485 | // Behold the weirdness! | |
486 | assertFalse(domain.registrySuffix().isRegistrySuffix()); | |
487 | } | |
488 | ||
489 | public void testRegistrySuffixMultipleUnders() { | |
490 | // PSL has both *.uk and *.sch.uk; the latter should win. | |
491 | // See http://code.google.com/p/guava-libraries/issues/detail?id=1176 | |
492 | ||
493 | InternetDomainName domain = InternetDomainName.from("www.essex.sch.uk"); | |
494 | assertTrue(domain.hasRegistrySuffix()); | |
495 | assertEquals("essex.sch.uk", domain.registrySuffix().toString()); | |
496 | assertEquals("www.essex.sch.uk", domain.topDomainUnderRegistrySuffix().toString()); | |
382 | 497 | } |
383 | 498 | |
384 | 499 | public void testEquality() { |
345 | 345 | testSortDescending(new double[] {1, 2}, new double[] {2, 1}); |
346 | 346 | testSortDescending(new double[] {1, 3, 1}, new double[] {3, 1, 1}); |
347 | 347 | testSortDescending(new double[] {-1, 1, -2, 2}, new double[] {2, 1, -1, -2}); |
348 | testSortDescending( | |
349 | new double[] {-1, 1, Double.NaN, -2, -0, 0, 2}, | |
350 | new double[] {Double.NaN, 2, 1, 0, -0, -1, -2}); | |
348 | if (sortWorksWithNaN()) { | |
349 | testSortDescending( | |
350 | new double[] {-1, 1, Double.NaN, -2, -0, 0, 2}, | |
351 | new double[] {Double.NaN, 2, 1, 0, -0, -1, -2}); | |
352 | } | |
351 | 353 | } |
352 | 354 | |
353 | 355 | public void testSortDescendingIndexed() { |
357 | 359 | testSortDescending(new double[] {1, 3, 1}, 0, 2, new double[] {3, 1, 1}); |
358 | 360 | testSortDescending(new double[] {1, 3, 1}, 0, 1, new double[] {1, 3, 1}); |
359 | 361 | testSortDescending(new double[] {-1, -2, 1, 2}, 1, 3, new double[] {-1, 1, -2, 2}); |
360 | testSortDescending( | |
361 | new double[] {-1, 1, Double.NaN, -2, 2}, 1, 4, new double[] {-1, Double.NaN, 1, -2, 2}); | |
362 | if (sortWorksWithNaN()) { | |
363 | testSortDescending( | |
364 | new double[] {-1, 1, Double.NaN, -2, 2}, 1, 4, new double[] {-1, Double.NaN, 1, -2, 2}); | |
365 | } | |
362 | 366 | } |
363 | 367 | |
364 | 368 | private static void testSortDescending(double[] input, double[] expectedOutput) { |
378 | 382 | for (int i = 0; i < input.length; i++) { |
379 | 383 | assertEquals(0, Double.compare(expectedOutput[i], input[i])); |
380 | 384 | } |
385 | } | |
386 | ||
387 | @GwtIncompatible // works with real browsers but fails with HtmlUnit | |
388 | public void testSortWorksWithNaNNonGwt() { | |
389 | assertTrue(sortWorksWithNaN()); | |
381 | 390 | } |
382 | 391 | |
383 | 392 | @GwtIncompatible // SerializableTester |
652 | 661 | } catch (NullPointerException expected) { |
653 | 662 | } |
654 | 663 | } |
664 | ||
665 | // HtmlUnit looks to be sorting double[] wrongly. We detect that and skip our tests there. | |
666 | private static boolean sortWorksWithNaN() { | |
667 | double[] array = new double[] {NaN, 0}; | |
668 | Arrays.sort(array); | |
669 | return array[0] == 0; | |
670 | } | |
655 | 671 | } |
342 | 342 | testSortDescending(new float[] {1, 2}, new float[] {2, 1}); |
343 | 343 | testSortDescending(new float[] {1, 3, 1}, new float[] {3, 1, 1}); |
344 | 344 | testSortDescending(new float[] {-1, 1, -2, 2}, new float[] {2, 1, -1, -2}); |
345 | testSortDescending( | |
346 | new float[] {-1, 1, Float.NaN, -2, -0, 0, 2}, new float[] {Float.NaN, 2, 1, 0, -0, -1, -2}); | |
345 | if (sortWorksWithNaN()) { | |
346 | testSortDescending( | |
347 | new float[] {-1, 1, Float.NaN, -2, -0, 0, 2}, new float[] {Float.NaN, 2, 1, 0, -0, -1, -2}); | |
348 | } | |
347 | 349 | } |
348 | 350 | |
349 | 351 | public void testSortDescendingIndexed() { |
353 | 355 | testSortDescending(new float[] {1, 3, 1}, 0, 2, new float[] {3, 1, 1}); |
354 | 356 | testSortDescending(new float[] {1, 3, 1}, 0, 1, new float[] {1, 3, 1}); |
355 | 357 | testSortDescending(new float[] {-1, -2, 1, 2}, 1, 3, new float[] {-1, 1, -2, 2}); |
356 | testSortDescending( | |
357 | new float[] {-1, 1, Float.NaN, -2, 2}, 1, 4, new float[] {-1, Float.NaN, 1, -2, 2}); | |
358 | if (sortWorksWithNaN()) { | |
359 | testSortDescending( | |
360 | new float[] {-1, 1, Float.NaN, -2, 2}, 1, 4, new float[] {-1, Float.NaN, 1, -2, 2}); | |
361 | } | |
358 | 362 | } |
359 | 363 | |
360 | 364 | private static void testSortDescending(float[] input, float[] expectedOutput) { |
374 | 378 | for (int i = 0; i < input.length; i++) { |
375 | 379 | assertEquals(0, Float.compare(expectedOutput[i], input[i])); |
376 | 380 | } |
381 | } | |
382 | ||
383 | @GwtIncompatible // works with real browsers but fails with HtmlUnit | |
384 | public void testSortWorksWithNaNNonGwt() { | |
385 | assertTrue(sortWorksWithNaN()); | |
377 | 386 | } |
378 | 387 | |
379 | 388 | @GwtIncompatible // SerializableTester |
628 | 637 | } catch (NullPointerException expected) { |
629 | 638 | } |
630 | 639 | } |
640 | ||
641 | // HtmlUnit looks to be sorting float[] wrongly. We detect that and skip our tests there. | |
642 | private static boolean sortWorksWithNaN() { | |
643 | float[] array = new float[] {NaN, 0}; | |
644 | Arrays.sort(array); | |
645 | return array[0] == 0; | |
646 | } | |
631 | 647 | } |
52 | 52 | Exception exception = new SampleCheckedException(); |
53 | 53 | try { |
54 | 54 | timeLimiter.callWithTimeout(callableThrowing(exception), DELAY_MS, TimeUnit.MILLISECONDS); |
55 | fail("Excpected ExecutionException"); | |
55 | fail("Expected ExecutionException"); | |
56 | 56 | } catch (ExecutionException e) { |
57 | 57 | assertThat(e.getCause()).isEqualTo(exception); |
58 | 58 | } |
62 | 62 | Exception exception = new RuntimeException("test"); |
63 | 63 | try { |
64 | 64 | timeLimiter.callWithTimeout(callableThrowing(exception), DELAY_MS, TimeUnit.MILLISECONDS); |
65 | fail("Excpected UncheckedExecutionException"); | |
65 | fail("Expected UncheckedExecutionException"); | |
66 | 66 | } catch (UncheckedExecutionException e) { |
67 | 67 | assertThat(e.getCause()).isEqualTo(exception); |
68 | 68 | } |
84 | 84 | RuntimeException exception = new RuntimeException("test"); |
85 | 85 | try { |
86 | 86 | timeLimiter.runWithTimeout(runnableThrowing(exception), DELAY_MS, TimeUnit.MILLISECONDS); |
87 | fail("Excpected UncheckedExecutionException"); | |
87 | fail("Expected UncheckedExecutionException"); | |
88 | 88 | } catch (UncheckedExecutionException e) { |
89 | 89 | assertThat(e.getCause()).isEqualTo(exception); |
90 | 90 | } |
95 | 95 | try { |
96 | 96 | timeLimiter.runUninterruptiblyWithTimeout( |
97 | 97 | runnableThrowing(exception), DELAY_MS, TimeUnit.MILLISECONDS); |
98 | fail("Excpected UncheckedExecutionException"); | |
98 | fail("Expected UncheckedExecutionException"); | |
99 | 99 | } catch (UncheckedExecutionException e) { |
100 | 100 | assertThat(e.getCause()).isEqualTo(exception); |
101 | 101 | } |
571 | 571 | verify(service).shutdown(); |
572 | 572 | } |
573 | 573 | |
574 | public void testGetExitingExcutorService_executorSetToUseDaemonThreads() { | |
574 | public void testGetExitingExecutorService_executorSetToUseDaemonThreads() { | |
575 | 575 | TestApplication application = new TestApplication(); |
576 | 576 | ThreadPoolExecutor executor = new ThreadPoolExecutor( |
577 | 577 | 1, 2, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1)); |
579 | 579 | assertTrue(executor.getThreadFactory().newThread(EMPTY_RUNNABLE).isDaemon()); |
580 | 580 | } |
581 | 581 | |
582 | public void testGetExitingExcutorService_executorDelegatesToOriginal() { | |
582 | public void testGetExitingExecutorService_executorDelegatesToOriginal() { | |
583 | 583 | TestApplication application = new TestApplication(); |
584 | 584 | ThreadPoolExecutor executor = mock(ThreadPoolExecutor.class); |
585 | 585 | ThreadFactory threadFactory = mock(ThreadFactory.class); |
588 | 588 | verify(executor).execute(EMPTY_RUNNABLE); |
589 | 589 | } |
590 | 590 | |
591 | public void testGetExitingExcutorService_shutdownHookRegistered() throws InterruptedException { | |
591 | public void testGetExitingExecutorService_shutdownHookRegistered() throws InterruptedException { | |
592 | 592 | TestApplication application = new TestApplication(); |
593 | 593 | ThreadPoolExecutor executor = mock(ThreadPoolExecutor.class); |
594 | 594 | ThreadFactory threadFactory = mock(ThreadFactory.class); |
598 | 598 | verify(executor).shutdown(); |
599 | 599 | } |
600 | 600 | |
601 | public void testGetExitingScheduledExcutorService_executorSetToUseDaemonThreads() { | |
601 | public void testGetExitingScheduledExecutorService_executorSetToUseDaemonThreads() { | |
602 | 602 | TestApplication application = new TestApplication(); |
603 | 603 | ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); |
604 | 604 | assertNotNull(application.getExitingScheduledExecutorService(executor)); |
605 | 605 | assertTrue(executor.getThreadFactory().newThread(EMPTY_RUNNABLE).isDaemon()); |
606 | 606 | } |
607 | 607 | |
608 | public void testGetExitingScheduledExcutorService_executorDelegatesToOriginal() { | |
608 | public void testGetExitingScheduledExecutorService_executorDelegatesToOriginal() { | |
609 | 609 | TestApplication application = new TestApplication(); |
610 | 610 | ScheduledThreadPoolExecutor executor = mock(ScheduledThreadPoolExecutor.class); |
611 | 611 | ThreadFactory threadFactory = mock(ThreadFactory.class); |
614 | 614 | verify(executor).execute(EMPTY_RUNNABLE); |
615 | 615 | } |
616 | 616 | |
617 | public void testGetScheduledExitingExcutorService_shutdownHookRegistered() | |
617 | public void testGetScheduledExitingExecutorService_shutdownHookRegistered() | |
618 | 618 | throws InterruptedException { |
619 | 619 | TestApplication application = new TestApplication(); |
620 | 620 | ScheduledThreadPoolExecutor executor = mock(ScheduledThreadPoolExecutor.class); |
114 | 114 | } |
115 | 115 | } |
116 | 116 | |
117 | public void testWeakReadWrite() { | |
118 | Striped<ReadWriteLock> striped = Striped.lazyWeakReadWriteLock(1000); | |
119 | Object key = new Object(); | |
120 | Lock readLock = striped.get(key).readLock(); | |
121 | WeakReference<Object> garbage = new WeakReference<>(new Object()); | |
122 | GcFinalization.awaitClear(garbage); | |
123 | Lock writeLock = striped.get(key).writeLock(); | |
124 | readLock.lock(); | |
125 | assertFalse(writeLock.tryLock()); | |
126 | readLock.unlock(); | |
127 | } | |
128 | ||
117 | 129 | public void testStrongImplementations() { |
118 | 130 | for (Striped<?> striped : strongImplementations()) { |
119 | 131 | WeakReference<Object> weakRef = new WeakReference<>(striped.get(new Object())); |
10 | 10 | </parent> |
11 | 11 | <groupId>com.google.guava</groupId> |
12 | 12 | <artifactId>guava-parent</artifactId> |
13 | <version>23.2-android</version> | |
13 | <version>23.3-android</version> | |
14 | 14 | <packaging>pom</packaging> |
15 | 15 | <name>Guava Maven Parent</name> |
16 | 16 | <url>https://github.com/google/guava</url> |
4 | 4 | <parent> |
5 | 5 | <groupId>com.google.guava</groupId> |
6 | 6 | <artifactId>guava-parent</artifactId> |
7 | <version>23.2-jre</version> | |
7 | <version>23.3-jre</version> | |
8 | 8 | </parent> |
9 | 9 | <artifactId>guava</artifactId> |
10 | 10 | <packaging>bundle</packaging> |
1497 | 1497 | |
1498 | 1498 | /** Implementation of {@link #digit()}. */ |
1499 | 1499 | private static final class Digit extends RangesMatcher { |
1500 | // Plug the following UnicodeSet pattern into | |
1501 | // https://unicode.org/cldr/utility/list-unicodeset.jsp | |
1502 | // [[:Nd:]&[:nv=0:]&[\u0000-\uFFFF]] | |
1503 | // and get the zeroes from there. | |
1500 | 1504 | |
1501 | 1505 | // Must be in ascending order. |
1502 | 1506 | private static final String ZEROES = |
1503 | "0\u0660\u06f0\u07c0\u0966\u09e6\u0a66\u0ae6\u0b66" | |
1504 | + "\u0be6\u0c66\u0ce6\u0d66\u0e50\u0ed0\u0f20\u1040\u1090\u17e0\u1810" | |
1505 | + "\u1946\u19d0\u1b50\u1bb0\u1c40\u1c50\ua620\ua8d0\ua900\uaa50\uff10"; | |
1507 | "0\u0660\u06f0\u07c0\u0966\u09e6\u0a66\u0ae6\u0b66\u0be6\u0c66\u0ce6\u0d66\u0de6" | |
1508 | + "\u0e50\u0ed0\u0f20\u1040\u1090\u17e0\u1810\u1946\u19d0\u1a80\u1a90\u1b50\u1bb0" | |
1509 | + "\u1c40\u1c50\ua620\ua8d0\ua900\ua9d0\ua9f0\uaa50\uabf0\uff10"; | |
1506 | 1510 | |
1507 | 1511 | private static char[] zeroes() { |
1508 | 1512 | return ZEROES.toCharArray(); |
1620 | 1624 | |
1621 | 1625 | /** Implementation of {@link #invisible()}. */ |
1622 | 1626 | private static final class Invisible extends RangesMatcher { |
1623 | ||
1627 | // Plug the following UnicodeSet pattern into | |
1628 | // https://unicode.org/cldr/utility/list-unicodeset.jsp | |
1629 | // [[[:Zs:][:Zl:][:Zp:][:Cc:][:Cf:][:Cs:][:Co:]]&[\u0000-\uFFFF]] | |
1630 | // with the "Abbreviate" option, and get the ranges from there. | |
1624 | 1631 | private static final String RANGE_STARTS = |
1625 | "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f\u1680\u180e\u2000\u2028\u205f\u2066\u2067" | |
1626 | + "\u2068\u2069\u206a\u3000\ud800\ufeff\ufff9\ufffa"; | |
1627 | private static final String RANGE_ENDS = | |
1628 | "\u0020\u00a0\u00ad\u0604\u061c\u06dd\u070f\u1680\u180e\u200f\u202f\u2064\u2066\u2067" | |
1629 | + "\u2068\u2069\u206f\u3000\uf8ff\ufeff\ufff9\ufffb"; | |
1632 | "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f\u08e2\u1680\u180e\u2000\u2028\u205f\u2066" | |
1633 | + "\u3000\ud800\ufeff\ufff9"; | |
1634 | private static final String RANGE_ENDS = // inclusive ends | |
1635 | "\u0020\u00a0\u00ad\u0605\u061c\u06dd\u070f\u08e2\u1680\u180e\u200f\u202f\u2064\u206f" | |
1636 | + "\u3000\uf8ff\ufeff\ufffb"; | |
1630 | 1637 | |
1631 | 1638 | static final Invisible INSTANCE = new Invisible(); |
1632 | 1639 |
32 | 32 | * |
33 | 33 | * @author Louis Wasserman |
34 | 34 | * @since 15.0 |
35 | * @deprecated Use {@link com.google.common.graph.Traverser} instead. All instance methods except | |
36 | * for {@link #inOrderTraversal} have their equivalent on the result of {@code | |
37 | * Traverser.forTree(tree)} where {@code tree} implements {@code SuccessorsFunction}, which has | |
38 | * a similar API as {@link #children}. | |
39 | * <p>This class is scheduled to be removed in January 2018. | |
35 | 40 | */ |
41 | @Deprecated | |
36 | 42 | @Beta |
37 | 43 | @GwtCompatible |
38 | 44 | public abstract class BinaryTreeTraverser<T> extends TreeTraverser<T> { |
63 | 63 | * |
64 | 64 | * @author Louis Wasserman |
65 | 65 | * @since 15.0 |
66 | * @deprecated Use {@link com.google.common.graph.Traverser} instead. All instance methods have | |
67 | * their equivalent on the result of {@code Traverser.forTree(tree)} where {@code tree} | |
68 | * implements {@code SuccessorsFunction}, which has a similar API as {@link #children} or can be | |
69 | * the same lambda function as passed into {@link #using(Function)}. | |
70 | * <p>This class is scheduled to be removed in January 2018. | |
66 | 71 | */ |
72 | @Deprecated | |
67 | 73 | @Beta |
68 | 74 | @GwtCompatible |
69 | 75 | public abstract class TreeTraverser<T> { |
75 | 81 | * {@code TreeTraverser} and implement its {@link #children} method directly. |
76 | 82 | * |
77 | 83 | * @since 20.0 |
78 | */ | |
84 | * @deprecated Use {@link com.google.common.graph.Traverser#forTree} instead. If you are using a | |
85 | * lambda, these methods have exactly the same signature. | |
86 | */ | |
87 | @Deprecated | |
79 | 88 | public static <T> TreeTraverser<T> using( |
80 | 89 | final Function<T, ? extends Iterable<T>> nodeToChildrenFunction) { |
81 | 90 | checkNotNull(nodeToChildrenFunction); |
93 | 102 | public abstract Iterable<T> children(T root); |
94 | 103 | |
95 | 104 | /** |
96 | * Returns an unmodifiable iterable over the nodes in a tree structure, using pre-order | |
97 | * traversal. That is, each node's subtrees are traversed after the node itself is returned. | |
98 | * | |
99 | * <p>No guarantees are made about the behavior of the traversal when nodes change while | |
100 | * iteration is in progress or when the iterators generated by {@link #children} are advanced. | |
101 | */ | |
105 | * Returns an unmodifiable iterable over the nodes in a tree structure, using pre-order traversal. | |
106 | * That is, each node's subtrees are traversed after the node itself is returned. | |
107 | * | |
108 | * <p>No guarantees are made about the behavior of the traversal when nodes change while iteration | |
109 | * is in progress or when the iterators generated by {@link #children} are advanced. | |
110 | * | |
111 | * @deprecated Use {@link com.google.common.graph.Traverser#depthFirstPreOrder} instead, which has | |
112 | * the same behavior. | |
113 | */ | |
114 | @Deprecated | |
102 | 115 | public final FluentIterable<T> preOrderTraversal(final T root) { |
103 | 116 | checkNotNull(root); |
104 | 117 | return new FluentIterable<T>() { |
158 | 171 | * Returns an unmodifiable iterable over the nodes in a tree structure, using post-order |
159 | 172 | * traversal. That is, each node's subtrees are traversed before the node itself is returned. |
160 | 173 | * |
161 | * <p>No guarantees are made about the behavior of the traversal when nodes change while | |
162 | * iteration is in progress or when the iterators generated by {@link #children} are advanced. | |
163 | */ | |
174 | * <p>No guarantees are made about the behavior of the traversal when nodes change while iteration | |
175 | * is in progress or when the iterators generated by {@link #children} are advanced. | |
176 | * | |
177 | * @deprecated Use {@link com.google.common.graph.Traverser#depthFirstPostOrder} instead, which | |
178 | * has the same behavior. | |
179 | */ | |
180 | @Deprecated | |
164 | 181 | public final FluentIterable<T> postOrderTraversal(final T root) { |
165 | 182 | checkNotNull(root); |
166 | 183 | return new FluentIterable<T>() { |
230 | 247 | * Returns an unmodifiable iterable over the nodes in a tree structure, using breadth-first |
231 | 248 | * traversal. That is, all the nodes of depth 0 are returned, then depth 1, then 2, and so on. |
232 | 249 | * |
233 | * <p>No guarantees are made about the behavior of the traversal when nodes change while | |
234 | * iteration is in progress or when the iterators generated by {@link #children} are advanced. | |
235 | */ | |
250 | * <p>No guarantees are made about the behavior of the traversal when nodes change while iteration | |
251 | * is in progress or when the iterators generated by {@link #children} are advanced. | |
252 | * | |
253 | * @deprecated Use {@link com.google.common.graph.Traverser#breadthFirst} instead, which has the | |
254 | * same behavior. | |
255 | */ | |
256 | @Deprecated | |
236 | 257 | public final FluentIterable<T> breadthFirstTraversal(final T root) { |
237 | 258 | checkNotNull(root); |
238 | 259 | return new FluentIterable<T>() { |
167 | 167 | * |
168 | 168 | * <p>See <a href="https://en.wikipedia.org/wiki/Breadth-first_search">Wikipedia</a> for more |
169 | 169 | * info. |
170 | * | |
171 | * @throws IllegalArgumentException if {@code startNode} is not an element of the graph | |
170 | 172 | */ |
171 | 173 | public abstract Iterable<N> breadthFirst(N startNode); |
172 | 174 | |
198 | 200 | * }</pre> |
199 | 201 | * |
200 | 202 | * <p>See <a href="https://en.wikipedia.org/wiki/Depth-first_search">Wikipedia</a> for more info. |
203 | * | |
204 | * @throws IllegalArgumentException if {@code startNode} is not an element of the graph | |
201 | 205 | */ |
202 | 206 | public abstract Iterable<N> depthFirstPreOrder(N startNode); |
203 | 207 | |
229 | 233 | * }</pre> |
230 | 234 | * |
231 | 235 | * <p>See <a href="https://en.wikipedia.org/wiki/Depth-first_search">Wikipedia</a> for more info. |
236 | * | |
237 | * @throws IllegalArgumentException if {@code startNode} is not an element of the graph | |
232 | 238 | */ |
233 | 239 | public abstract Iterable<N> depthFirstPostOrder(N startNode); |
234 | 240 | |
241 | 247 | |
242 | 248 | @Override |
243 | 249 | public Iterable<N> breadthFirst(final N startNode) { |
250 | checkNotNull(startNode); | |
251 | checkThatNodeIsInGraph(startNode); | |
244 | 252 | return new Iterable<N>() { |
245 | 253 | @Override |
246 | 254 | public Iterator<N> iterator() { |
251 | 259 | |
252 | 260 | @Override |
253 | 261 | public Iterable<N> depthFirstPreOrder(final N startNode) { |
262 | checkNotNull(startNode); | |
263 | checkThatNodeIsInGraph(startNode); | |
254 | 264 | return new Iterable<N>() { |
255 | 265 | @Override |
256 | 266 | public Iterator<N> iterator() { |
261 | 271 | |
262 | 272 | @Override |
263 | 273 | public Iterable<N> depthFirstPostOrder(final N startNode) { |
274 | checkNotNull(startNode); | |
275 | checkThatNodeIsInGraph(startNode); | |
264 | 276 | return new Iterable<N>() { |
265 | 277 | @Override |
266 | 278 | public Iterator<N> iterator() { |
267 | 279 | return new DepthFirstIterator(startNode, Order.POSTORDER); |
268 | 280 | } |
269 | 281 | }; |
282 | } | |
283 | ||
284 | @SuppressWarnings("CheckReturnValue") | |
285 | private void checkThatNodeIsInGraph(N startNode) { | |
286 | // successors() throws an IllegalArgumentException for nodes that are not an element of the | |
287 | // graph. | |
288 | graph.successors(startNode); | |
270 | 289 | } |
271 | 290 | |
272 | 291 | private final class BreadthFirstIterator extends UnmodifiableIterator<N> { |
359 | 378 | |
360 | 379 | @Override |
361 | 380 | public Iterable<N> breadthFirst(final N startNode) { |
381 | checkNotNull(startNode); | |
382 | checkThatNodeIsInTree(startNode); | |
362 | 383 | return new Iterable<N>() { |
363 | 384 | @Override |
364 | 385 | public Iterator<N> iterator() { |
369 | 390 | |
370 | 391 | @Override |
371 | 392 | public Iterable<N> depthFirstPreOrder(final N startNode) { |
393 | checkNotNull(startNode); | |
394 | checkThatNodeIsInTree(startNode); | |
372 | 395 | return new Iterable<N>() { |
373 | 396 | @Override |
374 | 397 | public Iterator<N> iterator() { |
379 | 402 | |
380 | 403 | @Override |
381 | 404 | public Iterable<N> depthFirstPostOrder(final N startNode) { |
405 | checkNotNull(startNode); | |
406 | checkThatNodeIsInTree(startNode); | |
382 | 407 | return new Iterable<N>() { |
383 | 408 | @Override |
384 | 409 | public Iterator<N> iterator() { |
385 | 410 | return new DepthFirstPostOrderIterator(startNode); |
386 | 411 | } |
387 | 412 | }; |
413 | } | |
414 | ||
415 | @SuppressWarnings("CheckReturnValue") | |
416 | private void checkThatNodeIsInTree(N startNode) { | |
417 | // successors() throws an IllegalArgumentException for nodes that are not an element of the | |
418 | // graph. | |
419 | tree.successors(startNode); | |
388 | 420 | } |
389 | 421 | |
390 | 422 | private final class BreadthFirstIterator extends UnmodifiableIterator<N> { |
22 | 22 | import com.google.common.base.Ascii; |
23 | 23 | import com.google.common.base.CharMatcher; |
24 | 24 | import com.google.common.base.Joiner; |
25 | import com.google.common.base.Optional; | |
25 | 26 | import com.google.common.base.Splitter; |
26 | 27 | import com.google.common.collect.ImmutableList; |
27 | 28 | import com.google.thirdparty.publicsuffix.PublicSuffixPatterns; |
29 | import com.google.thirdparty.publicsuffix.PublicSuffixType; | |
28 | 30 | import java.util.List; |
29 | 31 | import javax.annotation.Nullable; |
30 | 32 | |
31 | 33 | /** |
32 | * An immutable well-formed internet domain name, such as {@code com} or {@code | |
33 | * foo.co.uk}. Only syntactic analysis is performed; no DNS lookups or other network interactions | |
34 | * take place. Thus there is no guarantee that the domain actually exists on the internet. | |
34 | * An immutable well-formed internet domain name, such as {@code com} or {@code foo.co.uk}. Only | |
35 | * syntactic analysis is performed; no DNS lookups or other network interactions take place. Thus | |
36 | * there is no guarantee that the domain actually exists on the internet. | |
35 | 37 | * |
36 | 38 | * <p>One common use of this class is to determine whether a given string is likely to represent an |
37 | 39 | * addressable domain on the web -- that is, for a candidate string {@code "xxx"}, might browsing to |
39 | 41 | * done by determining whether the domain ended with a {@linkplain #isPublicSuffix() public suffix} |
40 | 42 | * but was not itself a public suffix. However, this test is no longer accurate. There are many |
41 | 43 | * domains which are both public suffixes and addressable as hosts; {@code "uk.com"} is one example. |
42 | * As a result, the only useful test to determine if a domain is a plausible web host is | |
43 | * {@link #hasPublicSuffix()}. This will return {@code true} for many domains which (currently) are | |
44 | * not hosts, such as {@code "com"}, but given that any public suffix may become a host without | |
45 | * warning, it is better to err on the side of permissiveness and thus avoid spurious rejection of | |
46 | * valid sites. | |
44 | * Using the subset of public suffixes that are {@linkplain #isRegistrySuffix() registry suffixes}, | |
45 | * one can get a better result, as only a few registry suffixes are addressable. However, the most | |
46 | * useful test to determine if a domain is a plausible web host is {@link #hasPublicSuffix()}. This | |
47 | * will return {@code true} for many domains which (currently) are not hosts, such as {@code "com"}, | |
48 | * but given that any public suffix may become a host without warning, it is better to err on the | |
49 | * side of permissiveness and thus avoid spurious rejection of valid sites. Of course, to actually | |
50 | * determine addressability of any host, clients of this class will need to perform their own DNS | |
51 | * lookups. | |
47 | 52 | * |
48 | 53 | * <p>During construction, names are normalized in two ways: |
49 | 54 | * |
50 | 55 | * <ol> |
51 | * <li>ASCII uppercase characters are converted to lowercase. | |
52 | * <li>Unicode dot separators other than the ASCII period ({@code '.'}) are converted to the ASCII | |
53 | * period. | |
56 | * <li>ASCII uppercase characters are converted to lowercase. | |
57 | * <li>Unicode dot separators other than the ASCII period ({@code '.'}) are converted to the ASCII | |
58 | * period. | |
54 | 59 | * </ol> |
55 | 60 | * |
56 | 61 | * <p>The normalized values will be returned from {@link #toString()} and {@link #parts()}, and will |
57 | 62 | * be reflected in the result of {@link #equals(Object)}. |
58 | 63 | * |
59 | 64 | * <p><a href="http://en.wikipedia.org/wiki/Internationalized_domain_name">Internationalized domain |
60 | * names</a> such as {@code 网络.cn} are supported, as are the equivalent | |
61 | * <a href="http://en.wikipedia.org/wiki/Internationalized_domain_name">IDNA Punycode-encoded</a> | |
65 | * names</a> such as {@code 网络.cn} are supported, as are the equivalent <a | |
66 | * href="http://en.wikipedia.org/wiki/Internationalized_domain_name">IDNA Punycode-encoded</a> | |
62 | 67 | * versions. |
63 | 68 | * |
64 | 69 | * @author Craig Berry |
73 | 78 | private static final Joiner DOT_JOINER = Joiner.on('.'); |
74 | 79 | |
75 | 80 | /** |
76 | * Value of {@link #publicSuffixIndex} which indicates that no public suffix was found. | |
77 | */ | |
78 | private static final int NO_PUBLIC_SUFFIX_FOUND = -1; | |
81 | * Value of {@link #publicSuffixIndex} or {@link #registrySuffixIndex} which indicates that no | |
82 | * relevant suffix was found. | |
83 | */ | |
84 | private static final int NO_SUFFIX_FOUND = -1; | |
79 | 85 | |
80 | 86 | private static final String DOT_REGEX = "\\."; |
81 | 87 | |
111 | 117 | |
112 | 118 | /** |
113 | 119 | * The index in the {@link #parts()} list at which the public suffix begins. For example, for the |
114 | * domain name {@code www.google.co.uk}, the value would be 2 (the index of the {@code co} part). | |
115 | * The value is negative (specifically, {@link #NO_PUBLIC_SUFFIX_FOUND}) if no public suffix was | |
116 | * found. | |
120 | * domain name {@code myblog.blogspot.co.uk}, the value would be 1 (the index of the {@code | |
121 | * blogspot} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no public | |
122 | * suffix was found. | |
117 | 123 | */ |
118 | 124 | private final int publicSuffixIndex; |
125 | ||
126 | /** | |
127 | * The index in the {@link #parts()} list at which the registry suffix begins. For example, for | |
128 | * the domain name {@code myblog.blogspot.co.uk}, the value would be 2 (the index of the {@code | |
129 | * co} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no registry suffix | |
130 | * was found. | |
131 | */ | |
132 | private final int registrySuffixIndex; | |
119 | 133 | |
120 | 134 | /** |
121 | 135 | * Constructor used to implement {@link #from(String)}, and from subclasses. |
139 | 153 | checkArgument(parts.size() <= MAX_PARTS, "Domain has too many parts: '%s'", name); |
140 | 154 | checkArgument(validateSyntax(parts), "Not a valid domain name: '%s'", name); |
141 | 155 | |
142 | this.publicSuffixIndex = findPublicSuffix(); | |
143 | } | |
144 | ||
145 | /** | |
146 | * Returns the index of the leftmost part of the public suffix, or -1 if not found. Note that the | |
147 | * value defined as the "public suffix" may not be a public suffix according to | |
148 | * {@link #isPublicSuffix()} if the domain ends with an excluded domain pattern such as | |
149 | * {@code "nhs.uk"}. | |
150 | */ | |
151 | private int findPublicSuffix() { | |
156 | this.publicSuffixIndex = findSuffixOfType(Optional.<PublicSuffixType>absent()); | |
157 | this.registrySuffixIndex = findSuffixOfType(Optional.of(PublicSuffixType.REGISTRY)); | |
158 | } | |
159 | ||
160 | /** | |
161 | * Returns the index of the leftmost part of the suffix, or -1 if not found. Note that the value | |
162 | * defined as a suffix may not produce {@code true} results from {@link #isPublicSuffix()} or | |
163 | * {@link #isRegistrySuffix()} if the domain ends with an excluded domain pattern such as {@code | |
164 | * "nhs.uk"}. | |
165 | * | |
166 | * <p>If a {@code desiredType} is specified, this method only finds suffixes of the given type. | |
167 | * Otherwise, it finds the first suffix of any type. | |
168 | */ | |
169 | private int findSuffixOfType(Optional<PublicSuffixType> desiredType) { | |
152 | 170 | final int partsSize = parts.size(); |
153 | 171 | |
154 | 172 | for (int i = 0; i < partsSize; i++) { |
155 | 173 | String ancestorName = DOT_JOINER.join(parts.subList(i, partsSize)); |
156 | 174 | |
157 | if (PublicSuffixPatterns.EXACT.containsKey(ancestorName)) { | |
175 | if (matchesType( | |
176 | desiredType, Optional.fromNullable(PublicSuffixPatterns.EXACT.get(ancestorName)))) { | |
158 | 177 | return i; |
159 | 178 | } |
160 | 179 | |
165 | 184 | return i + 1; |
166 | 185 | } |
167 | 186 | |
168 | if (matchesWildcardPublicSuffix(ancestorName)) { | |
187 | if (matchesWildcardSuffixType(desiredType, ancestorName)) { | |
169 | 188 | return i; |
170 | 189 | } |
171 | 190 | } |
172 | 191 | |
173 | return NO_PUBLIC_SUFFIX_FOUND; | |
192 | return NO_SUFFIX_FOUND; | |
174 | 193 | } |
175 | 194 | |
176 | 195 | /** |
177 | 196 | * Returns an instance of {@link InternetDomainName} after lenient validation. Specifically, |
178 | 197 | * validation against <a href="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</a> |
179 | * ("Internationalizing Domain Names in Applications") is skipped, while validation against | |
180 | * <a href="http://www.ietf.org/rfc/rfc1035.txt">RFC 1035</a> is relaxed in the following ways: | |
198 | * ("Internationalizing Domain Names in Applications") is skipped, while validation against <a | |
199 | * href="http://www.ietf.org/rfc/rfc1035.txt">RFC 1035</a> is relaxed in the following ways: | |
200 | * | |
181 | 201 | * <ul> |
182 | * <li>Any part containing non-ASCII characters is considered valid. | |
183 | * <li>Underscores ('_') are permitted wherever dashes ('-') are permitted. | |
184 | * <li>Parts other than the final part may start with a digit, as mandated by | |
185 | * <a href="https://tools.ietf.org/html/rfc1123#section-2">RFC 1123</a>. | |
202 | * <li>Any part containing non-ASCII characters is considered valid. | |
203 | * <li>Underscores ('_') are permitted wherever dashes ('-') are permitted. | |
204 | * <li>Parts other than the final part may start with a digit, as mandated by <a | |
205 | * href="https://tools.ietf.org/html/rfc1123#section-2">RFC 1123</a>. | |
186 | 206 | * </ul> |
187 | 207 | * |
188 | 208 | * |
189 | 209 | * @param domain A domain name (not IP address) |
190 | * @throws IllegalArgumentException if {@code name} is not syntactically valid according to | |
191 | * {@link #isValid} | |
210 | * @throws IllegalArgumentException if {@code name} is not syntactically valid according to {@link | |
211 | * #isValid} | |
192 | 212 | * @since 10.0 (previously named {@code fromLenient}) |
193 | 213 | */ |
194 | 214 | public static InternetDomainName from(String domain) { |
291 | 311 | /** |
292 | 312 | * Indicates whether this domain name represents a <i>public suffix</i>, as defined by the Mozilla |
293 | 313 | * Foundation's <a href="http://publicsuffix.org/">Public Suffix List</a> (PSL). A public suffix |
294 | * is one under which Internet users can directly register names, such as {@code com}, | |
295 | * {@code co.uk} or {@code pvt.k12.wy.us}. Examples of domain names that are <i>not</i> public | |
296 | * suffixes include {@code google}, {@code google.com} and {@code foo.co.uk}. | |
314 | * is one under which Internet users can directly register names, such as {@code com}, {@code | |
315 | * co.uk} or {@code pvt.k12.wy.us}. Examples of domain names that are <i>not</i> public suffixes | |
316 | * include {@code google.com}, {@code foo.co.uk}, and {@code myblog.blogspot.com}. | |
317 | * | |
318 | * <p>Public suffixes are a proper superset of {@linkplain #isRegistrySuffix() registry suffixes}. | |
319 | * The list of public suffixes additionally contains privately owned domain names under which | |
320 | * Internet users can register subdomains. An example of a public suffix that is not a registry | |
321 | * suffix is {@code blogspot.com}. Note that it is true that all public suffixes <i>have</i> | |
322 | * registry suffixes, since domain name registries collectively control all internet domain names. | |
323 | * | |
324 | * <p>For considerations on whether the public suffix or registry suffix designation is more | |
325 | * suitable for your application, see <a | |
326 | * href="https://github.com/google/guava/wiki/InternetDomainNameExplained">this article</a>. | |
297 | 327 | * |
298 | 328 | * @return {@code true} if this domain name appears exactly on the public suffix list |
299 | 329 | * @since 6.0 |
304 | 334 | |
305 | 335 | /** |
306 | 336 | * Indicates whether this domain name ends in a {@linkplain #isPublicSuffix() public suffix}, |
307 | * including if it is a public suffix itself. For example, returns {@code true} for | |
308 | * {@code www.google.com}, {@code foo.co.uk} and {@code com}, but not for {@code google} or | |
309 | * {@code google.foo}. This is the recommended method for determining whether a domain is | |
310 | * potentially an addressable host. | |
337 | * including if it is a public suffix itself. For example, returns {@code true} for {@code | |
338 | * www.google.com}, {@code foo.co.uk} and {@code com}, but not for {@code invalid} or {@code | |
339 | * google.invalid}. This is the recommended method for determining whether a domain is potentially | |
340 | * an addressable host. | |
341 | * | |
342 | * <p>Note that this method is equivalent to {@link #hasRegistrySuffix()} because all registry | |
343 | * suffixes are public suffixes <i>and</i> all public suffixes have registry suffixes. | |
311 | 344 | * |
312 | 345 | * @since 6.0 |
313 | 346 | */ |
314 | 347 | public boolean hasPublicSuffix() { |
315 | return publicSuffixIndex != NO_PUBLIC_SUFFIX_FOUND; | |
348 | return publicSuffixIndex != NO_SUFFIX_FOUND; | |
316 | 349 | } |
317 | 350 | |
318 | 351 | /** |
327 | 360 | |
328 | 361 | /** |
329 | 362 | * Indicates whether this domain name ends in a {@linkplain #isPublicSuffix() public suffix}, |
330 | * while not being a public suffix itself. For example, returns {@code true} for | |
331 | * {@code www.google.com}, {@code foo.co.uk} and {@code bar.ca.us}, but not for {@code google}, | |
332 | * {@code com}, or {@code | |
333 | * google.foo}. | |
334 | * | |
335 | * <p><b>Warning:</b> a {@code false} result from this method does not imply that the domain does | |
336 | * not represent an addressable host, as many public suffixes are also addressable hosts. Use | |
337 | * {@link #hasPublicSuffix()} for that test. | |
363 | * while not being a public suffix itself. For example, returns {@code true} for {@code | |
364 | * www.google.com}, {@code foo.co.uk} and {@code myblog.blogspot.com}, but not for {@code com}, | |
365 | * {@code co.uk}, {@code google.invalid}, or {@code blogspot.com}. | |
338 | 366 | * |
339 | 367 | * <p>This method can be used to determine whether it will probably be possible to set cookies on |
340 | 368 | * the domain, though even that depends on individual browsers' implementations of cookie |
348 | 376 | |
349 | 377 | /** |
350 | 378 | * Indicates whether this domain name is composed of exactly one subdomain component followed by a |
351 | * {@linkplain #isPublicSuffix() public suffix}. For example, returns {@code true} for | |
352 | * {@code google.com} and {@code foo.co.uk}, but not for {@code www.google.com} or {@code co.uk}. | |
353 | * | |
354 | * <p><b>Warning:</b> A {@code true} result from this method does not imply that the domain is at | |
355 | * the highest level which is addressable as a host, as many public suffixes are also addressable | |
356 | * hosts. For example, the domain {@code bar.uk.com} has a public suffix of {@code uk.com}, so it | |
357 | * would return {@code true} from this method. But {@code uk.com} is itself an addressable host. | |
379 | * {@linkplain #isPublicSuffix() public suffix}. For example, returns {@code true} for {@code | |
380 | * google.com} {@code foo.co.uk}, and {@code myblog.blogspot.com}, but not for {@code | |
381 | * www.google.com}, {@code co.uk}, or {@code blogspot.com}. | |
358 | 382 | * |
359 | 383 | * <p>This method can be used to determine whether a domain is probably the highest level for |
360 | 384 | * which cookies may be set, though even that depends on individual browsers' implementations of |
367 | 391 | } |
368 | 392 | |
369 | 393 | /** |
370 | * Returns the portion of this domain name that is one level beneath the public suffix. For | |
371 | * example, for {@code x.adwords.google.co.uk} it returns {@code google.co.uk}, since | |
372 | * {@code co.uk} is a public suffix. | |
394 | * Returns the portion of this domain name that is one level beneath the {@linkplain | |
395 | * #isPublicSuffix() public suffix}. For example, for {@code x.adwords.google.co.uk} it returns | |
396 | * {@code google.co.uk}, since {@code co.uk} is a public suffix. Similarly, for {@code | |
397 | * myblog.blogspot.com} it returns the same domain, {@code myblog.blogspot.com}, since {@code | |
398 | * blogspot.com} is a public suffix. | |
373 | 399 | * |
374 | 400 | * <p>If {@link #isTopPrivateDomain()} is true, the current domain name instance is returned. |
375 | * | |
376 | * <p>This method should not be used to determine the topmost parent domain which is addressable | |
377 | * as a host, as many public suffixes are also addressable hosts. For example, the domain | |
378 | * {@code foo.bar.uk.com} has a public suffix of {@code uk.com}, so it would return | |
379 | * {@code bar.uk.com} from this method. But {@code uk.com} is itself an addressable host. | |
380 | 401 | * |
381 | 402 | * <p>This method can be used to determine the probable highest level parent domain for which |
382 | 403 | * cookies may be set, though even that depends on individual browsers' implementations of cookie |
391 | 412 | } |
392 | 413 | checkState(isUnderPublicSuffix(), "Not under a public suffix: %s", name); |
393 | 414 | return ancestor(publicSuffixIndex - 1); |
415 | } | |
416 | ||
417 | /** | |
418 | * Indicates whether this domain name represents a <i>registry suffix</i>, as defined by a subset | |
419 | * of the Mozilla Foundation's <a href="http://publicsuffix.org/">Public Suffix List</a> (PSL). A | |
420 | * registry suffix is one under which Internet users can directly register names via a domain name | |
421 | * registrar, and have such registrations lawfully protected by internet-governing bodies such as | |
422 | * ICANN. Examples of registry suffixes include {@code com}, {@code co.uk}, and {@code | |
423 | * pvt.k12.wy.us}. Examples of domain names that are <i>not</i> registry suffixes include {@code | |
424 | * google.com} and {@code foo.co.uk}. | |
425 | * | |
426 | * <p>Registry suffixes are a proper subset of {@linkplain #isPublicSuffix() public suffixes}. The | |
427 | * list of public suffixes additionally contains privately owned domain names under which Internet | |
428 | * users can register subdomains. An example of a public suffix that is not a registry suffix is | |
429 | * {@code blogspot.com}. Note that it is true that all public suffixes <i>have</i> registry | |
430 | * suffixes, since domain name registries collectively control all internet domain names. | |
431 | * | |
432 | * <p>For considerations on whether the public suffix or registry suffix designation is more | |
433 | * suitable for your application, see <a | |
434 | * href="https://github.com/google/guava/wiki/InternetDomainNameExplained">this article</a>. | |
435 | * | |
436 | * @return {@code true} if this domain name appears exactly on the public suffix list as part of | |
437 | * the registry suffix section (labelled "ICANN"). | |
438 | * @since 23.3 | |
439 | */ | |
440 | public boolean isRegistrySuffix() { | |
441 | return registrySuffixIndex == 0; | |
442 | } | |
443 | ||
444 | /** | |
445 | * Indicates whether this domain name ends in a {@linkplain #isRegistrySuffix() registry suffix}, | |
446 | * including if it is a registry suffix itself. For example, returns {@code true} for {@code | |
447 | * www.google.com}, {@code foo.co.uk} and {@code com}, but not for {@code invalid} or {@code | |
448 | * google.invalid}. | |
449 | * | |
450 | * <p>Note that this method is equivalent to {@link #hasPublicSuffix()} because all registry | |
451 | * suffixes are public suffixes <i>and</i> all public suffixes have registry suffixes. | |
452 | * | |
453 | * @since 23.3 | |
454 | */ | |
455 | public boolean hasRegistrySuffix() { | |
456 | return registrySuffixIndex != NO_SUFFIX_FOUND; | |
457 | } | |
458 | ||
459 | /** | |
460 | * Returns the {@linkplain #isRegistrySuffix() registry suffix} portion of the domain name, or | |
461 | * {@code null} if no registry suffix is present. | |
462 | * | |
463 | * @since 23.3 | |
464 | */ | |
465 | public InternetDomainName registrySuffix() { | |
466 | return hasRegistrySuffix() ? ancestor(registrySuffixIndex) : null; | |
467 | } | |
468 | ||
469 | /** | |
470 | * Indicates whether this domain name ends in a {@linkplain #isRegistrySuffix() registry suffix}, | |
471 | * while not being a registry suffix itself. For example, returns {@code true} for {@code | |
472 | * www.google.com}, {@code foo.co.uk} and {@code blogspot.com}, but not for {@code com}, {@code | |
473 | * co.uk}, or {@code google.invalid}. | |
474 | * | |
475 | * @since 23.3 | |
476 | */ | |
477 | public boolean isUnderRegistrySuffix() { | |
478 | return registrySuffixIndex > 0; | |
479 | } | |
480 | ||
481 | /** | |
482 | * Indicates whether this domain name is composed of exactly one subdomain component followed by a | |
483 | * {@linkplain #isRegistrySuffix() registry suffix}. For example, returns {@code true} for {@code | |
484 | * google.com}, {@code foo.co.uk}, and {@code blogspot.com}, but not for {@code www.google.com}, | |
485 | * {@code co.uk}, or {@code myblog.blogspot.com}. | |
486 | * | |
487 | * <p><b>Warning:</b> This method should not be used to determine the probable highest level | |
488 | * parent domain for which cookies may be set. Use {@link #topPrivateDomain()} for that purpose. | |
489 | * | |
490 | * @since 23.3 | |
491 | */ | |
492 | public boolean isTopDomainUnderRegistrySuffix() { | |
493 | return registrySuffixIndex == 1; | |
494 | } | |
495 | ||
496 | /** | |
497 | * Returns the portion of this domain name that is one level beneath the {@linkplain | |
498 | * #isRegistrySuffix() registry suffix}. For example, for {@code x.adwords.google.co.uk} it | |
499 | * returns {@code google.co.uk}, since {@code co.uk} is a registry suffix. Similarly, for {@code | |
500 | * myblog.blogspot.com} it returns {@code blogspot.com}, since {@code com} is a registry suffix. | |
501 | * | |
502 | * <p>If {@link #isTopDomainUnderRegistrySuffix()} is true, the current domain name instance is | |
503 | * returned. | |
504 | * | |
505 | * <p><b>Warning:</b> This method should not be used to determine whether a domain is probably the | |
506 | * highest level for which cookies may be set. Use {@link #isTopPrivateDomain()} for that purpose. | |
507 | * | |
508 | * @throws IllegalStateException if this domain does not end with a registry suffix | |
509 | * @since 23.3 | |
510 | */ | |
511 | public InternetDomainName topDomainUnderRegistrySuffix() { | |
512 | if (isTopDomainUnderRegistrySuffix()) { | |
513 | return this; | |
514 | } | |
515 | checkState(isUnderRegistrySuffix(), "Not under a registry suffix: %s", name); | |
516 | return ancestor(registrySuffixIndex - 1); | |
394 | 517 | } |
395 | 518 | |
396 | 519 | /** |
468 | 591 | } |
469 | 592 | |
470 | 593 | /** |
471 | * Does the domain name match one of the "wildcard" patterns (e.g. {@code "*.ar"})? | |
472 | */ | |
473 | private static boolean matchesWildcardPublicSuffix(String domain) { | |
594 | * Does the domain name match one of the "wildcard" patterns (e.g. {@code "*.ar"})? If a {@code | |
595 | * desiredType} is specified, the wildcard pattern must also match that type. | |
596 | */ | |
597 | private static boolean matchesWildcardSuffixType( | |
598 | Optional<PublicSuffixType> desiredType, String domain) { | |
474 | 599 | final String[] pieces = domain.split(DOT_REGEX, 2); |
475 | return pieces.length == 2 && PublicSuffixPatterns.UNDER.containsKey(pieces[1]); | |
600 | return pieces.length == 2 | |
601 | && matchesType( | |
602 | desiredType, Optional.fromNullable(PublicSuffixPatterns.UNDER.get(pieces[1]))); | |
603 | } | |
604 | ||
605 | /** | |
606 | * If a {@code desiredType} is specified, returns true only if the {@code actualType} is | |
607 | * identical. Otherwise, returns true as long as {@code actualType} is present. | |
608 | */ | |
609 | private static boolean matchesType( | |
610 | Optional<PublicSuffixType> desiredType, Optional<PublicSuffixType> actualType) { | |
611 | return desiredType.isPresent() ? desiredType.equals(actualType) : actualType.isPresent(); | |
476 | 612 | } |
477 | 613 | |
478 | 614 | /** |
0 | /* | |
1 | * Copyright (C) 2017 The Guava Authors | |
2 | * | |
3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except | |
4 | * in compliance with the License. You may obtain a copy of the License at | |
5 | * | |
6 | * http://www.apache.org/licenses/LICENSE-2.0 | |
7 | * | |
8 | * Unless required by applicable law or agreed to in writing, software distributed under the License | |
9 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express | |
10 | * or implied. See the License for the specific language governing permissions and limitations under | |
11 | * the License. | |
12 | */ | |
13 | ||
14 | package com.google.common.util.concurrent; | |
15 | ||
16 | import java.util.Date; | |
17 | import java.util.concurrent.TimeUnit; | |
18 | import java.util.concurrent.locks.Condition; | |
19 | ||
20 | /** Forwarding wrapper around a {@code Condition}. */ | |
21 | abstract class ForwardingCondition implements Condition { | |
22 | abstract Condition delegate(); | |
23 | ||
24 | @Override | |
25 | public void await() throws InterruptedException { | |
26 | delegate().await(); | |
27 | } | |
28 | ||
29 | @Override | |
30 | public void awaitUninterruptibly() { | |
31 | delegate().awaitUninterruptibly(); | |
32 | } | |
33 | ||
34 | @Override | |
35 | public long awaitNanos(long nanosTimeout) throws InterruptedException { | |
36 | return delegate().awaitNanos(nanosTimeout); | |
37 | } | |
38 | ||
39 | @Override | |
40 | public boolean await(long time, TimeUnit unit) throws InterruptedException { | |
41 | return delegate().await(time, unit); | |
42 | } | |
43 | ||
44 | @Override | |
45 | public boolean awaitUntil(Date deadline) throws InterruptedException { | |
46 | return delegate().awaitUntil(deadline); | |
47 | } | |
48 | ||
49 | @Override | |
50 | public void signal() { | |
51 | delegate().signal(); | |
52 | } | |
53 | ||
54 | @Override | |
55 | public void signalAll() { | |
56 | delegate().signalAll(); | |
57 | } | |
58 | } |
0 | /* | |
1 | * Copyright (C) 2017 The Guava Authors | |
2 | * | |
3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except | |
4 | * in compliance with the License. You may obtain a copy of the License at | |
5 | * | |
6 | * http://www.apache.org/licenses/LICENSE-2.0 | |
7 | * | |
8 | * Unless required by applicable law or agreed to in writing, software distributed under the License | |
9 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express | |
10 | * or implied. See the License for the specific language governing permissions and limitations under | |
11 | * the License. | |
12 | */ | |
13 | ||
14 | package com.google.common.util.concurrent; | |
15 | ||
16 | import java.util.concurrent.TimeUnit; | |
17 | import java.util.concurrent.locks.Condition; | |
18 | import java.util.concurrent.locks.Lock; | |
19 | ||
20 | /** Forwarding wrapper around a {@code Lock}. */ | |
21 | abstract class ForwardingLock implements Lock { | |
22 | abstract Lock delegate(); | |
23 | ||
24 | @Override | |
25 | public void lock() { | |
26 | delegate().lock(); | |
27 | } | |
28 | ||
29 | @Override | |
30 | public void lockInterruptibly() throws InterruptedException { | |
31 | delegate().lockInterruptibly(); | |
32 | } | |
33 | ||
34 | @Override | |
35 | public boolean tryLock() { | |
36 | return delegate().tryLock(); | |
37 | } | |
38 | ||
39 | @Override | |
40 | public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { | |
41 | return delegate().tryLock(time, unit); | |
42 | } | |
43 | ||
44 | @Override | |
45 | public void unlock() { | |
46 | delegate().unlock(); | |
47 | } | |
48 | ||
49 | @Override | |
50 | public Condition newCondition() { | |
51 | return delegate().newCondition(); | |
52 | } | |
53 | } |
61 | 61 | Collections.synchronizedList(new ArrayList<PerListenerQueue<L>>()); |
62 | 62 | |
63 | 63 | /** Method reference-compatible listener event. */ |
64 | public interface Event<L> { | |
64 | interface Event<L> { | |
65 | 65 | /** Call a method on the listener. */ |
66 | 66 | void call(L listener); |
67 | 67 | } |
420 | 420 | * trucking. If an {@code Error} is thrown, the error will propagate and execution will stop until |
421 | 421 | * the next time a task is submitted. |
422 | 422 | * |
423 | * @deprecated Use {@link #newSequentialExecutor}. This method is scheduled for removal in | |
424 | * January 2018. | |
423 | 425 | * @since 23.1 |
426 | */ | |
427 | @Beta | |
428 | @Deprecated | |
429 | @GwtIncompatible | |
430 | public static Executor sequentialExecutor(Executor delegate) { | |
431 | return new SequentialExecutor(delegate); | |
432 | } | |
433 | ||
434 | /** | |
435 | * Returns an {@link Executor} that runs each task executed sequentially, such that no two tasks | |
436 | * are running concurrently. | |
437 | * | |
438 | * <p>The executor uses {@code delegate} in order to {@link Executor#execute execute} each task in | |
439 | * turn, and does not create any threads of its own. | |
440 | * | |
441 | * <p>After execution starts on the {@code delegate} {@link Executor}, tasks are polled and | |
442 | * executed from the queue until there are no more tasks. The thread will not be released until | |
443 | * there are no more tasks to run. | |
444 | * | |
445 | * <p>If a task is {@linkplain Thread#interrupt interrupted}, execution of subsequent tasks | |
446 | * continues. {@code RuntimeException}s thrown by tasks are simply logged and the executor keeps | |
447 | * trucking. If an {@code Error} is thrown, the error will propagate and execution will stop until | |
448 | * the next time a task is submitted. | |
449 | * | |
450 | * @since 23.3 (since 23.1 as {@link #sequentialExecutor(Executor)}) | |
424 | 451 | */ |
425 | 452 | @Beta |
426 | 453 | @GwtIncompatible |
427 | public static Executor sequentialExecutor(Executor delegate) { | |
454 | public static Executor newSequentialExecutor(Executor delegate) { | |
428 | 455 | return new SequentialExecutor(delegate); |
429 | 456 | } |
430 | 457 |
50 | 50 | |
51 | 51 | private final QueueWorker worker = new QueueWorker(); |
52 | 52 | |
53 | /** Use {@link MoreExecutors#sequentialExecutor} */ | |
53 | /** Use {@link MoreExecutors#newSequentialExecutor} */ | |
54 | 54 | SequentialExecutor(Executor executor) { |
55 | 55 | this.executor = Preconditions.checkNotNull(executor); |
56 | 56 | } |
34 | 34 | import java.util.concurrent.ConcurrentMap; |
35 | 35 | import java.util.concurrent.Semaphore; |
36 | 36 | import java.util.concurrent.atomic.AtomicReferenceArray; |
37 | import java.util.concurrent.locks.Condition; | |
37 | 38 | import java.util.concurrent.locks.Lock; |
38 | 39 | import java.util.concurrent.locks.ReadWriteLock; |
39 | 40 | import java.util.concurrent.locks.ReentrantLock; |
50 | 51 | * <p>The guarantee provided by this class is that equal keys lead to the same lock (or semaphore), |
51 | 52 | * i.e. {@code if (key1.equals(key2))} then {@code striped.get(key1) == striped.get(key2)} (assuming |
52 | 53 | * {@link Object#hashCode()} is correctly implemented for the keys). Note that if {@code key1} is |
53 | * <strong>not</strong> equal to {@code key2}, it is <strong>not</strong> guaranteed that | |
54 | * {@code striped.get(key1) != striped.get(key2)}; the elements might nevertheless be mapped to the | |
55 | * same lock. The lower the number of stripes, the higher the probability of this happening. | |
54 | * <strong>not</strong> equal to {@code key2}, it is <strong>not</strong> guaranteed that {@code | |
55 | * striped.get(key1) != striped.get(key2)}; the elements might nevertheless be mapped to the same | |
56 | * lock. The lower the number of stripes, the higher the probability of this happening. | |
56 | 57 | * |
57 | 58 | * <p>There are three flavors of this class: {@code Striped<Lock>}, {@code Striped<Semaphore>}, and |
58 | * {@code Striped<ReadWriteLock>}. For each type, two implementations are offered: | |
59 | * {@linkplain #lock(int) strong} and {@linkplain #lazyWeakLock(int) weak} {@code Striped<Lock>}, | |
60 | * {@linkplain #semaphore(int, int) strong} and {@linkplain #lazyWeakSemaphore(int, int) weak} | |
61 | * {@code Striped<Semaphore>}, and {@linkplain #readWriteLock(int) strong} and | |
62 | * {@linkplain #lazyWeakReadWriteLock(int) weak} {@code Striped<ReadWriteLock>}. <i>Strong</i> means | |
63 | * that all stripes (locks/semaphores) are initialized eagerly, and are not reclaimed unless | |
64 | * {@code Striped} itself is reclaimable. <i>Weak</i> means that locks/semaphores are created | |
65 | * lazily, and they are allowed to be reclaimed if nobody is holding on to them. This is useful, for | |
66 | * example, if one wants to create a {@code | |
67 | * Striped<Lock>} of many locks, but worries that in most cases only a small portion of these would | |
68 | * be in use. | |
59 | * {@code Striped<ReadWriteLock>}. For each type, two implementations are offered: {@linkplain | |
60 | * #lock(int) strong} and {@linkplain #lazyWeakLock(int) weak} {@code Striped<Lock>}, {@linkplain | |
61 | * #semaphore(int, int) strong} and {@linkplain #lazyWeakSemaphore(int, int) weak} {@code | |
62 | * Striped<Semaphore>}, and {@linkplain #readWriteLock(int) strong} and {@linkplain | |
63 | * #lazyWeakReadWriteLock(int) weak} {@code Striped<ReadWriteLock>}. <i>Strong</i> means that all | |
64 | * stripes (locks/semaphores) are initialized eagerly, and are not reclaimed unless {@code Striped} | |
65 | * itself is reclaimable. <i>Weak</i> means that locks/semaphores are created lazily, and they are | |
66 | * allowed to be reclaimed if nobody is holding on to them. This is useful, for example, if one | |
67 | * wants to create a {@code Striped<Lock>} of many locks, but worries that in most cases only a | |
68 | * small portion of these would be in use. | |
69 | 69 | * |
70 | 70 | * <p>Prior to this class, one might be tempted to use {@code Map<K, Lock>}, where {@code K} |
71 | 71 | * represents the task. This maximizes concurrency by having each unique key mapped to a unique |
92 | 92 | private Striped() {} |
93 | 93 | |
94 | 94 | /** |
95 | * Returns the stripe that corresponds to the passed key. It is always guaranteed that if | |
96 | * {@code key1.equals(key2)}, then {@code get(key1) == get(key2)}. | |
95 | * Returns the stripe that corresponds to the passed key. It is always guaranteed that if {@code | |
96 | * key1.equals(key2)}, then {@code get(key1) == get(key2)}. | |
97 | 97 | * |
98 | 98 | * @param key an arbitrary, non-null key |
99 | 99 | * @return the stripe that the passed key corresponds to |
114 | 114 | */ |
115 | 115 | abstract int indexFor(Object key); |
116 | 116 | |
117 | /** | |
118 | * Returns the total number of stripes in this instance. | |
119 | */ | |
117 | /** Returns the total number of stripes in this instance. */ | |
120 | 118 | public abstract int size(); |
121 | 119 | |
122 | 120 | /** |
123 | * Returns the stripes that correspond to the passed objects, in ascending (as per | |
124 | * {@link #getAt(int)}) order. Thus, threads that use the stripes in the order returned by this | |
125 | * method are guaranteed to not deadlock each other. | |
126 | * | |
127 | * <p>It should be noted that using a {@code Striped<L>} with relatively few stripes, and | |
128 | * {@code bulkGet(keys)} with a relative large number of keys can cause an excessive number of | |
129 | * shared stripes (much like the birthday paradox, where much fewer than anticipated birthdays are | |
130 | * needed for a pair of them to match). Please consider carefully the implications of the number | |
131 | * of stripes, the intended concurrency level, and the typical number of keys used in a | |
132 | * {@code bulkGet(keys)} operation. See <a href="http://www.mathpages.com/home/kmath199.htm">Balls | |
133 | * in Bins model</a> for mathematical formulas that can be used to estimate the probability of | |
121 | * Returns the stripes that correspond to the passed objects, in ascending (as per {@link | |
122 | * #getAt(int)}) order. Thus, threads that use the stripes in the order returned by this method | |
123 | * are guaranteed to not deadlock each other. | |
124 | * | |
125 | * <p>It should be noted that using a {@code Striped<L>} with relatively few stripes, and {@code | |
126 | * bulkGet(keys)} with a relative large number of keys can cause an excessive number of shared | |
127 | * stripes (much like the birthday paradox, where much fewer than anticipated birthdays are needed | |
128 | * for a pair of them to match). Please consider carefully the implications of the number of | |
129 | * stripes, the intended concurrency level, and the typical number of keys used in a {@code | |
130 | * bulkGet(keys)} operation. See <a href="http://www.mathpages.com/home/kmath199.htm">Balls in | |
131 | * Bins model</a> for mathematical formulas that can be used to estimate the probability of | |
134 | 132 | * collisions. |
135 | 133 | * |
136 | 134 | * @param keys arbitrary non-null keys |
283 | 281 | * @return a new {@code Striped<ReadWriteLock>} |
284 | 282 | */ |
285 | 283 | public static Striped<ReadWriteLock> lazyWeakReadWriteLock(int stripes) { |
286 | return lazy(stripes, READ_WRITE_LOCK_SUPPLIER); | |
287 | } | |
288 | ||
289 | // ReentrantReadWriteLock is large enough to make padding probably unnecessary | |
284 | return lazy(stripes, WEAK_SAFE_READ_WRITE_LOCK_SUPPLIER); | |
285 | } | |
286 | ||
290 | 287 | private static final Supplier<ReadWriteLock> READ_WRITE_LOCK_SUPPLIER = |
291 | 288 | new Supplier<ReadWriteLock>() { |
292 | 289 | @Override |
294 | 291 | return new ReentrantReadWriteLock(); |
295 | 292 | } |
296 | 293 | }; |
294 | ||
295 | private static final Supplier<ReadWriteLock> WEAK_SAFE_READ_WRITE_LOCK_SUPPLIER = | |
296 | new Supplier<ReadWriteLock>() { | |
297 | @Override | |
298 | public ReadWriteLock get() { | |
299 | return new WeakSafeReadWriteLock(); | |
300 | } | |
301 | }; | |
302 | ||
303 | /** | |
304 | * ReadWriteLock implementation whose read and write locks retain a reference back to this lock. | |
305 | * Otherwise, a reference to just the read lock or just the write lock would not suffice to ensure | |
306 | * the {@code ReadWriteLock} is retained. | |
307 | */ | |
308 | private static final class WeakSafeReadWriteLock implements ReadWriteLock { | |
309 | private final ReadWriteLock delegate; | |
310 | ||
311 | WeakSafeReadWriteLock() { | |
312 | this.delegate = new ReentrantReadWriteLock(); | |
313 | } | |
314 | ||
315 | @Override | |
316 | public Lock readLock() { | |
317 | return new WeakSafeLock(delegate.readLock(), this); | |
318 | } | |
319 | ||
320 | @Override | |
321 | public Lock writeLock() { | |
322 | return new WeakSafeLock(delegate.writeLock(), this); | |
323 | } | |
324 | } | |
325 | ||
326 | /** Lock object that ensures a strong reference is retained to a specified object. */ | |
327 | private static final class WeakSafeLock extends ForwardingLock { | |
328 | private final Lock delegate; | |
329 | ||
330 | @SuppressWarnings("unused") | |
331 | private final WeakSafeReadWriteLock strongReference; | |
332 | ||
333 | WeakSafeLock(Lock delegate, WeakSafeReadWriteLock strongReference) { | |
334 | this.delegate = delegate; | |
335 | this.strongReference = strongReference; | |
336 | } | |
337 | ||
338 | @Override | |
339 | Lock delegate() { | |
340 | return delegate; | |
341 | } | |
342 | ||
343 | @Override | |
344 | public Condition newCondition() { | |
345 | return new WeakSafeCondition(delegate.newCondition(), strongReference); | |
346 | } | |
347 | } | |
348 | ||
349 | /** Condition object that ensures a strong reference is retained to a specified object. */ | |
350 | private static final class WeakSafeCondition extends ForwardingCondition { | |
351 | private final Condition delegate; | |
352 | ||
353 | @SuppressWarnings("unused") | |
354 | private final WeakSafeReadWriteLock strongReference; | |
355 | ||
356 | WeakSafeCondition(Condition delegate, WeakSafeReadWriteLock strongReference) { | |
357 | this.delegate = delegate; | |
358 | this.strongReference = strongReference; | |
359 | } | |
360 | ||
361 | @Override | |
362 | Condition delegate() { | |
363 | return delegate; | |
364 | } | |
365 | } | |
297 | 366 | |
298 | 367 | private abstract static class PowerOfTwoStriped<L> extends Striped<L> { |
299 | 368 | /** Capacity (power of two) minus one, for fast mod evaluation */ |
456 | 525 | } |
457 | 526 | } |
458 | 527 | |
459 | /** | |
460 | * A bit mask were all bits are set. | |
461 | */ | |
528 | /** A bit mask were all bits are set. */ | |
462 | 529 | private static final int ALL_SET = ~0; |
463 | 530 | |
464 | 531 | private static int ceilToPowerOfTwo(int x) { |
13 | 13 | |
14 | 14 | package com.google.thirdparty.publicsuffix; |
15 | 15 | |
16 | import com.google.common.annotations.Beta; | |
16 | 17 | import com.google.common.annotations.GwtCompatible; |
17 | 18 | |
18 | 19 | /** |
19 | * Specifies the type of a top-level domain definition. | |
20 | * <b>Do not use this class directly. For access to public-suffix information, | |
21 | * use {@link com.google.common.net.InternetDomainName}.</b> | |
22 | * | |
23 | * <p>Specifies the type of a top-level domain definition. | |
24 | * | |
25 | * @since 23.3 | |
20 | 26 | */ |
27 | @Beta | |
21 | 28 | @GwtCompatible |
22 | enum PublicSuffixType { | |
29 | public enum PublicSuffixType { | |
23 | 30 | |
24 | /** private definition of a top-level domain */ | |
31 | /** Public suffix that is provided by a private company, e.g. "blogspot.com" */ | |
25 | 32 | PRIVATE(':', ','), |
26 | /** ICANN definition of a top-level domain */ | |
27 | ICANN('!', '?'); | |
33 | /** Public suffix that is backed by an ICANN-style domain name registry */ | |
34 | REGISTRY('!', '?'); | |
28 | 35 | |
29 | 36 | /** The character used for an inner node in the trie encoding */ |
30 | 37 | private final char innerNodeCode; |
56 | 63 | } |
57 | 64 | |
58 | 65 | static PublicSuffixType fromIsPrivate(boolean isPrivate) { |
59 | return isPrivate ? PRIVATE : ICANN; | |
66 | return isPrivate ? PRIVATE : REGISTRY; | |
60 | 67 | } |
61 | 68 | } |
17 | 17 | import com.google.common.base.Joiner; |
18 | 18 | import com.google.common.collect.ImmutableMap; |
19 | 19 | import com.google.common.collect.Lists; |
20 | ||
21 | 20 | import java.util.List; |
22 | 21 | |
23 | 22 | /** |
73 | 72 | stack.add(0, reverse(encoded.subSequence(0, idx))); |
74 | 73 | |
75 | 74 | if (c == '!' || c == '?' || c == ':' || c == ',') { |
76 | // '!' represents an interior node that represents an ICANN entry in the map. | |
77 | // '?' represents a leaf node, which represents an ICANN entry in map. | |
75 | // '!' represents an interior node that represents a REGISTRY entry in the map. | |
76 | // '?' represents a leaf node, which represents a REGISTRY entry in map. | |
78 | 77 | // ':' represents an interior node that represents a private entry in the map |
79 | 78 | // ',' represents a leaf node, which represents a private entry in the map. |
80 | 79 | String domain = PREFIX_JOINER.join(stack); |
4 | 4 | <parent> |
5 | 5 | <groupId>com.google.guava</groupId> |
6 | 6 | <artifactId>guava-parent</artifactId> |
7 | <version>23.2-jre</version> | |
7 | <version>23.3-jre</version> | |
8 | 8 | </parent> |
9 | 9 | <artifactId>guava-gwt</artifactId> |
10 | 10 | <name>Guava GWT compatible libs</name> |
24 | 24 | <inherits name="com.google.common.escape.Escape"/> |
25 | 25 | |
26 | 26 | <inherits name="com.google.thirdparty.publicsuffix.PublicSuffixPatterns"/> |
27 | ||
28 | <inherits name="com.google.thirdparty.publicsuffix.PublicSuffixType"/> | |
27 | 29 | |
28 | 30 | <inherits name="com.google.gwt.core.Core"/> |
29 | 31 |
87 | 87 | testCase.testCharacterSplitWithMatcherDelimiter(); |
88 | 88 | } |
89 | 89 | |
90 | public void testCharacterSplitWithMultitpleLetters() throws Exception { | |
91 | com.google.common.base.SplitterTest testCase = new com.google.common.base.SplitterTest(); | |
92 | testCase.testCharacterSplitWithMultitpleLetters(); | |
90 | public void testCharacterSplitWithMultipleLetters() throws Exception { | |
91 | com.google.common.base.SplitterTest testCase = new com.google.common.base.SplitterTest(); | |
92 | testCase.testCharacterSplitWithMultipleLetters(); | |
93 | 93 | } |
94 | 94 | |
95 | 95 | public void testCharacterSplitWithTrailingDelimiter() throws Exception { |
27 | 27 | testCase.testEquality(); |
28 | 28 | } |
29 | 29 | |
30 | public void testExclusion() throws Exception { | |
31 | com.google.common.net.InternetDomainNameTest testCase = new com.google.common.net.InternetDomainNameTest(); | |
32 | testCase.testExclusion(); | |
33 | } | |
34 | ||
35 | 30 | public void testInvalid() throws Exception { |
36 | 31 | com.google.common.net.InternetDomainNameTest testCase = new com.google.common.net.InternetDomainNameTest(); |
37 | 32 | testCase.testInvalid(); |
45 | 40 | public void testIsValid() throws Exception { |
46 | 41 | com.google.common.net.InternetDomainNameTest testCase = new com.google.common.net.InternetDomainNameTest(); |
47 | 42 | testCase.testIsValid(); |
48 | } | |
49 | ||
50 | public void testMultipleUnders() throws Exception { | |
51 | com.google.common.net.InternetDomainNameTest testCase = new com.google.common.net.InternetDomainNameTest(); | |
52 | testCase.testMultipleUnders(); | |
53 | 43 | } |
54 | 44 | |
55 | 45 | public void testParent() throws Exception { |
67 | 57 | testCase.testPublicSuffix(); |
68 | 58 | } |
69 | 59 | |
60 | public void testPublicSuffixExclusion() throws Exception { | |
61 | com.google.common.net.InternetDomainNameTest testCase = new com.google.common.net.InternetDomainNameTest(); | |
62 | testCase.testPublicSuffixExclusion(); | |
63 | } | |
64 | ||
65 | public void testPublicSuffixMultipleUnders() throws Exception { | |
66 | com.google.common.net.InternetDomainNameTest testCase = new com.google.common.net.InternetDomainNameTest(); | |
67 | testCase.testPublicSuffixMultipleUnders(); | |
68 | } | |
69 | ||
70 | public void testRegistrySuffix() throws Exception { | |
71 | com.google.common.net.InternetDomainNameTest testCase = new com.google.common.net.InternetDomainNameTest(); | |
72 | testCase.testRegistrySuffix(); | |
73 | } | |
74 | ||
75 | public void testRegistrySuffixExclusion() throws Exception { | |
76 | com.google.common.net.InternetDomainNameTest testCase = new com.google.common.net.InternetDomainNameTest(); | |
77 | testCase.testRegistrySuffixExclusion(); | |
78 | } | |
79 | ||
80 | public void testRegistrySuffixMultipleUnders() throws Exception { | |
81 | com.google.common.net.InternetDomainNameTest testCase = new com.google.common.net.InternetDomainNameTest(); | |
82 | testCase.testRegistrySuffixMultipleUnders(); | |
83 | } | |
84 | ||
70 | 85 | public void testToString() throws Exception { |
71 | 86 | com.google.common.net.InternetDomainNameTest testCase = new com.google.common.net.InternetDomainNameTest(); |
72 | 87 | testCase.testToString(); |
88 | } | |
89 | ||
90 | public void testTopDomainUnderRegistrySuffix() throws Exception { | |
91 | com.google.common.net.InternetDomainNameTest testCase = new com.google.common.net.InternetDomainNameTest(); | |
92 | testCase.testTopDomainUnderRegistrySuffix(); | |
73 | 93 | } |
74 | 94 | |
75 | 95 | public void testTopPrivateDomain() throws Exception { |
87 | 107 | testCase.testUnderPublicSuffix(); |
88 | 108 | } |
89 | 109 | |
110 | public void testUnderRegistrySuffix() throws Exception { | |
111 | com.google.common.net.InternetDomainNameTest testCase = new com.google.common.net.InternetDomainNameTest(); | |
112 | testCase.testUnderRegistrySuffix(); | |
113 | } | |
114 | ||
115 | public void testUnderTopDomainUnderRegistrySuffix() throws Exception { | |
116 | com.google.common.net.InternetDomainNameTest testCase = new com.google.common.net.InternetDomainNameTest(); | |
117 | testCase.testUnderTopDomainUnderRegistrySuffix(); | |
118 | } | |
119 | ||
90 | 120 | public void testValid() throws Exception { |
91 | 121 | com.google.common.net.InternetDomainNameTest testCase = new com.google.common.net.InternetDomainNameTest(); |
92 | 122 | testCase.testValid(); |
4 | 4 | <parent> |
5 | 5 | <groupId>com.google.guava</groupId> |
6 | 6 | <artifactId>guava-parent</artifactId> |
7 | <version>23.2-jre</version> | |
7 | <version>23.3-jre</version> | |
8 | 8 | </parent> |
9 | 9 | <artifactId>guava-testlib</artifactId> |
10 | 10 | <name>Guava Testing Library</name> |
4 | 4 | <parent> |
5 | 5 | <groupId>com.google.guava</groupId> |
6 | 6 | <artifactId>guava-parent</artifactId> |
7 | <version>23.2-jre</version> | |
7 | <version>23.3-jre</version> | |
8 | 8 | </parent> |
9 | 9 | <artifactId>guava-tests</artifactId> |
10 | 10 | <name>Guava Unit Tests</name> |
149 | 149 | assertNotNull(getClass().getResource("internal/Finalizer.class")); |
150 | 150 | } |
151 | 151 | |
152 | public void testFinalizeClassHasNoNestedClases() throws Exception { | |
152 | public void testFinalizeClassHasNoNestedClasses() throws Exception { | |
153 | 153 | // Ensure that the Finalizer class has no nested classes. |
154 | 154 | // See https://code.google.com/p/guava-libraries/issues/detail?id=1505 |
155 | 155 | assertEquals(Collections.emptyList(), Arrays.asList(Finalizer.class.getDeclaredClasses())); |
99 | 99 | assertThat(letters).containsExactly("", "a", "b", "c").inOrder(); |
100 | 100 | } |
101 | 101 | |
102 | public void testCharacterSplitWithMultitpleLetters() { | |
102 | public void testCharacterSplitWithMultipleLetters() { | |
103 | 103 | Iterable<String> testCharacteringMotto = Splitter.on('-').split( |
104 | 104 | "Testing-rocks-Debugging-sucks"); |
105 | 105 | assertThat(testCharacteringMotto) |
114 | 114 | createDirectedGraph("hd", "he", "hg", "da", "db", "dc", "gf"); |
115 | 115 | |
116 | 116 | /** |
117 | * Two disjoint tree-shaped graphs that look as follows (all edges are directed facing downwards): | |
118 | * | |
119 | * <pre>{@code | |
120 | * a c | |
121 | * | | | |
122 | * | | | |
123 | * b d | |
124 | * }</pre> | |
125 | */ | |
126 | private static final SuccessorsFunction<Character> TWO_TREES = createDirectedGraph("ab", "cd"); | |
127 | ||
128 | /** | |
129 | * A graph consisting of a single root {@code a}: | |
130 | * | |
131 | * <pre>{@code | |
132 | * a | |
133 | * }</pre> | |
134 | */ | |
135 | private static final SuccessorsFunction<Character> SINGLE_ROOT = createSingleRootGraph(); | |
136 | ||
137 | /** | |
117 | 138 | * A graph that is not a tree (for example, it has two antiparallel edge between {@code e} and |
118 | 139 | * {@code f} and thus has a cycle) but is a valid input to {@link Traverser#forTree} when starting |
119 | 140 | * e.g. at node {@code a} (all edges without an arrow are directed facing downwards): |
198 | 219 | assertEqualCharNodes(traverser.breadthFirst('a'), "a"); |
199 | 220 | } |
200 | 221 | |
222 | @Test | |
223 | public void forGraph_breadthFirst_twoTrees() { | |
224 | Iterable<Character> result = Traverser.forGraph(TWO_TREES).breadthFirst('a'); | |
225 | ||
226 | assertEqualCharNodes(result, "ab"); | |
227 | } | |
228 | ||
229 | @Test | |
230 | public void forGraph_breadthFirst_singleRoot() { | |
231 | Iterable<Character> result = Traverser.forGraph(SINGLE_ROOT).breadthFirst('a'); | |
232 | ||
233 | assertEqualCharNodes(result, "a"); | |
234 | } | |
235 | ||
236 | @Test | |
237 | public void forGraph_breadthFirst_emptyGraph() { | |
238 | try { | |
239 | Traverser.forGraph(createDirectedGraph()).breadthFirst('a'); | |
240 | fail("Expected IllegalArgumentException"); | |
241 | } catch (IllegalArgumentException expected) { | |
242 | } | |
243 | } | |
244 | ||
201 | 245 | /** |
202 | 246 | * Checks that the elements of the iterable are calculated on the fly. Concretely, that means that |
203 | 247 | * {@link SuccessorsFunction#successors(Object)} can only be called for a subset of all nodes. |
208 | 252 | Iterable<Character> result = Traverser.forGraph(graph).breadthFirst('a'); |
209 | 253 | |
210 | 254 | assertEqualCharNodes(Iterables.limit(result, 2), "ab"); |
211 | assertThat(graph.requestedNodes).containsExactly('a', 'b'); | |
255 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'b'); | |
212 | 256 | |
213 | 257 | // Iterate again to see if calculation is done again |
214 | 258 | assertEqualCharNodes(Iterables.limit(result, 2), "ab"); |
215 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'b', 'b'); | |
259 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'a', 'b', 'b'); | |
216 | 260 | } |
217 | 261 | |
218 | 262 | @Test |
269 | 313 | } |
270 | 314 | |
271 | 315 | @Test |
316 | public void forGraph_depthFirstPreOrder_twoTrees() { | |
317 | Iterable<Character> result = Traverser.forGraph(TWO_TREES).depthFirstPreOrder('a'); | |
318 | ||
319 | assertEqualCharNodes(result, "ab"); | |
320 | } | |
321 | ||
322 | @Test | |
323 | public void forGraph_depthFirstPreOrder_singleRoot() { | |
324 | Iterable<Character> result = Traverser.forGraph(SINGLE_ROOT).depthFirstPreOrder('a'); | |
325 | ||
326 | assertEqualCharNodes(result, "a"); | |
327 | } | |
328 | ||
329 | @Test | |
330 | public void forGraph_depthFirstPreOrder_emptyGraph() { | |
331 | try { | |
332 | Traverser.forGraph(createDirectedGraph()).depthFirstPreOrder('a'); | |
333 | fail("Expected IllegalArgumentException"); | |
334 | } catch (IllegalArgumentException expected) { | |
335 | } | |
336 | } | |
337 | ||
338 | @Test | |
272 | 339 | public void forGraph_depthFirstPreOrder_iterableIsLazy() { |
273 | 340 | RequestSavingGraph graph = new RequestSavingGraph(DIAMOND_GRAPH); |
274 | 341 | Iterable<Character> result = Traverser.forGraph(graph).depthFirstPreOrder('a'); |
275 | 342 | |
276 | 343 | assertEqualCharNodes(Iterables.limit(result, 2), "ab"); |
277 | assertThat(graph.requestedNodes).containsExactly('a', 'b', 'd'); | |
344 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'b', 'd'); | |
278 | 345 | |
279 | 346 | // Iterate again to see if calculation is done again |
280 | 347 | assertEqualCharNodes(Iterables.limit(result, 2), "ab"); |
281 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'b', 'b', 'd', 'd'); | |
348 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'a', 'b', 'b', 'd', 'd'); | |
282 | 349 | } |
283 | 350 | |
284 | 351 | @Test |
334 | 401 | } |
335 | 402 | |
336 | 403 | @Test |
404 | public void forGraph_depthFirstPostOrder_twoTrees() { | |
405 | Iterable<Character> result = Traverser.forGraph(TWO_TREES).depthFirstPostOrder('a'); | |
406 | ||
407 | assertEqualCharNodes(result, "ba"); | |
408 | } | |
409 | ||
410 | @Test | |
411 | public void forGraph_depthFirstPostOrder_singleRoot() { | |
412 | Iterable<Character> result = Traverser.forGraph(SINGLE_ROOT).depthFirstPostOrder('a'); | |
413 | ||
414 | assertEqualCharNodes(result, "a"); | |
415 | } | |
416 | ||
417 | @Test | |
418 | public void forGraph_depthFirstPostOrder_emptyGraph() { | |
419 | try { | |
420 | Traverser.forGraph(createDirectedGraph()).depthFirstPostOrder('a'); | |
421 | fail("Expected IllegalArgumentException"); | |
422 | } catch (IllegalArgumentException expected) { | |
423 | } | |
424 | } | |
425 | ||
426 | @Test | |
337 | 427 | public void forGraph_depthFirstPostOrder_iterableIsLazy() { |
338 | 428 | RequestSavingGraph graph = new RequestSavingGraph(DIAMOND_GRAPH); |
339 | 429 | Iterable<Character> result = Traverser.forGraph(graph).depthFirstPostOrder('a'); |
340 | 430 | |
341 | 431 | assertEqualCharNodes(Iterables.limit(result, 2), "db"); |
342 | assertThat(graph.requestedNodes).containsExactly('a', 'b', 'd'); | |
432 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'b', 'd'); | |
343 | 433 | |
344 | 434 | // Iterate again to see if calculation is done again |
345 | 435 | assertEqualCharNodes(Iterables.limit(result, 2), "db"); |
346 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'b', 'b', 'd', 'd'); | |
436 | assertThat(graph.requestedNodes).containsExactly('a', 'a', 'a', 'b', 'b', 'd', 'd'); | |
347 | 437 | } |
348 | 438 | |
349 | 439 | @Test |
437 | 527 | } |
438 | 528 | |
439 | 529 | @Test |
530 | public void forTree_breadthFirst_twoTrees() { | |
531 | Iterable<Character> result = Traverser.forTree(TWO_TREES).breadthFirst('a'); | |
532 | ||
533 | assertEqualCharNodes(result, "ab"); | |
534 | } | |
535 | ||
536 | @Test | |
537 | public void forTree_breadthFirst_singleRoot() { | |
538 | Iterable<Character> result = Traverser.forTree(SINGLE_ROOT).breadthFirst('a'); | |
539 | ||
540 | assertEqualCharNodes(result, "a"); | |
541 | } | |
542 | ||
543 | @Test | |
544 | public void forTree_breadthFirst_emptyGraph() { | |
545 | try { | |
546 | Traverser.forTree(createDirectedGraph()).breadthFirst('a'); | |
547 | fail("Expected IllegalArgumentException"); | |
548 | } catch (IllegalArgumentException expected) { | |
549 | } | |
550 | } | |
551 | ||
552 | @Test | |
440 | 553 | public void forTree_breadthFirst_iterableIsLazy() { |
441 | 554 | RequestSavingGraph graph = new RequestSavingGraph(TREE); |
442 | 555 | Iterable<Character> result = Traverser.forGraph(graph).breadthFirst('h'); |
443 | 556 | |
444 | 557 | assertEqualCharNodes(Iterables.limit(result, 2), "hd"); |
445 | assertThat(graph.requestedNodes).containsExactly('h', 'd'); | |
558 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'd'); | |
446 | 559 | |
447 | 560 | // Iterate again to see if calculation is done again |
448 | 561 | assertEqualCharNodes(Iterables.limit(result, 2), "hd"); |
449 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'd', 'd'); | |
562 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'h', 'd', 'd'); | |
450 | 563 | } |
451 | 564 | |
452 | 565 | @Test |
477 | 590 | } |
478 | 591 | |
479 | 592 | @Test |
593 | public void forTree_depthFirstPreOrder_twoTrees() { | |
594 | Iterable<Character> result = Traverser.forTree(TWO_TREES).depthFirstPreOrder('a'); | |
595 | ||
596 | assertEqualCharNodes(result, "ab"); | |
597 | } | |
598 | ||
599 | @Test | |
600 | public void forTree_depthFirstPreOrder_singleRoot() { | |
601 | Iterable<Character> result = Traverser.forTree(SINGLE_ROOT).depthFirstPreOrder('a'); | |
602 | ||
603 | assertEqualCharNodes(result, "a"); | |
604 | } | |
605 | ||
606 | @Test | |
607 | public void forTree_depthFirstPreOrder_emptyGraph() { | |
608 | try { | |
609 | Traverser.forTree(createDirectedGraph()).depthFirstPreOrder('a'); | |
610 | fail("Expected IllegalArgumentException"); | |
611 | } catch (IllegalArgumentException expected) { | |
612 | } | |
613 | } | |
614 | ||
615 | @Test | |
480 | 616 | public void forTree_depthFirstPreOrder_iterableIsLazy() { |
481 | 617 | RequestSavingGraph graph = new RequestSavingGraph(TREE); |
482 | 618 | Iterable<Character> result = Traverser.forGraph(graph).depthFirstPreOrder('h'); |
483 | 619 | |
484 | 620 | assertEqualCharNodes(Iterables.limit(result, 2), "hd"); |
485 | assertThat(graph.requestedNodes).containsExactly('h', 'd', 'a'); | |
621 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'd', 'a'); | |
486 | 622 | |
487 | 623 | // Iterate again to see if calculation is done again |
488 | 624 | assertEqualCharNodes(Iterables.limit(result, 2), "hd"); |
489 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'd', 'd', 'a', 'a'); | |
625 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'h', 'd', 'd', 'a', 'a'); | |
490 | 626 | } |
491 | 627 | |
492 | 628 | @Test |
517 | 653 | } |
518 | 654 | |
519 | 655 | @Test |
656 | public void forTree_depthFirstPostOrder_twoTrees() { | |
657 | Iterable<Character> result = Traverser.forTree(TWO_TREES).depthFirstPostOrder('a'); | |
658 | ||
659 | assertEqualCharNodes(result, "ba"); | |
660 | } | |
661 | ||
662 | @Test | |
663 | public void forTree_depthFirstPostOrder_singleRoot() { | |
664 | Iterable<Character> result = Traverser.forTree(SINGLE_ROOT).depthFirstPostOrder('a'); | |
665 | ||
666 | assertEqualCharNodes(result, "a"); | |
667 | } | |
668 | ||
669 | @Test | |
670 | public void forTree_depthFirstPostOrder_emptyGraph() { | |
671 | try { | |
672 | Traverser.forTree(createDirectedGraph()).depthFirstPostOrder('a'); | |
673 | fail("Expected IllegalArgumentException"); | |
674 | } catch (IllegalArgumentException expected) { | |
675 | } | |
676 | } | |
677 | ||
678 | @Test | |
520 | 679 | public void forTree_depthFirstPostOrder_iterableIsLazy() { |
521 | 680 | RequestSavingGraph graph = new RequestSavingGraph(TREE); |
522 | 681 | Iterable<Character> result = Traverser.forGraph(graph).depthFirstPostOrder('h'); |
523 | 682 | |
524 | 683 | assertEqualCharNodes(Iterables.limit(result, 2), "ab"); |
525 | assertThat(graph.requestedNodes).containsExactly('h', 'd', 'a', 'b'); | |
684 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'd', 'a', 'b'); | |
526 | 685 | |
527 | 686 | // Iterate again to see if calculation is done again |
528 | 687 | assertEqualCharNodes(Iterables.limit(result, 2), "ab"); |
529 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'd', 'd', 'a', 'a', 'b', 'b'); | |
688 | assertThat(graph.requestedNodes).containsExactly('h', 'h', 'h', 'd', 'd', 'a', 'a', 'b', 'b'); | |
530 | 689 | } |
531 | 690 | |
532 | 691 | private static SuccessorsFunction<Character> createDirectedGraph(String... edges) { |
560 | 719 | return new SuccessorsFunction<Character>() { |
561 | 720 | @Override |
562 | 721 | public Iterable<? extends Character> successors(Character node) { |
722 | checkArgument( | |
723 | graphMap.containsKey(node) || graphMap.containsValue(node), | |
724 | "Node %s is not an element of this graph", | |
725 | node); | |
563 | 726 | return Ordering.natural().immutableSortedCopy(graphMap.get(node)); |
564 | 727 | } |
565 | 728 | }; |
729 | } | |
730 | ||
731 | private static ImmutableGraph<Character> createSingleRootGraph() { | |
732 | MutableGraph<Character> graph = GraphBuilder.directed().build(); | |
733 | graph.addNode('a'); | |
734 | return ImmutableGraph.copyOf(graph); | |
566 | 735 | } |
567 | 736 | |
568 | 737 | private static void assertEqualCharNodes(Iterable<Character> result, String expectedCharacters) { |
58 | 58 | assertCrc(0x113fdb5c, descending); |
59 | 59 | } |
60 | 60 | |
61 | public void testScsiReadCommad() { | |
61 | public void testScsiReadCommand() { | |
62 | 62 | // Test SCSI read command. |
63 | 63 | byte[] scsiReadCommand = new byte[] { |
64 | 64 | 0x01, (byte) 0xc0, 0x00, 0x00, |
19 | 19 | import static com.google.common.math.MathTesting.FINITE_DOUBLE_CANDIDATES; |
20 | 20 | import static com.google.common.math.MathTesting.POSITIVE_FINITE_DOUBLE_CANDIDATES; |
21 | 21 | |
22 | import java.lang.reflect.Method; | |
22 | 23 | import java.math.BigInteger; |
23 | 24 | import junit.framework.TestCase; |
24 | 25 | |
28 | 29 | * @author Louis Wasserman |
29 | 30 | */ |
30 | 31 | public class DoubleUtilsTest extends TestCase { |
31 | @AndroidIncompatible // no FpUtils | |
32 | public void testNextDown() { | |
32 | @AndroidIncompatible // no FpUtils and no Math.nextDown in old versions | |
33 | public void testNextDown() throws Exception { | |
34 | Method jdkNextDown = getJdkNextDown(); | |
33 | 35 | for (double d : FINITE_DOUBLE_CANDIDATES) { |
34 | assertEquals(Math.nextDown(d), DoubleUtils.nextDown(d)); | |
36 | assertEquals(jdkNextDown.invoke(null, d), DoubleUtils.nextDown(d)); | |
37 | } | |
38 | } | |
39 | ||
40 | private static Method getJdkNextDown() throws Exception { | |
41 | try { | |
42 | return Math.class.getMethod("nextDown", double.class); | |
43 | } catch (NoSuchMethodException expectedBeforeJava8) { | |
44 | return Class.forName("sun.misc.FpUtils").getMethod("nextDown", double.class); | |
35 | 45 | } |
36 | 46 | } |
37 | 47 |
95 | 95 | ALMOST_TOO_MANY_LEVELS + "com", |
96 | 96 | ALMOST_TOO_LONG + ".c"); |
97 | 97 | |
98 | private static final ImmutableSet<String> PS = ImmutableSet.of( | |
99 | "com", | |
100 | "co.uk", | |
101 | "foo.bd", | |
102 | "xxxxxx.bd", | |
103 | "org.mK", | |
104 | "us", | |
105 | "uk\uFF61com.", // Alternate dot character | |
106 | "\u7f51\u7edc.Cn", // "网络.Cn" | |
107 | "j\u00f8rpeland.no", // "jorpeland.no" (first o slashed) | |
108 | "xn--jrpeland-54a.no" // IDNA (punycode) encoding of above | |
109 | ); | |
98 | private static final ImmutableSet<String> RS = | |
99 | ImmutableSet.of( | |
100 | "com", | |
101 | "co.uk", | |
102 | "foo.bd", | |
103 | "xxxxxx.bd", | |
104 | "org.mK", | |
105 | "us", | |
106 | "co.uk.", // Trailing dot | |
107 | "co\uFF61uk", // Alternate dot character | |
108 | "\u7f51\u7edc.Cn", // "网络.Cn" | |
109 | "j\u00f8rpeland.no", // "jorpeland.no" (first o slashed) | |
110 | "xn--jrpeland-54a.no"); // IDNA (punycode) encoding of above | |
111 | ||
112 | private static final ImmutableSet<String> PS_NOT_RS = | |
113 | ImmutableSet.of("blogspot.com", "blogspot.co.uk", "uk.com"); | |
114 | ||
115 | private static final ImmutableSet<String> PS = | |
116 | ImmutableSet.<String>builder().addAll(RS).addAll(PS_NOT_RS).build(); | |
110 | 117 | |
111 | 118 | private static final ImmutableSet<String> NO_PS = ImmutableSet.of( |
112 | 119 | "www", "foo.ihopethiswillneverbeapublicsuffix", "x.y.z"); |
113 | 120 | |
114 | private static final ImmutableSet<String> NON_PS = ImmutableSet.of( | |
115 | "foo.bar.com", "foo.ca", "foo.bar.ca", | |
116 | "foo.bar.co.il", "state.CA.us", "www.state.pa.us", "pvt.k12.ca.us", | |
117 | "www.google.com", "www4.yahoo.co.uk", "home.netscape.com", | |
118 | "web.MIT.edu", "foo.eDu.au", "utenti.blah.IT", "dominio.com.co"); | |
121 | /** | |
122 | * Having a public suffix is equivalent to having a registry suffix, because all registry suffixes | |
123 | * are public suffixes, and all public suffixes have registry suffixes. | |
124 | */ | |
125 | private static final ImmutableSet<String> NO_RS = NO_PS; | |
126 | ||
127 | private static final ImmutableSet<String> NON_PS = | |
128 | ImmutableSet.of( | |
129 | "foo.bar.com", | |
130 | "foo.ca", | |
131 | "foo.bar.ca", | |
132 | "foo.blogspot.com", | |
133 | "foo.blogspot.co.uk", | |
134 | "foo.uk.com", | |
135 | "foo.bar.co.il", | |
136 | "state.CA.us", | |
137 | "www.state.pa.us", | |
138 | "pvt.k12.ca.us", | |
139 | "www.google.com", | |
140 | "www4.yahoo.co.uk", | |
141 | "home.netscape.com", | |
142 | "web.MIT.edu", | |
143 | "foo.eDu.au", | |
144 | "utenti.blah.IT", | |
145 | "dominio.com.co"); | |
146 | ||
147 | private static final ImmutableSet<String> NON_RS = | |
148 | ImmutableSet.<String>builder().addAll(NON_PS).addAll(PS_NOT_RS).build(); | |
149 | ||
150 | private static final ImmutableSet<String> TOP_UNDER_REGISTRY_SUFFIX = | |
151 | ImmutableSet.of("google.com", "foo.Co.uk", "foo.ca.us."); | |
119 | 152 | |
120 | 153 | private static final ImmutableSet<String> TOP_PRIVATE_DOMAIN = |
121 | ImmutableSet.of("google.com", "foo.Co.uk", "foo.ca.us."); | |
154 | ImmutableSet.of("google.com", "foo.Co.uk", "foo.ca.us.", "foo.blogspot.com"); | |
155 | ||
156 | private static final ImmutableSet<String> UNDER_TOP_UNDER_REGISTRY_SUFFIX = | |
157 | ImmutableSet.of("foo.bar.google.com", "a.b.co.uk", "x.y.ca.us"); | |
122 | 158 | |
123 | 159 | private static final ImmutableSet<String> UNDER_PRIVATE_DOMAIN = |
124 | ImmutableSet.of("foo.bar.google.com", "a.b.co.uk", "x.y.ca.us"); | |
160 | ImmutableSet.of("foo.bar.google.com", "a.b.co.uk", "x.y.ca.us", "a.b.blogspot.com"); | |
125 | 161 | |
126 | 162 | private static final ImmutableSet<String> VALID_IP_ADDRS = ImmutableSet.of( |
127 | 163 | "1.2.3.4", "127.0.0.1", "::1", "2001:db8::1"); |
191 | 227 | "a\u7f51\u7edcA.\u7f51\u7edc.Cn" // "a网络A.网络.Cn" |
192 | 228 | ); |
193 | 229 | |
230 | private static final ImmutableSet<String> SOMEWHERE_UNDER_RS = | |
231 | ImmutableSet.<String>builder().addAll(SOMEWHERE_UNDER_PS).addAll(PS_NOT_RS).build(); | |
232 | ||
194 | 233 | public void testValid() { |
195 | 234 | for (String name : VALID_NAME) { |
196 | 235 | InternetDomainName.from(name); |
261 | 300 | assertTrue(name, domain.hasPublicSuffix()); |
262 | 301 | assertTrue(name, domain.isUnderPublicSuffix()); |
263 | 302 | assertFalse(name, domain.isTopPrivateDomain()); |
303 | } | |
304 | } | |
305 | ||
306 | public void testRegistrySuffix() { | |
307 | for (String name : RS) { | |
308 | final InternetDomainName domain = InternetDomainName.from(name); | |
309 | assertTrue(name, domain.isRegistrySuffix()); | |
310 | assertTrue(name, domain.hasRegistrySuffix()); | |
311 | assertFalse(name, domain.isUnderRegistrySuffix()); | |
312 | assertFalse(name, domain.isTopDomainUnderRegistrySuffix()); | |
313 | assertEquals(domain, domain.registrySuffix()); | |
314 | } | |
315 | ||
316 | for (String name : NO_RS) { | |
317 | final InternetDomainName domain = InternetDomainName.from(name); | |
318 | assertFalse(name, domain.isRegistrySuffix()); | |
319 | assertFalse(name, domain.hasRegistrySuffix()); | |
320 | assertFalse(name, domain.isUnderRegistrySuffix()); | |
321 | assertFalse(name, domain.isTopDomainUnderRegistrySuffix()); | |
322 | assertNull(domain.registrySuffix()); | |
323 | } | |
324 | ||
325 | for (String name : NON_RS) { | |
326 | final InternetDomainName domain = InternetDomainName.from(name); | |
327 | assertFalse(name, domain.isRegistrySuffix()); | |
328 | assertTrue(name, domain.hasRegistrySuffix()); | |
329 | assertTrue(name, domain.isUnderRegistrySuffix()); | |
330 | } | |
331 | } | |
332 | ||
333 | public void testUnderRegistrySuffix() { | |
334 | for (String name : SOMEWHERE_UNDER_RS) { | |
335 | final InternetDomainName domain = InternetDomainName.from(name); | |
336 | assertFalse(name, domain.isRegistrySuffix()); | |
337 | assertTrue(name, domain.hasRegistrySuffix()); | |
338 | assertTrue(name, domain.isUnderRegistrySuffix()); | |
339 | } | |
340 | } | |
341 | ||
342 | public void testTopDomainUnderRegistrySuffix() { | |
343 | for (String name : TOP_UNDER_REGISTRY_SUFFIX) { | |
344 | final InternetDomainName domain = InternetDomainName.from(name); | |
345 | assertFalse(name, domain.isRegistrySuffix()); | |
346 | assertTrue(name, domain.hasRegistrySuffix()); | |
347 | assertTrue(name, domain.isUnderRegistrySuffix()); | |
348 | assertTrue(name, domain.isTopDomainUnderRegistrySuffix()); | |
349 | assertEquals(domain.parent(), domain.registrySuffix()); | |
350 | } | |
351 | } | |
352 | ||
353 | public void testUnderTopDomainUnderRegistrySuffix() { | |
354 | for (String name : UNDER_TOP_UNDER_REGISTRY_SUFFIX) { | |
355 | final InternetDomainName domain = InternetDomainName.from(name); | |
356 | assertFalse(name, domain.isRegistrySuffix()); | |
357 | assertTrue(name, domain.hasRegistrySuffix()); | |
358 | assertTrue(name, domain.isUnderRegistrySuffix()); | |
359 | assertFalse(name, domain.isTopDomainUnderRegistrySuffix()); | |
264 | 360 | } |
265 | 361 | } |
266 | 362 | |
362 | 458 | } |
363 | 459 | } |
364 | 460 | |
365 | public void testExclusion() { | |
461 | public void testPublicSuffixExclusion() { | |
366 | 462 | InternetDomainName domain = InternetDomainName.from("foo.city.yokohama.jp"); |
367 | 463 | assertTrue(domain.hasPublicSuffix()); |
368 | 464 | assertEquals("yokohama.jp", domain.publicSuffix().toString()); |
371 | 467 | assertFalse(domain.publicSuffix().isPublicSuffix()); |
372 | 468 | } |
373 | 469 | |
374 | public void testMultipleUnders() { | |
470 | public void testPublicSuffixMultipleUnders() { | |
375 | 471 | // PSL has both *.uk and *.sch.uk; the latter should win. |
376 | 472 | // See http://code.google.com/p/guava-libraries/issues/detail?id=1176 |
377 | 473 | |
379 | 475 | assertTrue(domain.hasPublicSuffix()); |
380 | 476 | assertEquals("essex.sch.uk", domain.publicSuffix().toString()); |
381 | 477 | assertEquals("www.essex.sch.uk", domain.topPrivateDomain().toString()); |
478 | } | |
479 | ||
480 | public void testRegistrySuffixExclusion() { | |
481 | InternetDomainName domain = InternetDomainName.from("foo.city.yokohama.jp"); | |
482 | assertTrue(domain.hasRegistrySuffix()); | |
483 | assertEquals("yokohama.jp", domain.registrySuffix().toString()); | |
484 | ||
485 | // Behold the weirdness! | |
486 | assertFalse(domain.registrySuffix().isRegistrySuffix()); | |
487 | } | |
488 | ||
489 | public void testRegistrySuffixMultipleUnders() { | |
490 | // PSL has both *.uk and *.sch.uk; the latter should win. | |
491 | // See http://code.google.com/p/guava-libraries/issues/detail?id=1176 | |
492 | ||
493 | InternetDomainName domain = InternetDomainName.from("www.essex.sch.uk"); | |
494 | assertTrue(domain.hasRegistrySuffix()); | |
495 | assertEquals("essex.sch.uk", domain.registrySuffix().toString()); | |
496 | assertEquals("www.essex.sch.uk", domain.topDomainUnderRegistrySuffix().toString()); | |
382 | 497 | } |
383 | 498 | |
384 | 499 | public void testEquality() { |
345 | 345 | testSortDescending(new double[] {1, 2}, new double[] {2, 1}); |
346 | 346 | testSortDescending(new double[] {1, 3, 1}, new double[] {3, 1, 1}); |
347 | 347 | testSortDescending(new double[] {-1, 1, -2, 2}, new double[] {2, 1, -1, -2}); |
348 | testSortDescending( | |
349 | new double[] {-1, 1, Double.NaN, -2, -0, 0, 2}, | |
350 | new double[] {Double.NaN, 2, 1, 0, -0, -1, -2}); | |
348 | if (sortWorksWithNaN()) { | |
349 | testSortDescending( | |
350 | new double[] {-1, 1, Double.NaN, -2, -0, 0, 2}, | |
351 | new double[] {Double.NaN, 2, 1, 0, -0, -1, -2}); | |
352 | } | |
351 | 353 | } |
352 | 354 | |
353 | 355 | public void testSortDescendingIndexed() { |
357 | 359 | testSortDescending(new double[] {1, 3, 1}, 0, 2, new double[] {3, 1, 1}); |
358 | 360 | testSortDescending(new double[] {1, 3, 1}, 0, 1, new double[] {1, 3, 1}); |
359 | 361 | testSortDescending(new double[] {-1, -2, 1, 2}, 1, 3, new double[] {-1, 1, -2, 2}); |
360 | testSortDescending( | |
361 | new double[] {-1, 1, Double.NaN, -2, 2}, 1, 4, new double[] {-1, Double.NaN, 1, -2, 2}); | |
362 | if (sortWorksWithNaN()) { | |
363 | testSortDescending( | |
364 | new double[] {-1, 1, Double.NaN, -2, 2}, 1, 4, new double[] {-1, Double.NaN, 1, -2, 2}); | |
365 | } | |
362 | 366 | } |
363 | 367 | |
364 | 368 | private static void testSortDescending(double[] input, double[] expectedOutput) { |
378 | 382 | for (int i = 0; i < input.length; i++) { |
379 | 383 | assertEquals(0, Double.compare(expectedOutput[i], input[i])); |
380 | 384 | } |
385 | } | |
386 | ||
387 | @GwtIncompatible // works with real browsers but fails with HtmlUnit | |
388 | public void testSortWorksWithNaNNonGwt() { | |
389 | assertTrue(sortWorksWithNaN()); | |
381 | 390 | } |
382 | 391 | |
383 | 392 | @GwtIncompatible // SerializableTester |
652 | 661 | } catch (NullPointerException expected) { |
653 | 662 | } |
654 | 663 | } |
664 | ||
665 | // HtmlUnit looks to be sorting double[] wrongly. We detect that and skip our tests there. | |
666 | private static boolean sortWorksWithNaN() { | |
667 | double[] array = new double[] {NaN, 0}; | |
668 | Arrays.sort(array); | |
669 | return array[0] == 0; | |
670 | } | |
655 | 671 | } |
342 | 342 | testSortDescending(new float[] {1, 2}, new float[] {2, 1}); |
343 | 343 | testSortDescending(new float[] {1, 3, 1}, new float[] {3, 1, 1}); |
344 | 344 | testSortDescending(new float[] {-1, 1, -2, 2}, new float[] {2, 1, -1, -2}); |
345 | testSortDescending( | |
346 | new float[] {-1, 1, Float.NaN, -2, -0, 0, 2}, new float[] {Float.NaN, 2, 1, 0, -0, -1, -2}); | |
345 | if (sortWorksWithNaN()) { | |
346 | testSortDescending( | |
347 | new float[] {-1, 1, Float.NaN, -2, -0, 0, 2}, new float[] {Float.NaN, 2, 1, 0, -0, -1, -2}); | |
348 | } | |
347 | 349 | } |
348 | 350 | |
349 | 351 | public void testSortDescendingIndexed() { |
353 | 355 | testSortDescending(new float[] {1, 3, 1}, 0, 2, new float[] {3, 1, 1}); |
354 | 356 | testSortDescending(new float[] {1, 3, 1}, 0, 1, new float[] {1, 3, 1}); |
355 | 357 | testSortDescending(new float[] {-1, -2, 1, 2}, 1, 3, new float[] {-1, 1, -2, 2}); |
356 | testSortDescending( | |
357 | new float[] {-1, 1, Float.NaN, -2, 2}, 1, 4, new float[] {-1, Float.NaN, 1, -2, 2}); | |
358 | if (sortWorksWithNaN()) { | |
359 | testSortDescending( | |
360 | new float[] {-1, 1, Float.NaN, -2, 2}, 1, 4, new float[] {-1, Float.NaN, 1, -2, 2}); | |
361 | } | |
358 | 362 | } |
359 | 363 | |
360 | 364 | private static void testSortDescending(float[] input, float[] expectedOutput) { |
374 | 378 | for (int i = 0; i < input.length; i++) { |
375 | 379 | assertEquals(0, Float.compare(expectedOutput[i], input[i])); |
376 | 380 | } |
381 | } | |
382 | ||
383 | @GwtIncompatible // works with real browsers but fails with HtmlUnit | |
384 | public void testSortWorksWithNaNNonGwt() { | |
385 | assertTrue(sortWorksWithNaN()); | |
377 | 386 | } |
378 | 387 | |
379 | 388 | @GwtIncompatible // SerializableTester |
628 | 637 | } catch (NullPointerException expected) { |
629 | 638 | } |
630 | 639 | } |
640 | ||
641 | // HtmlUnit looks to be sorting float[] wrongly. We detect that and skip our tests there. | |
642 | private static boolean sortWorksWithNaN() { | |
643 | float[] array = new float[] {NaN, 0}; | |
644 | Arrays.sort(array); | |
645 | return array[0] == 0; | |
646 | } | |
631 | 647 | } |
52 | 52 | Exception exception = new SampleCheckedException(); |
53 | 53 | try { |
54 | 54 | timeLimiter.callWithTimeout(callableThrowing(exception), DELAY_MS, TimeUnit.MILLISECONDS); |
55 | fail("Excpected ExecutionException"); | |
55 | fail("Expected ExecutionException"); | |
56 | 56 | } catch (ExecutionException e) { |
57 | 57 | assertThat(e.getCause()).isEqualTo(exception); |
58 | 58 | } |
62 | 62 | Exception exception = new RuntimeException("test"); |
63 | 63 | try { |
64 | 64 | timeLimiter.callWithTimeout(callableThrowing(exception), DELAY_MS, TimeUnit.MILLISECONDS); |
65 | fail("Excpected UncheckedExecutionException"); | |
65 | fail("Expected UncheckedExecutionException"); | |
66 | 66 | } catch (UncheckedExecutionException e) { |
67 | 67 | assertThat(e.getCause()).isEqualTo(exception); |
68 | 68 | } |
84 | 84 | RuntimeException exception = new RuntimeException("test"); |
85 | 85 | try { |
86 | 86 | timeLimiter.runWithTimeout(runnableThrowing(exception), DELAY_MS, TimeUnit.MILLISECONDS); |
87 | fail("Excpected UncheckedExecutionException"); | |
87 | fail("Expected UncheckedExecutionException"); | |
88 | 88 | } catch (UncheckedExecutionException e) { |
89 | 89 | assertThat(e.getCause()).isEqualTo(exception); |
90 | 90 | } |
95 | 95 | try { |
96 | 96 | timeLimiter.runUninterruptiblyWithTimeout( |
97 | 97 | runnableThrowing(exception), DELAY_MS, TimeUnit.MILLISECONDS); |
98 | fail("Excpected UncheckedExecutionException"); | |
98 | fail("Expected UncheckedExecutionException"); | |
99 | 99 | } catch (UncheckedExecutionException e) { |
100 | 100 | assertThat(e.getCause()).isEqualTo(exception); |
101 | 101 | } |
571 | 571 | verify(service).shutdown(); |
572 | 572 | } |
573 | 573 | |
574 | public void testGetExitingExcutorService_executorSetToUseDaemonThreads() { | |
574 | public void testGetExitingExecutorService_executorSetToUseDaemonThreads() { | |
575 | 575 | TestApplication application = new TestApplication(); |
576 | 576 | ThreadPoolExecutor executor = new ThreadPoolExecutor( |
577 | 577 | 1, 2, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1)); |
579 | 579 | assertTrue(executor.getThreadFactory().newThread(EMPTY_RUNNABLE).isDaemon()); |
580 | 580 | } |
581 | 581 | |
582 | public void testGetExitingExcutorService_executorDelegatesToOriginal() { | |
582 | public void testGetExitingExecutorService_executorDelegatesToOriginal() { | |
583 | 583 | TestApplication application = new TestApplication(); |
584 | 584 | ThreadPoolExecutor executor = mock(ThreadPoolExecutor.class); |
585 | 585 | ThreadFactory threadFactory = mock(ThreadFactory.class); |
588 | 588 | verify(executor).execute(EMPTY_RUNNABLE); |
589 | 589 | } |
590 | 590 | |
591 | public void testGetExitingExcutorService_shutdownHookRegistered() throws InterruptedException { | |
591 | public void testGetExitingExecutorService_shutdownHookRegistered() throws InterruptedException { | |
592 | 592 | TestApplication application = new TestApplication(); |
593 | 593 | ThreadPoolExecutor executor = mock(ThreadPoolExecutor.class); |
594 | 594 | ThreadFactory threadFactory = mock(ThreadFactory.class); |
598 | 598 | verify(executor).shutdown(); |
599 | 599 | } |
600 | 600 | |
601 | public void testGetExitingScheduledExcutorService_executorSetToUseDaemonThreads() { | |
601 | public void testGetExitingScheduledExecutorService_executorSetToUseDaemonThreads() { | |
602 | 602 | TestApplication application = new TestApplication(); |
603 | 603 | ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); |
604 | 604 | assertNotNull(application.getExitingScheduledExecutorService(executor)); |
605 | 605 | assertTrue(executor.getThreadFactory().newThread(EMPTY_RUNNABLE).isDaemon()); |
606 | 606 | } |
607 | 607 | |
608 | public void testGetExitingScheduledExcutorService_executorDelegatesToOriginal() { | |
608 | public void testGetExitingScheduledExecutorService_executorDelegatesToOriginal() { | |
609 | 609 | TestApplication application = new TestApplication(); |
610 | 610 | ScheduledThreadPoolExecutor executor = mock(ScheduledThreadPoolExecutor.class); |
611 | 611 | ThreadFactory threadFactory = mock(ThreadFactory.class); |
614 | 614 | verify(executor).execute(EMPTY_RUNNABLE); |
615 | 615 | } |
616 | 616 | |
617 | public void testGetScheduledExitingExcutorService_shutdownHookRegistered() | |
617 | public void testGetScheduledExitingExecutorService_shutdownHookRegistered() | |
618 | 618 | throws InterruptedException { |
619 | 619 | TestApplication application = new TestApplication(); |
620 | 620 | ScheduledThreadPoolExecutor executor = mock(ScheduledThreadPoolExecutor.class); |
114 | 114 | } |
115 | 115 | } |
116 | 116 | |
117 | public void testWeakReadWrite() { | |
118 | Striped<ReadWriteLock> striped = Striped.lazyWeakReadWriteLock(1000); | |
119 | Object key = new Object(); | |
120 | Lock readLock = striped.get(key).readLock(); | |
121 | WeakReference<Object> garbage = new WeakReference<>(new Object()); | |
122 | GcFinalization.awaitClear(garbage); | |
123 | Lock writeLock = striped.get(key).writeLock(); | |
124 | readLock.lock(); | |
125 | assertFalse(writeLock.tryLock()); | |
126 | readLock.unlock(); | |
127 | } | |
128 | ||
117 | 129 | public void testStrongImplementations() { |
118 | 130 | for (Striped<?> striped : strongImplementations()) { |
119 | 131 | WeakReference<Object> weakRef = new WeakReference<>(striped.get(new Object())); |