package com.twitter.common.base;
import java.io.IOException;
import java.net.MalformedURLException;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import org.junit.Test;
import com.twitter.common.base.Either.Transformer;
import com.twitter.common.base.Either.UnguardedException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class EitherTest {
@Test
public void testLeft() {
Exception left = new Exception();
assertLeft(left, Either.<Exception, String>left(left));
}
@Test
public void testRight() {
assertRight("jake", Either.<Exception, String>right("jake"));
}
@Test
public void testSwap() {
assertLeft("jake", Either.right("jake").swap());
assertRight("jake", Either.left("jake").swap());
Either<String, Object> left = Either.left("jake");
assertEquals(left, left.swap().swap());
Either<Object, String> right = Either.right("jake");
assertEquals(right, right.swap().swap());
}
public static final Function<CharSequence, Integer> LENGTH =
new Function<CharSequence, Integer>() {
@Override public Integer apply(CharSequence item) {
return item.length();
}
};
public static final Function<Object, Integer> HASHCODE = new Function<Object, Integer>() {
@Override public Integer apply(Object item) {
return item.hashCode();
}
};
@Test
public void testMapLeft() {
RuntimeException left = new RuntimeException() {
@Override public int hashCode() {
return 42;
}
};
assertLeft(42, Either.left(left).mapLeft(HASHCODE));
assertRight("jake", Either.right("jake").mapLeft(HASHCODE));
}
@Test
public void testMapRight() {
assertRight(4, Either.right("jake").mapRight(LENGTH));
RuntimeException left = new RuntimeException();
assertLeft(left, Either.left(left).mapRight(HASHCODE));
}
@Test
public void testMap() {
Transformer<Object, CharSequence, Integer> transformer = Either.transformer(HASHCODE, LENGTH);
Object left = new Object() {
@Override public int hashCode() {
return 1137;
}
};
Either<Object, CharSequence> either = Either.left(left);
assertEquals(1137, either.map(transformer).intValue());
assertEquals(19, Either.right("The Meaning of Life").map(transformer).intValue());
}
private static final ImmutableList<Either<String, String>> LEFT_RESULTS =
ImmutableList.of(
Either.<String, String>left("jack"),
Either.<String, String>left("jill"));
private static final ImmutableList<Either<String, String>> RIGHT_RESULTS =
ImmutableList.of(
Either.<String, String>right("jack"),
Either.<String, String>right("jill"));
private static final ImmutableList<Either<String, String>> MIXED_RESULTS =
ImmutableList.of(
Either.<String, String>left("jack"),
Either.<String, String>right("jane"),
Either.<String, String>left("jill"));
@Test
public void testLefts() {
assertEquals(ImmutableList.of("jack", "jill"),
ImmutableList.copyOf(Either.lefts(LEFT_RESULTS)));
assertEquals(ImmutableList.of(), ImmutableList.copyOf(Either.lefts(RIGHT_RESULTS)));
assertEquals(ImmutableList.of("jack", "jill"),
ImmutableList.copyOf(Either.lefts(MIXED_RESULTS)));
}
@Test
public void testRights() {
assertEquals(ImmutableList.of(), ImmutableList.copyOf(Either.rights(LEFT_RESULTS)));
assertEquals(ImmutableList.of("jack", "jill"),
ImmutableList.copyOf(Either.rights(RIGHT_RESULTS)));
assertEquals(ImmutableList.of("jane"), ImmutableList.copyOf(Either.rights(MIXED_RESULTS)));
}
@Test
public void testTransformer() {
assertEquals(ImmutableList.of("jackjack", "4", "jilljill"),
ImmutableList.copyOf(Iterables.transform(MIXED_RESULTS,
new Transformer<String, String, String>() {
@Override public String mapLeft(String left) {
return left + left;
}
@Override public String mapRight(String right) {
return String.valueOf(right.length());
}
})));
}
static <T, X extends Exception> ExceptionalSupplier<T, X> constantSupplier(final T value) {
return new ExceptionalSupplier<T, X>() {
@Override public T get() {
return value;
}
};
}
static <T, X extends Exception> ExceptionalSupplier<T, X> failedSupplier(final X failure) {
return new ExceptionalSupplier<T, X>() {
@Override public T get() throws X {
throw failure;
}
};
}
@Test
public void testGuard() {
assertRight("jake",
Either.guard(IOException.class, EitherTest.<String, IOException>constantSupplier("jake")));
IOException left = new IOException();
assertLeft(left, Either.guard(IOException.class, failedSupplier(left)));
try {
Either.guard(IOException.class, new ExceptionalSupplier<Object, IOException>() {
@Override public String get() {
throw new ArithmeticException();
}
});
fail("Expected an unguarded exception type to fail fast.");
} catch (UnguardedException e) {
assertTrue(e.getCause() instanceof ArithmeticException);
}
Either<Exception, String> result =
Either.guard(ImmutableList.of(IOException.class, InterruptedException.class),
new SupplierE<String>() {
@Override public String get() throws InterruptedException {
throw new InterruptedException();
}
});
assertTrue(result.getLeft() instanceof InterruptedException);
result = Either.guard(ImmutableList.of(IOException.class, InterruptedException.class),
new SupplierE<String>() {
@Override public String get() throws IOException {
throw new MalformedURLException();
}
});
assertTrue(result.getLeft() instanceof IOException);
class MyException extends Exception { }
try {
Either.guard(ImmutableList.of(IOException.class, InterruptedException.class),
new SupplierE<String>() {
@Override public String get() throws Exception {
throw new MyException();
}
});
fail("Expected an unguarded exception type to fail fast.");
} catch (UnguardedException e) {
assertTrue(e.getCause() instanceof MyException);
}
}
private static <L, R> void assertLeft(L left, Either<L, R> either) {
assertEquals(Either.left(left), either);
assertTrue(either.isLeft());
assertTrue(either.left().isPresent());
assertSame(left, either.getLeft());
assertSame(left, either.left().get());
assertFalse(either.isRight());
assertFalse(either.right().isPresent());
try {
either.getRight();
fail("Expected a a left to throw when accessing its right.");
} catch (IllegalStateException e) {
// expected
}
try {
either.right().get();
fail("Expected a a left to throw when accessing its right.");
} catch (IllegalStateException e) {
// expected
}
}
private static <L, R> void assertRight(R right, Either<L, R> either) {
assertEquals(Either.right(right), either);
assertTrue(either.isRight());
assertTrue(either.right().isPresent());
assertSame(right, either.getRight());
assertSame(right, either.right().get());
assertFalse(either.isLeft());
assertFalse(either.left().isPresent());
try {
either.getLeft();
fail("Expected a a right to throw when accessing its left.");
} catch (IllegalStateException e) {
// expected
}
try {
either.left().get();
fail("Expected a a right to throw when accessing its left.");
} catch (IllegalStateException e) {
// expected
}
}
}