/*
* Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.groupbasedpolicy.ip.sgt.distribution.service.impl;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.common.util.concurrent.Futures;
import java.util.Collections;
import java.util.concurrent.Future;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import org.mockito.Matchers;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.sxp.util.time.TimeConv;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.RemoveIpSgtBindingFromPeerInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.RemoveIpSgtBindingFromPeerInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.SendIpSgtBindingToPeerInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.SendIpSgtBindingToPeerInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.rpc.fields.BindingBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.rpc.fields.binding.PeerNodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.controller.rev141002.AddNodeInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.controller.rev141002.AddNodeInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.controller.rev141002.AddNodeOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.controller.rev141002.AddNodeOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.controller.rev141002.SxpControllerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.peer.sequence.fields.PeerSequence;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.peer.sequence.fields.PeerSequenceBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.SxpDomains;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomain;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomainKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.sxp.databases.fields.MasterDatabase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.protocol.rev141002.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(IpSgtDistributionServiceImpl.class)
public class IpSgtDistributionServiceImplTest {
private static final PeerSequence EMPTY_PEER_SEQUENCE = new PeerSequenceBuilder().build();
private static final DateAndTime DUMMY_DT = TimeConv.toDt(123456L);
private final IpAddress ADDR = new IpAddress(new Ipv4Address("10.0.0.1"));
private final IpPrefix BINDING_ADDR = new IpPrefix(new Ipv4Prefix("192.168.50.1/32"));
private final Sgt BINDING_SGT = new Sgt(1010);
private final String NODE_ID = "node1";
private final String TOPOLOGY_ID = "test-topology";
private final String DOMAIN_ID = TOPOLOGY_ID + "/" + NODE_ID;
private final InstanceIdentifier<Node> PEER_IID = InstanceIdentifier.builder(NetworkTopology.class)
.child(Topology.class, new TopologyKey(new TopologyId("test-topology")))
.child(Node.class, new NodeKey(
new org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId(NODE_ID)))
.build();
private final InstanceIdentifier<Node> SXP_NODE_IID = InstanceIdentifier.builder(NetworkTopology.class)
.child(Topology.class, new TopologyKey(new TopologyId("sxp")))
.child(Node.class,
new NodeKey(
new org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId(
ADDR.getIpv4Address().getValue())))
.build();
private DataBroker dataBroker;
private IpSgtDistributionServiceImpl impl;
private SxpCapableNodeListener nodeListener;
@Before
public void init() throws Exception {
SxpControllerService sxpService = mock(SxpControllerService.class);
when(sxpService.addNode(any())).thenReturn(Futures.immediateFuture(
RpcResultBuilder.<AddNodeOutput>success(new AddNodeOutputBuilder().setResult(true).build()).build()));
nodeListener = PowerMockito.mock(SxpCapableNodeListener.class);
PowerMockito.whenNew(SxpCapableNodeListener.class).withAnyArguments().thenReturn(nodeListener);
dataBroker = mock(DataBroker.class);
impl = new IpSgtDistributionServiceImpl(dataBroker, sxpService, ADDR);
}
@Test
public void testInit() throws Exception {
RpcProviderRegistry rpcProvider = mock(RpcProviderRegistry.class);
SxpControllerService sxpService = mock(SxpControllerService.class);
when(rpcProvider.getRpcService(SxpControllerService.class)).thenReturn(sxpService);
when(sxpService.addNode(any())).thenReturn(Futures.immediateFuture(
RpcResultBuilder.<AddNodeOutput>success(new AddNodeOutputBuilder().setResult(true).build()).build()));
SxpCapableNodeListener nodeListener = PowerMockito.mock(SxpCapableNodeListener.class);
PowerMockito.whenNew(SxpCapableNodeListener.class).withAnyArguments().thenReturn(nodeListener);
impl = new IpSgtDistributionServiceImpl(dataBroker, sxpService, ADDR);
AddNodeInput addNodeInput = new AddNodeInputBuilder().setNodeId(new NodeId(ADDR.getIpv4Address().getValue()))
.setSourceIp(ADDR)
.setDescription(IpSgtDistributionServiceImpl.SXP_NODE_DESCRIPTION)
.build();
verify(sxpService).addNode(eq(addNodeInput));
PowerMockito.verifyNew(SxpCapableNodeListener.class);
}
@Test
public void testSendIpSgtBindingToPeer_successfullWrite() throws Exception {
SendIpSgtBindingToPeerInput input =
new SendIpSgtBindingToPeerInputBuilder()
.setBinding(
Collections
.singletonList(new BindingBuilder().setIpPrefix(BINDING_ADDR)
.setSgt(BINDING_SGT)
.setPeerNode(Collections
.singletonList(new PeerNodeBuilder().setNodeIid(PEER_IID).build()))
.build()))
.build();
WriteTransaction wtx = mock(WriteTransaction.class);
when(dataBroker.newWriteOnlyTransaction()).thenReturn(wtx);
when(wtx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
when(nodeListener.getDomainIdForPeer(PEER_IID)).thenReturn(DOMAIN_ID);
Future<RpcResult<Void>> response = impl.sendIpSgtBindingToPeer(input);
final MasterDatabaseBinding expectedMasterDBBinding = new MasterDatabaseBindingBuilder().setIpPrefix(BINDING_ADDR)
.setSecurityGroupTag(BINDING_SGT)
.setPeerSequence(EMPTY_PEER_SEQUENCE)
.setTimestamp(DUMMY_DT)
.build();
verify(wtx).put(eq(LogicalDatastoreType.CONFIGURATION),
eq(InstanceIdentifier.builder(SXP_NODE_IID)
.augmentation(SxpNodeIdentity.class)
.child(SxpDomains.class)
.child(SxpDomain.class, new SxpDomainKey(DOMAIN_ID))
.child(MasterDatabase.class)
.child(MasterDatabaseBinding.class, new MasterDatabaseBindingKey(BINDING_ADDR))
.build()),
Matchers.argThat(createMasterBDBindingMatcher(expectedMasterDBBinding)));
assertTrue(response.get().isSuccessful());
}
private static ArgumentMatcher<MasterDatabaseBinding> createMasterBDBindingMatcher(final MasterDatabaseBinding expectedMasterDBBinding) {
return new ArgumentMatcher<MasterDatabaseBinding>() {
@Override
public boolean matches(final Object o) {
boolean verdict = false;
if (o instanceof MasterDatabaseBinding) {
final MasterDatabaseBinding otherMasterDBBinding =
new MasterDatabaseBindingBuilder((MasterDatabaseBinding) o).setTimestamp(DUMMY_DT).build();
verdict = expectedMasterDBBinding.equals(otherMasterDBBinding);
}
return verdict;
}
};
}
@Test
public void testSendIpSgtBindingToPeer_failedWrite() throws Exception {
SendIpSgtBindingToPeerInput input =
new SendIpSgtBindingToPeerInputBuilder()
.setBinding(
Collections
.singletonList(new BindingBuilder().setIpPrefix(BINDING_ADDR)
.setSgt(BINDING_SGT)
.setPeerNode(Collections
.singletonList(new PeerNodeBuilder().setNodeIid(PEER_IID).build()))
.build()))
.build();
WriteTransaction wtx = mock(WriteTransaction.class);
when(dataBroker.newWriteOnlyTransaction()).thenReturn(wtx);
when(wtx.submit()).thenReturn(Futures.immediateFailedCheckedFuture(new TransactionCommitFailedException("")));
when(nodeListener.getDomainIdForPeer(PEER_IID)).thenReturn(DOMAIN_ID);
Future<RpcResult<Void>> response = impl.sendIpSgtBindingToPeer(input);
assertFalse(response.get().isSuccessful());
}
@Test
public void testSendIpSgtBindingToPeer_noSxpCapableNode() throws Exception {
SendIpSgtBindingToPeerInput input =
new SendIpSgtBindingToPeerInputBuilder()
.setBinding(
Collections
.singletonList(new BindingBuilder().setIpPrefix(BINDING_ADDR)
.setSgt(BINDING_SGT)
.setPeerNode(Collections
.singletonList(new PeerNodeBuilder().setNodeIid(PEER_IID).build()))
.build()))
.build();
when(nodeListener.getDomainIdForPeer(PEER_IID)).thenReturn(null);
Future<RpcResult<Void>> response = impl.sendIpSgtBindingToPeer(input);
assertFalse(response.get().isSuccessful());
}
@Test
public void testRemoveIpSgtBindingFromPeer_successfullWrite() throws Exception {
RemoveIpSgtBindingFromPeerInput input =
new RemoveIpSgtBindingFromPeerInputBuilder()
.setBinding(
Collections
.singletonList(new BindingBuilder().setIpPrefix(BINDING_ADDR)
.setSgt(BINDING_SGT)
.setPeerNode(Collections
.singletonList(new PeerNodeBuilder().setNodeIid(PEER_IID).build()))
.build()))
.build();
WriteTransaction wtx = mock(WriteTransaction.class);
when(dataBroker.newWriteOnlyTransaction()).thenReturn(wtx);
when(wtx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
when(nodeListener.getDomainIdForPeer(PEER_IID)).thenReturn(DOMAIN_ID);
Future<RpcResult<Void>> response = impl.removeIpSgtBindingFromPeer(input);
new MasterDatabaseBindingBuilder().setIpPrefix(BINDING_ADDR).setSecurityGroupTag(BINDING_SGT).build();
verify(wtx).delete(eq(LogicalDatastoreType.CONFIGURATION),
eq(InstanceIdentifier.builder(SXP_NODE_IID)
.augmentation(SxpNodeIdentity.class)
.child(SxpDomains.class)
.child(SxpDomain.class, new SxpDomainKey(DOMAIN_ID))
.child(MasterDatabase.class)
.child(MasterDatabaseBinding.class, new MasterDatabaseBindingKey(BINDING_ADDR))
.build()));
assertTrue(response.get().isSuccessful());
}
@Test
public void testRemoveIpSgtBindingFromPeer_failedWrite() throws Exception {
RemoveIpSgtBindingFromPeerInput input =
new RemoveIpSgtBindingFromPeerInputBuilder()
.setBinding(
Collections
.singletonList(new BindingBuilder().setIpPrefix(BINDING_ADDR)
.setSgt(BINDING_SGT)
.setPeerNode(Collections
.singletonList(new PeerNodeBuilder().setNodeIid(PEER_IID).build()))
.build()))
.build();
WriteTransaction wtx = mock(WriteTransaction.class);
when(dataBroker.newWriteOnlyTransaction()).thenReturn(wtx);
when(wtx.submit()).thenReturn(Futures.immediateFailedCheckedFuture(new TransactionCommitFailedException("")));
when(nodeListener.getDomainIdForPeer(PEER_IID)).thenReturn(DOMAIN_ID);
Future<RpcResult<Void>> response = impl.removeIpSgtBindingFromPeer(input);
assertFalse(response.get().isSuccessful());
}
@Test
public void testRemoveIpSgtBindingFromPeer_noSxpCapableNode() throws Exception {
RemoveIpSgtBindingFromPeerInput input =
new RemoveIpSgtBindingFromPeerInputBuilder()
.setBinding(
Collections
.singletonList(new BindingBuilder().setIpPrefix(BINDING_ADDR)
.setSgt(BINDING_SGT)
.setPeerNode(Collections
.singletonList(new PeerNodeBuilder().setNodeIid(PEER_IID).build()))
.build()))
.build();
when(nodeListener.getDomainIdForPeer(PEER_IID)).thenReturn(null);
Future<RpcResult<Void>> response = impl.removeIpSgtBindingFromPeer(input);
assertFalse(response.get().isSuccessful());
}
}