1 /* 2 * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 * @bug 8195649 26 * @summary Basic functional test of Optional 27 * @author Mike Duigou 28 * @build ObscureException 29 * @run testng Basic 30 */ 31 package test.java.util.Optional; 32 33 // Android-added: support for wrapper to avoid d8 backporting of Optional methods (b/191859202). 34 import java.lang.invoke.MethodHandle; 35 import java.lang.invoke.MethodHandles; 36 import java.lang.invoke.MethodType; 37 import java.util.function.Consumer; 38 import java.util.function.Supplier; 39 40 import java.util.List; 41 import java.util.NoSuchElementException; 42 import java.util.Optional; 43 import java.util.stream.Collectors; 44 import java.util.stream.Stream; 45 import java.util.concurrent.atomic.AtomicBoolean; 46 import java.util.concurrent.atomic.AtomicInteger; 47 import java.util.concurrent.atomic.AtomicBoolean; 48 49 import static java.util.stream.Collectors.toList; 50 51 import static org.testng.Assert.*; 52 import org.testng.annotations.Test; 53 54 public class Basic { 55 56 /** 57 * Checks a block of assertions over an empty Optional. 58 */ checkEmpty(Optional<String> empty)59 void checkEmpty(Optional<String> empty) { 60 assertTrue(empty.equals(Optional.empty())); 61 assertTrue(Optional.empty().equals(empty)); 62 assertFalse(empty.equals(Optional.of("unexpected"))); 63 assertFalse(Optional.of("unexpected").equals(empty)); 64 assertFalse(empty.equals("unexpected")); 65 66 assertFalse(empty.isPresent()); 67 // Android-changed: use Optional_isEmpty() to a void d8 backporting (b/191859202). 68 // assertTrue(empty.isEmpty()); 69 assertTrue(Optional_isEmpty(empty)); 70 assertEquals(empty.hashCode(), 0); 71 assertEquals(empty.orElse("x"), "x"); 72 assertEquals(empty.orElseGet(() -> "y"), "y"); 73 74 assertThrows(NoSuchElementException.class, () -> empty.get()); 75 // Android-changed: use Optional_orElseThrow() to a void d8 backporting (b/191859202). 76 // assertThrows(NoSuchElementException.class, () -> empty.orElseThrow()); 77 assertThrows(NoSuchElementException.class, () -> Optional_orElseThrow(empty)); 78 assertThrows(ObscureException.class, () -> empty.orElseThrow(ObscureException::new)); 79 80 var b = new AtomicBoolean(); 81 empty.ifPresent(s -> b.set(true)); 82 assertFalse(b.get()); 83 84 var b1 = new AtomicBoolean(false); 85 var b2 = new AtomicBoolean(false); 86 // Android-changed: use Optional_ifPresentOrElse() to a void d8 backporting (b/191859202). 87 // empty.ifPresentOrElse(s -> b1.set(true), () -> b2.set(true)); 88 Optional_ifPresentOrElse(empty, s -> b1.set(true), () -> b2.set(true)); 89 assertFalse(b1.get()); 90 assertTrue(b2.get()); 91 92 assertEquals(empty.toString(), "Optional.empty"); 93 } 94 95 /** 96 * Checks a block of assertions over an Optional that is expected to 97 * have a particular value present. 98 */ checkPresent(Optional<String> opt, String expected)99 void checkPresent(Optional<String> opt, String expected) { 100 assertFalse(opt.equals(Optional.empty())); 101 assertFalse(Optional.empty().equals(opt)); 102 assertTrue(opt.equals(Optional.of(expected))); 103 assertTrue(Optional.of(expected).equals(opt)); 104 assertFalse(opt.equals(Optional.of("unexpected"))); 105 assertFalse(Optional.of("unexpected").equals(opt)); 106 assertFalse(opt.equals("unexpected")); 107 108 assertTrue(opt.isPresent()); 109 // Android-changed: use Optional_isEmpty() to a void d8 backporting (b/191859202). 110 //assertFalse(opt.isEmpty()); 111 assertFalse(Optional_isEmpty(opt)); 112 assertEquals(opt.hashCode(), expected.hashCode()); 113 assertEquals(opt.orElse("unexpected"), expected); 114 assertEquals(opt.orElseGet(() -> "unexpected"), expected); 115 116 assertEquals(opt.get(), expected); 117 // Android-changed: use Optional_orElseThrow() to a void d8 backporting (b/191859202). 118 // assertEquals(opt.orElseThrow(), expected); 119 assertEquals(Optional_orElseThrow(opt), expected); 120 assertEquals(opt.orElseThrow(ObscureException::new), expected); 121 122 var b = new AtomicBoolean(false); 123 opt.ifPresent(s -> b.set(true)); 124 assertTrue(b.get()); 125 126 var b1 = new AtomicBoolean(false); 127 var b2 = new AtomicBoolean(false); 128 // Android-changed: use Optional_ifPresentOrElse() to a void d8 backporting (b/191859202). 129 // opt.ifPresentOrElse(s -> b1.set(true), () -> b2.set(true)); 130 Optional_ifPresentOrElse(opt, s -> b1.set(true), () -> b2.set(true)); 131 assertTrue(b1.get()); 132 assertFalse(b2.get()); 133 134 assertEquals(opt.toString(), "Optional[" + expected + "]"); 135 } 136 137 @Test(groups = "unit") testEmpty()138 public void testEmpty() { 139 checkEmpty(Optional.empty()); 140 } 141 142 @SuppressWarnings("NullArgumentForNonNullParameter") 143 @Test(groups = "unit") testOfNull()144 public void testOfNull() { 145 assertThrows(NullPointerException.class, () -> Optional.of(null)); 146 } 147 148 @Test(groups = "unit") testOfPresent()149 public void testOfPresent() { 150 checkPresent(Optional.of("xyzzy"), "xyzzy"); 151 } 152 153 @Test(groups = "unit") testOfNullableNull()154 public void testOfNullableNull() { 155 checkEmpty(Optional.ofNullable(null)); 156 } 157 158 @Test(groups = "unit") testOfNullablePresent()159 public void testOfNullablePresent() { 160 checkPresent(Optional.ofNullable("xyzzy"), "xyzzy"); 161 } 162 163 @Test(groups = "unit") testFilterEmpty()164 public void testFilterEmpty() { 165 checkEmpty(Optional.<String>empty().filter(s -> { fail(); return true; })); 166 } 167 168 @Test(groups = "unit") testFilterFalse()169 public void testFilterFalse() { 170 checkEmpty(Optional.of("xyzzy").filter(s -> s.equals("plugh"))); 171 } 172 173 @Test(groups = "unit") testFilterTrue()174 public void testFilterTrue() { 175 checkPresent(Optional.of("xyzzy").filter(s -> s.equals("xyzzy")), "xyzzy"); 176 } 177 178 @Test(groups = "unit") testMapEmpty()179 public void testMapEmpty() { 180 checkEmpty(Optional.empty().map(s -> { fail(); return ""; })); 181 } 182 183 @Test(groups = "unit") testMapPresent()184 public void testMapPresent() { 185 checkPresent(Optional.of("xyzzy").map(s -> s.replace("xyzzy", "plugh")), "plugh"); 186 } 187 188 @Test(groups = "unit") testFlatMapEmpty()189 public void testFlatMapEmpty() { 190 checkEmpty(Optional.empty().flatMap(s -> { fail(); return Optional.of(""); })); 191 } 192 193 @Test(groups = "unit") testFlatMapPresentReturnEmpty()194 public void testFlatMapPresentReturnEmpty() { 195 checkEmpty(Optional.of("xyzzy") 196 .flatMap(s -> { assertEquals(s, "xyzzy"); return Optional.empty(); })); 197 } 198 199 @Test testFlatMapPresentReturnPresent()200 public void testFlatMapPresentReturnPresent() { 201 checkPresent(Optional.of("xyzzy") 202 .flatMap(s -> { assertEquals(s, "xyzzy"); return Optional.of("plugh"); }), 203 "plugh"); 204 } 205 206 @Test testOrEmptyEmpty()207 public void testOrEmptyEmpty() { 208 // Android-changed: use Optional_or() to a void d8 backporting (b/191859202). 209 // checkEmpty(Optional.<String>empty().or(() -> Optional.empty())); 210 checkEmpty(Optional_or(Optional.<String>empty(), () -> Optional.empty())); 211 } 212 213 @Test testOrEmptyPresent()214 public void testOrEmptyPresent() { 215 // Android-changed: use Optional_or() to a void d8 backporting (b/191859202). 216 // checkPresent(Optional.<String>empty().or(() -> Optional.of("plugh")), "plugh"); 217 checkPresent(Optional_or(Optional.<String>empty(), () -> Optional.of("plugh")), "plugh"); 218 } 219 220 @Test testOrPresentDontCare()221 public void testOrPresentDontCare() { 222 // Android-changed: use Optional_or() to a void d8 backporting (b/191859202). 223 // checkPresent(Optional.of("xyzzy").or(() -> { fail(); return Optional.of("plugh"); }), "xyzzy"); 224 checkPresent(Optional_or(Optional.of("xyzzy"), () -> { fail(); return Optional.of("plugh"); }), "xyzzy"); 225 } 226 227 @Test testStreamEmpty()228 public void testStreamEmpty() { 229 // Android-changed: use Optional_stream() to a void d8 backporting (b/191859202). 230 // assertEquals(Optional.empty().stream().collect(toList()), List.of()); 231 assertEquals(Optional_stream(Optional.empty()).collect(toList()), List.of()); 232 } 233 234 @Test testStreamPresent()235 public void testStreamPresent() { 236 // Android-changed: use Optional_stream() to a void d8 backporting (b/191859202). 237 // assertEquals(Optional.of("xyzzy").stream().collect(toList()), List.of("xyzzy")); 238 assertEquals(Optional_stream(Optional.of("xyzzy")).collect(toList()), List.of("xyzzy")); 239 } 240 241 // BEGIN Android-added: More tests for coverage http://b/203822442. 242 // Also improves coverage for Optional{Int,Long,Double} 243 private static final Optional<Integer> P = Optional.<Integer>of(3); 244 private static final Optional<Integer> E = Optional.<Integer>empty(); 245 246 @Test testIfPresentOrElse_empty()247 void testIfPresentOrElse_empty() { 248 AtomicInteger flag = new AtomicInteger(0); 249 // Note use Optional_ifPresentOrElse() to a void d8 backporting (b/191859202). 250 // E.ifPresentOrElse(integer -> flag.set(1), () -> flag.set(2)); 251 Optional_ifPresentOrElse(E, integer -> flag.set(1), () -> flag.set(2)); 252 assertEquals(flag.get(), 2); 253 } 254 255 @Test testIfPresentOrElse_present()256 void testIfPresentOrElse_present() { 257 AtomicInteger flag = new AtomicInteger(0); 258 // Note use Optional_ifPresentOrElse() to a void d8 backporting (b/191859202). 259 // P.ifPresentOrElse(integer -> flag.set(1), () -> flag.set(2)); 260 Optional_ifPresentOrElse(P, integer -> flag.set(1), () -> flag.set(2)); 261 assertEquals(flag.get(), 1); 262 } 263 264 @Test testOr_empty()265 void testOr_empty() { 266 // Note use Optional_or() to a void d8 backporting (b/191859202). 267 Optional<Integer> o = Optional_or(E, () -> Optional.of(5)); 268 assertEquals((int) o.get(), 5); 269 } 270 271 @Test testOr_present()272 void testOr_present() { 273 // Note use Optional_or() to a void d8 backporting (b/191859202). 274 // Optional<Integer> o = P.or(() -> Optional.of(5)); 275 Optional<Integer> o = Optional_or(P, () -> Optional.of(5)); 276 assertEquals((int) o.get(), 3); 277 } 278 279 @Test testStream_empty()280 public void testStream_empty() { 281 // Not use Optional_stream() to a void d8 backporting (b/191859202). 282 // Stream<Integer> s = E.stream(); 283 Stream<Integer> s = Optional_stream(E); 284 assertEquals(s.collect(Collectors.toList()), List.of()); 285 } 286 287 @Test testStream_present()288 public void testStream_present() { 289 // Not use Optional_stream() to a void d8 backporting (b/191859202). 290 // Stream<Integer> s = P.stream(); 291 Stream<Integer> s = Optional_stream(P); 292 assertEquals(s.collect(Collectors.toList()), List.of(3)); 293 } 294 295 @Test(expectedExceptions = NoSuchElementException.class) testOrElseThrow_empty()296 public void testOrElseThrow_empty() { 297 // Note use Optional_orElseThrow() to a void d8 backporting (b/191859202). 298 // E.orElseThrow(); 299 Optional_orElseThrow(E); 300 } 301 302 @Test testOrElseThrow_present()303 public void testOrElseThrow_present() { 304 // Note use Optional_orElseThrow() to a void d8 backporting (b/191859202). 305 // assertEquals((int) P.orElseThrow(), 3); 306 assertEquals((int) Optional_orElseThrow(P), 3); 307 } 308 309 @Test testIsEmpty_empty()310 public void testIsEmpty_empty() { 311 // Note use Optional_isEmpty() to a void d8 backporting (b/191859202). 312 // assertTrue(E.isEmpty()); 313 assertTrue(Optional_isEmpty(E)); 314 } 315 316 @Test testIsEmpty_present()317 public void testIsEmpty_present() { 318 // Note use Optional_isEmpty() to a void d8 backporting (b/191859202). 319 // assertFalse(P.isEmpty()); 320 assertFalse(Optional_isEmpty(P)); 321 } 322 // END Android-added: More tests for coverage http://b/203822442. 323 324 // Android-added: wrapper to avoid d8 backporting of Optional.ifPresentOrElse() (b/191859202). Optional_ifPresentOrElse( Optional<T> receiver, Consumer<? super T> action, Runnable emptyAction)325 private static <T> void Optional_ifPresentOrElse( 326 Optional<T> receiver, Consumer<? super T> action, Runnable emptyAction) { 327 try { 328 MethodType type = MethodType.methodType(void.class, Consumer.class, Runnable.class); 329 MethodHandle mh = 330 MethodHandles.lookup().findVirtual(Optional.class, "ifPresentOrElse", type); 331 mh.invokeExact(receiver, action, emptyAction); 332 } catch (Throwable t) { 333 throw new RuntimeException(t); 334 } 335 } 336 337 // Android-added: wrapper to avoid d8 backporting of Optional.isEmpty() (b/191859202). Optional_isEmpty(Optional<T> receiver)338 private static <T> boolean Optional_isEmpty(Optional<T> receiver) { 339 try { 340 MethodType type = MethodType.methodType(boolean.class); 341 MethodHandle mh = MethodHandles.lookup().findVirtual(Optional.class, "isEmpty", type); 342 return (boolean) mh.invokeExact(receiver); 343 } catch (Throwable t) { 344 throw new RuntimeException(t); 345 } 346 } 347 348 // Android-added: wrapper to avoid d8 backporting of Optional.or(Supplier) (b/191859202). Optional_or(Optional<T> receiver, Supplier<? extends Optional<? extends T>> supplier)349 private static <T> Optional<T> Optional_or(Optional<T> receiver, 350 Supplier<? extends Optional<? extends T>> supplier) { 351 try { 352 MethodType type = MethodType.methodType(Optional.class, Supplier.class); 353 MethodHandle mh = MethodHandles.lookup().findVirtual(Optional.class, "or", type); 354 return (Optional<T>) mh.invokeExact(receiver, supplier); 355 } catch (Throwable t) { 356 throw new RuntimeException(t); 357 } 358 } 359 360 // Android-added: wrapper to avoid d8 backporting of Optional.orElseThrow() (b/191859202). Optional_orElseThrow(Optional<T> receiver)361 private static <T> T Optional_orElseThrow(Optional<T> receiver) { 362 try { 363 MethodType type = MethodType.methodType(Object.class); 364 MethodHandle mh = 365 MethodHandles.lookup().findVirtual(Optional.class, "orElseThrow", type); 366 return (T) mh.invokeExact(receiver); 367 } catch (NoSuchElementException expected) { 368 throw expected; // Underlying method may throw NoSuchElementException 369 } catch (Throwable t) { 370 throw new RuntimeException(t); 371 } 372 } 373 374 // Android-added: wrapper to avoid d8 backporting of Optional.stream() (b/191859202). Optional_stream(Optional<T> receiver)375 private static <T> Stream<T> Optional_stream(Optional<T> receiver) { 376 try { 377 MethodType type = MethodType.methodType(Stream.class); 378 MethodHandle mh = MethodHandles.lookup().findVirtual(Optional.class, "stream", type); 379 return (Stream<T>) mh.invokeExact(receiver); 380 } catch (Throwable t) { 381 throw new RuntimeException(t); 382 } 383 } 384 } 385