From a6ee12d91ddadc775123a40a11c3a3bae7373ebe Mon Sep 17 00:00:00 2001 From: Andrej Mak Date: Thu, 9 Mar 2017 15:19:38 +0100 Subject: [PATCH 1/1] Add VotingFuture unit test Change-Id: Ib3abc7c59d1047d508e5d2446acc50ebf67e1b44 Signed-off-by: Andrej Mak --- .../actors/dds/VotingFutureTest.java | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/VotingFutureTest.java diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/VotingFutureTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/VotingFutureTest.java new file mode 100644 index 0000000000..85d6582ecf --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/VotingFutureTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.cluster.databroker.actors.dds; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class VotingFutureTest { + + private static final int TIMEOUT = 3; + + private Object result; + private ScheduledExecutorService executor; + private VotingFuture future; + + @Before + public void setUp() throws Exception { + result = new Object(); + future = new VotingFuture<>(result, 3); + executor = Executors.newScheduledThreadPool(1); + } + + @After + public void tearDown() throws Exception { + executor.shutdownNow(); + } + + @Test + public void testTrivialCases() throws Exception { + final VotingFuture oneYesVoteFuture = new VotingFuture<>(result, 1); + oneYesVoteFuture.voteYes(); + checkSuccess(oneYesVoteFuture, result); + final VotingFuture oneNoVoteFuture = new VotingFuture<>(result, 1); + final RuntimeException cause = new RuntimeException("fail"); + oneNoVoteFuture.voteNo(cause); + checkException(oneNoVoteFuture, cause); + } + + @Test + public void testVoteYes() throws Exception { + future.voteYes(); + future.voteYes(); + future.voteYes(); + checkSuccess(future, result); + } + + @Test + public void testVoteYesBlocking() throws Exception { + final AtomicBoolean voted = new AtomicBoolean(false); + future.voteYes(); + future.voteYes(); + executor.schedule(() -> { + voted.set(true); + future.voteYes(); + }, 1, TimeUnit.SECONDS); + checkSuccess(future, result); + Assert.assertTrue("Future completed before vote", voted.get()); + } + + @Test + public void testVoteNo() throws Exception { + future.voteYes(); + final RuntimeException cause = new RuntimeException("fail"); + future.voteNo(cause); + future.voteYes(); + checkException(future, cause); + } + + @Test + public void testVoteNoFirst() throws Exception { + final RuntimeException cause = new RuntimeException("fail"); + future.voteNo(cause); + future.voteYes(); + future.voteYes(); + checkException(future, cause); + } + + @Test + public void testVoteNoLast() throws Exception { + future.voteYes(); + future.voteYes(); + final RuntimeException cause = new RuntimeException("fail"); + future.voteNo(cause); + checkException(future, cause); + } + + @Test + public void testVoteNoBlocking() throws Exception { + final AtomicBoolean voted = new AtomicBoolean(false); + future.voteYes(); + final RuntimeException cause = new RuntimeException("fail"); + future.voteNo(cause); + executor.schedule(() -> { + voted.set(true); + future.voteYes(); + }, 1, TimeUnit.SECONDS); + checkException(future, cause); + Assert.assertTrue("Future completed before vote", voted.get()); + } + + @Test + public void testMultipleVoteNo() throws Exception { + future.voteYes(); + final RuntimeException cause1 = new RuntimeException("fail"); + final RuntimeException cause2 = new RuntimeException("fail"); + future.voteNo(cause1); + future.voteNo(cause2); + try { + future.get(TIMEOUT, TimeUnit.SECONDS); + Assert.fail("ExecutionException expected"); + } catch (final ExecutionException e) { + //first no is set as cause + Assert.assertEquals(cause1, e.getCause()); + //subsequent no causes are added as suppressed + final Throwable[] suppressed = e.getCause().getSuppressed(); + Assert.assertEquals(1, suppressed.length); + Assert.assertEquals(cause2, suppressed[0]); + } + } + + private static void checkException(final Future future, final RuntimeException cause) throws Exception { + try { + future.get(TIMEOUT, TimeUnit.SECONDS); + Assert.fail("ExecutionException expected"); + } catch (final ExecutionException e) { + Assert.assertEquals(cause, e.getCause()); + } + } + + private static void checkSuccess(final Future future, final Object result) throws Exception { + Assert.assertEquals(result, future.get(TIMEOUT, TimeUnit.SECONDS)); + } + +} \ No newline at end of file -- 2.36.6