Emulate Optional<T> and its int, long, double variants Change-Id: Id69894008c48a4e3dca06f9f739f7ed2cd5e76e1
diff --git a/user/super/com/google/gwt/emul/java/util/Optional.java b/user/super/com/google/gwt/emul/java/util/Optional.java new file mode 100644 index 0000000..51b5f15 --- /dev/null +++ b/user/super/com/google/gwt/emul/java/util/Optional.java
@@ -0,0 +1,134 @@ +/* + * Copyright 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package java.util; + +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; + +import static javaemul.internal.InternalPreconditions.checkCriticalElement; +import static javaemul.internal.InternalPreconditions.checkCriticalNotNull; + +/** + * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html"> + * the official Java API doc</a> for details. + * + * @param <T> type of the wrapped reference + */ +public final class Optional<T> { + + @SuppressWarnings("unchecked") + public static <T> Optional<T> empty() { + return (Optional<T>) EMPTY; + } + + public static <T> Optional<T> of(T value) { + return new Optional<>(value); + } + + public static <T> Optional<T> ofNullable(T value) { + return value == null ? empty() : of(value); + } + + private static final Optional<?> EMPTY = new Optional<>(); + + private final T ref; + + private Optional() { + ref = null; + } + + private Optional(T ref) { + this.ref = checkCriticalNotNull(ref); + } + + public boolean isPresent() { + return ref != null; + } + + public T get() { + checkCriticalElement(isPresent()); + return ref; + } + + public void ifPresent(Consumer<? super T> consumer) { + if (isPresent()) { + consumer.accept(ref); + } + } + + public Optional<T> filter(Predicate<? super T> predicate) { + checkCriticalNotNull(predicate); + if (!isPresent() || predicate.test(ref)) { + return this; + } + return empty(); + } + + public <U> Optional<U> map(Function<? super T, ? extends U> mapper) { + checkCriticalNotNull(mapper); + if (isPresent()) { + return ofNullable(mapper.apply(ref)); + } + return empty(); + } + + public <U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) { + checkCriticalNotNull(mapper); + if (isPresent()) { + return checkCriticalNotNull(mapper.apply(ref)); + } + return empty(); + } + + public T orElse(T other) { + return isPresent() ? ref : other; + } + + public T orElseGet(Supplier<? extends T> other) { + return isPresent() ? ref : other.get(); + } + + public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X { + if (isPresent()) { + return ref; + } + throw exceptionSupplier.get(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Optional)) { + return false; + } + Optional<?> other = (Optional<?>) obj; + return Objects.equals(ref, other.ref); + } + + @Override + public int hashCode() { + return Objects.hashCode(ref); + } + + @Override + public String toString() { + return isPresent() ? "Optional.of(" + String.valueOf(ref) + ")" : "Optional.empty()"; + } +}
diff --git a/user/super/com/google/gwt/emul/java/util/OptionalDouble.java b/user/super/com/google/gwt/emul/java/util/OptionalDouble.java new file mode 100644 index 0000000..e6b06af --- /dev/null +++ b/user/super/com/google/gwt/emul/java/util/OptionalDouble.java
@@ -0,0 +1,104 @@ +/* + * Copyright 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package java.util; + +import java.util.function.DoubleConsumer; +import java.util.function.DoubleSupplier; +import java.util.function.Supplier; + +import static javaemul.internal.InternalPreconditions.checkCriticalElement; + +/** + * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/OptionalDouble.html"> + * the official Java API doc</a> for details. + */ +public final class OptionalDouble { + + public static OptionalDouble empty() { + return EMPTY; + } + + public static OptionalDouble of(double value) { + return new OptionalDouble(value); + } + + private static final OptionalDouble EMPTY = new OptionalDouble(); + + private final double ref; + private final boolean present; + + private OptionalDouble() { + ref = 0; + present = false; + } + + private OptionalDouble(double value) { + ref = value; + present = true; + } + + public boolean isPresent() { + return present; + } + + public double getAsDouble() { + checkCriticalElement(present); + return ref; + } + + public void ifPresent(DoubleConsumer consumer) { + if (present) { + consumer.accept(ref); + } + } + + public double orElse(double other) { + return present ? ref : other; + } + + public double orElseGet(DoubleSupplier other) { + return present ? ref : other.getAsDouble(); + } + + public <X extends Throwable> double orElseThrow(Supplier<X> exceptionSupplier) throws X { + if (present) { + return ref; + } + throw exceptionSupplier.get(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof OptionalDouble)) { + return false; + } + OptionalDouble other = (OptionalDouble) obj; + return present == other.present && Double.compare(ref, other.ref) == 0; + } + + @Override + public int hashCode() { + return present ? Double.hashCode(ref) : 0; + } + + @Override + public String toString() { + return present ? "OptionalDouble.of(" + Double.toString(ref) + ")" : "OptionalDouble.empty()"; + } +}
diff --git a/user/super/com/google/gwt/emul/java/util/OptionalInt.java b/user/super/com/google/gwt/emul/java/util/OptionalInt.java new file mode 100644 index 0000000..10b7ce6 --- /dev/null +++ b/user/super/com/google/gwt/emul/java/util/OptionalInt.java
@@ -0,0 +1,104 @@ +/* + * Copyright 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package java.util; + +import java.util.function.IntConsumer; +import java.util.function.IntSupplier; +import java.util.function.Supplier; + +import static javaemul.internal.InternalPreconditions.checkCriticalElement; + +/** + * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/OptionalInt.html"> + * the official Java API doc</a> for details. + */ +public final class OptionalInt { + + public static OptionalInt empty() { + return EMPTY; + } + + public static OptionalInt of(int value) { + return new OptionalInt(value); + } + + private static final OptionalInt EMPTY = new OptionalInt(); + + private final int ref; + private final boolean present; + + private OptionalInt() { + ref = 0; + present = false; + } + + private OptionalInt(int value) { + ref = value; + present = true; + } + + public boolean isPresent() { + return present; + } + + public int getAsInt() { + checkCriticalElement(present); + return ref; + } + + public void ifPresent(IntConsumer consumer) { + if (present) { + consumer.accept(ref); + } + } + + public int orElse(int other) { + return present ? ref : other; + } + + public int orElseGet(IntSupplier other) { + return present ? ref : other.getAsInt(); + } + + public <X extends Throwable> int orElseThrow(Supplier<X> exceptionSupplier) throws X { + if (present) { + return ref; + } + throw exceptionSupplier.get(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof OptionalInt)) { + return false; + } + OptionalInt other = (OptionalInt) obj; + return present == other.present && Integer.compare(ref, other.ref) == 0; + } + + @Override + public int hashCode() { + return present ? Integer.hashCode(ref) : 0; + } + + @Override + public String toString() { + return present ? "OptionalInt.of(" + Integer.toString(ref) + ")" : "OptionalInt.empty()"; + } +}
diff --git a/user/super/com/google/gwt/emul/java/util/OptionalLong.java b/user/super/com/google/gwt/emul/java/util/OptionalLong.java new file mode 100644 index 0000000..8551777 --- /dev/null +++ b/user/super/com/google/gwt/emul/java/util/OptionalLong.java
@@ -0,0 +1,104 @@ +/* + * Copyright 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package java.util; + +import java.util.function.LongConsumer; +import java.util.function.LongSupplier; +import java.util.function.Supplier; + +import static javaemul.internal.InternalPreconditions.checkCriticalElement; + +/** + * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/OptionalLong.html"> + * the official Java API doc</a> for details. + */ +public final class OptionalLong { + + public static OptionalLong empty() { + return EMPTY; + } + + public static OptionalLong of(long value) { + return new OptionalLong(value); + } + + private static final OptionalLong EMPTY = new OptionalLong(); + + private final long ref; + private final boolean present; + + private OptionalLong() { + ref = 0; + present = false; + } + + private OptionalLong(long value) { + ref = value; + present = true; + } + + public boolean isPresent() { + return present; + } + + public long getAsLong() { + checkCriticalElement(present); + return ref; + } + + public void ifPresent(LongConsumer consumer) { + if (present) { + consumer.accept(ref); + } + } + + public long orElse(long other) { + return present ? ref : other; + } + + public long orElseGet(LongSupplier other) { + return present ? ref : other.getAsLong(); + } + + public <X extends Throwable> long orElseThrow(Supplier<X> exceptionSupplier) throws X { + if (present) { + return ref; + } + throw exceptionSupplier.get(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof OptionalLong)) { + return false; + } + OptionalLong other = (OptionalLong) obj; + return present == other.present && Long.compare(ref, other.ref) == 0; + } + + @Override + public int hashCode() { + return present ? Long.hashCode(ref) : 0; + } + + @Override + public String toString() { + return present ? "OptionalLong.of(" + Long.toString(ref) + ")" : "OptionalLong.empty()"; + } +}
diff --git a/user/test/com/google/gwt/emultest/EmulJava8Suite.java b/user/test/com/google/gwt/emultest/EmulJava8Suite.java index ee43edf..053cbb1 100644 --- a/user/test/com/google/gwt/emultest/EmulJava8Suite.java +++ b/user/test/com/google/gwt/emultest/EmulJava8Suite.java
@@ -15,6 +15,9 @@ */ package com.google.gwt.emultest; +import com.google.gwt.emultest.java8.util.OptionalDoubleTest; +import com.google.gwt.emultest.java8.util.OptionalIntTest; +import com.google.gwt.emultest.java8.util.OptionalLongTest; import com.google.gwt.emultest.java8.util.OptionalTest; import com.google.gwt.junit.tools.GWTTestSuite; @@ -30,6 +33,9 @@ //-- java.util suite.addTestSuite(OptionalTest.class); + suite.addTestSuite(OptionalIntTest.class); + suite.addTestSuite(OptionalLongTest.class); + suite.addTestSuite(OptionalDoubleTest.class); return suite; }
diff --git a/user/test/com/google/gwt/emultest/java8/util/OptionalDoubleTest.java b/user/test/com/google/gwt/emultest/java8/util/OptionalDoubleTest.java new file mode 100644 index 0000000..c8361eb --- /dev/null +++ b/user/test/com/google/gwt/emultest/java8/util/OptionalDoubleTest.java
@@ -0,0 +1,176 @@ +/* + * Copyright 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java8.util; + +import com.google.gwt.junit.client.GWTTestCase; + +import java.util.NoSuchElementException; +import java.util.OptionalDouble; + +/** + * Tests for OptionalDouble JRE emulation. + */ +public class OptionalDoubleTest extends GWTTestCase { + + private static final double REFERENCE = 10d; + private static final double OTHER_REFERENCE = 20d; + private boolean[] mutableFlag; + private OptionalDouble empty; + private OptionalDouble present; + + @Override + public String getModuleName() { + return "com.google.gwt.emultest.EmulSuite"; + } + + @Override + protected void gwtSetUp() throws Exception { + super.gwtSetUp(); + mutableFlag = new boolean[1]; + empty = OptionalDouble.empty(); + present = OptionalDouble.of(REFERENCE); + } + + public void testIsPresent() { + // empty case + assertFalse(empty.isPresent()); + + // non-empty case + assertTrue(present.isPresent()); + } + + public void testGetAsDouble() { + // empty case + try { + empty.getAsDouble(); + fail("Empty Optional should throw NoSuchElementException"); + } catch (NoSuchElementException e) { + // expected + } + + // non-empty case + assertEquals(REFERENCE, present.getAsDouble()); + } + + public void testIfPresent() { + // empty case + empty.ifPresent(null); // should not fail as per JavaDoc + empty.ifPresent(wrapped -> fail("Empty Optional should not execute consumer")); + + // non-empty case + try { + present.ifPresent(null); + fail("Non-Empty Optional must throw NullPointerException if consumer is null"); + } catch (NullPointerException e) { + // expected + } + + present.ifPresent((wrapped) -> { + assertEquals(REFERENCE, wrapped); + mutableFlag[0] = true; + }); + assertTrue("Consumer not executed", mutableFlag[0]); + } + + public void testOrElse() { + // empty case + assertEquals(OTHER_REFERENCE, empty.orElse(OTHER_REFERENCE)); + + // non-empty case + assertEquals(REFERENCE, present.orElse(OTHER_REFERENCE)); + } + + public void testOrElseGet() { + // empty case + try { + empty.orElseGet(null); + fail("Empty Optional must throw NullPointerException if supplier is null"); + } catch (NullPointerException e) { + // expected + } + + assertEquals(OTHER_REFERENCE, empty.orElseGet(() -> OTHER_REFERENCE)); + + // non-empty case + assertEquals(REFERENCE, present.orElseGet(() -> { + fail("Optional must not execute supplier"); + return OTHER_REFERENCE; + })); + } + + public void testOrElseThrow() { + // empty case + try { + empty.orElseThrow(null); + fail("Empty Optional must throw NullPointerException if supplier is null"); + } catch (NullPointerException e) { + // expected + } + + try { + empty.orElseThrow(() -> null); + fail("Empty Optional must throw NullPointerException if supplier returns null"); + } catch (NullPointerException e) { + // expected + } + + try { + empty.orElseThrow(IllegalStateException::new); + fail("Empty Optional must throw supplied exception"); + } catch (IllegalStateException e) { + // expected + } + + // non-empty case + try { + Object reference = present.orElseThrow(null); + assertEquals(REFERENCE, reference); + } catch (NullPointerException e) { + fail("Optional must not throw NullPointerException if supplier is null"); + } + + assertEquals(REFERENCE, present.orElseThrow(() -> { + fail("Optional must not execute supplier"); + return new RuntimeException("should not execute"); + })); + } + + public void testEquals() { + // empty case + assertFalse(empty.equals(null)); + assertFalse(empty.equals("should not be equal")); + assertFalse(empty.equals(present)); + assertTrue(empty.equals(empty)); + assertTrue(empty.equals(OptionalDouble.empty())); + + // non empty case + assertFalse(present.equals(null)); + assertFalse(present.equals("should not be equal")); + assertFalse(present.equals(empty)); + assertFalse(present.equals(OptionalDouble.of(OTHER_REFERENCE))); + assertTrue(present.equals(present)); + assertTrue(present.equals(OptionalDouble.of(REFERENCE))); + } + + public void testHashcode() { + // empty case + assertEquals(0, empty.hashCode()); + + // non empty case + assertEquals(Double.hashCode(REFERENCE), present.hashCode()); + } + +}
diff --git a/user/test/com/google/gwt/emultest/java8/util/OptionalIntTest.java b/user/test/com/google/gwt/emultest/java8/util/OptionalIntTest.java new file mode 100644 index 0000000..f1080e9 --- /dev/null +++ b/user/test/com/google/gwt/emultest/java8/util/OptionalIntTest.java
@@ -0,0 +1,176 @@ +/* + * Copyright 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java8.util; + +import com.google.gwt.junit.client.GWTTestCase; + +import java.util.NoSuchElementException; +import java.util.OptionalInt; + +/** + * Tests for OptionalInt JRE emulation. + */ +public class OptionalIntTest extends GWTTestCase { + + private static final int REFERENCE = 10; + private static final int OTHER_REFERENCE = 20; + private boolean[] mutableFlag; + private OptionalInt empty; + private OptionalInt present; + + @Override + public String getModuleName() { + return "com.google.gwt.emultest.EmulSuite"; + } + + @Override + protected void gwtSetUp() throws Exception { + super.gwtSetUp(); + mutableFlag = new boolean[1]; + empty = OptionalInt.empty(); + present = OptionalInt.of(REFERENCE); + } + + public void testIsPresent() { + // empty case + assertFalse(empty.isPresent()); + + // non-empty case + assertTrue(present.isPresent()); + } + + public void testGetAsInt() { + // empty case + try { + empty.getAsInt(); + fail("Empty Optional should throw NoSuchElementException"); + } catch (NoSuchElementException e) { + // expected + } + + // non-empty case + assertEquals(REFERENCE, present.getAsInt()); + } + + public void testIfPresent() { + // empty case + empty.ifPresent(null); // should not fail as per JavaDoc + empty.ifPresent(wrapped -> fail("Empty Optional should not execute consumer")); + + // non-empty case + try { + present.ifPresent(null); + fail("Non-Empty Optional must throw NullPointerException if consumer is null"); + } catch (NullPointerException e) { + // expected + } + + present.ifPresent((wrapped) -> { + assertEquals(REFERENCE, wrapped); + mutableFlag[0] = true; + }); + assertTrue("Consumer not executed", mutableFlag[0]); + } + + public void testOrElse() { + // empty case + assertEquals(OTHER_REFERENCE, empty.orElse(OTHER_REFERENCE)); + + // non-empty case + assertEquals(REFERENCE, present.orElse(OTHER_REFERENCE)); + } + + public void testOrElseGet() { + // empty case + try { + empty.orElseGet(null); + fail("Empty Optional must throw NullPointerException if supplier is null"); + } catch (NullPointerException e) { + // expected + } + + assertEquals(OTHER_REFERENCE, empty.orElseGet(() -> OTHER_REFERENCE)); + + // non-empty case + assertEquals(REFERENCE, present.orElseGet(() -> { + fail("Optional must not execute supplier"); + return OTHER_REFERENCE; + })); + } + + public void testOrElseThrow() { + // empty case + try { + empty.orElseThrow(null); + fail("Empty Optional must throw NullPointerException if supplier is null"); + } catch (NullPointerException e) { + // expected + } + + try { + empty.orElseThrow(() -> null); + fail("Empty Optional must throw NullPointerException if supplier returns null"); + } catch (NullPointerException e) { + // expected + } + + try { + empty.orElseThrow(IllegalStateException::new); + fail("Empty Optional must throw supplied exception"); + } catch (IllegalStateException e) { + // expected + } + + // non-empty case + try { + Object reference = present.orElseThrow(null); + assertEquals(REFERENCE, reference); + } catch (NullPointerException e) { + fail("Optional must not throw NullPointerException if supplier is null"); + } + + assertEquals(REFERENCE, present.orElseThrow(() -> { + fail("Optional must not execute supplier"); + return new RuntimeException("should not execute"); + })); + } + + public void testEquals() { + // empty case + assertFalse(empty.equals(null)); + assertFalse(empty.equals("should not be equal")); + assertFalse(empty.equals(present)); + assertTrue(empty.equals(empty)); + assertTrue(empty.equals(OptionalInt.empty())); + + // non empty case + assertFalse(present.equals(null)); + assertFalse(present.equals("should not be equal")); + assertFalse(present.equals(empty)); + assertFalse(present.equals(OptionalInt.of(OTHER_REFERENCE))); + assertTrue(present.equals(present)); + assertTrue(present.equals(OptionalInt.of(REFERENCE))); + } + + public void testHashcode() { + // empty case + assertEquals(0, empty.hashCode()); + + // non empty case + assertEquals(Integer.hashCode(REFERENCE), present.hashCode()); + } + +}
diff --git a/user/test/com/google/gwt/emultest/java8/util/OptionalLongTest.java b/user/test/com/google/gwt/emultest/java8/util/OptionalLongTest.java new file mode 100644 index 0000000..4d1396f --- /dev/null +++ b/user/test/com/google/gwt/emultest/java8/util/OptionalLongTest.java
@@ -0,0 +1,176 @@ +/* + * Copyright 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.emultest.java8.util; + +import com.google.gwt.junit.client.GWTTestCase; + +import java.util.NoSuchElementException; +import java.util.OptionalLong; + +/** + * Tests for OptionalLong JRE emulation. + */ +public class OptionalLongTest extends GWTTestCase { + + private static final long REFERENCE = 10L; + private static final long OTHER_REFERENCE = 20L; + private boolean[] mutableFlag; + private OptionalLong empty; + private OptionalLong present; + + @Override + public String getModuleName() { + return "com.google.gwt.emultest.EmulSuite"; + } + + @Override + protected void gwtSetUp() throws Exception { + super.gwtSetUp(); + mutableFlag = new boolean[1]; + empty = OptionalLong.empty(); + present = OptionalLong.of(REFERENCE); + } + + public void testIsPresent() { + // empty case + assertFalse(empty.isPresent()); + + // non-empty case + assertTrue(present.isPresent()); + } + + public void testGetAsLong() { + // empty case + try { + empty.getAsLong(); + fail("Empty Optional should throw NoSuchElementException"); + } catch (NoSuchElementException e) { + // expected + } + + // non-empty case + assertEquals(REFERENCE, present.getAsLong()); + } + + public void testIfPresent() { + // empty case + empty.ifPresent(null); // should not fail as per JavaDoc + empty.ifPresent(wrapped -> fail("Empty Optional should not execute consumer")); + + // non-empty case + try { + present.ifPresent(null); + fail("Non-Empty Optional must throw NullPointerException if consumer is null"); + } catch (NullPointerException e) { + // expected + } + + present.ifPresent((wrapped) -> { + assertEquals(REFERENCE, wrapped); + mutableFlag[0] = true; + }); + assertTrue("Consumer not executed", mutableFlag[0]); + } + + public void testOrElse() { + // empty case + assertEquals(OTHER_REFERENCE, empty.orElse(OTHER_REFERENCE)); + + // non-empty case + assertEquals(REFERENCE, present.orElse(OTHER_REFERENCE)); + } + + public void testOrElseGet() { + // empty case + try { + empty.orElseGet(null); + fail("Empty Optional must throw NullPointerException if supplier is null"); + } catch (NullPointerException e) { + // expected + } + + assertEquals(OTHER_REFERENCE, empty.orElseGet(() -> OTHER_REFERENCE)); + + // non-empty case + assertEquals(REFERENCE, present.orElseGet(() -> { + fail("Optional must not execute supplier"); + return OTHER_REFERENCE; + })); + } + + public void testOrElseThrow() { + // empty case + try { + empty.orElseThrow(null); + fail("Empty Optional must throw NullPointerException if supplier is null"); + } catch (NullPointerException e) { + // expected + } + + try { + empty.orElseThrow(() -> null); + fail("Empty Optional must throw NullPointerException if supplier returns null"); + } catch (NullPointerException e) { + // expected + } + + try { + empty.orElseThrow(IllegalStateException::new); + fail("Empty Optional must throw supplied exception"); + } catch (IllegalStateException e) { + // expected + } + + // non-empty case + try { + Object reference = present.orElseThrow(null); + assertEquals(REFERENCE, reference); + } catch (NullPointerException e) { + fail("Optional must not throw NullPointerException if supplier is null"); + } + + assertEquals(REFERENCE, present.orElseThrow(() -> { + fail("Optional must not execute supplier"); + return new RuntimeException("should not execute"); + })); + } + + public void testEquals() { + // empty case + assertFalse(empty.equals(null)); + assertFalse(empty.equals("should not be equal")); + assertFalse(empty.equals(present)); + assertTrue(empty.equals(empty)); + assertTrue(empty.equals(OptionalLong.empty())); + + // non empty case + assertFalse(present.equals(null)); + assertFalse(present.equals("should not be equal")); + assertFalse(present.equals(empty)); + assertFalse(present.equals(OptionalLong.of(OTHER_REFERENCE))); + assertTrue(present.equals(present)); + assertTrue(present.equals(OptionalLong.of(REFERENCE))); + } + + public void testHashcode() { + // empty case + assertEquals(0, empty.hashCode()); + + // non empty case + assertEquals(Long.hashCode(REFERENCE), present.hashCode()); + } + +}
diff --git a/user/test/com/google/gwt/emultest/java8/util/OptionalTest.java b/user/test/com/google/gwt/emultest/java8/util/OptionalTest.java index fbb8daa..3384a46 100644 --- a/user/test/com/google/gwt/emultest/java8/util/OptionalTest.java +++ b/user/test/com/google/gwt/emultest/java8/util/OptionalTest.java
@@ -17,34 +17,260 @@ import com.google.gwt.junit.client.GWTTestCase; +import java.util.NoSuchElementException; +import java.util.Optional; + /** * Tests for Optional JRE emulation. */ public class OptionalTest extends GWTTestCase { + private static final Object REFERENCE = new Object(); + private static final Object OTHER_REFERENCE = new Object(); + private boolean[] mutableFlag; + private Optional<Object> empty; + private Optional<Object> present; + @Override public String getModuleName() { return "com.google.gwt.emultest.EmulSuite"; } - public void testSomething() { + @Override + protected void gwtSetUp() throws Exception { + super.gwtSetUp(); + mutableFlag = new boolean[1]; + empty = Optional.empty(); + present = Optional.of(REFERENCE); + } + + public void testIsPresent() { + // empty case + assertFalse(empty.isPresent()); + + empty = Optional.ofNullable(null); + assertFalse(empty.isPresent()); + + // non-empty case + assertTrue(present.isPresent()); + + present = Optional.ofNullable(REFERENCE); + assertTrue(present.isPresent()); + } + + public void testGet() { + // empty case try { - requireNonNull(null, () -> "Must not be null"); - fail("must throw NPE"); + empty.get(); + fail("Empty Optional should throw NoSuchElementException"); + } catch (NoSuchElementException e) { + // expected + } + + // non-empty case + assertSame(REFERENCE, present.get()); + } + + public void testIfPresent() { + // empty case + empty.ifPresent(null); // should not fail as per JavaDoc + empty.ifPresent(wrapped -> fail("Empty Optional should not execute consumer")); + + // non-empty case + try { + present.ifPresent(null); + fail("Non-Empty Optional must throw NullPointerException if consumer is null"); } catch (NullPointerException e) { // expected } + + present.ifPresent((wrapped) -> { + assertSame(REFERENCE, wrapped); + mutableFlag[0] = true; + }); + assertTrue("Consumer not executed", mutableFlag[0]); } - private static <T> T requireNonNull(T obj, Supplier<String> messageSupplier) { - if (obj == null) { - throw new NullPointerException(messageSupplier.get()); + public void testFilter() { + // empty case + try { + empty.filter(null); + fail("Optional must throw NullPointerException if predicate is null"); + } catch (NullPointerException e) { + // expected } - return obj; + + Optional<Object> filtered = empty.filter(wrapped -> true); + assertFalse(filtered.isPresent()); + + filtered = empty.filter(wrapped -> false); + assertFalse(filtered.isPresent()); + + // non-empty case + try { + present.filter(null); + fail("Optional must throw NullPointerException if predicate is null"); + } catch (NullPointerException e) { + // expected + } + + filtered = present.filter(wrapped -> true); + assertSame(REFERENCE, filtered.get()); + + filtered = present.filter(wrapped -> false); + assertFalse(filtered.isPresent()); } - @FunctionalInterface - private interface Supplier<T> { - T get(); + public void testMap() { + // empty case + try { + empty.map(null); + fail("Optional must throw NullPointerException if mapper is null"); + } catch (NullPointerException e) { + // expected + } + + empty.map(wrapped -> { + fail("Empty Optional must not execute mapper"); + return "should not execute"; + }); + + // non-empty case + try { + present.map(null); + fail("Optional must throw NullPointerException if mapper is null"); + } catch (NullPointerException e) { + // expected + } + Optional<String> mapped = present.map(wrapped -> null); + assertFalse(mapped.isPresent()); + + mapped = present.map(Object::toString); + assertEquals(REFERENCE.toString(), mapped.get()); } + + public void testFlatMap() { + // empty case + try { + empty.flatMap(null); + fail("Optional must throw NullPointerException if mapper is null"); + } catch (NullPointerException e) { + // expected + } + + empty.flatMap(wrapped -> { + fail("Empty Optional must not execute mapper"); + return Optional.of("should not execute"); + }); + + // non-empty case + try { + present.flatMap(null); + fail("Optional must throw NullPointerException if mapper is null"); + } catch (NullPointerException e) { + // expected + } + + try { + present.flatMap(wrapped -> null); + fail("Optional must throw NullPointerException if mapper returns null"); + } catch (NullPointerException e) { + // expected + } + + Optional<String> mapped = present.flatMap(wrapped -> Optional.empty()); + assertFalse(mapped.isPresent()); + + mapped = present.flatMap(wrapped -> Optional.of(wrapped.toString())); + assertEquals(REFERENCE.toString(), mapped.get()); + } + + public void testOrElse() { + // empty case + assertSame(OTHER_REFERENCE, empty.orElse(OTHER_REFERENCE)); + + // non-empty case + assertSame(REFERENCE, present.orElse(OTHER_REFERENCE)); + } + + public void testOrElseGet() { + // empty case + try { + empty.orElseGet(null); + fail("Empty Optional must throw NullPointerException if supplier is null"); + } catch (NullPointerException e) { + // expected + } + + assertSame(OTHER_REFERENCE, empty.orElseGet(() -> OTHER_REFERENCE)); + + // non-empty case + assertSame(REFERENCE, present.orElseGet(() -> { + fail("Optional must not execute supplier"); + return OTHER_REFERENCE; + })); + } + + public void testOrElseThrow() { + // empty case + try { + empty.orElseThrow(null); + fail("Empty Optional must throw NullPointerException if supplier is null"); + } catch (NullPointerException e) { + // expected + } + + try { + empty.<RuntimeException>orElseThrow(() -> null); + fail("Empty Optional must throw NullPointerException if supplier returns null"); + } catch (NullPointerException e) { + // expected + } + + try { + empty.orElseThrow(IllegalStateException::new); + fail("Empty Optional must throw supplied exception"); + } catch (IllegalStateException e) { + // expected + } + + // non-empty case + try { + Object reference = present.orElseThrow(null); + assertSame(REFERENCE, reference); + } catch (NullPointerException e) { + fail("Optional must not throw NullPointerException if supplier is null"); + } + + assertSame(REFERENCE, present.orElseThrow(() -> { + fail("Optional must not execute supplier"); + return new RuntimeException("should not execute"); + })); + } + + public void testEquals() { + // empty case + assertFalse(empty.equals(null)); + assertFalse(empty.equals("should not be equal")); + assertFalse(empty.equals(present)); + assertTrue(empty.equals(empty)); + assertTrue(empty.equals(Optional.empty())); + + // non empty case + assertFalse(present.equals(null)); + assertFalse(present.equals("should not be equal")); + assertFalse(present.equals(empty)); + assertFalse(present.equals(Optional.of(OTHER_REFERENCE))); + assertTrue(present.equals(present)); + assertTrue(present.equals(Optional.of(REFERENCE))); + } + + public void testHashcode() { + // empty case + assertEquals(0, empty.hashCode()); + + // non empty case + assertEquals(REFERENCE.hashCode(), present.hashCode()); + } + }