BUG-110 : integration test : pcep message -> topology provider -> md sal 56/3256/4
authorDana Kutenicsova <dkutenic@cisco.com>
Fri, 29 Nov 2013 16:04:42 +0000 (17:04 +0100)
committerDana Kutenicsova <dkutenic@cisco.com>
Sun, 1 Dec 2013 10:25:34 +0000 (11:25 +0100)
Change-Id: I6885e62321a7d3dd7b054e46a9f7c4ba8a29ceee
Signed-off-by: Dana Kutenicsova <dkutenic@cisco.com>
bgp/util/src/main/java/org/opendaylight/protocol/bgp/util/HexDumpBGPFileParser.java
integration-tests/src/test/resources/pcep-hex.txt [new file with mode: 0644]
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/DefaultPCEPSessionNegotiator.java
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/PCEPSessionImpl.java
pcep/topology-provider/pom.xml
pcep/topology-provider/src/main/java/org/opendaylight/bgpcep/pcep/topology/provider/ServerSessionManager.java
pcep/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/ParserToSalTest.java [new file with mode: 0644]
util/pom.xml
util/src/main/java/org/opendaylight/protocol/util/PCEPHexDumpParser.java [new file with mode: 0644]
util/src/test/java/org/opendaylight/protocol/util/PCEPHexDumpParserTest.java [new file with mode: 0644]
util/src/test/resources/pcep-hex.txt [new file with mode: 0644]

index 9ea256ba6b79ccb8c7e78e24369826356e68e805..82a6515975e1e0d19560595fa60e934f72b9e03a 100644 (file)
@@ -36,7 +36,7 @@ import com.google.common.io.CharStreams;
 @Immutable
 public final class HexDumpBGPFileParser {
        private static final int MINIMAL_LENGTH = 19;
-       private static final Logger logger = LoggerFactory.getLogger(HexDumpBGPFileParser.class);
+       private static final Logger LOG = LoggerFactory.getLogger(HexDumpBGPFileParser.class);
        private static final String FF_16 = Strings.repeat("FF", 16);
 
        private HexDumpBGPFileParser() {
@@ -62,8 +62,8 @@ public final class HexDumpBGPFileParser {
                // search for 16 FFs
 
                final List<byte[]> messages = Lists.newLinkedList();
-               int idx = 0;
-               while ((idx = content.indexOf(FF_16, idx)) > -1) {
+               int idx = content.indexOf(FF_16, 0);
+               while (idx > -1) {
                        // next 2 bytes are length
                        final int lengthIdx = idx + 16 * 2;
                        final int messageIdx = lengthIdx + 4;
@@ -91,8 +91,9 @@ public final class HexDumpBGPFileParser {
                        }
                        messages.add(message);
                        idx = messageEndIdx;
+                       idx = content.indexOf(FF_16, idx);
                }
-               logger.info("Succesfully extracted {} messages", messages.size());
+               LOG.info("Succesfully extracted {} messages", messages.size());
                return messages;
        }
 
@@ -100,5 +101,4 @@ public final class HexDumpBGPFileParser {
        static String clearWhiteSpaceToUpper(final String line) {
                return line.replaceAll("\\s", "").toUpperCase();
        }
-
 }
diff --git a/integration-tests/src/test/resources/pcep-hex.txt b/integration-tests/src/test/resources/pcep-hex.txt
new file mode 100644 (file)
index 0000000..434a46c
--- /dev/null
@@ -0,0 +1,37 @@
+Received PCEP Open message. Length:28.
+
+20 01 00 1c 01 10 00 18  20 1e 78 03 00 10 00 04
+00 00 00 05 00 1a 00 04  00 00 00 b4
+
+Received PCEP Keepalive message. Length:4.
+
+20 02 00 04
+
+Received PCEPReport message. Length:12.
+
+20 0a 00 0c 20 10 00 08  00 00 00 00
+
+Received PCEPReport message. Length:56.
+
+20 0a 00 38 20 10 00 34  00 00 50 01 00 11 00 28
+74 75 6e 6e 65 6c 5f 66  72 6f 6d 5f 4f 66 2d 39
+6b 2d 30 32 5f 74 6f 5f  4f 66 2d 39 6b 2d 30 33
+4f 66 2d 39 6b 2d 30 32
+
+Received PCEPReport message. Length:120.
+
+20 0a 00 78 20 10 00 44  00 00 50 05 00 11 00 28
+74 75 6e 6e 65 6c 5f 66  72 6f 6d 5f 4f 66 2d 39
+6b 2d 30 32 5f 74 6f 5f  4f 66 2d 39 6b 2d 30 33
+4f 66 2d 39 6b 2d 30 32  00 12 00 0c 2a 2a 2a 2a
+00 00 00 04 2a 2a 2a 2a  07 10 00 14 01 08 c6 14
+a0 2b 20 00 01 08 2b 2b  2b 2b 20 00 09 10 00 14
+00 00 00 00 00 00 00 00  00 00 00 00 07 07 00 00
+05 20 00 08 00 00 00 00
+
+Received PCEPReport message. Length:56.
+
+20 0a 00 38 20 10 00 34  00 00 50 0c 00 11 00 28
+74 75 6e 6e 65 6c 5f 66  72 6f 6d 5f 4f 66 2d 39
+6b 2d 30 32 5f 74 6f 5f  4f 66 2d 39 6b 2d 30 33
+4f 66 2d 39 6b 2d 30 32
index b64e3be9be7981c67f7622e476dc33e3f4fae143..10527cee74ed595e536211e8a10bc77da8eb0420 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.protocol.pcep.PCEPSessionListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.Open;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.OpenBuilder;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 
 public final class DefaultPCEPSessionNegotiator extends AbstractPCEPSessionNegotiator {
@@ -38,7 +39,8 @@ public final class DefaultPCEPSessionNegotiator extends AbstractPCEPSessionNegot
        }
 
        @Override
-       protected PCEPSessionImpl createSession(final Timer timer, final Channel channel, final Open localPrefs, final Open remotePrefs) {
+       @VisibleForTesting
+       public PCEPSessionImpl createSession(final Timer timer, final Channel channel, final Open localPrefs, final Open remotePrefs) {
                return new PCEPSessionImpl(timer, this.listener, this.maxUnknownMessages, channel, localPrefs, remotePrefs);
        }
 
index 5804abe17af09f5edafde2f600d8c508ba6dec95..4302612e30876524bad0a1081c08f98be7972ae2 100644 (file)
@@ -384,7 +384,8 @@ public class PCEPSessionImpl extends AbstractProtocolSession<Message> implements
        }
 
        @Override
-       protected void sessionUp() {
+       @VisibleForTesting
+       public void sessionUp() {
                this.listener.onSessionUp(this);
        }
 
index ed88e892f5ed229d53076ad0e71d3bda09a99b13..53cdd3cec514cc8ea03298a4d3bd7a7b0ded6544 100644 (file)
                        <groupId>${project.groupId}</groupId>
                        <artifactId>mockito-configuration</artifactId>
         </dependency>
+        <dependency>
+                       <groupId>${project.groupId}</groupId>
+                       <artifactId>pcep-impl</artifactId>
+                       <scope>test</scope>
+               </dependency>
+        <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+               </dependency>
        </dependencies>
 
        <build>
index 8a74cde694f8c11a8c3e33782e3c51b78948479d..cba6cdb58ebda0e1ab0bb48446a851d12d285da4 100644 (file)
@@ -10,9 +10,11 @@ package org.opendaylight.bgpcep.pcep.topology.provider;
 import io.netty.util.concurrent.FutureListener;
 
 import java.net.InetAddress;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
 
 import javax.annotation.concurrent.GuardedBy;
 
@@ -60,17 +62,23 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.PccSyncState;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspArgs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TopologyTypes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TopologyTypes1Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspArgs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClient;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClientBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLsps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLspsKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.StatefulTlvBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.topology.pcep.type.TopologyPcepBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 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.TopologyBuilder;
+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.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypesBuilder;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -88,7 +96,7 @@ import com.google.common.util.concurrent.SettableFuture;
 /**
  *
  */
-final class ServerSessionManager implements SessionListenerFactory<PCEPSessionListener> {
+final class ServerSessionManager implements SessionListenerFactory<PCEPSessionListener>, AutoCloseable {
        private static String createNodeId(final InetAddress addr) {
                return "pcc://" + addr.getHostAddress();
        }
@@ -191,13 +199,12 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                        final DataModificationTransaction trans = ServerSessionManager.this.dataProvider.beginTransaction();
 
                        // The session went down. Undo all the Topology changes we have done.
-                       trans.removeRuntimeData(this.topologyAugment);
+                       trans.removeOperationalData(this.topologyAugment);
                        if (this.ownsTopology) {
-                               trans.removeRuntimeData(this.topologyNode);
+                               trans.removeOperationalData(this.topologyNode);
                        }
 
-                       Futures.addCallback(JdkFutureAdapters.listenInPoolThread(trans.commit()),
-                                       new FutureCallback<RpcResult<TransactionStatus>>() {
+                       Futures.addCallback(JdkFutureAdapters.listenInPoolThread(trans.commit()), new FutureCallback<RpcResult<TransactionStatus>>() {
                                @Override
                                public void onSuccess(final RpcResult<TransactionStatus> result) {
                                        // Nothing to do
@@ -237,9 +244,8 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                }
 
                private InstanceIdentifier<ReportedLsps> lspIdentifier(final SymbolicPathName name) {
-                       return InstanceIdentifier.builder(this.topologyAugment).
-                                       child(PathComputationClient.class).
-                                       child(ReportedLsps.class, new ReportedLspsKey(name.getPathName())).toInstance();
+                       return InstanceIdentifier.builder(this.topologyAugment).child(PathComputationClient.class).child(ReportedLsps.class,
+                                       new ReportedLspsKey(name.getPathName())).toInstance();
                }
 
                @Override
@@ -292,7 +298,7 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                                if (lsp.isRemove()) {
                                        final SymbolicPathName name = this.lsps.remove(id);
                                        if (name != null) {
-                                               trans.removeRuntimeData(lspIdentifier(name));
+                                               trans.removeOperationalData(lspIdentifier(name));
                                        }
 
                                        LOG.debug("LSP {} removed", lsp);
@@ -307,6 +313,7 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                                                        // TODO: what should we do here?
                                                        continue;
                                                }
+                                               this.lsps.put(id, name);
                                        }
 
                                        final SymbolicPathName name = this.lsps.get(id);
@@ -316,8 +323,7 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                                }
                        }
 
-                       Futures.addCallback(JdkFutureAdapters.listenInPoolThread(trans.commit()),
-                                       new FutureCallback<RpcResult<TransactionStatus>>() {
+                       Futures.addCallback(JdkFutureAdapters.listenInPoolThread(trans.commit()), new FutureCallback<RpcResult<TransactionStatus>>() {
                                @Override
                                public void onSuccess(final RpcResult<TransactionStatus> result) {
                                        // Nothing to do
@@ -391,6 +397,24 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
        public ServerSessionManager(final DataProviderService dataProvider, final InstanceIdentifier<Topology> topology) {
                this.dataProvider = Preconditions.checkNotNull(dataProvider);
                this.topology = Preconditions.checkNotNull(topology);
+
+               // Make sure the topology does not exist
+               final Object c = dataProvider.readOperationalData(topology);
+               Preconditions.checkArgument(c == null, "Topology %s already exists", topology);
+
+               // Now create the base topology
+               final TopologyKey k = InstanceIdentifier.keyOf(topology);
+               final DataModificationTransaction t = dataProvider.beginTransaction();
+               t.putOperationalData(
+                               topology,
+                               new TopologyBuilder().setKey(k).setTopologyId(k.getTopologyId()).setTopologyTypes(
+                                               new TopologyTypesBuilder().addAugmentation(TopologyTypes1.class,
+                                                               new TopologyTypes1Builder().setTopologyPcep(new TopologyPcepBuilder().build()).build()).build()).setNode(
+                                               new ArrayList<Node>()).build());
+
+               // FIXME: attach to the future to notify of failures
+               t.commit();
+
        }
 
        @Override
@@ -407,9 +431,8 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                }
 
                // Make sure there is no such LSP
-               final InstanceIdentifier<ReportedLsps> lsp = InstanceIdentifier.builder(l.topologyAugment).
-                               child(PathComputationClient.class).
-                               child(ReportedLsps.class, new ReportedLspsKey(input.getName())).toInstance();
+               final InstanceIdentifier<ReportedLsps> lsp = InstanceIdentifier.builder(l.topologyAugment).child(PathComputationClient.class).child(
+                               ReportedLsps.class, new ReportedLspsKey(input.getName())).toInstance();
                if (this.dataProvider.readOperationalData(lsp) != null) {
                        LOG.debug("Node {} already contains lsp {} at {}", input.getNode(), input.getName(), lsp);
                        return Futures.immediateFuture(OPERATION_UNSENT);
@@ -451,9 +474,8 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                }
 
                // Make sure the LSP exists, we need it for PLSP-ID
-               final InstanceIdentifier<ReportedLsps> lsp = InstanceIdentifier.builder(l.topologyAugment).
-                               child(PathComputationClient.class).
-                               child(ReportedLsps.class, new ReportedLspsKey(input.getName())).toInstance();
+               final InstanceIdentifier<ReportedLsps> lsp = InstanceIdentifier.builder(l.topologyAugment).child(PathComputationClient.class).child(
+                               ReportedLsps.class, new ReportedLspsKey(input.getName())).toInstance();
                final ReportedLsps rep = (ReportedLsps) this.dataProvider.readOperationalData(lsp);
                if (rep == null) {
                        LOG.debug("Node {} does not contain LSP {}", input.getNode(), input.getName());
@@ -479,9 +501,8 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                }
 
                // Make sure the LSP exists
-               final InstanceIdentifier<ReportedLsps> lsp = InstanceIdentifier.builder(l.topologyAugment).
-                               child(PathComputationClient.class).
-                               child(ReportedLsps.class, new ReportedLspsKey(input.getName())).toInstance();
+               final InstanceIdentifier<ReportedLsps> lsp = InstanceIdentifier.builder(l.topologyAugment).child(PathComputationClient.class).child(
+                               ReportedLsps.class, new ReportedLspsKey(input.getName())).toInstance();
                final ReportedLsps rep = (ReportedLsps) this.dataProvider.readOperationalData(lsp);
                if (rep == null) {
                        LOG.debug("Node {} does not contain LSP {}", input.getNode(), input.getName());
@@ -525,4 +546,11 @@ final class ServerSessionManager implements SessionListenerFactory<PCEPSessionLi
                        return Futures.immediateFuture(OPERATION_UNSENT);
                }
        }
+
+       @Override
+       public void close() throws InterruptedException, ExecutionException {
+               final DataModificationTransaction t = this.dataProvider.beginTransaction();
+               t.removeOperationalData(this.topology);
+               t.commit().get();
+       }
 }
diff --git a/pcep/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/ParserToSalTest.java b/pcep/topology-provider/src/test/java/org/opendaylight/bgpcep/pcep/topology/provider/ParserToSalTest.java
new file mode 100644 (file)
index 0000000..ab680f8
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2013 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.bgpcep.pcep.topology.provider;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelPipeline;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.concurrent.Promise;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.protocol.pcep.impl.DefaultPCEPSessionNegotiator;
+import org.opendaylight.protocol.pcep.impl.PCEPSessionImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcrpt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcrptBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.PlspId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.SymbolicPathName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.object.LspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.Open;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.OpenBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.open.TlvsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrpt.message.PcrptMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrpt.message.pcrpt.message.Reports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrpt.message.pcrpt.message.ReportsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.stateful.capability.tlv.StatefulBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.symbolic.path.name.tlv.SymbolicPathNameBuilder;
+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.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+public class ParserToSalTest {
+
+       private static final Logger LOG = LoggerFactory.getLogger(ParserToSalTest.class);
+
+       private List<Notification> receivedMsgs;
+
+       private PCEPSessionImpl session;
+
+       @Mock
+       private Channel clientListener;
+
+       @Mock
+       private ChannelPipeline pipeline;
+
+       @Mock
+       DataProviderService providerService;
+
+       @Mock
+       DataModificationTransaction mockedTransaction;
+
+       private final Open localPrefs = new OpenBuilder().setDeadTimer((short) 30).setKeepalive((short) 10).setTlvs(
+                       new TlvsBuilder().setStateful(new StatefulBuilder().build()).build()).build();
+
+       private Pcrpt rptmsg;
+
+       @Before
+       public void setUp() throws IOException {
+               MockitoAnnotations.initMocks(this);
+
+               doAnswer(new Answer<Object>() {
+                       @Override
+                       public Object answer(final InvocationOnMock invocation) {
+                               final Object[] args = invocation.getArguments();
+                               ParserToSalTest.this.receivedMsgs.add((Notification) args[0]);
+                               return mock(ChannelFuture.class);
+                       }
+               }).when(this.clientListener).writeAndFlush(any(Notification.class));
+               doReturn("TestingChannel").when(this.clientListener).toString();
+               doReturn(this.pipeline).when(this.clientListener).pipeline();
+               doReturn(this.pipeline).when(this.pipeline).replace(any(ChannelHandler.class), any(String.class), any(ChannelHandler.class));
+               doReturn(true).when(this.clientListener).isActive();
+               final SocketAddress sa = new InetSocketAddress("127.0.0.1", 4189);
+               doReturn(sa).when(this.clientListener).remoteAddress();
+               doReturn(mock(ChannelFuture.class)).when(this.clientListener).close();
+
+               Mockito.doReturn(this.mockedTransaction).when(this.providerService).beginTransaction();
+               Mockito.doReturn(new Future<RpcResult<TransactionStatus>>() {
+                       int i = 0;
+
+                       @Override
+                       public boolean cancel(final boolean mayInterruptIfRunning) {
+                               LOG.debug("Cancel.");
+                               return false;
+                       }
+
+                       @Override
+                       public boolean isCancelled() {
+                               LOG.debug("Is cancelled.");
+                               return false;
+                       }
+
+                       @Override
+                       public boolean isDone() {
+                               this.i++;
+                               LOG.debug("Done. {}", this.i);
+                               return true;
+                       }
+
+                       @Override
+                       public RpcResult<TransactionStatus> get() throws InterruptedException, ExecutionException {
+                               return null;
+                       }
+
+                       @Override
+                       public RpcResult<TransactionStatus> get(final long timeout, final TimeUnit unit) throws InterruptedException,
+                                       ExecutionException, TimeoutException {
+                               return null;
+                       }
+               }).when(this.mockedTransaction).commit();
+
+               final HashMap<Object, Object> data = new HashMap<>();
+
+               Mockito.doAnswer(new Answer<Object>() {
+                       @Override
+                       public Object answer(final InvocationOnMock invocation) throws Throwable {
+                               final Object[] args = invocation.getArguments();
+                               LOG.debug("Get key {}", args[0]);
+                               return data.get(args[0]);
+                       }
+
+               }).when(this.mockedTransaction).readOperationalData(Matchers.any(InstanceIdentifier.class));
+
+               Mockito.doAnswer(new Answer<Object>() {
+                       @Override
+                       public Object answer(final InvocationOnMock invocation) throws Throwable {
+                               final Object[] args = invocation.getArguments();
+                               LOG.debug("Get key {}", args[0]);
+                               return data.get(args[0]);
+                       }
+
+               }).when(this.providerService).readOperationalData(Matchers.any(InstanceIdentifier.class));
+
+               Mockito.doAnswer(new Answer<String>() {
+                       @Override
+                       public String answer(final InvocationOnMock invocation) throws Throwable {
+                               final Object[] args = invocation.getArguments();
+                               LOG.debug("Put key {} value {}", args[0]);
+                               LOG.debug("Put value {}", args[1]);
+                               data.put(args[0], args[1]);
+                               return null;
+                       }
+
+               }).when(this.mockedTransaction).putOperationalData(Matchers.any(InstanceIdentifier.class), Matchers.any(DataObject.class));
+
+               final ServerSessionManager manager = new ServerSessionManager(this.providerService, InstanceIdentifier.builder(
+                               NetworkTopology.class).child(Topology.class, new TopologyKey(new TopologyId("testtopo"))).toInstance());
+               final DefaultPCEPSessionNegotiator neg = new DefaultPCEPSessionNegotiator(new HashedWheelTimer(), mock(Promise.class), this.clientListener, manager.getSessionListener(), (short) 1, 5, this.localPrefs);
+               this.session = neg.createSession(new HashedWheelTimer(), this.clientListener, this.localPrefs, this.localPrefs);
+
+               final List<Reports> reports = Lists.newArrayList(new ReportsBuilder().setLsp(
+                               new LspBuilder().setPlspId(new PlspId(5L)).setSync(false).setRemove(false).setTlvs(
+                                               new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.object.lsp.TlvsBuilder().setSymbolicPathName(
+                                                               new SymbolicPathNameBuilder().setPathName(new SymbolicPathName(new byte[] { 22, 34 })).build()).build()).build()).build());
+               this.rptmsg = new PcrptBuilder().setPcrptMessage(new PcrptMessageBuilder().setReports(reports).build()).build();
+       }
+
+       @Test
+       public void testUnknownLsp() {
+               this.session.sessionUp();
+               this.session.handleMessage(this.rptmsg);
+               Mockito.verify(this.mockedTransaction, Mockito.times(4)).putOperationalData(Matchers.any(InstanceIdentifier.class),
+                               Matchers.any(DataObject.class));
+               Mockito.verify(this.mockedTransaction, Mockito.times(3)).commit();
+       }
+}
index d10c918def7ad8ce8e061a73fa687d6cb8deb439..14b8931553fb4c4eb835dff5260496e1cded20bd 100644 (file)
                        <artifactId>commons-codec</artifactId>
                        <version>${commonscodec.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
 
         <!-- Testing dependencies -->
         <dependency>
diff --git a/util/src/main/java/org/opendaylight/protocol/util/PCEPHexDumpParser.java b/util/src/main/java/org/opendaylight/protocol/util/PCEPHexDumpParser.java
new file mode 100644 (file)
index 0000000..b9ccb90
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013 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.protocol.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.List;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.io.CharStreams;
+
+/**
+ * Parses PCEP messages from a text file. Messages need to follow this formatting:
+ *
+ * Received PCEP Open message. Length:28.
+ *
+ * 20 01 00 1c 01 10 00 18 20 1e 78 03 00 10 00 04 00 00 00 05 00 1a 00 04 00 00 00 b4
+ *
+ */
+public class PCEPHexDumpParser {
+       private static final int MINIMAL_LENGTH = 4;
+       private static final Logger LOG = LoggerFactory.getLogger(PCEPHexDumpParser.class);
+       private static final String LENGTH = "LENGTH:";
+
+       private PCEPHexDumpParser() {
+
+       }
+
+       public static List<byte[]> parseMessages(final File file) throws IOException {
+               Preconditions.checkArgument(file != null, "Filename cannot be null");
+               return parseMessages(new FileInputStream(file));
+       }
+
+       public static List<byte[]> parseMessages(final InputStream is) throws IOException {
+               Preconditions.checkNotNull(is);
+               try (InputStreamReader isr = new InputStreamReader(is)) {
+                       return parseMessages(CharStreams.toString(isr));
+               } finally {
+                       is.close();
+               }
+       }
+
+       private static List<byte[]> parseMessages(final String c) {
+               final String content = clearWhiteSpaceToUpper(c);
+
+               final List<byte[]> messages = Lists.newLinkedList();
+               int idx = content.indexOf(LENGTH, 0);
+               while (idx > -1) {
+                       // next chars are final length, ending with '.'
+                       final int lengthIdx = idx + LENGTH.length();
+                       final int messageIdx = content.indexOf('.', lengthIdx);
+
+                       final int length = Integer.valueOf(content.substring(lengthIdx, messageIdx));
+                       final int messageEndIdx = idx + length * 2;
+
+                       // Assert that message is longer than minimum 4(header.length == 4)
+                       // If length in PCEP message would be 0, loop would never end
+                       Preconditions.checkArgument(length >= MINIMAL_LENGTH, "Invalid message at index " + idx + ", length atribute is lower than "
+                                       + MINIMAL_LENGTH);
+
+                       final String hexMessage = content.substring(idx, messageEndIdx);
+                       byte[] message = null;
+                       try {
+                               message = Hex.decodeHex(hexMessage.toCharArray());
+                       } catch (final DecoderException e) {
+                               new RuntimeException(e);
+                       }
+                       messages.add(message);
+                       idx = messageEndIdx;
+                       idx = content.indexOf(LENGTH, idx);
+               }
+               LOG.info("Succesfully extracted {} messages", messages.size());
+               return messages;
+       }
+
+       private static String clearWhiteSpaceToUpper(final String line) {
+               return line.replaceAll("\\s", "").toUpperCase();
+       }
+}
diff --git a/util/src/test/java/org/opendaylight/protocol/util/PCEPHexDumpParserTest.java b/util/src/test/java/org/opendaylight/protocol/util/PCEPHexDumpParserTest.java
new file mode 100644 (file)
index 0000000..56601e0
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 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.protocol.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.List;
+
+import org.junit.Test;
+
+public class PCEPHexDumpParserTest {
+
+       public static final String hexDumpFileName = "/pcep-hex.txt";
+       private final int expectedSize = 6;
+
+       @Test
+       public void testParsing() throws Exception {
+               final List<byte[]> result = PCEPHexDumpParser.parseMessages(getClass().getResourceAsStream(PCEPHexDumpParserTest.hexDumpFileName));
+               assertEquals(this.expectedSize, result.size());
+       }
+
+       @Test
+       public void testParsingInvalidFile() throws Exception {
+               try {
+                       PCEPHexDumpParser.parseMessages(new File("bad file name"));
+                       fail("Exception should have occured.");
+               } catch (final FileNotFoundException e) {
+                       assertThat(e.getMessage(), containsString("bad file name (No such file or directory)"));
+               }
+       }
+}
diff --git a/util/src/test/resources/pcep-hex.txt b/util/src/test/resources/pcep-hex.txt
new file mode 100644 (file)
index 0000000..434a46c
--- /dev/null
@@ -0,0 +1,37 @@
+Received PCEP Open message. Length:28.
+
+20 01 00 1c 01 10 00 18  20 1e 78 03 00 10 00 04
+00 00 00 05 00 1a 00 04  00 00 00 b4
+
+Received PCEP Keepalive message. Length:4.
+
+20 02 00 04
+
+Received PCEPReport message. Length:12.
+
+20 0a 00 0c 20 10 00 08  00 00 00 00
+
+Received PCEPReport message. Length:56.
+
+20 0a 00 38 20 10 00 34  00 00 50 01 00 11 00 28
+74 75 6e 6e 65 6c 5f 66  72 6f 6d 5f 4f 66 2d 39
+6b 2d 30 32 5f 74 6f 5f  4f 66 2d 39 6b 2d 30 33
+4f 66 2d 39 6b 2d 30 32
+
+Received PCEPReport message. Length:120.
+
+20 0a 00 78 20 10 00 44  00 00 50 05 00 11 00 28
+74 75 6e 6e 65 6c 5f 66  72 6f 6d 5f 4f 66 2d 39
+6b 2d 30 32 5f 74 6f 5f  4f 66 2d 39 6b 2d 30 33
+4f 66 2d 39 6b 2d 30 32  00 12 00 0c 2a 2a 2a 2a
+00 00 00 04 2a 2a 2a 2a  07 10 00 14 01 08 c6 14
+a0 2b 20 00 01 08 2b 2b  2b 2b 20 00 09 10 00 14
+00 00 00 00 00 00 00 00  00 00 00 00 07 07 00 00
+05 20 00 08 00 00 00 00
+
+Received PCEPReport message. Length:56.
+
+20 0a 00 38 20 10 00 34  00 00 50 0c 00 11 00 28
+74 75 6e 6e 65 6c 5f 66  72 6f 6d 5f 4f 66 2d 39
+6b 2d 30 32 5f 74 6f 5f  4f 66 2d 39 6b 2d 30 33
+4f 66 2d 39 6b 2d 30 32