Sho SHIMIZU
Committed by Ray Milkey

Add constraint for link annotated value

Change-Id: Ia51e488de1ae885da02493f09156afbd52c53592
/*
* Copyright 2014 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.onlab.onos.net.intent.constraint;
import com.google.common.base.MoreObjects;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.resource.LinkResourceService;
import java.util.Objects;
/**
* Constraint that evaluates an arbitrary link annotated value is under the specified threshold.
*/
public class AnnotationConstraint extends BooleanConstraint {
private final String key;
private final double threshold;
/**
* Creates a new constraint to keep the value for the specified key
* of link annotation under the threshold.
*
* @param key key of link annotation
* @param threshold threshold value of the specified link annotation
*/
public AnnotationConstraint(String key, double threshold) {
this.key = key;
this.threshold = threshold;
}
/**
* Returns the key of link annotation this constraint designates.
* @return key of link annotation
*/
public String key() {
return key;
}
/**
* Returns the threshold this constraint ensures as link annotated value.
*
* @return threshold as link annotated value
*/
public double threshold() {
return threshold;
}
@Override
public boolean isValid(Link link, LinkResourceService resourceService) {
double value = getAnnotatedValue(link, key);
return value <= threshold;
}
/**
* Returns the annotated value of the specified link. The annotated value
* is expected to be String that can be parsed as double. If parsing fails,
* the returned value will be 1.0.
*
* @param link link whose annotated value is obtained
* @param key key of link annotation
* @return double value of link annotation for the specified key
*/
private double getAnnotatedValue(Link link, String key) {
double value;
try {
value = Double.parseDouble(link.annotations().value(key));
} catch (NumberFormatException e) {
value = 1.0;
}
return value;
}
@Override
public double cost(Link link, LinkResourceService resourceService) {
if (isValid(link, resourceService)) {
return getAnnotatedValue(link, key);
} else {
return -1;
}
}
@Override
public int hashCode() {
return Objects.hash(key, threshold);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof AnnotationConstraint)) {
return false;
}
final AnnotationConstraint other = (AnnotationConstraint) obj;
return Objects.equals(this.key, other.key) && Objects.equals(this.threshold, other.threshold);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("key", key)
.add("threshold", threshold)
.toString();
}
}
/*
* Copyright 2014 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.onlab.onos.net.intent.constraint;
import com.google.common.testing.EqualsTester;
import org.junit.Before;
import org.junit.Test;
import org.onlab.onos.net.DefaultAnnotations;
import org.onlab.onos.net.DefaultLink;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.net.resource.LinkResourceService;
import static org.easymock.EasyMock.createMock;
import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.assertThat;
import static org.onlab.onos.net.DefaultLinkTest.cp;
import static org.onlab.onos.net.DeviceId.deviceId;
import static org.onlab.onos.net.Link.Type.DIRECT;
import static org.onlab.onos.net.PortNumber.portNumber;
/**
* Test for link annotated value threshold.
*/
public class AnnotationConstraintTest {
private static final ProviderId PID = new ProviderId("of", "foo");
private static final DeviceId DID1 = deviceId("of:1");
private static final DeviceId DID2 = deviceId("of:2");
private static final PortNumber PID1 = portNumber(1);
private static final PortNumber PID2 = portNumber(2);
private static final String KEY = "distance";
private static final double VALUE = 100;
private AnnotationConstraint sut;
private Link link;
private LinkResourceService linkResourceService;
@Before
public void setUp() {
linkResourceService = createMock(LinkResourceService.class);
DefaultAnnotations annotations = DefaultAnnotations.builder().set(KEY, String.valueOf(VALUE)).build();
link = new DefaultLink(PID, cp(DID1, PID1), cp(DID2, PID2), DIRECT, annotations);
}
/**
* Tests the specified annotated value is less than the threshold.
*/
@Test
public void testLessThanThreshold() {
double value = 120;
sut = new AnnotationConstraint(KEY, value);
assertThat(sut.isValid(link, linkResourceService), is(true));
assertThat(sut.cost(link, linkResourceService), is(closeTo(VALUE, 1.0e-6)));
}
/**
* Tests the specified annotated value is more than the threshold.
*/
@Test
public void testMoreThanThreshold() {
double value = 80;
sut = new AnnotationConstraint(KEY, value);
assertThat(sut.isValid(link, linkResourceService), is(false));
assertThat(sut.cost(link, linkResourceService), is(lessThan(0.0)));
}
@Test
public void testEquality() {
new EqualsTester()
.addEqualityGroup(new AnnotationConstraint(KEY, 100), new AnnotationConstraint(KEY, 100))
.addEqualityGroup(new AnnotationConstraint(KEY, 120))
.addEqualityGroup(new AnnotationConstraint("latency", 100))
.testEquals();
}
}