[ONOS-4051] Path computation algorithm implementation (Coding & UT).

Change-Id: If94be2ba2a010a203003b7ce38289b516ab20f59
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
index 2ff3a49..7ea9934 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
@@ -18,8 +18,10 @@
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.onosproject.incubator.net.tunnel.Tunnel.Type.MPLS;
 
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -34,8 +36,15 @@
 import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.incubator.net.tunnel.TunnelService;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.Path;
 import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.topology.LinkWeight;
+import org.onosproject.net.topology.PathService;
+import org.onosproject.net.topology.TopologyEdge;
 import org.onosproject.pce.pceservice.api.PceService;
+import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
 import org.onosproject.store.serializers.KryoNamespaces;
 import org.onosproject.store.service.DistributedSet;
 import org.onosproject.store.service.Serializer;
@@ -43,6 +52,8 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.ImmutableList;
+
 /**
  * Implementation of PCE service.
  */
@@ -66,6 +77,15 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected StorageService storageService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected PathService pathService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected ResourceService resourceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceService deviceService;
+
     private ApplicationId appId;
 
     /**
@@ -92,6 +112,36 @@
         log.info("Stopped");
     }
 
+    /**
+     * Returns an edge-weight capable of evaluating links on the basis of the
+     * specified constraints.
+     *
+     * @param constraints path constraints
+     * @return edge-weight function
+     */
+    private LinkWeight weight(List<Constraint> constraints) {
+        return new TeConstraintBasedLinkWeight(constraints);
+    }
+
+    /**
+     * Computes a path between two devices.
+     *
+     * @param src ingress device
+     * @param dst egress device
+     * @param constraints path constraints
+     * @return computed path based on constraints
+     */
+    protected Set<Path> computePath(DeviceId src, DeviceId dst, List<Constraint> constraints) {
+        if (pathService == null) {
+            return null;
+        }
+        Set<Path> paths = pathService.getPaths(src, dst, weight(constraints));
+        if (!paths.isEmpty()) {
+            return paths;
+        }
+        return null;
+    }
+
     //[TODO:] handle requests in queue
     @Override
     public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
@@ -103,8 +153,8 @@
         checkNotNull(lspType);
 
         // TODO: compute and setup path.
-
-        return true;
+        //TODO: gets the path based on constraints and creates a tunnel in network via tunnel manager
+        return computePath(src, dst, constraints) != null ? true : false;
     }
 
 
@@ -159,4 +209,44 @@
         return value;
     }
 
+    protected class TeConstraintBasedLinkWeight implements LinkWeight {
+
+        private final List<Constraint> constraints;
+
+        /**
+         * Creates a new edge-weight function capable of evaluating links
+         * on the basis of the specified constraints.
+         *
+         * @param constraints path constraints
+         */
+        public TeConstraintBasedLinkWeight(List<Constraint> constraints) {
+            if (constraints == null) {
+                this.constraints = Collections.emptyList();
+            } else {
+                this.constraints = ImmutableList.copyOf(constraints);
+            }
+        }
+
+        @Override
+        public double weight(TopologyEdge edge) {
+            if (!constraints.iterator().hasNext()) {
+                //Takes default cost/hopcount as 1 if no constraints specified
+                return 1.0;
+            }
+
+            Iterator<Constraint> it = constraints.iterator();
+            double cost = 1;
+
+            //If any constraint fails return -1 also value of cost returned from cost constraint can't be negative
+            while (it.hasNext() && cost > 0) {
+                Constraint constraint = it.next();
+                if (constraint instanceof CapabilityConstraint) {
+                    cost = ((CapabilityConstraint) constraint).isValidLink(edge.link(), deviceService) ? 1 : -1;
+                } else {
+                    cost = constraint.cost(edge.link(), resourceService::isAvailable);
+                }
+            }
+            return cost;
+        }
+    }
 }
\ No newline at end of file
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/constraint/CapabilityConstraint.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/constraint/CapabilityConstraint.java
new file mode 100644
index 0000000..a479c38
--- /dev/null
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/constraint/CapabilityConstraint.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pce.pceservice.constraint;
+
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.Device;
+import org.onosproject.net.Link;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.intent.ResourceContext;
+import org.onosproject.net.intent.constraint.BooleanConstraint;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Constraint that evaluates whether devices satisfies capability.
+ */
+public final class CapabilityConstraint extends BooleanConstraint {
+
+    private final CapabilityType capabilityType;
+    public static final String PCECC_CAPABILITY = "pceccCapability";
+    public static final String SR_CAPABILITY = "srCapability";
+    public static final String LABEL_STACK_CAPABILITY = "labelStackCapability";
+    public static final String LSRID = "lsrId";
+    public static final String L3 = "L3";
+    public static final String TRUE = "true";
+
+    /**
+     * Represents about capability type.
+     */
+    public enum CapabilityType {
+        /**
+         * Signifies that path is created via signaling mode.
+         */
+        WITH_SIGNALLING(0),
+
+        /**
+         * Signifies that path is created via SR mode.
+         */
+        SR_WITHOUT_SIGNALLING(1),
+
+        /**
+         * Signifies that path is created via without signaling and without SR mode.
+         */
+        WITHOUT_SIGNALLING_AND_WITHOUT_SR(2);
+
+        int value;
+
+        /**
+         * Assign val with the value as the capability type.
+         *
+         * @param val capability type
+         */
+        CapabilityType(int val) {
+            value = val;
+        }
+
+        /**
+         * Returns value of capability type.
+         *
+         * @return capability type
+         */
+        public byte type() {
+            return (byte) value;
+        }
+    }
+
+    // Constructor for serialization
+    private CapabilityConstraint() {
+        capabilityType = null;
+    }
+
+    /**
+     * Creates a new capability constraint.
+     *
+     * @param capabilityType type of capability device supports
+     */
+    public CapabilityConstraint(CapabilityType capabilityType) {
+        this.capabilityType = capabilityType;
+    }
+
+    /**
+     * Creates a new capability constraint.
+     *
+     * @param capabilityType type of capability device supports
+     * @return instance of CapabilityConstraint for specified capability type
+     */
+    public static CapabilityConstraint of(CapabilityType capabilityType) {
+        return new CapabilityConstraint(capabilityType);
+    }
+
+    /**
+     * Obtains type of capability.
+     *
+     * @return type of capability
+     */
+    public CapabilityType capabilityType() {
+        return capabilityType;
+    }
+
+    /**
+     * Validates the link based on capability constraint.
+     *
+     * @param link to validate source and destination based on capability constraint
+     * @param deviceService instance of DeviceService
+     * @return true if link satisfies capability constraint otherwise false
+     */
+    public boolean isValidLink(Link link, DeviceService deviceService) {
+        if (deviceService == null) {
+            return false;
+        }
+
+        Device srcDevice = deviceService.getDevice(link.src().deviceId());
+        Device dstDevice = deviceService.getDevice(link.dst().deviceId());
+
+        //TODO: Usage of annotations are for transient solution. In future will be replaces with the
+        // network config service / Projection model.
+        // L3 device
+        if (srcDevice == null
+                || dstDevice == null
+                || srcDevice.annotations().value(AnnotationKeys.TYPE) == null
+                || dstDevice.annotations().value(AnnotationKeys.TYPE) == null
+                || !srcDevice.annotations().value(AnnotationKeys.TYPE).equals(L3)
+                || !dstDevice.annotations().value(AnnotationKeys.TYPE).equals(L3)) {
+            return false;
+        }
+
+        String scrLsrId = srcDevice.annotations().value(LSRID);
+        String dstLsrId = dstDevice.annotations().value(LSRID);
+
+        Device srcCapDevice = null;
+        Device dstCapDevice = null;
+
+        // Get Capability device
+        Iterable<Device> devices = deviceService.getAvailableDevices();
+        for (Device dev : devices) {
+            if (dev.annotations().value(LSRID).equals(scrLsrId)) {
+                srcCapDevice = dev;
+            } else if (dev.annotations().value(LSRID).equals(dstLsrId)) {
+                dstCapDevice = dev;
+            }
+        }
+
+        if (srcCapDevice == null || dstCapDevice == null) {
+            return false;
+        }
+
+        switch (capabilityType) {
+        case WITH_SIGNALLING:
+            return true;
+        case WITHOUT_SIGNALLING_AND_WITHOUT_SR:
+            if (srcCapDevice.annotations().value(PCECC_CAPABILITY) != null
+                    && dstCapDevice.annotations().value(PCECC_CAPABILITY) != null) {
+                return srcCapDevice.annotations().value(PCECC_CAPABILITY).equals(TRUE)
+                        && dstCapDevice.annotations().value(PCECC_CAPABILITY).equals(TRUE);
+            }
+            return false;
+        case SR_WITHOUT_SIGNALLING:
+            if (srcCapDevice.annotations().value(LABEL_STACK_CAPABILITY) != null
+                    && dstCapDevice.annotations().value(LABEL_STACK_CAPABILITY) != null
+                    && srcCapDevice.annotations().value(SR_CAPABILITY) != null
+                    && dstCapDevice.annotations().value(SR_CAPABILITY) != null) {
+                return srcCapDevice.annotations().value(LABEL_STACK_CAPABILITY).equals(TRUE)
+                        && dstCapDevice.annotations().value(LABEL_STACK_CAPABILITY).equals(TRUE)
+                        && srcCapDevice.annotations().value(SR_CAPABILITY).equals(TRUE)
+                        && dstCapDevice.annotations().value(SR_CAPABILITY).equals(TRUE);
+            }
+            return false;
+        default:
+            return false;
+        }
+    }
+
+    @Override
+    public boolean isValid(Link link, ResourceContext context) {
+        return false;
+        //Do nothing instead using isValidLink needs device service to validate link
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(capabilityType);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof CapabilityConstraint) {
+            CapabilityConstraint other = (CapabilityConstraint) obj;
+            return Objects.equals(this.capabilityType, other.capabilityType);
+        }
+
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("capabilityType", capabilityType)
+                .toString();
+    }
+}
\ No newline at end of file
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/constraint/CostConstraint.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/constraint/CostConstraint.java
new file mode 100644
index 0000000..229644d
--- /dev/null
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/constraint/CostConstraint.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pce.pceservice.constraint;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.intent.ResourceContext;
+import org.onosproject.net.intent.Constraint;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Constraint that evaluates whether cost for a link is available, if yes return cost for that link.
+ */
+public final class CostConstraint implements Constraint {
+
+    /**
+     * Represents about cost types.
+     */
+    public enum Type {
+        /**
+         * Signifies that cost is IGP cost.
+         */
+        COST(1),
+
+        /**
+         * Signifies that cost is TE cost.
+         */
+        TE_COST(2);
+
+        int value;
+
+        /**
+         * Assign val with the value as the Cost type.
+         *
+         * @param val Cost type
+         */
+        Type(int val) {
+            value = val;
+        }
+
+        /**
+         * Returns value of Cost type.
+         *
+         * @return Cost type
+         */
+        public byte type() {
+            return (byte) value;
+        }
+    }
+
+    private final Type type;
+    public static final String TE_COST = "teCost";
+    public static final String COST = "cost";
+
+    // Constructor for serialization
+    private CostConstraint() {
+        this.type = null;
+    }
+
+    /**
+     * Creates a new cost constraint.
+     *
+     * @param type of a link
+     */
+    public CostConstraint(Type type) {
+        this.type = checkNotNull(type, "Type cannot be null");
+    }
+
+    /**
+     * Creates new CostConstraint with specified cost type.
+     *
+     * @param type of cost
+     * @return instance of CostConstraint
+     */
+    public static CostConstraint of(Type type) {
+        return new CostConstraint(type);
+    }
+
+    /**
+     * Returns the type of a cost specified in a constraint.
+     *
+     * @return required cost type
+     */
+    public Type type() {
+        return type;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof CostConstraint) {
+            CostConstraint other = (CostConstraint) obj;
+            return Objects.equals(this.type, other.type);
+        }
+
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("type", type)
+                .toString();
+    }
+
+    @Override
+    public double cost(Link link, ResourceContext context) {
+        //TODO: Usage of annotations are for transient solution. In future will be replaces with the
+        // network config service / Projection model.
+        switch (type) {
+        case COST:
+            if (link.annotations().value(COST) != null) {
+                return Double.parseDouble(link.annotations().value(COST));
+            }
+
+            //If cost annotations absent return -1[It is not L3 device]
+            return -1;
+        case TE_COST:
+            if (link.annotations().value(TE_COST) != null) {
+                return Double.parseDouble(link.annotations().value(TE_COST));
+            }
+
+            //If TE cost annotations absent return -1[It is not L3 device]
+            return -1;
+        default:
+            return -1;
+        }
+    }
+
+    @Override
+    public boolean validate(Path path, ResourceContext context) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/constraint/SharedBandwidthConstraint.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/constraint/SharedBandwidthConstraint.java
new file mode 100644
index 0000000..2985f24
--- /dev/null
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/constraint/SharedBandwidthConstraint.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pce.pceservice.constraint;
+
+import org.onlab.util.Bandwidth;
+import org.onosproject.net.Link;
+import org.onosproject.net.intent.ResourceContext;
+import org.onosproject.net.intent.constraint.BooleanConstraint;
+import org.onosproject.net.resource.Resources;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Constraint that evaluates whether links satisfies sharedbandwidth request.
+ */
+public final class SharedBandwidthConstraint extends BooleanConstraint {
+
+    private final List<Link> links;
+    private final Bandwidth sharedBwValue;
+    private final Bandwidth requestBwValue;
+    //temporary variable declared to hold changed bandwidth value
+    private Bandwidth changedBwValue;
+
+    // Constructor for serialization
+    private SharedBandwidthConstraint() {
+        links = null;
+        sharedBwValue = null;
+        requestBwValue = null;
+    }
+
+    /**
+     * Creates a new SharedBandwidth constraint.
+     *
+     * @param links shared links
+     * @param sharedBwValue shared bandwidth of the links
+     * @param requestBwValue requested bandwidth value
+     */
+    public SharedBandwidthConstraint(List<Link> links, Bandwidth sharedBwValue, Bandwidth requestBwValue) {
+        this.links = links;
+        this.sharedBwValue = sharedBwValue;
+        this.requestBwValue = requestBwValue;
+    }
+
+    /**
+     * Creates a new SharedBandwidth constraint.
+     *
+     * @param links shared links
+     * @param sharedBwValue shared bandwidth of the links
+     * @param requestBwValue requested bandwidth value
+     * @return SharedBandwidth instance
+     */
+    public static SharedBandwidthConstraint of(List<Link> links, Bandwidth sharedBwValue, Bandwidth requestBwValue) {
+        return new SharedBandwidthConstraint(links, sharedBwValue, requestBwValue);
+    }
+
+    /**
+     * Obtains shared links.
+     *
+     * @return shared links
+     */
+    public List<Link> links() {
+        return links;
+    }
+
+    /**
+     * Obtains shared bandwidth of the links.
+     *
+     * @return shared bandwidth
+     */
+    public Bandwidth sharedBwValue() {
+        return sharedBwValue;
+    }
+
+    /**
+     * Obtains requested bandwidth value.
+     *
+     * @return requested bandwidth value
+     */
+    public Bandwidth requestBwValue() {
+        return requestBwValue;
+    }
+
+    @Override
+    public boolean isValid(Link link, ResourceContext context) {
+        changedBwValue = requestBwValue;
+        if (links.contains(link)) {
+            changedBwValue = requestBwValue.isGreaterThan(sharedBwValue) ? requestBwValue.subtract(sharedBwValue)
+                    : Bandwidth.bps(0);
+        }
+
+        return Stream
+                .of(link.src(), link.dst())
+                .map(cp -> Resources.continuous(cp.deviceId(), cp.port(), Bandwidth.class).resource(
+                        changedBwValue.bps())).allMatch(context::isAvailable);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(requestBwValue, sharedBwValue, links);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof SharedBandwidthConstraint) {
+            SharedBandwidthConstraint other = (SharedBandwidthConstraint) obj;
+            return Objects.equals(this.requestBwValue, other.requestBwValue)
+                    && Objects.equals(this.sharedBwValue, other.sharedBwValue)
+                    && Objects.equals(this.links, other.links);
+        }
+
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("requestBwValue", requestBwValue)
+                .add("sharedBwValue", sharedBwValue)
+                .add("links", links)
+                .toString();
+    }
+}
\ No newline at end of file
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/constraint/package-info.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/constraint/package-info.java
new file mode 100644
index 0000000..a788a42
--- /dev/null
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/constraint/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Constraints for path computation for PCE service.
+ */
+package org.onosproject.pce.pceservice.constraint;
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PathComputationTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PathComputationTest.java
new file mode 100644
index 0000000..446aea2
--- /dev/null
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PathComputationTest.java
@@ -0,0 +1,1032 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pce.pceservice;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.graph.AbstractGraphPathSearch;
+import org.onlab.graph.AdjacencyListsGraph;
+import org.onlab.graph.DijkstraGraphSearch;
+import org.onlab.graph.Graph;
+import org.onlab.graph.GraphPathSearch;
+import org.onlab.packet.ChassisId;
+import org.onlab.util.Bandwidth;
+import org.onlab.util.Tools;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.DefaultPath;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.IntentId;
+import org.onosproject.net.Device.Type;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.net.device.DeviceServiceAdapter;
+import org.onosproject.net.resource.ContinuousResource;
+import org.onosproject.net.resource.ContinuousResourceId;
+import org.onosproject.net.resource.DiscreteResource;
+import org.onosproject.net.resource.DiscreteResourceId;
+import org.onosproject.net.resource.Resource;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceConsumer;
+import org.onosproject.net.resource.ResourceId;
+import org.onosproject.net.resource.Resources;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.net.topology.DefaultTopologyEdge;
+import org.onosproject.net.topology.DefaultTopologyVertex;
+import org.onosproject.net.topology.LinkWeight;
+import org.onosproject.net.topology.TopologyEdge;
+import org.onosproject.net.topology.TopologyVertex;
+import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
+import org.onosproject.pce.pceservice.constraint.CostConstraint;
+import org.onosproject.pce.pceservice.constraint.SharedBandwidthConstraint;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
+import static org.onosproject.core.CoreService.CORE_PROVIDER_ID;
+import static com.google.common.collect.ImmutableSet.of;
+import static org.onosproject.net.resource.Resources.continuous;
+import static org.onosproject.net.Link.Type.DIRECT;
+import static org.onosproject.net.Link.State.ACTIVE;
+import static org.onosproject.net.DeviceId.deviceId;
+import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.COST;
+import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.TE_COST;
+
+/**
+ * Test for CSPF path computation.
+ */
+public class PathComputationTest {
+
+    private final MockPathResourceService resourceService = new MockPathResourceService();
+    private final MockDeviceService deviceService = new MockDeviceService();
+    private PceManager pceManager = new PceManager();
+    public static ProviderId providerId = new ProviderId("pce", "foo");
+    private static final String DEVICE1 = "D001";
+    private static final String DEVICE2 = "D002";
+    private static final String DEVICE3 = "D003";
+    private static final String DEVICE4 = "D004";
+    private static final String DEVICE5 = "D005";
+    public static final String PCEPDEVICE1 = "PD001";
+    public static final String PCEPDEVICE2 = "PD002";
+    public static final String PCEPDEVICE3 = "PD003";
+    public static final String PCEPDEVICE4 = "PD004";
+    private static final TopologyVertex D1 = new DefaultTopologyVertex(DeviceId.deviceId("D001"));
+    private static final TopologyVertex D2 = new DefaultTopologyVertex(DeviceId.deviceId("D002"));
+    private static final TopologyVertex D3 = new DefaultTopologyVertex(DeviceId.deviceId("D003"));
+    private static final TopologyVertex D4 = new DefaultTopologyVertex(DeviceId.deviceId("D004"));
+    private static final TopologyVertex D5 = new DefaultTopologyVertex(DeviceId.deviceId("D005"));
+    private static final String ANNOTATION_COST = "cost";
+    private static final String ANNOTATION_TE_COST = "teCost";
+    private static final String UNKNOWN = "unknown";
+    public static final String LSRID = "lsrId";
+    public static final String L3 = "L3";
+    public static final String PCECC_CAPABILITY = "pceccCapability";
+    public static final String SR_CAPABILITY = "srCapability";
+    public static final String LABEL_STACK_CAPABILITY = "labelStackCapability";
+
+    @Before
+    public void startUp() {
+        pceManager.resourceService = resourceService;
+        pceManager.deviceService = deviceService;
+    }
+
+    /**
+     * Selects path computation algorithm.
+     *
+     * @return graph path search algorithm
+     */
+    private AbstractGraphPathSearch<TopologyVertex, TopologyEdge> graphSearch() {
+        return new DijkstraGraphSearch<>();
+    }
+
+    /**
+     * Returns link for two devices.
+     *
+     * @param device source device
+     * @param port source port
+     * @param device2 destination device
+     * @param port2 destination port
+     * @return link
+     */
+    private Link addLink(String device, long port, String device2, long port2, boolean setCost, int value) {
+        ConnectPoint src = new ConnectPoint(DeviceId.deviceId(device), PortNumber.portNumber(port));
+        ConnectPoint dst = new ConnectPoint(DeviceId.deviceId(device2), PortNumber.portNumber(port2));
+        Link curLink;
+        DefaultAnnotations.Builder annotationBuilder = DefaultAnnotations.builder();
+        if (setCost) {
+            annotationBuilder.set(ANNOTATION_COST, String.valueOf(value));
+        } else {
+            annotationBuilder.set(ANNOTATION_TE_COST, String.valueOf(value));
+        }
+
+        //TODO:If cost not set cost : default value case
+        curLink = DefaultLink.builder().src(src).dst(dst).state(ACTIVE).type(DIRECT)
+                 .providerId(PathComputationTest.providerId).annotations(annotationBuilder.build()).build();
+        return curLink;
+    }
+
+    @After
+    public void tearDown() {
+        pceManager.resourceService = null;
+        pceManager.deviceService = null;
+    }
+
+    /**
+     * Returns an edge-weight capable of evaluating links on the basis of the
+     * specified constraints.
+     *
+     * @param constraints path constraints
+     * @return edge-weight function
+     */
+    private LinkWeight weight(List<Constraint> constraints) {
+        return new MockTeConstraintBasedLinkWeight(constraints);
+    }
+
+    private Set<Path> computePath(Link link1, Link link2, Link link3, Link link4, List<Constraint> constraints) {
+        Graph<TopologyVertex, TopologyEdge> graph = new AdjacencyListsGraph<>(of(D1, D2, D3, D4),
+                of(new DefaultTopologyEdge(D1, D2, link1),
+                   new DefaultTopologyEdge(D2, D4, link2),
+                   new DefaultTopologyEdge(D1, D3, link3),
+                   new DefaultTopologyEdge(D3, D4, link4)));
+
+        GraphPathSearch.Result<TopologyVertex, TopologyEdge> result =
+                graphSearch().search(graph, D1, D4, weight(constraints), ALL_PATHS);
+        ImmutableSet.Builder<Path> builder = ImmutableSet.builder();
+        for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
+            builder.add(networkPath(path));
+        }
+        return builder.build();
+    }
+
+    private class MockDeviceService extends DeviceServiceAdapter {
+        List<Device> devices = new LinkedList<>();
+
+        private void addDevice(Device dev) {
+            devices.add(dev);
+        }
+
+        @Override
+        public Device getDevice(DeviceId deviceId) {
+            for (Device dev : devices) {
+                if (dev.id().equals(deviceId)) {
+                    return dev;
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public Iterable<Device> getAvailableDevices() {
+            return devices;
+        }
+    }
+
+    private class MockTeConstraintBasedLinkWeight implements LinkWeight {
+
+        private final List<Constraint> constraints;
+
+        /**
+         * Creates a new edge-weight function capable of evaluating links
+         * on the basis of the specified constraints.
+         *
+         * @param constraints path constraints
+         */
+        MockTeConstraintBasedLinkWeight(List<Constraint> constraints) {
+            if (constraints == null) {
+                this.constraints = Collections.emptyList();
+            } else {
+                this.constraints = ImmutableList.copyOf(constraints);
+            }
+        }
+
+        public double weight(TopologyEdge edge) {
+            if (!constraints.iterator().hasNext()) {
+                //Takes default cost/hopcount as 1 if no constraints specified
+                return 1.0;
+            }
+
+            Iterator<Constraint> it = constraints.iterator();
+            double cost = 1;
+
+            //If any constraint fails return -1 also value of cost returned from cost constraint can't be negative
+            while (it.hasNext() && cost > 0) {
+                Constraint constraint = it.next();
+                if (constraint instanceof CapabilityConstraint) {
+                    cost = ((CapabilityConstraint) constraint).isValidLink(edge.link(), deviceService) ? 1 : -1;
+                } else {
+                    cost = constraint.cost(edge.link(), resourceService::isAvailable);
+                }
+            }
+            return cost;
+        }
+    }
+
+    private Path networkPath(org.onlab.graph.Path<TopologyVertex, TopologyEdge> path) {
+        List<Link> links = path.edges().stream().map(TopologyEdge::link).collect(Collectors.toList());
+        return new DefaultPath(CORE_PROVIDER_ID, links, path.cost());
+    }
+
+    /**
+     * Test Resource service for path computation.
+     */
+    private class MockPathResourceService extends ResourceServiceAdapter {
+        private final Map<Resource, ResourceConsumer> assignment = new HashMap<>();
+        private Map<ResourceId, List<ResourceAllocation>> resourcesAllocations = new HashMap<>();
+
+        @Override
+        public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<Resource> resources) {
+            for (Resource resource: resources) {
+                if (resource instanceof ContinuousResource) {
+                    List<ResourceAllocation> allocs = new LinkedList<>();
+                    allocs.add(new ResourceAllocation(resource, consumer));
+                    resourcesAllocations.put(resource.id(), allocs);
+                }
+            }
+            return resources.stream()
+                    .map(x -> new ResourceAllocation(x, consumer))
+                    .collect(Collectors.toList());
+        }
+
+        @Override
+        public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
+            if (id instanceof ContinuousResourceId) {
+                return resourcesAllocations.get(id);
+            }
+            DiscreteResource discrete = Resources.discrete((DiscreteResourceId) id).resource();
+            return Optional.ofNullable(assignment.get(discrete))
+                    .map(x -> ImmutableList.of(new ResourceAllocation(discrete, x)))
+                    .orElse(ImmutableList.of());
+        }
+
+        @Override
+        public <T> Set<Resource> getAvailableResources(DiscreteResourceId parent, Class<T> cls) {
+            return getAvailableResources(parent).stream()
+                    .filter(x -> x.isTypeOf(cls))
+                    .collect(Collectors.toSet());
+        }
+
+        @Override
+        public <T> Set<T> getAvailableResourceValues(DiscreteResourceId parent, Class<T> cls) {
+            return getAvailableResources(parent).stream()
+                    .filter(x -> x.isTypeOf(cls))
+                    .flatMap(x -> Tools.stream(x.valueAs(cls)))
+                    .collect(Collectors.toSet());
+        }
+
+        @Override
+        public boolean isAvailable(Resource resource) {
+            if (resource instanceof DiscreteResource) {
+                return true;
+            }
+
+            if (resource instanceof ContinuousResource) {
+                List<ResourceAllocation> resalloc = resourcesAllocations.get(resource.id());
+
+                if ((resalloc != null) && (!resalloc.isEmpty())) {
+                    if (((ContinuousResource) resalloc.iterator().next().resource()).value()
+                            >= ((ContinuousResource) resource).value()) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * All links with different costs with L1-L2 as least cost path.
+     */
+    @Test
+    public void testpathComputationCase1() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 50);
+
+        CostConstraint costConst = CostConstraint.of(COST);
+        List<Constraint> constraints = new LinkedList<>();
+        constraints.add(costConst);
+
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        List<Link> links = new LinkedList<>();
+
+        links.add(link1);
+        links.add(link2);
+
+        assertThat(paths.iterator().next().links(), is(links));
+        assertThat(paths.iterator().next().cost(), is((double) 70));
+    }
+
+    /**
+     * Links with same cost 100 except link3.
+     */
+    @Test
+    public void testpathComputationCase2() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 100);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 100);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 1000);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 100);
+
+        CostConstraint costConst = CostConstraint.of(COST);
+        List<Constraint> constraints = new LinkedList<>();
+        constraints.add(costConst);
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        List<Link> links = new LinkedList<>();
+        links.add(link1);
+        links.add(link2);
+
+        assertThat(paths.iterator().next().links(), is(links));
+        assertThat(paths.iterator().next().cost(), is((double) 200));
+    }
+
+    /**
+     * Path which satisfy bandwidth as a constraint with 10bps.
+     */
+    @Test
+    public void testpathComputationCase3() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 50);
+
+        List<Resource> resources = new LinkedList<>();
+
+        resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class)
+                .resource(50));
+        resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class)
+                .resource(50));
+        resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class)
+                .resource(100));
+        resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class)
+                .resource(100));
+
+        resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class)
+                .resource(50));
+        resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class)
+                .resource(50));
+        resources.add(continuous(link3.dst().deviceId(), link3.src().port(), Bandwidth.class)
+                .resource(100));
+        resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class)
+                .resource(100));
+
+        resourceService.allocate(IntentId.valueOf(70), resources);
+
+        BandwidthConstraint bandwidthConst = new BandwidthConstraint(Bandwidth.bps(10.0));
+
+        List<Constraint> constraints = new LinkedList<>();
+        constraints.add(bandwidthConst);
+
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        assertThat(paths.iterator().next().cost(), is((double) 2));
+    }
+
+    /**
+     * Path which satisfy bandwidth as a constraint with 60bps.
+     */
+    @Test
+    public void testpathComputationCase4() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 50);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 100);
+
+        List<Resource> resources = new LinkedList<>();
+
+        resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(50));
+        resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(50));
+        resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(100));
+        resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(100));
+
+        resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(50));
+        resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(50));
+        resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(100));
+        resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(100));
+
+        resourceService.allocate(IntentId.valueOf(70), resources);
+
+        BandwidthConstraint bandwidthConst = new BandwidthConstraint(Bandwidth.bps(60.0));
+
+        List<Constraint> constraints = new LinkedList<>();
+        constraints.add(bandwidthConst);
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        assertThat(paths.iterator().next().cost(), is((double) 2));
+    }
+
+    /**
+     * Shared bandwidth as L1, L2 with its value 10 bps and bandwidth constraint as 20 bps.
+     */
+    @Test
+    public void testpathComputationCase5() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
+
+        List<Resource> resources = new LinkedList<>();
+
+        resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(50));
+        resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(50));
+        resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(100));
+        resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(100));
+
+        resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(50));
+        resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(50));
+        resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(100));
+        resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(100));
+        resourceService.allocate(IntentId.valueOf(70), resources);
+
+        List<Constraint> constraints = new LinkedList<>();
+
+        List<Link> sharedLinks = new LinkedList<>();
+
+        List<Link> links = new LinkedList<>();
+        links.add(link1);
+        links.add(link2);
+
+        CostConstraint costConst = CostConstraint.of(COST);
+        sharedLinks.addAll(links);
+        SharedBandwidthConstraint sharedBw = new SharedBandwidthConstraint(sharedLinks, Bandwidth.bps(10),
+                Bandwidth.bps(20.0));
+        constraints.add(sharedBw);
+        constraints.add(costConst);
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+        assertThat(paths.iterator().next().links(), is(links));
+        assertThat(paths.iterator().next().cost(), is((double) 70));
+    }
+
+    /**
+     * Shared bandwidth as L1, L2 with its value 20 bps and bandwidth constraint as 10 bps.
+     */
+    @Test
+    public void testpathComputationCase6() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
+
+        List<Resource> resources = new LinkedList<>();
+
+        resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(50));
+        resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(50));
+        resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(100));
+        resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(100));
+
+        resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(50));
+        resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(50));
+        resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(100));
+        resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(100));
+        resourceService.allocate(IntentId.valueOf(70), resources);
+
+        List<Constraint> constraints = new LinkedList<>();
+
+        List<Link> sharedLinks = new LinkedList<>();
+
+        List<Link> links = new LinkedList<>();
+        links.add(link1);
+        links.add(link2);
+        CostConstraint costConst = CostConstraint.of(COST);
+        sharedLinks.addAll(links);
+        SharedBandwidthConstraint sharedBwConst = new SharedBandwidthConstraint(sharedLinks, Bandwidth.bps(20),
+                Bandwidth.bps(10.0));
+        constraints.add(sharedBwConst);
+        constraints.add(costConst);
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        assertThat(paths.iterator().next().links(), is(links));
+        assertThat(paths.iterator().next().cost(), is((double) 70));
+    }
+
+    /**
+     * Path without constraints.
+     */
+    @Test
+    public void testpathComputationCase7() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
+        List<Constraint> constraints = new LinkedList<>();
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        assertThat(paths.iterator().next().cost(), is((double) 2));
+    }
+
+    /**
+     * With TeCost as a constraints.
+     */
+    @Test
+    public void testpathComputationCase8() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
+
+        CostConstraint tecostConst = CostConstraint.of(TE_COST);
+
+        List<Constraint> constraints = new LinkedList<>();
+        constraints.add(tecostConst);
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        List<Link> links = new LinkedList<>();
+        links.add(link1);
+        links.add(link2);
+        assertThat(paths.iterator().next().links(), is(links));
+        assertThat(paths.iterator().next().cost(), is((double) 70));
+    }
+
+    /**
+     * With device supporting RSVP capability as a constraints.
+     */
+    @Test
+    public void testpathComputationCase9() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
+
+        CostConstraint tecostConst = CostConstraint.of(TE_COST);
+        CapabilityConstraint capabilityConst = CapabilityConstraint
+                .of(CapabilityConstraint.CapabilityType.WITH_SIGNALLING);
+
+        List<Constraint> constraints = new LinkedList<>();
+        constraints.add(capabilityConst);
+        constraints.add(tecostConst);
+        //Device1
+        DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "1.1.1.1");
+        addDevice(DEVICE1, builder);
+
+        //Device2
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "2.2.2.2");
+        addDevice(DEVICE2, builder);
+
+        //Device3
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "3.3.3.3");
+        addDevice(DEVICE3, builder);
+
+        //Device4
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "4.4.4.4");
+        addDevice(DEVICE4, builder);
+
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        List<Link> links = new LinkedList<>();
+        links.add(link1);
+        links.add(link2);
+        assertThat(paths.iterator().next().links(), is(links));
+        assertThat(paths.iterator().next().cost(), is((double) 70));
+    }
+
+    /**
+     * Devices supporting CR capability.
+     */
+    @Test
+    public void testpathComputationCase10() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
+
+        CapabilityConstraint capabilityConst = CapabilityConstraint
+                .of(CapabilityConstraint.CapabilityType.WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+
+        List<Constraint> constraints = new LinkedList<>();
+        constraints.add(capabilityConst);
+        CostConstraint costConst = CostConstraint.of(COST);
+        constraints.add(costConst);
+        //Device1
+        DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "1.1.1.1");
+        addDevice(DEVICE1, builder);
+        builder.set(PCECC_CAPABILITY, "true");
+        addDevice(PCEPDEVICE1, builder);
+
+        //Device2
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "2.2.2.2");
+        addDevice(DEVICE2, builder);
+        builder.set(PCECC_CAPABILITY, "true");
+        addDevice(PCEPDEVICE2, builder);
+
+        //Device3
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "3.3.3.3");
+        addDevice(DEVICE3, builder);
+        builder.set(PCECC_CAPABILITY, "true");
+        addDevice(PCEPDEVICE3, builder);
+
+        //Device4
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "4.4.4.4");
+        addDevice(DEVICE4, builder);
+        builder.set(PCECC_CAPABILITY, "true");
+        addDevice(PCEPDEVICE4, builder);
+
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        List<Link> links = new LinkedList<>();
+        links.add(link1);
+        links.add(link2);
+        assertThat(paths.iterator().next().links(), is(links));
+        assertThat(paths.iterator().next().cost(), is((double) 70));
+    }
+
+    /**
+     * Device supporting SR capability.
+     */
+    @Test
+    public void testpathComputationCase11() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
+
+        CapabilityConstraint capabilityConst = CapabilityConstraint
+                .of(CapabilityConstraint.CapabilityType.SR_WITHOUT_SIGNALLING);
+
+        List<Constraint> constraints = new LinkedList<>();
+        constraints.add(capabilityConst);
+        CostConstraint costConst = CostConstraint.of(COST);
+        constraints.add(costConst);
+        //Device1
+        DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "1.1.1.1");
+        addDevice(DEVICE1, builder);
+        builder.set(SR_CAPABILITY, "true");
+        builder.set(LABEL_STACK_CAPABILITY, "true");
+        addDevice(PCEPDEVICE1, builder);
+
+        //Device2
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "2.2.2.2");
+        addDevice(DEVICE2, builder);
+        builder.set(SR_CAPABILITY, "true");
+        builder.set(LABEL_STACK_CAPABILITY, "true");
+        addDevice(PCEPDEVICE2, builder);
+
+        //Device3
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "3.3.3.3");
+        addDevice(DEVICE3, builder);
+        builder.set(SR_CAPABILITY, "true");
+        builder.set(LABEL_STACK_CAPABILITY, "true");
+        addDevice(PCEPDEVICE3, builder);
+
+        //Device4
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "4.4.4.4");
+        addDevice(DEVICE4, builder);
+        builder.set(SR_CAPABILITY, "true");
+        builder.set(LABEL_STACK_CAPABILITY, "true");
+        addDevice(PCEPDEVICE4, builder);
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        List<Link> links = new LinkedList<>();
+        links.add(link1);
+        links.add(link2);
+        assertThat(paths.iterator().next().links(), is(links));
+        assertThat(paths.iterator().next().cost(), is((double) 70));
+    }
+
+    /**
+     * Path with TE and SR capability constraint.
+     */
+    @Test
+    public void testpathComputationCase12() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
+
+        CostConstraint tecostConst = CostConstraint.of(TE_COST);
+        CapabilityConstraint capabilityConst = CapabilityConstraint
+                .of(CapabilityConstraint.CapabilityType.SR_WITHOUT_SIGNALLING);
+
+        List<Constraint> constraints = new LinkedList<>();
+
+        constraints.add(capabilityConst);
+        constraints.add(tecostConst);
+        //Device1
+        DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "1.1.1.1");
+        addDevice(DEVICE1, builder);
+        builder.set(SR_CAPABILITY, "true");
+        builder.set(LABEL_STACK_CAPABILITY, "true");
+        addDevice(PCEPDEVICE1, builder);
+
+        //Device2
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "2.2.2.2");
+        addDevice(DEVICE2, builder);
+        builder.set(SR_CAPABILITY, "true");
+        builder.set(LABEL_STACK_CAPABILITY, "true");
+        addDevice(PCEPDEVICE2, builder);
+
+        //Device3
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "3.3.3.3");
+        addDevice(DEVICE3, builder);
+        builder.set(SR_CAPABILITY, "true");
+        builder.set(LABEL_STACK_CAPABILITY, "true");
+        addDevice(PCEPDEVICE3, builder);
+
+        //Device4
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "4.4.4.4");
+        addDevice(DEVICE4, builder);
+        builder.set(SR_CAPABILITY, "true");
+        builder.set(LABEL_STACK_CAPABILITY, "true");
+        addDevice(PCEPDEVICE4, builder);
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        List<Link> links = new LinkedList<>();
+        links.add(link1);
+        links.add(link2);
+        assertThat(paths.iterator().next().links(), is(links));
+        assertThat(paths.iterator().next().cost(), is((double) 70));
+    }
+
+    /**
+     * Path with capability constraint and with default cost.
+     */
+    @Test
+    public void testpathComputationCase13() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
+
+        CapabilityConstraint capabilityConst = CapabilityConstraint
+                .of(CapabilityConstraint.CapabilityType.SR_WITHOUT_SIGNALLING);
+
+        List<Constraint> constraints = new LinkedList<>();
+        constraints.add(capabilityConst);
+        //Device1
+        DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "1.1.1.1");
+        addDevice(DEVICE1, builder);
+        builder.set(SR_CAPABILITY, "true");
+        builder.set(LABEL_STACK_CAPABILITY, "true");
+        addDevice(PCEPDEVICE1, builder);
+
+        //Device2
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "2.2.2.2");
+        addDevice(DEVICE2, builder);
+        builder.set(SR_CAPABILITY, "true");
+        builder.set(LABEL_STACK_CAPABILITY, "true");
+        addDevice(PCEPDEVICE2, builder);
+
+        //Device3
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "3.3.3.3");
+        addDevice(DEVICE3, builder);
+        builder.set(SR_CAPABILITY, "true");
+        builder.set(LABEL_STACK_CAPABILITY, "true");
+        addDevice(PCEPDEVICE3, builder);
+
+        //Device4
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "4.4.4.4");
+        addDevice(DEVICE4, builder);
+        builder.set(SR_CAPABILITY, "true");
+        builder.set(LABEL_STACK_CAPABILITY, "true");
+        addDevice(PCEPDEVICE4, builder);
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        List<Link> links = new LinkedList<>();
+        links.add(link1);
+        links.add(link2);
+        assertThat(paths.iterator().next().cost(), is((double) 2));
+    }
+
+    /**
+     * Test case with empty constraints.
+     */
+    @Test
+    public void testpathComputationCase14() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
+
+        List<Constraint> constraints = new LinkedList<>();
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        assertThat(paths.iterator().next().cost(), is((double) 2));
+    }
+
+    /**
+     * Test case with constraints as null.
+     */
+    @Test
+    public void testpathComputationCase15() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
+
+        List<Constraint> constraints = null;
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        assertThat(paths.iterator().next().cost(), is((double) 2));
+    }
+
+    /**
+     * Path with cost constraint.
+     */
+    @Test
+    public void testpathComputationCase16() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 100);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 10);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 10);
+        Link link5 = addLink(DEVICE4, 90, DEVICE5, 100, true, 20);
+
+        CostConstraint costConst = CostConstraint.of(COST);
+
+        List<Constraint> constraints = new LinkedList<>();
+        constraints.add(costConst);
+        Graph<TopologyVertex, TopologyEdge> graph = new AdjacencyListsGraph<>(of(D1, D2, D3, D4, D5),
+                of(new DefaultTopologyEdge(D1, D2, link1),
+                   new DefaultTopologyEdge(D2, D4, link2),
+                   new DefaultTopologyEdge(D1, D3, link3),
+                   new DefaultTopologyEdge(D3, D4, link4),
+                   new DefaultTopologyEdge(D4, D5, link5)));
+
+        GraphPathSearch.Result<TopologyVertex, TopologyEdge> result =
+                graphSearch().search(graph, D1, D5, weight(constraints), ALL_PATHS);
+        ImmutableSet.Builder<Path> builder = ImmutableSet.builder();
+        for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
+            builder.add(networkPath(path));
+        }
+
+        List<Link> links = new LinkedList<>();
+        links.add(link3);
+        links.add(link4);
+        links.add(link5);
+        assertThat(builder.build().iterator().next().links(), is(links));
+        assertThat(builder.build().iterator().next().cost(), is((double) 40));
+    }
+
+    /**
+     * D3 doesn't support capability constraint, so path is L1-L2.
+     */
+    @Test
+    public void testpathComputationCase17() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
+
+        CapabilityConstraint capabilityConst = CapabilityConstraint
+                .of(CapabilityConstraint.CapabilityType.WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+
+        List<Constraint> constraints = new LinkedList<>();
+        constraints.add(capabilityConst);
+        //Device1
+        DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "1.1.1.1");
+        addDevice(DEVICE1, builder);
+        builder.set(PCECC_CAPABILITY, "true");
+        addDevice(PCEPDEVICE1, builder);
+
+        //Device2
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "2.2.2.2");
+        addDevice(DEVICE2, builder);
+        builder.set(PCECC_CAPABILITY, "true");
+        addDevice(PCEPDEVICE2, builder);
+
+        //Device4
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "4.4.4.4");
+        addDevice(DEVICE4, builder);
+        builder.set(PCECC_CAPABILITY, "true");
+        addDevice(PCEPDEVICE4, builder);
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        List<Link> links = new LinkedList<>();
+        links.add(link1);
+        links.add(link2);
+
+        assertThat(paths.iterator().next().links(), is(links));
+        assertThat(paths.iterator().next().cost(), is((double) 2));
+    }
+
+    /**
+     * L2 doesn't support cost constraint and D3 doesn't support capability constraint, both constraint fails hence no
+     * path.
+     */
+    @Test
+    public void testpathComputationCase18() {
+        Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
+        Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
+        Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 10);
+        Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 10);
+
+        CapabilityConstraint capabilityConst = CapabilityConstraint
+                .of(CapabilityConstraint.CapabilityType.WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+        CostConstraint costConst = CostConstraint.of(COST);
+        List<Constraint> constraints = new LinkedList<>();
+        constraints.add(capabilityConst);
+        constraints.add(costConst);
+        //Device1
+        DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "1.1.1.1");
+        addDevice(DEVICE2, builder);
+        builder.set(PCECC_CAPABILITY, "true");
+        addDevice(PCEPDEVICE1, builder);
+
+        //Device2
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "2.2.2.2");
+        addDevice(DEVICE2, builder);
+        builder.set(PCECC_CAPABILITY, "true");
+        addDevice(PCEPDEVICE2, builder);
+
+        //Device4
+        builder = DefaultAnnotations.builder();
+        builder.set(AnnotationKeys.TYPE, L3);
+        builder.set(LSRID, "4.4.4.4");
+        addDevice(DEVICE4, builder);
+        builder.set(PCECC_CAPABILITY, "true");
+        addDevice(PCEPDEVICE4, builder);
+        Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
+
+        assertThat(paths, is(new HashSet<>()));
+    }
+
+    private void addDevice(String device, DefaultAnnotations.Builder builder) {
+        deviceService.addDevice(new DefaultDevice(ProviderId.NONE, deviceId(device), Type.ROUTER,
+        UNKNOWN, UNKNOWN, UNKNOWN,
+        UNKNOWN, new ChassisId(), builder.build()));
+    }
+}
\ No newline at end of file
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/ResourceServiceAdapter.java b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/ResourceServiceAdapter.java
new file mode 100644
index 0000000..791ca6e
--- /dev/null
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/ResourceServiceAdapter.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pce.pceservice;
+
+import org.onosproject.net.resource.DiscreteResourceId;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceConsumer;
+import org.onosproject.net.resource.ResourceId;
+import org.onosproject.net.resource.ResourceListener;
+import org.onosproject.net.resource.Resource;
+import org.onosproject.net.resource.ResourceService;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Adapter for resource service for path computation.
+ */
+public class ResourceServiceAdapter implements ResourceService {
+
+    @Override
+    public void addListener(ResourceListener listener) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void removeListener(ResourceListener listener) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<Resource> resources) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean release(List<ResourceAllocation> allocations) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean release(ResourceConsumer consumer) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <T> Collection<ResourceAllocation> getResourceAllocations(DiscreteResourceId parent, Class<T> cls) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Collection<ResourceAllocation> getResourceAllocations(ResourceConsumer consumer) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Set<Resource> getAvailableResources(DiscreteResourceId parent) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <T> Set<Resource> getAvailableResources(DiscreteResourceId parent, Class<T> cls) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <T> Set<T> getAvailableResourceValues(DiscreteResourceId parent, Class<T> cls) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Set<Resource> getRegisteredResources(DiscreteResourceId parent) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean isAvailable(Resource resource) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+}