2 * Copyright (c) 2015 Inocybe Technologies 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.ovsdb.southbound.transactions.md;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertSame;
13 import static org.junit.Assert.assertTrue;
14 import static org.mockito.ArgumentMatchers.any;
15 import static org.mockito.Mockito.doNothing;
16 import static org.mockito.Mockito.doReturn;
17 import static org.mockito.Mockito.mock;
18 import static org.mockito.Mockito.verify;
19 import static org.powermock.reflect.Whitebox.getInternalState;
21 import com.google.common.collect.ImmutableList;
22 import java.util.AbstractMap.SimpleImmutableEntry;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.Map.Entry;
27 import java.util.Queue;
28 import java.util.concurrent.ExecutorService;
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.mockito.Mock;
33 import org.mockito.junit.MockitoJUnitRunner;
34 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
35 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
36 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
37 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
38 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
40 @RunWith(MockitoJUnitRunner.class)
41 public class TransactionInvokerImplTest {
43 private BindingTransactionChain chain;
45 private DataBroker db;
49 doReturn(chain).when(db).createTransactionChain(any(TransactionChainListener.class));
50 doNothing().when(chain).close();
54 public void testConstructor() throws InterruptedException {
55 try (TransactionInvokerImpl invoker = new TransactionInvokerImpl(db)) {
56 verify(db).createTransactionChain(any(TransactionChainListener.class));
57 assertNotNull(getInternalState(invoker, "executor"));
62 public void testInvoke() {
63 final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, new ArrayList<>());
64 final TransactionCommand command = mock(TransactionCommand.class);
65 invoker.invoke(command);
67 Queue<TransactionCommand> inputQueue = getInternalState(invoker, "inputQueue");
68 assertEquals(1, inputQueue.size());
69 assertTrue(inputQueue.contains(command));
73 public void testOnTransactionChainFailed() {
74 final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, new ArrayList<>());
76 final AsyncTransaction<?, ?> transaction = mock(AsyncTransaction.class);
77 invoker.onTransactionChainFailed(chain, transaction, new Throwable());
79 final Queue<?> failedQueue = getInternalState(invoker, "failedTransactionQueue");
80 assertEquals(1, failedQueue.size());
81 assertTrue(failedQueue.contains(transaction));
85 public void testExtractResubmitCommands() {
86 final ReadWriteTransaction tx1 = mock(ReadWriteTransaction.class);
87 final ReadWriteTransaction tx2 = mock(ReadWriteTransaction.class);
88 final ReadWriteTransaction tx3 = mock(ReadWriteTransaction.class);
89 final TransactionCommand cmd1 = mock(TransactionCommand.class);
90 final TransactionCommand cmd2 = mock(TransactionCommand.class);
91 final TransactionCommand cmd3 = mock(TransactionCommand.class);
93 final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db,
94 // Given pending transaction order ...
95 ImmutableList.of(entry(tx1, cmd1), entry(tx2, cmd2), entry(tx3, cmd3)),
96 // .. if tx2 fails ...
97 Collections.singletonList(tx2));
99 // .. we want to replay tx2 and tx3
100 assertEquals(ImmutableList.of(cmd2, cmd3), invoker.extractResubmitCommands());
103 private static <K, V> Entry<K, V> entry(final K key, final V value) {
104 return new SimpleImmutableEntry<>(key, value);
108 public void testResetTransactionQueue() {
109 final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, Collections.emptyList(),
110 Collections.singletonList(mock(ReadWriteTransaction.class)));
112 invoker.resetTransactionQueue();
114 assertEmpty(getInternalState(invoker, "pendingTransactions"));
115 assertEmpty(getInternalState(invoker, "failedTransactionQueue"));
118 private static void assertEmpty(final Collection<?> collection) {
119 assertNotNull(collection);
120 assertEquals(0, collection.size());
124 public void testRecordPendingTransaction() {
125 final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, Collections.emptyList());
127 final TransactionCommand command = mock(TransactionCommand.class);
128 final ReadWriteTransaction transaction = mock(ReadWriteTransaction.class);
129 invoker.recordPendingTransaction(command, transaction);
131 Queue<Entry<?, ?>> endingTransactions = getInternalState(invoker, "pendingTransactions");
132 assertEquals(1, endingTransactions.size());
133 assertSame(transaction, endingTransactions.element().getKey());
134 assertSame(command, endingTransactions.element().getValue());
138 public void testExtractCommands() throws InterruptedException {
139 final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, Collections.emptyList());
141 final TransactionCommand command = mock(TransactionCommand.class);
142 invoker.invoke(command);
144 assertEquals(Collections.singletonList(command), invoker.extractCommands());
148 public void testExtractCommandsFromQueue() throws InterruptedException {
149 final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, Collections.emptyList());
151 final TransactionCommand command = mock(TransactionCommand.class);
152 invoker.invoke(command);
154 assertEquals(Collections.singletonList(command), invoker.extractCommandsFromQueue());
158 public void testClose() throws InterruptedException {
159 final ExecutorService executor = mock(ExecutorService.class);
160 doNothing().when(executor).shutdown();
162 try (TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, executor)) {
163 // No-op, but invokes close
166 verify(executor).shutdown();