BUG-8372: fix abort message confusion
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / databroker / actors / dds / VotingFutureTest.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.cluster.databroker.actors.dds;
9
10 import static org.opendaylight.controller.cluster.databroker.actors.dds.TestUtils.assertFutureEquals;
11 import static org.opendaylight.controller.cluster.databroker.actors.dds.TestUtils.assertOperationThrowsException;
12 import static org.opendaylight.controller.cluster.databroker.actors.dds.TestUtils.getWithTimeout;
13
14 import java.util.concurrent.ExecutionException;
15 import java.util.concurrent.Executors;
16 import java.util.concurrent.Future;
17 import java.util.concurrent.ScheduledExecutorService;
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.atomic.AtomicBoolean;
20 import org.junit.After;
21 import org.junit.Assert;
22 import org.junit.Before;
23 import org.junit.Test;
24
25 public class VotingFutureTest {
26
27     private Object result;
28     private ScheduledExecutorService executor;
29     private VotingFuture<Object> future;
30
31     @Before
32     public void setUp() throws Exception {
33         result = new Object();
34         future = new VotingFuture<>(result, 3);
35         executor = Executors.newScheduledThreadPool(1);
36     }
37
38     @After
39     public void tearDown() throws Exception {
40         executor.shutdownNow();
41     }
42
43     @Test
44     public void testTrivialCases() throws Exception {
45         final VotingFuture<Object> oneYesVoteFuture = new VotingFuture<>(result, 1);
46         oneYesVoteFuture.voteYes();
47         assertFutureEquals(result, oneYesVoteFuture);
48         final VotingFuture<Object> oneNoVoteFuture = new VotingFuture<>(result, 1);
49         final RuntimeException cause = new RuntimeException("fail");
50         oneNoVoteFuture.voteNo(cause);
51         checkException(oneNoVoteFuture, cause);
52     }
53
54     @Test
55     public void testVoteYes() throws Exception {
56         future.voteYes();
57         future.voteYes();
58         future.voteYes();
59         assertFutureEquals(result, future);
60     }
61
62     @Test
63     public void testVoteYesBlocking() throws Exception {
64         final AtomicBoolean voted = new AtomicBoolean(false);
65         future.voteYes();
66         future.voteYes();
67         executor.schedule(() -> {
68             voted.set(true);
69             future.voteYes();
70         }, 1, TimeUnit.SECONDS);
71         assertFutureEquals(result, future);
72         Assert.assertTrue("Future completed before vote", voted.get());
73     }
74
75     @Test
76     public void testVoteNo() throws Exception {
77         future.voteYes();
78         final RuntimeException cause = new RuntimeException("fail");
79         future.voteNo(cause);
80         future.voteYes();
81         checkException(future, cause);
82     }
83
84     @Test
85     public void testVoteNoFirst() throws Exception {
86         final RuntimeException cause = new RuntimeException("fail");
87         future.voteNo(cause);
88         future.voteYes();
89         future.voteYes();
90         checkException(future, cause);
91     }
92
93     @Test
94     public void testVoteNoLast() throws Exception {
95         future.voteYes();
96         future.voteYes();
97         final RuntimeException cause = new RuntimeException("fail");
98         future.voteNo(cause);
99         checkException(future, cause);
100     }
101
102     @Test
103     public void testVoteNoBlocking() throws Exception {
104         final AtomicBoolean voted = new AtomicBoolean(false);
105         future.voteYes();
106         final RuntimeException cause = new RuntimeException("fail");
107         future.voteNo(cause);
108         executor.schedule(() -> {
109             voted.set(true);
110             future.voteYes();
111         }, 1, TimeUnit.SECONDS);
112         checkException(future, cause);
113         Assert.assertTrue("Future completed before vote", voted.get());
114     }
115
116     @Test
117     public void testMultipleVoteNo() throws Exception {
118         future.voteYes();
119         final RuntimeException cause1 = new RuntimeException("fail");
120         final RuntimeException cause2 = new RuntimeException("fail");
121         future.voteNo(cause1);
122         future.voteNo(cause2);
123         final Throwable thrown = assertOperationThrowsException(() -> getWithTimeout(future), ExecutionException.class);
124         //first no is set as cause
125         Assert.assertEquals(cause1, thrown.getCause());
126         //subsequent no causes are added as suppressed
127         final Throwable[] suppressed = thrown.getCause().getSuppressed();
128         Assert.assertEquals(1, suppressed.length);
129         Assert.assertEquals(cause2, suppressed[0]);
130     }
131
132     private static void checkException(final Future<Object> future, final RuntimeException cause) throws Exception {
133         final Throwable thrown = assertOperationThrowsException(() -> getWithTimeout(future), ExecutionException.class);
134         Assert.assertEquals(cause, thrown.getCause());
135     }
136
137 }