825203e04f1a36135d647d4ccdf47f81f34ea085
[openflowplugin.git] / openflowplugin / src / test / java / org / opendaylight / openflowplugin / openflow / md / core / sal / ConcurrentSalRegistrationManagerTest.java
1 /*
2  * Copyright (c) 2014 Cisco 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
9 package org.opendaylight.openflowplugin.openflow.md.core.sal;
10
11 import static java.lang.Thread.sleep;
12 import static org.mockito.Mockito.when;
13
14 import java.math.BigInteger;
15 import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.ExecutorService;
17 import java.util.concurrent.Executors;
18 import org.junit.Before;
19 import org.junit.Test;
20 import org.junit.runner.RunWith;
21 import org.mockito.MockitoAnnotations.Mock;
22 import org.mockito.runners.MockitoJUnitRunner;
23 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
24 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
25 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
26 import org.opendaylight.controller.sal.binding.api.BindingAwareService;
27 import org.opendaylight.controller.sal.binding.api.NotificationListener;
28 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
29 import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
30 import org.opendaylight.openflowplugin.api.OFConstants;
31 import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
32 import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
33 import org.opendaylight.openflowplugin.openflow.md.core.session.SwitchSessionKeyOF;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
35 import org.opendaylight.yangtools.concepts.ListenerRegistration;
36 import org.opendaylight.yangtools.concepts.Path;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.opendaylight.yangtools.yang.binding.Notification;
39 import org.opendaylight.yangtools.yang.binding.RpcService;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 /**
44  * Created by Martin Bobak mbobak@cisco.com on 9/22/14.
45  */
46 @RunWith(MockitoJUnitRunner.class)
47 public class ConcurrentSalRegistrationManagerTest {
48
49
50     private static final ExecutorService taskExecutor = Executors.newFixedThreadPool(3);
51     private static final SalRegistrationManager registrationManager = new SalRegistrationManager();
52
53     private static final SwitchSessionKeyOF SWITCH_SESSION_KEY_OF = new SwitchSessionKeyOF();
54     private static final MockProviderContext MOCK_PROVIDER_CONTEXT = new MockProviderContext();
55     private final MockNotificationProviderService MOCK_NOTIFICATION_PROVIDER_SERVICE = new MockNotificationProviderService();
56
57     private static final Logger LOG = LoggerFactory.getLogger(ConcurrentSalRegistrationManagerTest.class);
58     private static final long THREAD_SLEEP_MILLIS = 1000;
59     private static final String DELAYED_THREAD = "DELAYED_THREAD";
60     private static final String NO_DELAY_THREAD = "NO_DELAY_THREAD";
61
62     @Mock
63     private SessionContext context;
64
65     @Mock
66     private GetFeaturesOutput features;
67
68     @Mock
69     private ConnectionConductor connectionConductor;
70
71     @Before
72     public void setupRegistrationManager() {
73         registrationManager.onSessionInitiated(MOCK_PROVIDER_CONTEXT);
74         SWITCH_SESSION_KEY_OF.setDatapathId(BigInteger.ONE);
75
76         when(context.getFeatures()).thenReturn(features);
77         when(features.getDatapathId()).thenReturn(BigInteger.valueOf(42));
78         when(context.getPrimaryConductor()).thenReturn(connectionConductor);
79         when(connectionConductor.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
80     }
81
82     @Test
83     /**
84      * Test method which verifies that session could not be invalidated while in creation.
85      */
86     public void testConcurrentRemoveSessionContext() throws InterruptedException, ExecutionException {
87
88
89         Thread delayedThread = new Thread(new Runnable() {
90             @Override
91             public void run() {
92                 LOG.info("Delayed session adding thread started.");
93                 Thread.currentThread().setName(DELAYED_THREAD);
94                 registrationManager.setPublishService(MOCK_NOTIFICATION_PROVIDER_SERVICE);
95                 registrationManager.onSessionAdded(SWITCH_SESSION_KEY_OF, context);
96                 LOG.info("Delayed session adding thread finished.");
97             }
98         }
99         );
100         taskExecutor.execute(delayedThread);
101
102         Thread noDelayThread = new Thread(new Runnable() {
103             @Override
104             public void run() {
105                 LOG.info("Session removing thread started.");
106                 Thread.currentThread().setName(NO_DELAY_THREAD);
107                 registrationManager.setPublishService(MOCK_NOTIFICATION_PROVIDER_SERVICE);
108                 registrationManager.onSessionRemoved(context);
109                 LOG.info("Session removing thread finished.");
110             }
111         }
112         );
113         taskExecutor.execute(noDelayThread);
114         taskExecutor.shutdown();
115         while (!taskExecutor.isTerminated()) {
116         }
117         LOG.info("All tasks have finished.");
118     }
119
120     private final class MockNotificationProviderService implements NotificationProviderService {
121
122         @Override
123         public void publish(Notification notification) {
124             if (Thread.currentThread().getName().equals(DELAYED_THREAD)) {
125                 try {
126                     LOG.info(String.format("Will wait for %d millis", THREAD_SLEEP_MILLIS));
127                     sleep(THREAD_SLEEP_MILLIS);
128                 } catch (InterruptedException e) {
129                     e.printStackTrace();
130                 }
131             }
132         }
133
134         @Override
135         public void publish(Notification notification, ExecutorService executorService) {
136
137         }
138
139         @Override
140         public ListenerRegistration<NotificationInterestListener> registerInterestListener(NotificationInterestListener notificationInterestListener) {
141             return null;
142         }
143
144         @Override
145         public <T extends Notification> ListenerRegistration<NotificationListener<T>> registerNotificationListener(Class<T> tClass, NotificationListener<T> tNotificationListener) {
146             return null;
147         }
148
149         @Override
150         public ListenerRegistration<org.opendaylight.yangtools.yang.binding.NotificationListener> registerNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener notificationListener) {
151             return null;
152         }
153     }
154
155     private static final class MockProviderContext implements BindingAwareBroker.ProviderContext {
156
157
158         @Override
159         public void registerFunctionality(BindingAwareProvider.ProviderFunctionality functionality) {
160
161         }
162
163         @Override
164         public void unregisterFunctionality(BindingAwareProvider.ProviderFunctionality functionality) {
165
166         }
167
168         @Override
169         public <T extends BindingAwareService> T getSALService(Class<T> service) {
170             return null;
171         }
172
173         @Override
174         public <T extends RpcService> BindingAwareBroker.RpcRegistration<T> addRpcImplementation(Class<T> serviceInterface, T implementation) throws IllegalStateException {
175             return null;
176         }
177
178         @Override
179         public <T extends RpcService> BindingAwareBroker.RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> serviceInterface, T implementation) throws IllegalStateException {
180             return new MockRpcRegistration(implementation);
181         }
182
183         @Override
184         public <L extends RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(L listener) {
185             return null;
186         }
187
188         @Override
189         public <T extends RpcService> T getRpcService(Class<T> serviceInterface) {
190             return null;
191         }
192     }
193
194     private static final class MockRpcRegistration implements BindingAwareBroker.RoutedRpcRegistration {
195
196         private Object implementation;
197
198         public MockRpcRegistration(Object instance) {
199             this.implementation = instance;
200
201         }
202
203         @Override
204         public void registerInstance(Class context, InstanceIdentifier instance) {
205
206         }
207
208         @Override
209         public void unregisterInstance(Class context, InstanceIdentifier instance) {
210
211         }
212
213         @Override
214         public Object getInstance() {
215             return this.implementation;
216         }
217
218         @Override
219         public void registerPath(Object context, Path path) {
220
221         }
222
223         @Override
224         public void unregisterPath(Object context, Path path) {
225
226         }
227
228         @Override
229         public Class getServiceType() {
230             return null;
231         }
232
233         @Override
234         public void close() {
235
236         }
237     }
238
239 }