View Javadoc
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.NoSuchElementException;
8   import java.util.Set;
9   import java.util.concurrent.atomic.AtomicInteger;
10  import java.util.function.Function;
11  import java.util.stream.IntStream;
12  
13  import static io.atlassian.fugue.Functions.identity;
14  import static java.util.stream.Collectors.toList;
15  import static java.util.stream.Collectors.toSet;
16  import static org.hamcrest.CoreMatchers.instanceOf;
17  import static org.hamcrest.Matchers.contains;
18  import static org.hamcrest.core.Is.is;
19  import static org.junit.Assert.assertThat;
20  
21  public class TryTest {
22  
23    private static final Integer STARTING_VALUE = 1;
24    private static final String EXCEPTION_MESSAGE = "exception message";
25    private Try<Integer> successT = Checked.now(() -> STARTING_VALUE);
26    private Try<Integer> failT = Checked.now(() -> {
27      throw new IOException(EXCEPTION_MESSAGE);
28    });
29    private Function<Integer, Try<String>> f = n -> Checked.now(n::toString);
30    private Function<String, Try<String>> g = s -> Checked.now(s::toUpperCase);
31    private Function<Integer, Try<Integer>> unit = (Integer x) -> Checked.now(() -> x);
32  
33    @Test public void leftIdentity() throws Throwable {
34      assertThat(unit.apply(STARTING_VALUE).flatMap(f), is(f.apply(STARTING_VALUE)));
35    }
36  
37    @Test public void rightIdentity() {
38      assertThat(successT.flatMap(x -> unit.apply(x)), is(successT));
39      assertThat(failT.flatMap(x -> unit.apply(x)), is(failT));
40    }
41  
42    @Test public void associativitySuccessCase() {
43      Try<String> lhs = successT.flatMap(f).flatMap(g);
44      Try<String> rhs = successT.flatMap(x -> f.apply(x).flatMap(g));
45  
46      assertThat(lhs, is(rhs));
47    }
48  
49    @Test public void associativityFailureCase() {
50      Try<String> lhs = failT.flatMap(f).flatMap(g);
51      Try<String> rhs = failT.flatMap(x -> f.apply(x).flatMap(g));
52  
53      assertThat(lhs, is(rhs));
54    }
55  
56    @Test public void sequenceReturnsFirstFailure() {
57      Try<String> failed1 = Checked.now(() -> {
58        throw new RuntimeException("FIRST");
59      });
60      Try<String> failed2 = Checked.now(() -> {
61        throw new RuntimeException("SECOND");
62      });
63      Try<String> failed3 = Checked.now(() -> {
64        throw new RuntimeException("THIRD");
65      });
66  
67      Try<Iterable<String>> result = Try.sequence(Arrays.asList(failed1, failed2, failed3));
68  
69      assertThat(result.isFailure(), is(true));
70  
71      final Exception e = result.fold(identity(), x -> {
72        throw new NoSuchElementException();
73      });
74      assertThat(e, instanceOf(RuntimeException.class));
75      assertThat(e.getMessage(), is("FIRST"));
76    }
77  
78    @Test public void sequenceReturnsValuesFromAllSuccesses() {
79      Try<Iterable<Integer>> result = Try.sequence(IntStream.range(0, 10).mapToObj(i -> Checked.now(() -> i))::iterator);
80  
81      assertThat(result.isSuccess(), is(true));
82      Iterable<Integer> vals = result.fold(f -> {
83        throw new NoSuchElementException();
84      }, identity());
85      assertThat(vals, is(IntStream.range(0, 10).boxed().collect(toList())));
86    }
87  
88    @Test public void delayedSequenceEvaluatesFirstFailure() {
89      AtomicInteger called = new AtomicInteger(0);
90      Try<String> failed1 = Checked.delay(() -> {
91        throw new RuntimeException("FIRST " + called.addAndGet(1));
92      });
93      Try<String> failed2 = Checked.delay(() -> {
94        throw new RuntimeException("SECOND " + called.addAndGet(10));
95      });
96      Try<String> failed3 = Checked.delay(() -> {
97        throw new RuntimeException("THIRD " + called.addAndGet(100));
98      });
99  
100     Try<Iterable<String>> result = Try.sequence(Arrays.asList(failed1, failed2, failed3));
101 
102     assertThat(result.isFailure(), is(true));
103 
104     final Exception e = result.fold(identity(), x -> {
105       throw new NoSuchElementException();
106     });
107     assertThat(e, instanceOf(RuntimeException.class));
108     assertThat(e.getMessage(), is("FIRST 1"));
109 
110     assertThat(called.get(), is(1));
111   }
112 
113   @Test public void delayedSequenceReturnsValuesFromAllSuccesses() {
114     Try<Iterable<Integer>> result = Try.sequence(IntStream.range(0, 10).mapToObj(i -> Checked.delay(() -> i))::iterator);
115 
116     assertThat(result.isSuccess(), is(true));
117     Iterable<Integer> vals = result.fold(f -> {
118       throw new NoSuchElementException();
119     }, identity());
120     assertThat(vals, is(IntStream.range(0, 10).boxed().collect(toList())));
121   }
122 
123   @Test public void sequenceReturnsValuesFromAllSuccessesWithCustomCollector() {
124     Try<Set<Integer>> result = Try.sequence(IntStream.range(0, 10).map(i -> i % 4).mapToObj(i -> Checked.now(() -> i)).collect(toList()), toSet());
125 
126     assertThat(result.isSuccess(), is(true));
127     Set<Integer> vals = result.fold(f -> {
128       throw new NoSuchElementException();
129     }, identity());
130     assertThat(vals, contains(0, 1, 2, 3));
131   }
132 
133   @Test public void flattenNestedSuccess() {
134     Try<Try<Integer>> nested = Checked.now(() -> successT);
135 
136     Try<Integer> flattened = Try.flatten(nested);
137 
138     assertThat(flattened, is(successT));
139   }
140 
141   @Test public void flattenNestedFailure() {
142     Try<Try<Integer>> nested = Checked.now(() -> failT);
143 
144     Try<Integer> flattened = Try.flatten(nested);
145 
146     assertThat(flattened.isFailure(), is(true));
147     final Exception e = flattened.fold(identity(), x -> {
148       throw new NoSuchElementException();
149     });
150     assertThat(e, instanceOf(IOException.class));
151     assertThat(e.getMessage(), is(EXCEPTION_MESSAGE));
152   }
153 
154 }