2 * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
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
8 package org.opendaylight.controller.cluster.databroker.actors.dds;
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;
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;
25 public class VotingFutureTest {
27 private Object result;
28 private ScheduledExecutorService executor;
29 private VotingFuture<Object> future;
32 public void setUp() throws Exception {
33 result = new Object();
34 future = new VotingFuture<>(result, 3);
35 executor = Executors.newScheduledThreadPool(1);
39 public void tearDown() throws Exception {
40 executor.shutdownNow();
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);
55 public void testVoteYes() throws Exception {
59 assertFutureEquals(result, future);
63 public void testVoteYesBlocking() throws Exception {
64 final AtomicBoolean voted = new AtomicBoolean(false);
67 executor.schedule(() -> {
70 }, 1, TimeUnit.SECONDS);
71 assertFutureEquals(result, future);
72 Assert.assertTrue("Future completed before vote", voted.get());
76 public void testVoteNo() throws Exception {
78 final RuntimeException cause = new RuntimeException("fail");
81 checkException(future, cause);
85 public void testVoteNoFirst() throws Exception {
86 final RuntimeException cause = new RuntimeException("fail");
90 checkException(future, cause);
94 public void testVoteNoLast() throws Exception {
97 final RuntimeException cause = new RuntimeException("fail");
99 checkException(future, cause);
103 public void testVoteNoBlocking() throws Exception {
104 final AtomicBoolean voted = new AtomicBoolean(false);
106 final RuntimeException cause = new RuntimeException("fail");
107 future.voteNo(cause);
108 executor.schedule(() -> {
111 }, 1, TimeUnit.SECONDS);
112 checkException(future, cause);
113 Assert.assertTrue("Future completed before vote", voted.get());
117 public void testMultipleVoteNo() throws Exception {
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]);
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());