import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
import java.util.concurrent.Future;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
import org.opendaylight.netconf.sal.restconf.impl.BrokerFacade;
import org.opendaylight.netconf.sal.restconf.impl.ControllerContext;
+import org.opendaylight.netconf.sal.restconf.impl.PutResult;
import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
import org.opendaylight.netconf.sal.restconf.impl.RestconfError;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType;
import org.opendaylight.netconf.sal.streams.listeners.ListenerAdapter;
+import org.opendaylight.netconf.sal.streams.listeners.NotificationListenerAdapter;
import org.opendaylight.netconf.sal.streams.listeners.Notificator;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.common.QName;
* @author Thomas Pantelis
*/
public class BrokerFacadeTest {
-
- @Mock
- DOMDataBroker domDataBroker;
-
- @Mock
- ConsumerSession context;
-
- @Mock
- DOMRpcService mockRpcService;
-
- @Mock
- DOMMountPoint mockMountInstance;
-
- BrokerFacade brokerFacade = BrokerFacade.getInstance();
-
- NormalizedNode<?, ?> dummyNode = createDummyNode("test:module", "2014-01-09", "interfaces");
- CheckedFuture<Optional<NormalizedNode<?, ?>>,ReadFailedException> dummyNodeInFuture = wrapDummyNode(dummyNode);
-
- QName qname = TestUtils.buildQName("interfaces","test:module", "2014-01-09");
-
- SchemaPath type = SchemaPath.create(true, qname);
-
- YangInstanceIdentifier instanceID = YangInstanceIdentifier.builder().node(qname).build();
-
- @Mock
- DOMDataReadOnlyTransaction rTransaction;
-
- @Mock
- DOMDataWriteTransaction wTransaction;
-
- @Mock
- DOMDataReadWriteTransaction rwTransaction;
+ @Mock private DOMDataBroker domDataBroker;
+ @Mock private DOMNotificationService domNotification;
+ @Mock private ConsumerSession context;
+ @Mock private DOMRpcService mockRpcService;
+ @Mock private DOMMountPoint mockMountInstance;
+
+ private final BrokerFacade brokerFacade = BrokerFacade.getInstance();
+ private final NormalizedNode<?, ?> dummyNode = createDummyNode("test:module", "2014-01-09", "interfaces");
+ private final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> dummyNodeInFuture =
+ wrapDummyNode(dummyNode);
+ private final QName qname = TestUtils.buildQName("interfaces","test:module", "2014-01-09");
+ private final SchemaPath type = SchemaPath.create(true, qname);
+ private final YangInstanceIdentifier instanceID = YangInstanceIdentifier.builder().node(qname).build();
+
+ @Mock private DOMDataReadOnlyTransaction rTransaction;
+ @Mock private DOMDataWriteTransaction wTransaction;
+ @Mock private DOMDataReadWriteTransaction rwTransaction;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- // TODO it is started before every test method
- brokerFacade.setDomDataBroker(domDataBroker);
- brokerFacade.setRpcService(mockRpcService);
- brokerFacade.setContext(context);
- when(domDataBroker.newReadOnlyTransaction()).thenReturn(rTransaction);
- when(domDataBroker.newWriteOnlyTransaction()).thenReturn(wTransaction);
- when(domDataBroker.newReadWriteTransaction()).thenReturn(rwTransaction);
+ this.brokerFacade.setDomDataBroker(this.domDataBroker);
+ this.brokerFacade.setDomNotificationService(this.domNotification);
+ this.brokerFacade.setRpcService(this.mockRpcService);
+ this.brokerFacade.setContext(this.context);
+ when(this.domDataBroker.newReadOnlyTransaction()).thenReturn(this.rTransaction);
+ when(this.domDataBroker.newWriteOnlyTransaction()).thenReturn(this.wTransaction);
+ when(this.domDataBroker.newReadWriteTransaction()).thenReturn(this.rwTransaction);
ControllerContext.getInstance().setSchemas(TestUtils.loadSchemaContext("/full-versions/test-module"));
-
}
- private CheckedFuture<Optional<NormalizedNode<?, ?>>,ReadFailedException> wrapDummyNode(final NormalizedNode<?, ?> dummyNode) {
- return Futures.immediateCheckedFuture(Optional.<NormalizedNode<?, ?>> of(dummyNode));
+ private CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> wrapDummyNode(
+ final NormalizedNode<?, ?> dummyNode) {
+ return Futures.immediateCheckedFuture(Optional.<NormalizedNode<?, ?>> of(dummyNode));
}
- private CheckedFuture<Boolean,ReadFailedException> wrapExistence(final Boolean exists) {
- return Futures.immediateCheckedFuture(exists);
+ private CheckedFuture<Boolean, ReadFailedException> wrapExistence(final Boolean exists) {
+ return Futures.immediateCheckedFuture(exists);
}
-
/**
* Value of this node shouldn't be important for testing purposes
*/
@Test
public void testReadConfigurationData() {
- when(rTransaction.read(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class))).thenReturn(
- dummyNodeInFuture);
+ when(this.rTransaction.read(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class))).thenReturn(
+ this.dummyNodeInFuture);
- final NormalizedNode<?, ?> actualNode = brokerFacade.readConfigurationData(instanceID);
+ final NormalizedNode<?, ?> actualNode = this.brokerFacade.readConfigurationData(this.instanceID);
- assertSame("readConfigurationData", dummyNode, actualNode);
+ assertSame("readConfigurationData", this.dummyNode, actualNode);
}
@Test
public void testReadOperationalData() {
- when(rTransaction.read(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class))).thenReturn(
- dummyNodeInFuture);
+ when(this.rTransaction.read(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class))).thenReturn(
+ this.dummyNodeInFuture);
- final NormalizedNode<?, ?> actualNode = brokerFacade.readOperationalData(instanceID);
+ final NormalizedNode<?, ?> actualNode = this.brokerFacade.readOperationalData(this.instanceID);
- assertSame("readOperationalData", dummyNode, actualNode);
+ assertSame("readOperationalData", this.dummyNode, actualNode);
}
@Test(expected = RestconfDocumentedException.class)
public void testReadOperationalDataWithNoDataBroker() {
- brokerFacade.setDomDataBroker(null);
+ this.brokerFacade.setDomDataBroker(null);
- brokerFacade.readOperationalData(instanceID);
+ this.brokerFacade.readOperationalData(this.instanceID);
}
@Test
public void testInvokeRpc() throws Exception {
final DOMRpcResult expResult = mock(DOMRpcResult.class);
final CheckedFuture<DOMRpcResult, DOMRpcException> future = Futures.immediateCheckedFuture(expResult);
- when(mockRpcService.invokeRpc(type, dummyNode)).thenReturn(future);
+ when(this.mockRpcService.invokeRpc(this.type, this.dummyNode)).thenReturn(future);
- final CheckedFuture<DOMRpcResult, DOMRpcException> actualFuture = brokerFacade.invokeRpc(type, dummyNode);
+ final CheckedFuture<DOMRpcResult, DOMRpcException> actualFuture = this.brokerFacade
+ .invokeRpc(this.type, this.dummyNode);
assertNotNull("Future is null", actualFuture);
final DOMRpcResult actualResult = actualFuture.get();
assertSame("invokeRpc", expResult, actualResult);
@Test(expected = RestconfDocumentedException.class)
public void testInvokeRpcWithNoConsumerSession() {
- brokerFacade.setContext(null);
- brokerFacade.invokeRpc(type, dummyNode);
+ this.brokerFacade.setContext(null);
+ this.brokerFacade.invokeRpc(this.type, this.dummyNode);
}
- @Ignore
@Test
- public void testCommitConfigurationDataPut() {
+ public void testCommitConfigurationDataPut() throws Exception {
@SuppressWarnings("unchecked")
final CheckedFuture<Void, TransactionCommitFailedException> expFuture = mock(CheckedFuture.class);
+ when(this.rwTransaction.submit()).thenReturn(expFuture);
+
+ final Optional<NormalizedNode<?, ?>> optionalMock = mock(Optional.class);
+ when(optionalMock.get()).thenReturn(null);
- when(wTransaction.submit()).thenReturn(expFuture);
+ final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readFuture = Futures
+ .immediateCheckedFuture(optionalMock);
+ when(this.rwTransaction.read(LogicalDatastoreType.CONFIGURATION, this.instanceID)).thenReturn(readFuture);
- final Future<Void> actualFuture = brokerFacade.commitConfigurationDataPut((SchemaContext)null, instanceID, dummyNode);
+ final PutResult result = this.brokerFacade.commitConfigurationDataPut(mock(SchemaContext.class),
+ this.instanceID, this.dummyNode);
+
+ final Future<Void> actualFuture = result.getFutureOfPutData();
assertSame("commitConfigurationDataPut", expFuture, actualFuture);
- final InOrder inOrder = inOrder(domDataBroker, wTransaction);
- inOrder.verify(domDataBroker).newWriteOnlyTransaction();
- inOrder.verify(wTransaction).put(LogicalDatastoreType.CONFIGURATION, instanceID, dummyNode);
- inOrder.verify(wTransaction).submit();
+ final InOrder inOrder = inOrder(this.domDataBroker, this.rwTransaction);
+ inOrder.verify(this.domDataBroker).newReadWriteTransaction();
+ inOrder.verify(this.rwTransaction).put(LogicalDatastoreType.CONFIGURATION, this.instanceID, this.dummyNode);
+ inOrder.verify(this.rwTransaction).submit();
}
@Test
@SuppressWarnings("unchecked")
final CheckedFuture<Void, TransactionCommitFailedException> expFuture = mock(CheckedFuture.class);
- when(rwTransaction.exists(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn(
- wrapExistence(false));
-
+ when(this.rwTransaction.exists(LogicalDatastoreType.CONFIGURATION, this.instanceID))
+ .thenReturn(wrapExistence(false));
- when(rwTransaction.submit()).thenReturn(expFuture);
+ when(this.rwTransaction.submit()).thenReturn(expFuture);
- final CheckedFuture<Void, TransactionCommitFailedException> actualFuture = brokerFacade.commitConfigurationDataPost(
- (SchemaContext)null, instanceID, dummyNode);
+ final CheckedFuture<Void, TransactionCommitFailedException> actualFuture = this.brokerFacade
+ .commitConfigurationDataPost(mock(SchemaContext.class), this.instanceID, this.dummyNode);
assertSame("commitConfigurationDataPost", expFuture, actualFuture);
- final InOrder inOrder = inOrder(domDataBroker, rwTransaction);
- inOrder.verify(domDataBroker).newReadWriteTransaction();
- inOrder.verify(rwTransaction).exists(LogicalDatastoreType.CONFIGURATION, instanceID);
- inOrder.verify(rwTransaction).put(LogicalDatastoreType.CONFIGURATION, instanceID, dummyNode);
- inOrder.verify(rwTransaction).submit();
+ final InOrder inOrder = inOrder(this.domDataBroker, this.rwTransaction);
+ inOrder.verify(this.domDataBroker).newReadWriteTransaction();
+ inOrder.verify(this.rwTransaction).exists(LogicalDatastoreType.CONFIGURATION, this.instanceID);
+ inOrder.verify(this.rwTransaction).put(LogicalDatastoreType.CONFIGURATION, this.instanceID, this.dummyNode);
+ inOrder.verify(this.rwTransaction).submit();
}
@Test(expected = RestconfDocumentedException.class)
public void testCommitConfigurationDataPostAlreadyExists() {
final CheckedFuture<Boolean, ReadFailedException> successFuture = Futures.immediateCheckedFuture(Boolean.TRUE);
- when(rwTransaction.exists(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn(
- successFuture);
+ when(this.rwTransaction.exists(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class)))
+ .thenReturn(successFuture);
try {
// Schema context is only necessary for ensuring parent structure
- brokerFacade.commitConfigurationDataPost((SchemaContext)null, instanceID, dummyNode);
+ this.brokerFacade.commitConfigurationDataPost((SchemaContext) null, this.instanceID, this.dummyNode);
} catch (final RestconfDocumentedException e) {
assertEquals("getErrorTag", RestconfError.ErrorTag.DATA_EXISTS, e.getErrors().get(0).getErrorTag());
throw e;
}
}
+ /**
+ * Positive test of delete operation when data to delete exits. Returned value and order of steps are validated.
+ */
@Test
- public void testCommitConfigurationDataDelete() {
+ public void testCommitConfigurationDataDelete() throws Exception {
+ // assume that data to delete exists
+ prepareDataForDelete(true);
+
+ // expected result
@SuppressWarnings("unchecked")
final CheckedFuture<Void, TransactionCommitFailedException> expFuture = mock(CheckedFuture.class);
+ when(this.rwTransaction.submit()).thenReturn(expFuture);
- when(wTransaction.submit()).thenReturn(expFuture);
-
- final CheckedFuture<Void, TransactionCommitFailedException> actualFuture = brokerFacade
- .commitConfigurationDataDelete(instanceID);
+ // test
+ final CheckedFuture<Void, TransactionCommitFailedException> actualFuture = this.brokerFacade
+ .commitConfigurationDataDelete(this.instanceID);
+ // verify result and interactions
assertSame("commitConfigurationDataDelete", expFuture, actualFuture);
- final InOrder inOrder = inOrder(domDataBroker, wTransaction);
- inOrder.verify(domDataBroker).newWriteOnlyTransaction();
- inOrder.verify(wTransaction).delete(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class));
- inOrder.verify(wTransaction).submit();
+ // check exists, delete, submit
+ final InOrder inOrder = inOrder(this.domDataBroker, this.rwTransaction);
+ inOrder.verify(this.rwTransaction).exists(LogicalDatastoreType.CONFIGURATION, this.instanceID);
+ inOrder.verify(this.rwTransaction).delete(LogicalDatastoreType.CONFIGURATION, this.instanceID);
+ inOrder.verify(this.rwTransaction).submit();
+ }
+
+ /**
+ * Negative test of delete operation when data to delete does not exist. Error 404 should be returned.
+ */
+ @Test
+ public void testCommitConfigurationDataDeleteNoData() throws Exception {
+ // assume that data to delete does not exist
+ prepareDataForDelete(false);
+
+ // try to delete and expect 404 error
+ try {
+ this.brokerFacade.commitConfigurationDataDelete(this.instanceID);
+ fail("Delete operation should fail due to missing data");
+ } catch (final RestconfDocumentedException e) {
+ assertEquals(ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
+ assertEquals(ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
+ assertEquals(404, e.getErrors().get(0).getErrorTag().getStatusCode());
+ }
+ }
+
+ /**
+ * Prepare conditions to test delete operation. Data to delete exists or does not exist according to value of
+ * {@code assumeDataExists} parameter.
+ * @param assumeDataExists
+ */
+ private void prepareDataForDelete(final boolean assumeDataExists) {
+ when(this.rwTransaction.exists(LogicalDatastoreType.CONFIGURATION, this.instanceID))
+ .thenReturn(Futures.immediateCheckedFuture(new Boolean(assumeDataExists)));
}
- @SuppressWarnings("unchecked")
@Test
public void testRegisterToListenDataChanges() {
- final ListenerAdapter listener = Notificator.createListener(instanceID, "stream");
+ final ListenerAdapter listener = Notificator.createListener(this.instanceID, "stream");
+ @SuppressWarnings("unchecked")
final ListenerRegistration<DOMDataChangeListener> mockRegistration = mock(ListenerRegistration.class);
- when(
- domDataBroker.registerDataChangeListener(any(LogicalDatastoreType.class), eq(instanceID), eq(listener),
- eq(DataChangeScope.BASE))).thenReturn(mockRegistration);
+ when(this.domDataBroker.registerDataChangeListener(any(LogicalDatastoreType.class), eq(this.instanceID),
+ eq(listener), eq(DataChangeScope.BASE))).thenReturn(mockRegistration);
- brokerFacade.registerToListenDataChanges(LogicalDatastoreType.CONFIGURATION, DataChangeScope.BASE, listener);
+ this.brokerFacade.registerToListenDataChanges(
+ LogicalDatastoreType.CONFIGURATION, DataChangeScope.BASE, listener);
- verify(domDataBroker).registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, instanceID, listener,
- DataChangeScope.BASE);
+ verify(this.domDataBroker).registerDataChangeListener(
+ LogicalDatastoreType.CONFIGURATION, this.instanceID, listener, DataChangeScope.BASE);
assertEquals("isListening", true, listener.isListening());
- brokerFacade.registerToListenDataChanges(LogicalDatastoreType.CONFIGURATION, DataChangeScope.BASE, listener);
- verifyNoMoreInteractions(domDataBroker);
+ this.brokerFacade.registerToListenDataChanges(
+ LogicalDatastoreType.CONFIGURATION, DataChangeScope.BASE, listener);
+ verifyNoMoreInteractions(this.domDataBroker);
+ }
+ /**
+ * Create, register, close and remove notification listener.
+ */
+ @Test
+ public void testRegisterToListenNotificationChanges() {
+ // create test notification listener
+ final String identifier = "create-notification-stream/toaster:toastDone";
+ final SchemaPath path = SchemaPath.create(true,
+ QName.create("http://netconfcentral.org/ns/toaster", "2009-11-20", "toastDone"));
+ Notificator.createNotificationListener(Lists.newArrayList(path), identifier, "XML");
+ final NotificationListenerAdapter listener = Notificator.getNotificationListenerFor(identifier).get(0);
+
+ // mock registration
+ final ListenerRegistration<NotificationListenerAdapter> registration = mock(ListenerRegistration.class);
+ when(this.domNotification.registerNotificationListener(listener, listener.getSchemaPath()))
+ .thenReturn(registration);
+
+ // test to register listener for the first time
+ this.brokerFacade.registerToListenNotification(listener);
+ assertEquals("Registration was not successful", true, listener.isListening());
+
+ // try to register for the second time
+ this.brokerFacade.registerToListenNotification(listener);
+ assertEquals("Registration was not successful", true, listener.isListening());
+
+ // registrations should be invoked only once
+ verify(this.domNotification, times(1)).registerNotificationListener(listener, listener.getSchemaPath());
+
+ // close and remove test notification listener
+ listener.close();
+ Notificator.removeNotificationListenerIfNoSubscriberExists(listener);
}
}