Bug 6110: Fixed bugs in statistics manager due to race condition.
[openflowplugin.git] / applications / statistics-manager / src / test / java / org / opendaylight / openflowplugin / applications / statistics / manager / impl / StatAbstractListenCommitTest.java
1 /*
2  * Copyright (c) 2015 Brocade Communications Systems, Inc. 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.openflowplugin.applications.statistics.manager.impl;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertSame;
12 import static org.mockito.Mockito.doAnswer;
13 import static org.mockito.Mockito.doReturn;
14 import static org.mockito.Mockito.mock;
15 import static org.mockito.Mockito.never;
16 import static org.mockito.Mockito.times;
17 import static org.mockito.Mockito.verify;
18 import com.google.common.base.Optional;
19 import com.google.common.util.concurrent.CheckedFuture;
20 import com.google.common.util.concurrent.Futures;
21 import org.junit.Before;
22 import org.junit.Test;
23 import org.mockito.Mock;
24 import org.mockito.MockitoAnnotations;
25 import org.mockito.invocation.InvocationOnMock;
26 import org.mockito.stubbing.Answer;
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
29
30 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
31 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
32 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
33 import org.opendaylight.openflowplugin.applications.statistics.manager.StatNodeRegistration;
34 import org.opendaylight.openflowplugin.applications.statistics.manager.StatisticsManager;
35 import org.opendaylight.yangtools.yang.binding.DataObject;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.opendaylight.yangtools.yang.binding.NotificationListener;
38
39 import java.util.ArrayList;
40
41
42 /**
43  * Unit tests for StatAbstractListenCommit.
44  *
45  * @author Thomas Pantelis
46  */
47 public class StatAbstractListenCommitTest {
48
49     @Mock
50     private NotificationProviderService mockNotificationProviderService;
51
52     @Mock
53     private StatisticsManager mockStatisticsManager;
54
55     @Mock
56     private DataBroker mockDataBroker;
57
58     @Mock
59     private NotificationListener mockNotificationListener;
60
61     @Mock
62     private StatNodeRegistration statsNodeRegistration;
63
64
65     @SuppressWarnings("rawtypes")
66     private StatAbstractListenCommit statCommit;
67
68     @SuppressWarnings({ "rawtypes", "unchecked" })
69     @Before
70     public void setup() {
71         MockitoAnnotations.initMocks(this);
72
73         statCommit = new StatAbstractListenCommit(mockStatisticsManager, mockDataBroker,
74                 mockNotificationProviderService, DataObject.class, statsNodeRegistration) {
75             @Override
76             protected InstanceIdentifier getWildCardedRegistrationPath() {
77                 return InstanceIdentifier.create(DataObject.class);
78             }
79
80             @Override
81             protected NotificationListener getStatNotificationListener() {
82                 return mockNotificationListener;
83             }
84         };
85     }
86
87
88     @SuppressWarnings("unchecked")
89     @Test
90     public void testReadLatestConfiguration() {
91
92         InstanceIdentifier<DataObject> path = InstanceIdentifier.create(DataObject.class);
93
94         ReadOnlyTransaction mockReadTx = mock(ReadOnlyTransaction.class);
95         doReturn(mockReadTx).when(mockDataBroker).newReadOnlyTransaction();
96
97         Optional<DataObject> expected = Optional.of(mock(DataObject.class));
98         doReturn(Futures.immediateCheckedFuture(expected)).when(mockReadTx).read(
99                 LogicalDatastoreType.CONFIGURATION, path);
100
101         Optional<DataObject> actual = statCommit.readLatestConfiguration(path);
102
103         assertSame("Optional instance", expected, actual);
104
105         actual = statCommit.readLatestConfiguration(path);
106
107         assertSame("Optional instance", expected, actual);
108
109         verify(mockReadTx, never()).close();
110         verify(mockDataBroker).newReadOnlyTransaction();
111     }
112
113     @SuppressWarnings("unchecked")
114     @Test
115     public void testReadLatestConfigurationWithReadFailure() {
116
117         InstanceIdentifier<DataObject> path = InstanceIdentifier.create(DataObject.class);
118
119         ReadOnlyTransaction mockReadTx1 = mock(ReadOnlyTransaction.class);
120         ReadOnlyTransaction mockReadTx2 = mock(ReadOnlyTransaction.class);
121         ReadOnlyTransaction mockReadTx3 = mock(ReadOnlyTransaction.class);
122         doReturn(mockReadTx1).doReturn(mockReadTx2).doReturn(mockReadTx3).when(mockDataBroker).newReadOnlyTransaction();
123
124         doReturn(Futures.immediateFailedCheckedFuture(new ReadFailedException("mock"))).when(mockReadTx1).read(
125                 LogicalDatastoreType.CONFIGURATION, path);
126
127         doReturn(Futures.immediateFailedCheckedFuture(new ReadFailedException("mock"))).when(mockReadTx2).read(
128                 LogicalDatastoreType.CONFIGURATION, path);
129
130         Optional<DataObject> expected = Optional.of(mock(DataObject.class));
131         doReturn(Futures.immediateCheckedFuture(expected)).when(mockReadTx3).read(
132                 LogicalDatastoreType.CONFIGURATION, path);
133
134         Optional<DataObject> actual = statCommit.readLatestConfiguration(path);
135
136         assertEquals("Optional isPresent", false, actual.isPresent());
137
138         actual = statCommit.readLatestConfiguration(path);
139
140         assertSame("Optional instance", expected, actual);
141     }
142
143     @SuppressWarnings("unchecked")
144     @Test
145     public void testReadLatestConfigurationWithInterveningOnDataTreeChanged() {
146
147         InstanceIdentifier<DataObject> path = InstanceIdentifier.create(DataObject.class);
148
149         ReadOnlyTransaction mockReadTx1 = mock(ReadOnlyTransaction.class);
150         ReadOnlyTransaction mockReadTx2 = mock(ReadOnlyTransaction.class);
151         doReturn(mockReadTx1).doReturn(mockReadTx2).when(mockDataBroker).newReadOnlyTransaction();
152
153         final Optional<DataObject> expected1 = Optional.of(mock(DataObject.class));
154         Answer<CheckedFuture<Optional<DataObject>, ReadFailedException>> answer =
155                 new Answer<CheckedFuture<Optional<DataObject>, ReadFailedException>>() {
156                     @Override
157                     public CheckedFuture<Optional<DataObject>, ReadFailedException> answer(
158                             InvocationOnMock unused) {
159                         statCommit.onDataTreeChanged(new ArrayList<>());
160                         return Futures.immediateCheckedFuture(expected1);
161                     }
162                 };
163
164         doAnswer(answer).when(mockReadTx1).read(LogicalDatastoreType.CONFIGURATION, path);
165
166         Optional<DataObject> expected2 = Optional.of(mock(DataObject.class));
167         doReturn(Futures.immediateCheckedFuture(expected2)).when(mockReadTx2).read(
168                 LogicalDatastoreType.CONFIGURATION, path);
169
170         Optional<DataObject> actual = statCommit.readLatestConfiguration(path);
171
172         assertSame("Optional instance", expected1, actual);
173
174         actual = statCommit.readLatestConfiguration(path);
175
176         assertSame("Optional instance", expected2, actual);
177
178         actual = statCommit.readLatestConfiguration(path);
179
180         assertSame("Optional instance", expected2, actual);
181
182         verify(mockReadTx1).close();
183         verify(mockReadTx2, never()).close();
184         verify(mockDataBroker, times(2)).newReadOnlyTransaction();
185     }
186 }