a676347a2148c9d86fb96fdb0088a74bf73216da
[ovsdb.git] / southbound / southbound-impl / src / test / java / org / opendaylight / ovsdb / southbound / transactions / md / TransactionInvokerImplTest.java
1 /*
2  * Copyright (c) 2015 Inocybe Technologies 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.ovsdb.southbound.transactions.md;
9
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;
20
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;
39
40 @RunWith(MockitoJUnitRunner.class)
41 public class TransactionInvokerImplTest {
42     @Mock
43     private BindingTransactionChain chain;
44     @Mock
45     private DataBroker db;
46
47     @Before
48     public void setUp() {
49         doReturn(chain).when(db).createTransactionChain(any(TransactionChainListener.class));
50         doNothing().when(chain).close();
51     }
52
53     @Test
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"));
58         }
59     }
60
61     @Test
62     public void testInvoke() {
63         final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, new ArrayList<>());
64         final TransactionCommand command = mock(TransactionCommand.class);
65         invoker.invoke(command);
66
67         Queue<TransactionCommand> inputQueue = getInternalState(invoker, "inputQueue");
68         assertEquals(1, inputQueue.size());
69         assertTrue(inputQueue.contains(command));
70     }
71
72     @Test
73     public void testOnTransactionChainFailed() {
74         final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, new ArrayList<>());
75
76         final AsyncTransaction<?, ?> transaction = mock(AsyncTransaction.class);
77         invoker.onTransactionChainFailed(chain, transaction, new Throwable());
78
79         final Queue<?> failedQueue = getInternalState(invoker, "failedTransactionQueue");
80         assertEquals(1, failedQueue.size());
81         assertTrue(failedQueue.contains(transaction));
82     }
83
84     @Test
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);
92
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));
98
99         // .. we want to replay tx2 and tx3
100         assertEquals(ImmutableList.of(cmd2, cmd3), invoker.extractResubmitCommands());
101     }
102
103     private static <K, V> Entry<K, V> entry(final K key, final V value) {
104         return new SimpleImmutableEntry<>(key, value);
105     }
106
107     @Test
108     public void testResetTransactionQueue() {
109         final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, Collections.emptyList(),
110             Collections.singletonList(mock(ReadWriteTransaction.class)));
111
112         invoker.resetTransactionQueue();
113
114         assertEmpty(getInternalState(invoker, "pendingTransactions"));
115         assertEmpty(getInternalState(invoker, "failedTransactionQueue"));
116     }
117
118     private static void assertEmpty(final Collection<?> collection) {
119         assertNotNull(collection);
120         assertEquals(0, collection.size());
121     }
122
123     @Test
124     public void testRecordPendingTransaction() {
125         final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, Collections.emptyList());
126
127         final TransactionCommand command = mock(TransactionCommand.class);
128         final ReadWriteTransaction transaction = mock(ReadWriteTransaction.class);
129         invoker.recordPendingTransaction(command, transaction);
130
131         Queue<Entry<?, ?>> endingTransactions = getInternalState(invoker, "pendingTransactions");
132         assertEquals(1, endingTransactions.size());
133         assertSame(transaction, endingTransactions.element().getKey());
134         assertSame(command, endingTransactions.element().getValue());
135     }
136
137     @Test
138     public void testExtractCommands() throws InterruptedException {
139         final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, Collections.emptyList());
140
141         final TransactionCommand command = mock(TransactionCommand.class);
142         invoker.invoke(command);
143
144         assertEquals(Collections.singletonList(command), invoker.extractCommands());
145     }
146
147     @Test
148     public void testExtractCommandsFromQueue() throws InterruptedException {
149         final TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, Collections.emptyList());
150
151         final TransactionCommand command = mock(TransactionCommand.class);
152         invoker.invoke(command);
153
154         assertEquals(Collections.singletonList(command), invoker.extractCommandsFromQueue());
155     }
156
157     @Test
158     public void testClose() throws InterruptedException {
159         final ExecutorService executor = mock(ExecutorService.class);
160         doNothing().when(executor).shutdown();
161
162         try (TransactionInvokerImpl invoker = new TransactionInvokerImpl(db, executor)) {
163             // No-op, but invokes close
164         }
165
166         verify(executor).shutdown();
167     }
168 }