test/jdk/java/util/Optional/Basic.java
branchJDK-8195649-branch
changeset 56383 4872fc3de1b0
parent 56376 718b9df3e302
equal deleted inserted replaced
56376:718b9df3e302 56383:4872fc3de1b0
     1 /*
     1 /*
     2  * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    20  * or visit www.oracle.com if you need additional information or have any
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    21  * questions.
    22  */
    22  */
    23 
    23 
    24 /* @test
    24 /* @test
    25  * @bug 8195649
       
    26  * @summary Basic functional test of Optional
    25  * @summary Basic functional test of Optional
    27  * @author Mike Duigou
    26  * @author Mike Duigou
    28  * @build ObscureException
       
    29  * @run testng Basic
    27  * @run testng Basic
    30  */
    28  */
    31 
    29 
    32 import java.util.List;
    30 import java.lang.AssertionError;
       
    31 import java.lang.NullPointerException;
       
    32 import java.lang.Throwable;
    33 import java.util.NoSuchElementException;
    33 import java.util.NoSuchElementException;
    34 import java.util.Optional;
    34 import java.util.Optional;
    35 import java.util.concurrent.atomic.AtomicBoolean;
    35 import java.util.concurrent.atomic.AtomicBoolean;
    36 import java.util.stream.Stream;
    36 import java.util.stream.Stream;
    37 
    37 
    38 import static java.util.stream.Collectors.toList;
       
    39 
       
    40 import static org.testng.Assert.*;
    38 import static org.testng.Assert.*;
    41 import org.testng.annotations.Test;
    39 import org.testng.annotations.Test;
    42 
    40 
       
    41 
    43 public class Basic {
    42 public class Basic {
    44 
    43 
    45     /**
    44     @Test(groups = "unit")
    46      * Checks a block of assertions over an empty Optional.
    45     public void testEmpty() {
    47      */
    46         Optional<Boolean> empty = Optional.empty();
    48     void checkEmpty(Optional<String> empty) {
    47         Optional<String> presentEmptyString = Optional.of("");
       
    48         Optional<Boolean> present = Optional.of(Boolean.TRUE);
       
    49 
       
    50         // empty
       
    51         assertTrue(empty.equals(empty));
    49         assertTrue(empty.equals(Optional.empty()));
    52         assertTrue(empty.equals(Optional.empty()));
    50         assertTrue(Optional.empty().equals(empty));
    53         assertTrue(!empty.equals(present));
    51         assertFalse(empty.equals(Optional.of("unexpected")));
    54         assertTrue(0 == empty.hashCode());
    52         assertFalse(Optional.of("unexpected").equals(empty));
    55         assertTrue(!empty.toString().isEmpty());
    53         assertFalse(empty.equals("unexpected"));
    56         assertTrue(!empty.toString().equals(presentEmptyString.toString()));
    54 
    57         assertTrue(!empty.isPresent());
    55         assertFalse(empty.isPresent());
    58 
    56         assertEquals(empty.hashCode(), 0);
    59         empty.ifPresent(v -> fail());
    57         assertEquals(empty.orElse("x"), "x");
    60 
    58         assertEquals(empty.orElseGet(() -> "y"), "y");
    61         AtomicBoolean emptyCheck = new AtomicBoolean();
    59 
    62         empty.ifPresentOrElse(v -> fail(), () -> emptyCheck.set(true));
    60         assertThrows(NoSuchElementException.class, () -> empty.get());
    63         assertTrue(emptyCheck.get());
    61         assertThrows(NoSuchElementException.class, () -> empty.orElseThrow());
    64 
    62         assertThrows(ObscureException.class,       () -> empty.orElseThrow(ObscureException::new));
    65         try {
    63 
    66             empty.ifPresentOrElse(v -> fail(), () -> { throw new ObscureException(); });
    64         var b = new AtomicBoolean();
    67             fail();
    65         empty.ifPresent(s -> b.set(true));
    68         } catch (ObscureException expected) {
    66         assertFalse(b.get());
    69         } catch (AssertionError e) {
    67 
    70             throw e;
    68         var b1 = new AtomicBoolean(false);
    71         } catch (Throwable t) {
    69         var b2 = new AtomicBoolean(false);
    72             fail();
    70         empty.ifPresentOrElse(s -> b1.set(true), () -> b2.set(true));
    73         }
    71         assertFalse(b1.get());
    74 
    72         assertTrue(b2.get());
    75         assertSame(null, empty.orElse(null));
    73 
    76         RuntimeException orElse = new RuntimeException() { };
    74         assertEquals(empty.toString(), "Optional.empty");
    77         assertSame(Boolean.FALSE, empty.orElse(Boolean.FALSE));
    75     }
    78         assertSame(null, empty.orElseGet(() -> null));
    76 
    79         assertSame(Boolean.FALSE, empty.orElseGet(() -> Boolean.FALSE));
    77     /**
    80     }
    78      * Checks a block of assertions over an Optional that is expected to
    81 
    79      * have a particular value present.
    82     @Test(groups = "unit")
    80      */
    83     public void testIfPresentAndOrElseAndNull() {
    81     void checkPresent(Optional<String> opt, String expected) {
    84         Optional<Boolean> empty = Optional.empty();
    82         assertFalse(opt.equals(Optional.empty()));
    85         Optional<Boolean> present = Optional.of(Boolean.TRUE);
    83         assertFalse(Optional.empty().equals(opt));
    86 
    84         assertTrue(opt.equals(Optional.of(expected)));
    87         // No NPE
    85         assertTrue(Optional.of(expected).equals(opt));
    88         present.ifPresentOrElse(v -> {}, null);
    86         assertFalse(opt.equals(Optional.of("unexpected")));
    89         empty.ifPresent(null);
    87         assertFalse(Optional.of("unexpected").equals(opt));
    90         empty.ifPresentOrElse(null, () -> {});
    88         assertFalse(opt.equals("unexpected"));
    91 
    89 
    92         // NPE
    90         assertTrue(opt.isPresent());
    93         try {
    91         assertEquals(opt.hashCode(), expected.hashCode());
    94             present.ifPresent(null);
    92         assertEquals(opt.orElse("unexpected"), expected);
    95             fail();
    93         assertEquals(opt.orElseGet(() -> "unexpected"), expected);
    96         } catch (NullPointerException ex) {}
    94 
    97         try {
    95         assertEquals(opt.get(), expected);
    98             present.ifPresentOrElse(null, () -> {});
    96         assertEquals(opt.orElseThrow(), expected);
    99             fail();
    97         assertEquals(opt.orElseThrow(ObscureException::new), expected);
   100         } catch (NullPointerException ex) {}
    98 
   101         try {
    99         var b = new AtomicBoolean(false);
   102             empty.ifPresentOrElse(v -> {}, null);
   100         opt.ifPresent(s -> b.set(true));
   103             fail();
   101         assertTrue(b.get());
   104         } catch (NullPointerException ex) {}
   102 
   105     }
   103         var b1 = new AtomicBoolean(false);
   106 
   104         var b2 = new AtomicBoolean(false);
   107     @Test(expectedExceptions=NoSuchElementException.class)
   105         opt.ifPresentOrElse(s -> b1.set(true), () -> b2.set(true));
   108     public void testEmptyGet() {
   106         assertTrue(b1.get());
   109         Optional<Boolean> empty = Optional.empty();
   107         assertFalse(b2.get());
   110 
   108 
   111         Boolean got = empty.get();
   109         assertEquals(opt.toString(), "Optional[" + expected + "]");
   112     }
   110     }
   113 
   111 
   114     @Test(expectedExceptions=NullPointerException.class)
   112     @Test(groups = "unit")
   115     public void testEmptyOrElseGetNull() {
   113     public void testEmpty() {
   116         Optional<Boolean> empty = Optional.empty();
   114         checkEmpty(Optional.empty());
   117 
   115     }
   118         Boolean got = empty.orElseGet(null);
   116 
   119     }
   117     @Test(groups = "unit")
   120 
   118     public void testOfNull() {
   121     @Test(expectedExceptions=NullPointerException.class)
   119         assertThrows(NullPointerException.class, () -> Optional.of(null));
   122     public void testEmptyOrElseThrowNull() throws Throwable {
   120     }
   123         Optional<Boolean> empty = Optional.empty();
   121 
   124 
   122     @Test(groups = "unit")
   125         Boolean got = empty.orElseThrow(null);
   123     public void testOfPresent() {
   126     }
   124         checkPresent(Optional.of("xyzzy"), "xyzzy");
   127 
   125     }
   128     @Test(expectedExceptions=ObscureException.class)
   126 
   129     public void testEmptyOrElseThrow() throws Exception {
   127     @Test(groups = "unit")
   130         Optional<Boolean> empty = Optional.empty();
   128     public void testOfNullableNull() {
   131 
   129         checkEmpty(Optional.ofNullable(null));
   132         Boolean got = empty.orElseThrow(ObscureException::new);
   130     }
   133     }
   131 
   134 
   132     @Test(groups = "unit")
   135     @Test(expectedExceptions=NoSuchElementException.class)
   133     public void testOfNullablePresent() {
   136     public void testEmptyOrElseThrowNoArg() throws Exception {
   134         checkPresent(Optional.of("xyzzy"), "xyzzy");
   137         Optional<Boolean> empty = Optional.empty();
   135     }
   138 
   136 
   139         Boolean got = empty.orElseThrow();
   137     @Test(groups = "unit")
   140     }
   138     public void testFilterEmpty() {
   141 
   139         checkEmpty(Optional.<String>empty().filter(s -> { fail(); return true; }));
   142     @Test(groups = "unit")
   140     }
   143     public void testPresent() {
   141 
   144         Optional<Boolean> empty = Optional.empty();
   142     @Test(groups = "unit")
   145         Optional<String> presentEmptyString = Optional.of("");
   143     public void testFilterFalse() {
   146         Optional<Boolean> present = Optional.of(Boolean.TRUE);
   144         checkEmpty(Optional.of("xyzzy").filter(s -> s.equals("plugh")));
   147 
   145     }
   148         // present
   146 
   149         assertTrue(present.equals(present));
   147     @Test(groups = "unit")
   150         assertTrue(present.equals(Optional.of(Boolean.TRUE)));
   148     public void testFilterTrue() {
   151         assertTrue(!present.equals(empty));
   149         checkPresent(Optional.of("xyzzy").filter(s -> s.equals("xyzzy")), "xyzzy");
   152         assertTrue(Boolean.TRUE.hashCode() == present.hashCode());
   150     }
   153         assertTrue(!present.toString().isEmpty());
   151 
   154         assertTrue(!present.toString().equals(presentEmptyString.toString()));
   152     @Test(groups = "unit")
   155         assertTrue(-1 != present.toString().indexOf(Boolean.TRUE.toString()));
   153     public void testMapEmpty() {
   156         assertSame(Boolean.TRUE, present.get());
   154         checkEmpty(Optional.empty().map(s -> { fail(); return ""; }));
   157         assertSame(Boolean.TRUE, present.orElseThrow());
   155     }
   158 
   156 
   159         AtomicBoolean presentCheck = new AtomicBoolean();
   157     @Test(groups = "unit")
   160         present.ifPresent(v -> presentCheck.set(true));
   158     public void testMapPresent() {
   161         assertTrue(presentCheck.get());
   159         checkPresent(Optional.of("xyzzy").map(s -> s.replace("xyzzy", "plugh")), "plugh");
   162         presentCheck.set(false);
   160     }
   163         present.ifPresentOrElse(v -> presentCheck.set(true), () -> fail());
   161 
   164         assertTrue(presentCheck.get());
   162     @Test(groups = "unit")
   165 
   163     public void testFlatMapEmpty() {
   166         try {
   164         checkEmpty(Optional.empty().flatMap(s -> { fail(); return Optional.of(""); }));
   167             present.ifPresent(v -> { throw new ObscureException(); });
   165     }
   168             fail();
   166 
   169         } catch (ObscureException expected) {
   167     @Test(groups = "unit")
   170         } catch (AssertionError e) {
   168     public void testFlatMapPresentReturnEmpty() {
   171             throw e;
   169         checkEmpty(Optional.of("xyzzy")
   172         } catch (Throwable t) {
   170                            .flatMap(s -> { assertEquals(s, "xyzzy"); return Optional.empty(); }));
   173             fail();
   171     }
   174         }
   172 
   175         try {
   173     @Test(groups = "unit")
   176             present.ifPresentOrElse(v -> { throw new ObscureException(); }, () -> fail());
   174     public void testFlatMapPresentReturnPresent() {
   177             fail();
   175         checkPresent(Optional.of("xyzzy")
   178         } catch (ObscureException expected) {
   176                              .flatMap(s -> { assertEquals(s, "xyzzy"); return Optional.of("plugh"); }),
   179         } catch (AssertionError e) {
   177                      "plugh");
   180             throw e;
   178     }
   181         } catch (Throwable t) {
   179 
   182             fail();
   180     @Test(groups = "unit")
   183         }
   181     public void testOrEmptyEmpty() {
   184 
   182         checkEmpty(Optional.<String>empty().or(() -> Optional.empty()));
   185         assertSame(Boolean.TRUE, present.orElse(null));
   183     }
   186         assertSame(Boolean.TRUE, present.orElse(Boolean.FALSE));
   184 
   187         assertSame(Boolean.TRUE, present.orElseGet(null));
   185     @Test(groups = "unit")
   188         assertSame(Boolean.TRUE, present.orElseGet(() -> null));
   186     public void testOrEmptyPresent() {
   189         assertSame(Boolean.TRUE, present.orElseGet(() -> Boolean.FALSE));
   187         checkPresent(Optional.<String>empty().or(() -> Optional.of("plugh")), "plugh");
   190         assertSame(Boolean.TRUE, present.<RuntimeException>orElseThrow(null));
   188     }
   191         assertSame(Boolean.TRUE, present.<RuntimeException>orElseThrow(ObscureException::new));
   189 
   192     }
   190     @Test(groups = "unit")
   193 
   191     public void testOrPresentDontCare() {
   194     @Test(groups = "unit")
   192         checkPresent(Optional.of("xyzzy").or(() -> { fail(); return Optional.of("plugh"); }), "xyzzy");
   195     public void testOfNullable() {
   193     }
   196         Optional<String> instance = Optional.ofNullable(null);
   194 
   197         assertFalse(instance.isPresent());
   195     @Test(groups = "unit")
   198 
   196     public void testStreamEmpty() {
   199         instance = Optional.ofNullable("Duke");
   197         assertEquals(Optional.empty().stream().collect(toList()), List.of());
   200         assertTrue(instance.isPresent());
   198     }
   201         assertEquals(instance.get(), "Duke");
   199 
   202         assertEquals(instance.orElseThrow(), "Duke");
   200     @Test(groups = "unit")
   203     }
   201     public void testStreamPresent() {
   204 
   202         assertEquals(Optional.of("xyzzy").stream().collect(toList()), List.of("xyzzy"));
   205     @Test(groups = "unit")
       
   206     public void testFilter() {
       
   207         // Null mapper function
       
   208         Optional<String> empty = Optional.empty();
       
   209         Optional<String> duke = Optional.of("Duke");
       
   210 
       
   211         try {
       
   212             Optional<String> result = empty.filter(null);
       
   213             fail("Should throw NPE on null mapping function");
       
   214         } catch (NullPointerException npe) {
       
   215             // expected
       
   216         }
       
   217 
       
   218         Optional<String> result = empty.filter(String::isEmpty);
       
   219         assertFalse(result.isPresent());
       
   220 
       
   221         result = duke.filter(String::isEmpty);
       
   222         assertFalse(result.isPresent());
       
   223         result = duke.filter(s -> s.startsWith("D"));
       
   224         assertTrue(result.isPresent());
       
   225         assertEquals(result.get(), "Duke");
       
   226         assertEquals(result.orElseThrow(), "Duke");
       
   227 
       
   228         Optional<String> emptyString = Optional.of("");
       
   229         result = emptyString.filter(String::isEmpty);
       
   230         assertTrue(result.isPresent());
       
   231         assertEquals(result.get(), "");
       
   232         assertEquals(result.orElseThrow(), "");
       
   233     }
       
   234 
       
   235     @Test(groups = "unit")
       
   236     public void testMap() {
       
   237         Optional<String> empty = Optional.empty();
       
   238         Optional<String> duke = Optional.of("Duke");
       
   239 
       
   240         // Null mapper function
       
   241         try {
       
   242             Optional<Boolean> b = empty.map(null);
       
   243             fail("Should throw NPE on null mapping function");
       
   244         } catch (NullPointerException npe) {
       
   245             // expected
       
   246         }
       
   247 
       
   248         // Map an empty value
       
   249         Optional<Boolean> b = empty.map(String::isEmpty);
       
   250         assertFalse(b.isPresent());
       
   251 
       
   252         // Map into null
       
   253         b = empty.map(n -> null);
       
   254         assertFalse(b.isPresent());
       
   255         b = duke.map(s -> null);
       
   256         assertFalse(b.isPresent());
       
   257 
       
   258         // Map to value
       
   259         Optional<Integer> l = duke.map(String::length);
       
   260         assertEquals(l.get().intValue(), 4);
       
   261     }
       
   262 
       
   263     @Test(groups = "unit")
       
   264     public void testFlatMap() {
       
   265         Optional<String> empty = Optional.empty();
       
   266         Optional<String> duke = Optional.of("Duke");
       
   267 
       
   268         // Null mapper function
       
   269         try {
       
   270             Optional<Boolean> b = empty.flatMap(null);
       
   271             fail("Should throw NPE on null mapping function");
       
   272         } catch (NullPointerException npe) {
       
   273             // expected
       
   274         }
       
   275 
       
   276         // Map into null
       
   277         try {
       
   278             Optional<Boolean> b = duke.flatMap(s -> null);
       
   279             fail("Should throw NPE when mapper return null");
       
   280         } catch (NullPointerException npe) {
       
   281             // expected
       
   282         }
       
   283 
       
   284         // Empty won't invoke mapper function
       
   285         try {
       
   286             Optional<Boolean> b = empty.flatMap(s -> null);
       
   287             assertFalse(b.isPresent());
       
   288         } catch (NullPointerException npe) {
       
   289             fail("Mapper function should not be invoked");
       
   290         }
       
   291 
       
   292         // Map an empty value
       
   293         Optional<Integer> l = empty.flatMap(s -> Optional.of(s.length()));
       
   294         assertFalse(l.isPresent());
       
   295 
       
   296         // Map to value
       
   297         Optional<Integer> fixture = Optional.of(Integer.MAX_VALUE);
       
   298         l = duke.flatMap(s -> Optional.of(s.length()));
       
   299         assertTrue(l.isPresent());
       
   300         assertEquals(l.get().intValue(), 4);
       
   301         assertEquals(l.orElseThrow().intValue(), 4);
       
   302 
       
   303         // Verify same instance
       
   304         l = duke.flatMap(s -> fixture);
       
   305         assertSame(l, fixture);
       
   306     }
       
   307 
       
   308     @Test(groups = "unit")
       
   309     public void testOr() {
       
   310         Optional<String> empty = Optional.empty();
       
   311         Optional<String> duke = Optional.of("Duke");
       
   312 
       
   313         // Null supplier
       
   314         try {
       
   315             Optional<String> b = empty.or(null);
       
   316             fail("Should throw NPE on null supplier");
       
   317         } catch (NullPointerException npe) {
       
   318             // expected
       
   319         }
       
   320 
       
   321         // Supply null
       
   322         try {
       
   323             Optional<String> b = empty.or(() -> null);
       
   324             fail("Should throw NPE when supplier returns null");
       
   325         } catch (NullPointerException npe) {
       
   326             // expected
       
   327         }
       
   328 
       
   329         // Non-empty won't invoke supplier
       
   330         try {
       
   331             Optional<String> b = duke.or(() -> null);
       
   332             assertTrue(b.isPresent());
       
   333         } catch (NullPointerException npe) {
       
   334             fail("Supplier should not be invoked");
       
   335         }
       
   336 
       
   337         // Supply for empty
       
   338         Optional<String> suppliedDuke = empty.or(() -> duke);
       
   339         assertTrue(suppliedDuke.isPresent());
       
   340         assertSame(suppliedDuke, duke);
       
   341 
       
   342         // Supply for non-empty
       
   343         Optional<String> actualDuke = duke.or(() -> Optional.of("Other Duke"));
       
   344         assertTrue(actualDuke.isPresent());
       
   345         assertSame(actualDuke, duke);
       
   346     }
       
   347 
       
   348     @Test(groups = "unit")
       
   349     public void testStream() {
       
   350         {
       
   351             Stream<String> s = Optional.<String>empty().stream();
       
   352             assertFalse(s.isParallel());
       
   353 
       
   354             Object[] es = s.toArray();
       
   355             assertEquals(es.length, 0);
       
   356         }
       
   357 
       
   358         {
       
   359             Stream<String> s = Optional.of("Duke").stream();
       
   360             assertFalse(s.isParallel());
       
   361 
       
   362             String[] es = s.toArray(String[]::new);
       
   363             assertEquals(es.length, 1);
       
   364             assertEquals(es[0], "Duke");
       
   365         }
       
   366     }
       
   367 
       
   368     private static class ObscureException extends RuntimeException {
       
   369 
   203     }
   370     }
   204 }
   371 }