2 * Copyright (c) 2014 Cisco Systems, Inc. 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
9 package org.opendaylight.openflowplugin.openflow.md.core.sal;
11 import static java.lang.Thread.sleep;
12 import static org.mockito.Mockito.when;
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.api.openflow.md.core.ConnectionConductor;
32 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
33 import org.opendaylight.openflowplugin.api.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;
44 * Created by Martin Bobak mbobak@cisco.com on 9/22/14.
46 @RunWith(MockitoJUnitRunner.class)
47 public class ConcurrentSalRegistrationManagerTest {
50 private static final ExecutorService taskExecutor = Executors.newFixedThreadPool(3);
51 private static final SalRegistrationManager registrationManager = new SalRegistrationManager();
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();
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";
63 private SessionContext context;
66 private GetFeaturesOutput features;
69 private ConnectionConductor connectionConductor;
72 public void setupRegistrationManager() {
73 registrationManager.onSessionInitiated(MOCK_PROVIDER_CONTEXT);
74 SWITCH_SESSION_KEY_OF.setDatapathId(BigInteger.ONE);
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);
84 * Test method which verifies that session could not be invalidated while in creation.
86 public void testConcurrentRemoveSessionContext() throws InterruptedException, ExecutionException {
89 Thread delayedThread = new Thread(new Runnable() {
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.");
100 taskExecutor.execute(delayedThread);
102 Thread noDelayThread = new Thread(new Runnable() {
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.");
113 taskExecutor.execute(noDelayThread);
114 taskExecutor.shutdown();
115 while (!taskExecutor.isTerminated()) {
117 LOG.info("All tasks have finished.");
120 private final class MockNotificationProviderService implements NotificationProviderService {
123 public void publish(Notification notification) {
124 if (Thread.currentThread().getName().equals(DELAYED_THREAD)) {
126 LOG.info(String.format("Will wait for %d millis", THREAD_SLEEP_MILLIS));
127 sleep(THREAD_SLEEP_MILLIS);
128 } catch (InterruptedException e) {
135 public void publish(Notification notification, ExecutorService executorService) {
140 public ListenerRegistration<NotificationInterestListener> registerInterestListener(NotificationInterestListener notificationInterestListener) {
145 public <T extends Notification> ListenerRegistration<NotificationListener<T>> registerNotificationListener(Class<T> tClass, NotificationListener<T> tNotificationListener) {
150 public ListenerRegistration<org.opendaylight.yangtools.yang.binding.NotificationListener> registerNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener notificationListener) {
155 private static final class MockProviderContext implements BindingAwareBroker.ProviderContext {
159 public void registerFunctionality(BindingAwareProvider.ProviderFunctionality functionality) {
164 public void unregisterFunctionality(BindingAwareProvider.ProviderFunctionality functionality) {
169 public <T extends BindingAwareService> T getSALService(Class<T> service) {
174 public <T extends RpcService> BindingAwareBroker.RpcRegistration<T> addRpcImplementation(Class<T> serviceInterface, T implementation) throws IllegalStateException {
179 public <T extends RpcService> BindingAwareBroker.RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> serviceInterface, T implementation) throws IllegalStateException {
180 return new MockRpcRegistration(implementation);
184 public <L extends RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(L listener) {
189 public <T extends RpcService> T getRpcService(Class<T> serviceInterface) {
194 private static final class MockRpcRegistration implements BindingAwareBroker.RoutedRpcRegistration {
196 private Object implementation;
198 public MockRpcRegistration(Object instance) {
199 this.implementation = instance;
204 public void registerInstance(Class context, InstanceIdentifier instance) {
209 public void unregisterInstance(Class context, InstanceIdentifier instance) {
214 public Object getInstance() {
215 return this.implementation;
219 public void registerPath(Object context, Path path) {
224 public void unregisterPath(Object context, Path path) {
229 public Class getServiceType() {
234 public void close() {