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 OptionalInt 27 * @author Mike Duigou 28 * @build ObscureException 29 * @run testng BasicInt 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.IntConsumer; 38 import java.util.stream.IntStream; 39 40 import java.util.NoSuchElementException; 41 import java.util.OptionalInt; 42 import java.util.concurrent.atomic.AtomicBoolean; 43 44 import static org.testng.Assert.*; 45 import org.testng.annotations.Test; 46 47 public class BasicInt { 48 49 static final int INTVAL = 33_550_336; 50 static final int UNEXPECTED = 0xCAFEBABE; 51 52 /** 53 * Checks a block of assertions over an empty OptionalInt. 54 */ checkEmpty(OptionalInt empty)55 void checkEmpty(OptionalInt empty) { 56 assertTrue(empty.equals(OptionalInt.empty())); 57 assertTrue(OptionalInt.empty().equals(empty)); 58 assertFalse(empty.equals(OptionalInt.of(UNEXPECTED))); 59 assertFalse(OptionalInt.of(UNEXPECTED).equals(empty)); 60 assertFalse(empty.equals("unexpected")); 61 62 assertFalse(empty.isPresent()); 63 // Android-changed: Avoid backporting of isEmpty() (b/191859202). 64 // assertTrue(empty.isEmpty()); 65 assertTrue(OptionalInt_isEmpty(empty)); 66 assertEquals(empty.hashCode(), 0); 67 assertEquals(empty.orElse(UNEXPECTED), UNEXPECTED); 68 assertEquals(empty.orElseGet(() -> UNEXPECTED), UNEXPECTED); 69 70 assertThrows(NoSuchElementException.class, () -> empty.getAsInt()); 71 // Android-changed: Avoid backporting of orElseThrow() (b/191859202). 72 // assertThrows(NoSuchElementException.class, () -> empty.orElseThrow()); 73 assertThrows(NoSuchElementException.class, () -> OptionalInt_orElseThrow(empty)); 74 assertThrows(ObscureException.class, () -> empty.orElseThrow(ObscureException::new)); 75 76 var b = new AtomicBoolean(); 77 empty.ifPresent(s -> b.set(true)); 78 assertFalse(b.get()); 79 80 var b1 = new AtomicBoolean(false); 81 var b2 = new AtomicBoolean(false); 82 // Android-changed: Avoid backporting of ifPresentOrElse() (b/191859202). 83 // empty.ifPresentOrElse(s -> b1.set(true), () -> b2.set(true)); 84 OptionalInt_ifPresentOrElse(empty, s -> b1.set(true), () -> b2.set(true)); 85 assertFalse(b1.get()); 86 assertTrue(b2.get()); 87 88 assertEquals(empty.toString(), "OptionalInt.empty"); 89 } 90 91 /** 92 * Checks a block of assertions over an OptionalInt that is expected to 93 * have a particular value present. 94 */ checkPresent(OptionalInt opt, int expected)95 void checkPresent(OptionalInt opt, int expected) { 96 assertFalse(opt.equals(OptionalInt.empty())); 97 assertFalse(OptionalInt.empty().equals(opt)); 98 assertTrue(opt.equals(OptionalInt.of(expected))); 99 assertTrue(OptionalInt.of(expected).equals(opt)); 100 assertFalse(opt.equals(OptionalInt.of(UNEXPECTED))); 101 assertFalse(OptionalInt.of(UNEXPECTED).equals(opt)); 102 assertFalse(opt.equals("unexpected")); 103 104 assertTrue(opt.isPresent()); 105 // Android-changed: Avoid backporting of isEmpty() (b/191859202). 106 // assertFalse(opt.isEmpty()); 107 assertFalse(OptionalInt_isEmpty(opt)); 108 assertEquals(opt.hashCode(), Integer.hashCode(expected)); 109 assertEquals(opt.orElse(UNEXPECTED), expected); 110 assertEquals(opt.orElseGet(() -> UNEXPECTED), expected); 111 112 assertEquals(opt.getAsInt(), expected); 113 // Android-changed: Avoid backporting of orElseThrow() (b/191859202). 114 assertEquals(OptionalInt_orElseThrow(opt), expected); 115 assertEquals(opt.orElseThrow(ObscureException::new), expected); 116 117 var b = new AtomicBoolean(false); 118 opt.ifPresent(s -> b.set(true)); 119 assertTrue(b.get()); 120 121 var b1 = new AtomicBoolean(false); 122 var b2 = new AtomicBoolean(false); 123 // Android-changed: Avoid backporting of ifPresentOrElse() (b/191859202). 124 // opt.ifPresentOrElse(s -> b1.set(true), () -> b2.set(true)); 125 OptionalInt_ifPresentOrElse(opt, s -> b1.set(true), () -> b2.set(true)); 126 assertTrue(b1.get()); 127 assertFalse(b2.get()); 128 129 assertEquals(opt.toString(), "OptionalInt[" + expected + "]"); 130 } 131 132 @Test(groups = "unit") testEmpty()133 public void testEmpty() { 134 checkEmpty(OptionalInt.empty()); 135 } 136 137 @Test(groups = "unit") testPresent()138 public void testPresent() { 139 checkPresent(OptionalInt.of(INTVAL), INTVAL); 140 } 141 142 @Test testStreamEmpty()143 public void testStreamEmpty() { 144 // Android-changed: Avoid backporting of stream() (b/191859202). 145 // assertEquals(OptionalInt.empty().stream().toArray(), new int[] { }); 146 assertEquals(OptionalInt_stream(OptionalInt.empty()).toArray(), new int[] { }); 147 } 148 149 @Test testStreamPresent()150 public void testStreamPresent() { 151 // Android-changed: Avoid backporting of stream() (b/191859202). 152 // assertEquals(OptionalInt.of(INTVAL).stream().toArray(), new int[] { INTVAL }); 153 assertEquals(OptionalInt_stream(OptionalInt.of(INTVAL)).toArray(), new int[] { INTVAL }); 154 } 155 156 // Android-added: wrapper for d8 backport of OptionalInt.ifPresentOrElse() (b/191859202). OptionalInt_ifPresentOrElse( OptionalInt receiver, IntConsumer action, Runnable emptyAction)157 private static void OptionalInt_ifPresentOrElse( 158 OptionalInt receiver, IntConsumer action, Runnable emptyAction) { 159 try { 160 MethodType type = MethodType.methodType(void.class, IntConsumer.class, Runnable.class); 161 MethodHandle mh = 162 MethodHandles.lookup().findVirtual(OptionalInt.class, "ifPresentOrElse", type); 163 mh.invokeExact(receiver, action, emptyAction); 164 } catch (Throwable t) { 165 throw new RuntimeException(t); 166 } 167 } 168 169 // Android-added: wrapper to avoid d8 backport of OptionalInt.isEmpty() (b/191859202). OptionalInt_isEmpty(OptionalInt receiver)170 private static boolean OptionalInt_isEmpty(OptionalInt receiver) { 171 try { 172 MethodType type = MethodType.methodType(boolean.class); 173 MethodHandle mh = 174 MethodHandles.lookup().findVirtual(OptionalInt.class, "isEmpty", type); 175 return (boolean) mh.invokeExact(receiver); 176 } catch (Throwable t) { 177 throw new RuntimeException(t); 178 } 179 } 180 181 // Android-added: wrapper to avoid d8 backport of OptionalInt.orElseThrow() (b/191859202). OptionalInt_orElseThrow(OptionalInt receiver)182 private static int OptionalInt_orElseThrow(OptionalInt receiver) { 183 try { 184 MethodType type = MethodType.methodType(int.class); 185 MethodHandle mh = 186 MethodHandles.lookup().findVirtual(OptionalInt.class, "orElseThrow", type); 187 return (int) mh.invokeExact(receiver); 188 } catch (NoSuchElementException expected) { 189 throw expected; // Underlying method may throw NoSuchElementException 190 } catch (Throwable t) { 191 throw new RuntimeException(t); 192 } 193 } 194 195 // Android-added: wrapper to avoid d8 backport of OptionalInt.stream() (b/191859202). OptionalInt_stream(OptionalInt receiver)196 private static IntStream OptionalInt_stream(OptionalInt receiver) { 197 try { 198 MethodType type = MethodType.methodType(IntStream.class); 199 MethodHandle mh = 200 MethodHandles.lookup().findVirtual(OptionalInt.class, "stream", type); 201 return (IntStream) mh.invokeExact(receiver); 202 } catch (Throwable t) { 203 throw new RuntimeException(t); 204 } 205 } 206 } 207