1 package io.atlassian.fugue;
2
3 import org.junit.Test;
4
5 import java.io.IOException;
6 import java.util.Arrays;
7 import java.util.List;
8 import java.util.NoSuchElementException;
9 import java.util.function.Function;
10 import java.util.stream.IntStream;
11
12 import static io.atlassian.fugue.Functions.identity;
13 import static java.util.stream.Collectors.toList;
14 import static org.hamcrest.CoreMatchers.instanceOf;
15 import static org.hamcrest.core.Is.is;
16 import static org.junit.Assert.assertThat;
17
18 public class TryTest {
19
20 private static final Integer STARTING_VALUE = 1;
21 private static final String EXCEPTION_MESSAGE = "exception message";
22 private Try<Integer> successT = Checked.of(() -> STARTING_VALUE);
23 private Try<Integer> failT = Checked.of(() -> {
24 throw new IOException(EXCEPTION_MESSAGE);
25 });
26 private Function<Integer, Try<String>> f = n -> Checked.of(n::toString);
27 private Function<String, Try<String>> g = s -> Checked.of(s::toUpperCase);
28 private Function<Integer, Try<Integer>> unit = (Integer x) -> Checked.of(() -> x);
29
30 @Test public void leftIdentity() throws Throwable {
31 assertThat(unit.apply(STARTING_VALUE).flatMap(f), is(f.apply(STARTING_VALUE)));
32 }
33
34 @Test public void rightIdentity() {
35 assertThat(successT.flatMap(x -> unit.apply(x)), is(successT));
36 assertThat(failT.flatMap(x -> unit.apply(x)), is(failT));
37 }
38
39 @Test public void associativitySuccessCase() {
40 Try<String> lhs = successT.flatMap(f).flatMap(g);
41 Try<String> rhs = successT.flatMap(x -> f.apply(x).flatMap(g));
42
43 assertThat(lhs, is(rhs));
44 }
45
46 @Test public void associativityFailureCase() {
47 Try<String> lhs = failT.flatMap(f).flatMap(g);
48 Try<String> rhs = failT.flatMap(x -> f.apply(x).flatMap(g));
49
50 assertThat(lhs, is(rhs));
51 }
52
53 @Test public void sequenceReturnsFirstFailure() {
54 Try<String> failed1 = Checked.of(() -> {
55 throw new RuntimeException("FIRST");
56 });
57 Try<String> failed2 = Checked.of(() -> {
58 throw new RuntimeException("SECOND");
59 });
60 Try<String> failed3 = Checked.of(() -> {
61 throw new RuntimeException("THIRD");
62 });
63
64 Try<Iterable<String>> result = Try.sequence(Arrays.asList(failed1, failed2, failed3));
65
66 assertThat(result.isFailure(), is(true));
67
68 final Exception e = result.fold(identity(), x -> {
69 throw new NoSuchElementException();
70 });
71 assertThat(e, instanceOf(RuntimeException.class));
72 assertThat(e.getMessage(), is("FIRST"));
73 }
74
75 @Test public void sequenceReturnsValuesFromAllSuccesses() {
76 Try<Iterable<Integer>> result = Try.sequence(IntStream.range(0, 10).mapToObj(i -> Checked.of(() -> i))::iterator);
77
78 assertThat(result.isSuccess(), is(true));
79 Iterable<Integer> vals = result.fold(f -> {
80 throw new NoSuchElementException();
81 }, identity());
82 assertThat(vals, is(IntStream.range(0, 10).boxed().collect(toList())));
83 }
84
85 @Test public void flattenNestedSuccess() {
86 Try<Try<Integer>> nested = Checked.of(() -> successT);
87
88 Try<Integer> flattened = Try.flatten(nested);
89
90 assertThat(flattened, is(successT));
91 }
92
93 @Test public void flattenNestedFailure() {
94 Try<Try<Integer>> nested = Checked.of(() -> failT);
95
96 Try<Integer> flattened = Try.flatten(nested);
97
98 assertThat(flattened.isFailure(), is(true));
99 final Exception e = flattened.fold(identity(), x -> {
100 throw new NoSuchElementException();
101 });
102 assertThat(e, instanceOf(IOException.class));
103 assertThat(e.getMessage(), is(EXCEPTION_MESSAGE));
104 }
105
106 }