Initial import of CFM and SOAM api
Change-Id: Icf5cc2d5fb34b75460e80e8cced0d70265bcd33b
diff --git a/apps/cfm/src/test/java/org/onosproject/soam/impl/DmWebResourceTest.java b/apps/cfm/src/test/java/org/onosproject/soam/impl/DmWebResourceTest.java
new file mode 100644
index 0000000..702bc09
--- /dev/null
+++ b/apps/cfm/src/test/java/org/onosproject/soam/impl/DmWebResourceTest.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.soam.impl;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onlab.rest.BaseResource;
+import org.onosproject.cfm.CfmCodecContext;
+import org.onosproject.cfm.impl.CfmResourceTest;
+import org.onosproject.codec.CodecService;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamService;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementEntry;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementStatCurrent;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+
+import static junit.framework.TestCase.fail;
+import static org.easymock.EasyMock.*;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+public class DmWebResourceTest extends CfmResourceTest {
+ private final CfmMepService mepService = createMock(CfmMepService.class);
+ private final SoamService soamService = createMock(SoamService.class);
+
+ private static final MdId MDNAME1 = MdIdCharStr.asMdId("md-1");
+ private static final MaIdShort MANAME1 = MaIdCharStr.asMaId("ma-1-1");
+ private static final MepId MEPID1 = MepId.valueOf((short) 1);
+ private static final SoamId DM1 = SoamId.valueOf(1);
+ private static final SoamId DM2 = SoamId.valueOf(2);
+
+ private DelayMeasurementEntry dm1;
+ private DelayMeasurementEntry dm2;
+
+ private final Instant now = Instant.now();
+
+ @Before
+ public void setUpTest() throws CfmConfigException, SoamConfigException {
+ CfmCodecContext context = new CfmCodecContext();
+ ServiceDirectory testDirectory = new TestServiceDirectory()
+ .add(CfmMepService.class, mepService)
+ .add(SoamService.class, soamService)
+ .add(CodecService.class, context.codecManager());
+ BaseResource.setServiceDirectory(testDirectory);
+
+ DelayMeasurementStatCurrent.DmStatCurrentBuilder dmCurrBuilder1 =
+ (DelayMeasurementStatCurrent.DmStatCurrentBuilder)
+ DefaultDelayMeasurementStatCurrent
+ .builder(Duration.ofMinutes(1), false)
+ .startTime(now)
+ .frameDelayBackwardAvg(Duration.ofMillis(10))
+ .frameDelayForwardAvg(Duration.ofMillis(11))
+ .frameDelayRangeBackwardAvg(Duration.ofMillis(12));
+
+ dm1 = DefaultDelayMeasurementEntry.builder(DM1,
+ DelayMeasurementCreate.DmType.DMDMM,
+ DelayMeasurementCreate.Version.Y17312008,
+ MepId.valueOf((short) 2),
+ Mep.Priority.PRIO1)
+ .sessionStatus(DelayMeasurementEntry.SessionStatus.ACTIVE)
+ .frameDelayTwoWay(Duration.ofMillis(40))
+ .frameDelayBackward(Duration.ofMillis(30))
+ .frameDelayForward(Duration.ofMillis(10))
+ .interFrameDelayVariationTwoWay(Duration.ofMillis(8))
+ .interFrameDelayVariationBackward(Duration.ofMillis(3))
+ .interFrameDelayVariationForward(Duration.ofMillis(5))
+ .currentResult((DelayMeasurementStatCurrent) dmCurrBuilder1.build())
+ .build();
+
+ dm2 = DefaultDelayMeasurementEntry.builder(DM2,
+ DelayMeasurementCreate.DmType.DMDMM,
+ DelayMeasurementCreate.Version.Y17312011,
+ MepId.valueOf((short) 2),
+ Mep.Priority.PRIO2)
+ .build();
+ }
+
+ @Test
+ public void testGetAllDmsForMep() throws CfmConfigException, SoamConfigException {
+
+ List<DelayMeasurementEntry> dmList = new ArrayList<>();
+ dmList.add(dm1);
+ dmList.add(dm2);
+
+ expect(soamService.getAllDms(MDNAME1, MANAME1, MEPID1)).andReturn(dmList).anyTimes();
+ replay(soamService);
+
+ final WebTarget wt = target();
+ final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" +
+ MANAME1.maName() + "/mep/" + MEPID1.value() + "/dm")
+ .request().get(String.class);
+
+ assertThat(response, is("{\"dms\":[[" +
+ "{" +
+ "\"dmId\":\"1\"," +
+ "\"sessionStatus\":\"ACTIVE\"," +
+ "\"frameDelayTwoWay\":\"PT0.04S\"," +
+ "\"frameDelayForward\":\"PT0.01S\"," +
+ "\"frameDelayBackward\":\"PT0.03S\"," +
+ "\"interFrameDelayVariationTwoWay\":\"PT0.008S\"," +
+ "\"interFrameDelayVariationForward\":\"PT0.005S\"," +
+ "\"interFrameDelayVariationBackward\":\"PT0.003S\"," +
+ "\"dmCfgType\":\"DMDMM\"," +
+ "\"version\":\"Y17312008\"," +
+ "\"remoteMepId\":2," +
+ "\"priority\":\"PRIO1\"," +
+ "\"measurementsEnabled\":[]," +
+ "\"current\":{" +
+ "\"startTime\":\"" + now + "\"," +
+ "\"elapsedTime\":\"PT1M\"," +
+ "\"suspectStatus\":\"false\"," +
+ "\"frameDelayForwardAvg\":\"PT0.011S\"," +
+ "\"frameDelayBackwardAvg\":\"PT0.01S\"," +
+ "\"frameDelayRangeBackwardAvg\":\"PT0.012S\"" +
+ "}," +
+ "\"historic\":[]" +
+ "},{" +
+ "\"dmId\":\"2\"," +
+ "\"dmCfgType\":\"DMDMM\"," +
+ "\"version\":\"Y17312011\"," +
+ "\"remoteMepId\":2," +
+ "\"priority\":\"PRIO2\"," +
+ "\"measurementsEnabled\":[]," +
+ "\"historic\":[]}]]" +
+ "}"));
+ }
+
+ @Test
+ public void testGetAllDmsForMepEmpty() throws CfmConfigException, SoamConfigException {
+
+ List<DelayMeasurementEntry> dmListEmpty = new ArrayList<>();
+
+ expect(soamService.getAllDms(MDNAME1, MANAME1, MEPID1)).andReturn(dmListEmpty).anyTimes();
+ replay(soamService);
+
+ final WebTarget wt = target();
+ final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" +
+ MANAME1.maName() + "/mep/" + MEPID1.value() + "/dm")
+ .request().get(String.class);
+
+ assertThat(response, is("{\"dms\":[[]]}"));
+ }
+
+ @Test
+ public void testGetDm() throws CfmConfigException, SoamConfigException {
+
+ expect(soamService.getDm(MDNAME1, MANAME1, MEPID1, DM1)).andReturn(dm1).anyTimes();
+ replay(soamService);
+
+ final WebTarget wt = target();
+ final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" +
+ MANAME1.maName() + "/mep/" + MEPID1.value() + "/dm/" + DM1.value())
+ .request().get(String.class);
+
+ assertThat(response, is("{\"dm\":" +
+ "{" +
+ "\"dmId\":\"1\"," +
+ "\"sessionStatus\":\"ACTIVE\"," +
+ "\"frameDelayTwoWay\":\"PT0.04S\"," +
+ "\"frameDelayForward\":\"PT0.01S\"," +
+ "\"frameDelayBackward\":\"PT0.03S\"," +
+ "\"interFrameDelayVariationTwoWay\":\"PT0.008S\"," +
+ "\"interFrameDelayVariationForward\":\"PT0.005S\"," +
+ "\"interFrameDelayVariationBackward\":\"PT0.003S\"," +
+ "\"dmCfgType\":\"DMDMM\"," +
+ "\"version\":\"Y17312008\"," +
+ "\"remoteMepId\":2," +
+ "\"priority\":\"PRIO1\"," +
+ "\"measurementsEnabled\":[]," +
+ "\"current\":{" +
+ "\"startTime\":\"" + now + "\"," +
+ "\"elapsedTime\":\"PT1M\"," +
+ "\"suspectStatus\":\"false\"," +
+ "\"frameDelayForwardAvg\":\"PT0.011S\"," +
+ "\"frameDelayBackwardAvg\":\"PT0.01S\"," +
+ "\"frameDelayRangeBackwardAvg\":\"PT0.012S\"" +
+ "}," +
+ "\"historic\":[]" +
+ "}}"));
+ }
+
+ @Test
+ public void testGetDmInvalid() throws CfmConfigException, SoamConfigException, IOException {
+
+ SoamId dm3 = SoamId.valueOf(3);
+
+ expect(soamService.getDm(MDNAME1, MANAME1, MEPID1, dm3)).andReturn(null).anyTimes();
+ replay(soamService);
+
+ final WebTarget wt = target();
+ try {
+ final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" +
+ MANAME1.maName() + "/mep/" + MEPID1.value() + "/dm/" + dm3.value())
+ .request().get(String.class);
+ fail("Expecting excpetion");
+ } catch (InternalServerErrorException e) {
+ ByteArrayInputStream is = (ByteArrayInputStream) e.getResponse().getEntity();
+ BufferedReader br = new BufferedReader(new InputStreamReader(is));
+ String line = null;
+ StringBuffer sb = new StringBuffer();
+ while ((line = br.readLine()) != null) {
+ sb.append(line);
+ }
+ assertEquals("{ \"failure\":\"DM md-1/ma-1-1/1/3 not found\" }", sb.toString());
+ }
+ }
+
+ @Test
+ public void testAbortDm() {
+
+ final WebTarget wt = target();
+ final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" +
+ MANAME1.maName() + "/mep/" + MEPID1.value() + "/dm/" + DM1.value())
+ .request().delete();
+
+ assertEquals(200, response.getStatus());
+ }
+
+ @Test
+ public void testCreateDm() throws CfmConfigException, SoamConfigException {
+ MepEntry mep1 = DefaultMepEntry.builder(MEPID1, DeviceId.deviceId("netconf:1.2.3.4:830"),
+ PortNumber.portNumber(1), Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).buildEntry();
+
+ expect(mepService.getMep(MDNAME1, MANAME1, MEPID1)).andReturn(mep1).anyTimes();
+ replay(mepService);
+
+ ObjectMapper mapper = new ObjectMapper();
+ CfmCodecContext context = new CfmCodecContext();
+ ObjectNode node = mapper.createObjectNode();
+ node.set("dm", context.codec(DelayMeasurementCreate.class).encode(dm1, context));
+
+ final WebTarget wt = target();
+ final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" +
+ MANAME1.maName() + "/mep/" + MEPID1.value() + "/dm")
+ .request().post(Entity.json(node.toString()));
+
+ assertEquals(201, response.getStatus());
+ }
+
+ @Test
+ public void testClearDmHistory() {
+
+ final WebTarget wt = target();
+ final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" +
+ MANAME1.maName() + "/mep/" + MEPID1.value() + "/dm/" + DM1.value() +
+ "/clear-history")
+ .request().put(Entity.json(""));
+
+ assertEquals(200, response.getStatus());
+ }
+
+}
diff --git a/apps/cfm/src/test/java/org/onosproject/soam/impl/LmWebResourceTest.java b/apps/cfm/src/test/java/org/onosproject/soam/impl/LmWebResourceTest.java
new file mode 100644
index 0000000..9dd70e6
--- /dev/null
+++ b/apps/cfm/src/test/java/org/onosproject/soam/impl/LmWebResourceTest.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.soam.impl;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onlab.rest.BaseResource;
+import org.onosproject.cfm.CfmCodecContext;
+import org.onosproject.cfm.impl.CfmResourceTest;
+import org.onosproject.codec.CodecService;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
+import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
+import org.onosproject.incubator.net.l2monitoring.soam.MilliPct;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamService;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.DefaultLmEntry;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+public class LmWebResourceTest extends CfmResourceTest {
+ private final CfmMepService mepService = createMock(CfmMepService.class);
+ private final SoamService soamService = createMock(SoamService.class);
+
+ private static final MdId MDNAME1 = MdIdCharStr.asMdId("md-1");
+ private static final MaIdShort MANAME1 = MaIdCharStr.asMaId("ma-1-1");
+ private static final MepId MEPID1 = MepId.valueOf((short) 1);
+ private static final SoamId LMID1 = SoamId.valueOf(1);
+ private static final SoamId LMID2 = SoamId.valueOf(2);
+
+ private LossMeasurementEntry lm1;
+ private LossMeasurementEntry lm2;
+
+ private final Instant now = Instant.now();
+
+ @Before
+ public void setUpTest() throws CfmConfigException, SoamConfigException {
+ CfmCodecContext context = new CfmCodecContext();
+ ServiceDirectory testDirectory = new TestServiceDirectory()
+ .add(CfmMepService.class, mepService)
+ .add(SoamService.class, soamService)
+ .add(CodecService.class, context.codecManager());
+ BaseResource.setServiceDirectory(testDirectory);
+
+ lm1 = DefaultLmEntry.builder(
+ DelayMeasurementCreate.Version.Y17312008,
+ MepId.valueOf((short) 10),
+ Mep.Priority.PRIO1,
+ LossMeasurementCreate.LmType.LMLMM,
+ LMID1)
+ .build();
+ lm2 = DefaultLmEntry.builder(
+ DelayMeasurementCreate.Version.Y17312011,
+ MepId.valueOf((short) 10),
+ Mep.Priority.PRIO2,
+ LossMeasurementCreate.LmType.LMLMM,
+ LMID2)
+ .measuredAvailabilityBackwardStatus(LossMeasurementEntry.AvailabilityType.AVAILABLE)
+ .measuredAvailabilityForwardStatus(LossMeasurementEntry.AvailabilityType.UNKNOWN)
+ .measuredBackwardFlr(MilliPct.ofPercent(49.9f))
+ .measuredForwardFlr(MilliPct.ofRatio(0.51f))
+ .measuredBackwardLastTransitionTime(now)
+ .measuredForwardLastTransitionTime(now)
+ .build();
+
+ }
+
+ @Test
+ public void testGetAllLmsForMep() throws CfmConfigException, SoamConfigException {
+ List<LossMeasurementEntry> lmList = new ArrayList<>();
+ lmList.add(lm1);
+ lmList.add(lm2);
+
+ expect(soamService.getAllLms(MDNAME1, MANAME1, MEPID1)).andReturn(lmList).anyTimes();
+ replay(soamService);
+
+ final WebTarget wt = target();
+ final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" +
+ MANAME1.maName() + "/mep/" + MEPID1.value() + "/lm")
+ .request().get(String.class);
+
+ assertThat(response, is("{\"lms\":[[" +
+ "{" +
+ "\"lmId\":\"1\"," +
+ "\"lmCfgType\":\"LMLMM\"," +
+ "\"version\":\"Y17312008\"," +
+ "\"remoteMepId\":10," +
+ "\"priority\":\"PRIO1\"," +
+ "\"countersEnabled\":[]," +
+ "\"measurementHistories\":[]," +
+ "\"availabilityHistories\":[]" +
+ "},{" +
+ "\"lmId\":\"2\"," +
+ "\"measuredForwardFlr\":51.0," +
+ "\"measuredBackwardFlr\":49.9," +
+ "\"measuredAvailabilityForwardStatus\":\"UNKNOWN\"," +
+ "\"measuredAvailabilityBackwardStatus\":\"AVAILABLE\"," +
+ "\"measuredForwardLastTransitionTime\":\"" + now + "\"," +
+ "\"measuredBackwardLastTransitionTime\":\"" + now + "\"," +
+ "\"lmCfgType\":\"LMLMM\"," +
+ "\"version\":\"Y17312011\"," +
+ "\"remoteMepId\":10," +
+ "\"priority\":\"PRIO2\"," +
+ "\"countersEnabled\":[]," +
+ "\"measurementHistories\":[]," +
+ "\"availabilityHistories\":[]" +
+ "}]]}"));
+ }
+
+ @Test
+ public void testGetAllLmsForMepEmpty() throws CfmConfigException, SoamConfigException {
+ List<LossMeasurementEntry> lmList = new ArrayList<>();
+
+ expect(soamService.getAllLms(MDNAME1, MANAME1, MEPID1)).andReturn(lmList).anyTimes();
+ replay(soamService);
+
+ final WebTarget wt = target();
+ final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" +
+ MANAME1.maName() + "/mep/" + MEPID1.value() + "/lm")
+ .request().get(String.class);
+
+ assertThat(response, is("{\"lms\":[[]]}"));
+ }
+
+ @Test
+ public void testGetLm() throws CfmConfigException, SoamConfigException {
+
+ expect(soamService.getLm(MDNAME1, MANAME1, MEPID1, LMID1)).andReturn(lm1).anyTimes();
+ replay(soamService);
+
+ final WebTarget wt = target();
+ final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" +
+ MANAME1.maName() + "/mep/" + MEPID1.value() + "/lm/" + LMID1.value())
+ .request().get(String.class);
+
+ assertThat(response, is("{\"lm\":" +
+ "{" +
+ "\"lmId\":\"1\"," +
+ "\"lmCfgType\":\"LMLMM\"," +
+ "\"version\":\"Y17312008\"," +
+ "\"remoteMepId\":10," +
+ "\"priority\":\"PRIO1\"," +
+ "\"countersEnabled\":[]," +
+ "\"measurementHistories\":[]," +
+ "\"availabilityHistories\":[]" +
+ "}}"));
+ }
+
+ @Test
+ public void testGetLmEmpty() throws CfmConfigException, SoamConfigException, IOException {
+ SoamId lmId3 = SoamId.valueOf(3);
+ expect(soamService.getLm(MDNAME1, MANAME1, MEPID1, lmId3))
+ .andReturn(null).anyTimes();
+ replay(soamService);
+
+ final WebTarget wt = target();
+ try {
+ final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" +
+ MANAME1.maName() + "/mep/" + MEPID1.value() + "/lm/" + lmId3.value())
+ .request().get(String.class);
+ } catch (InternalServerErrorException e) {
+ ByteArrayInputStream is = (ByteArrayInputStream) e.getResponse().getEntity();
+ BufferedReader br = new BufferedReader(new InputStreamReader(is));
+ String line = null;
+ StringBuffer sb = new StringBuffer();
+ while ((line = br.readLine()) != null) {
+ sb.append(line);
+ }
+ assertEquals("{ \"failure\":\"LM md-1/ma-1-1/1/3 not found\" }",
+ sb.toString());
+ }
+ }
+
+ @Test
+ public void testAbortLm() {
+
+ final WebTarget wt = target();
+ final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" +
+ MANAME1.maName() + "/mep/" + MEPID1.value() + "/lm/" + LMID1.value())
+ .request().delete();
+ assertEquals(200, response.getStatus());
+ }
+
+ @Test
+ public void testCreateLm() throws CfmConfigException, SoamConfigException {
+ MepEntry mep1 = DefaultMepEntry.builder(MEPID1, DeviceId.deviceId("netconf:1.2.3.4:830"),
+ PortNumber.portNumber(1), Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).buildEntry();
+
+ expect(mepService.getMep(MDNAME1, MANAME1, MEPID1)).andReturn(mep1).anyTimes();
+ replay(mepService);
+
+ ObjectMapper mapper = new ObjectMapper();
+ CfmCodecContext context = new CfmCodecContext();
+ ObjectNode node = mapper.createObjectNode();
+ node.set("lm", context.codec(LossMeasurementCreate.class).encode(lm1, context));
+
+ final WebTarget wt = target();
+ final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" +
+ MANAME1.maName() + "/mep/" + MEPID1.value() + "/lm")
+ .request().post(Entity.json(node.toString()));
+ assertEquals(201, response.getStatus());
+ }
+
+ @Test
+ public void testClearLmHistory() {
+
+ final WebTarget wt = target();
+ final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" +
+ MANAME1.maName() + "/mep/" + MEPID1.value() + "/lm/" + LMID1.value() +
+ "/clear-history")
+ .request().put(Entity.json(""));
+
+ assertEquals(200, response.getStatus());
+ }
+}
diff --git a/apps/cfm/src/test/java/org/onosproject/soam/web/DmCreateCodecTest.java b/apps/cfm/src/test/java/org/onosproject/soam/web/DmCreateCodecTest.java
new file mode 100644
index 0000000..2f31310
--- /dev/null
+++ b/apps/cfm/src/test/java/org/onosproject/soam/web/DmCreateCodecTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.soam.web;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.time.Duration;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.cfm.CfmCodecContext;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmCreateBuilder;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmType;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+public class DmCreateCodecTest {
+ ObjectMapper mapper;
+ CfmCodecContext context;
+
+ @Before
+ public void setUp() throws Exception {
+ mapper = new ObjectMapper();
+ context = new CfmCodecContext();
+ }
+
+ @Test
+ public void testDecodeObjectNodeCodecContext1()
+ throws JsonProcessingException, IOException {
+ String moStr = "{\"dm\": {}}";
+
+ InputStream input = new ByteArrayInputStream(
+ moStr.getBytes(StandardCharsets.UTF_8));
+ JsonNode cfg = mapper.readTree(input);
+
+ try {
+ context.codec(DelayMeasurementCreate.class)
+ .decode((ObjectNode) cfg, context);
+ fail("Expecting an exception");
+ } catch (IllegalArgumentException e) {
+ assertEquals("remoteMepId is required", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testDecodeObjectNodeCodecContext2()
+ throws JsonProcessingException, IOException {
+ String moStr = "{\"dm\": {" +
+ "\"version\":\"Y17312008\"," +
+ "\"dmType\":\"DMDMM\"," +
+ "\"remoteMepId\":12," +
+ "\"priority\":\"PRIO6\"," +
+ "\"measurementsEnabled\" :" +
+ "[\"FRAME_DELAY_RANGE_BACKWARD_AVERAGE\", " +
+ "\"INTER_FRAME_DELAY_VARIATION_FORWARD_AVERAGE\"]" +
+ "}}";
+
+ InputStream input = new ByteArrayInputStream(
+ moStr.getBytes(StandardCharsets.UTF_8));
+ JsonNode cfg = mapper.readTree(input);
+
+ DelayMeasurementCreate dmCreate = context
+ .codec(DelayMeasurementCreate.class)
+ .decode((ObjectNode) cfg, context);
+
+ assertEquals(Version.Y17312008, dmCreate.version());
+ assertEquals(DmType.DMDMM, dmCreate.dmCfgType());
+ assertEquals(12, dmCreate.remoteMepId().id().shortValue());
+ }
+
+ @Test
+ public void testEncodeDelayMeasurementCreateCodecContext()
+ throws SoamConfigException {
+ DmCreateBuilder builder = DefaultDelayMeasurementCreate
+ .builder(DmType.DM1DMRX, Version.Y17312011,
+ MepId.valueOf((short) 16), Priority.PRIO5);
+ builder.addToMeasurementsEnabled(
+ MeasurementOption.FRAME_DELAY_BACKWARD_MAX);
+ builder.addToMeasurementsEnabled(
+ MeasurementOption.FRAME_DELAY_TWO_WAY_MAX);
+ builder.addToMeasurementsEnabled(
+ MeasurementOption.INTER_FRAME_DELAY_VARIATION_BACKWARD_BINS);
+ builder = (DmCreateBuilder) builder.messagePeriod(Duration.ofMillis(100));
+ builder = (DmCreateBuilder) builder.frameSize((short) 1200);
+
+ ObjectNode node = mapper.createObjectNode();
+ node.set("dm", context.codec(DelayMeasurementCreate.class)
+ .encode(builder.build(), context));
+
+ assertEquals(DmType.DM1DMRX.name(), node.get("dm").get("dmCfgType").asText());
+ assertEquals(Version.Y17312011.name(), node.get("dm").get("version").asText());
+ assertEquals(16, node.get("dm").get("remoteMepId").asInt());
+ assertEquals(Priority.PRIO5.name(), node.get("dm").get("priority").asText());
+ assertEquals(100, node.get("dm").get("messagePeriodMs").asInt());
+ assertEquals(1200, node.get("dm").get("frameSize").asInt());
+
+ assertEquals(3, ((ArrayNode) node.get("dm").get("measurementsEnabled")).size());
+ }
+
+}
diff --git a/apps/cfm/src/test/java/org/onosproject/soam/web/DmEntryCodecTest.java b/apps/cfm/src/test/java/org/onosproject/soam/web/DmEntryCodecTest.java
new file mode 100644
index 0000000..028fad8
--- /dev/null
+++ b/apps/cfm/src/test/java/org/onosproject/soam/web/DmEntryCodecTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.soam.web;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.cfm.CfmCodecContext;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementEntry;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmType;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry.DmEntryBuilder;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry.SessionStatus;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+public class DmEntryCodecTest {
+ ObjectMapper mapper;
+ CfmCodecContext context;
+ DelayMeasurementEntry dmEntry1;
+
+ @Before
+ public void setUp() throws Exception, SoamConfigException {
+ mapper = new ObjectMapper();
+ context = new CfmCodecContext();
+ DmEntryBuilder builder = DefaultDelayMeasurementEntry
+ .builder(SoamId.valueOf(12), DmType.DM1DMTX,
+ Version.Y17312008, MepId.valueOf((short) 10), Priority.PRIO4);
+ builder = builder.sessionStatus(SessionStatus.NOT_ACTIVE);
+ builder = builder.frameDelayTwoWay(Duration.ofNanos(101 * 1000));
+ builder = builder.frameDelayForward(Duration.ofNanos(102 * 1000));
+ builder = builder.frameDelayBackward(Duration.ofNanos(103 * 1000));
+ builder = builder.interFrameDelayVariationTwoWay(Duration.ofNanos(104 * 1000));
+ builder = builder.interFrameDelayVariationForward(Duration.ofNanos(105 * 1000));
+ builder = builder.interFrameDelayVariationBackward(Duration.ofNanos(106 * 1000));
+ builder.addToMeasurementsEnabled(MeasurementOption.FRAME_DELAY_BACKWARD_MAX);
+ builder.addToMeasurementsEnabled(MeasurementOption.FRAME_DELAY_TWO_WAY_MAX);
+ builder.addToMeasurementsEnabled(MeasurementOption.INTER_FRAME_DELAY_VARIATION_BACKWARD_BINS);
+
+ dmEntry1 = builder.build();
+ }
+
+ @Test
+ public void testEncodeDelayMeasurementEntryCodecContext()
+ throws JsonProcessingException, IOException {
+ ObjectNode node = mapper.createObjectNode();
+ node.set("dm", context.codec(DelayMeasurementEntry.class)
+ .encode(dmEntry1, context));
+
+ assertEquals(12, node.get("dm").get("dmId").asInt());
+ assertEquals(DmType.DM1DMTX.name(), node.get("dm").get("dmCfgType").asText());
+ assertEquals(Version.Y17312008.name(), node.get("dm").get("version").asText());
+ assertEquals(10, node.get("dm").get("remoteMepId").asInt());
+ assertEquals(3, ((ArrayNode) node.get("dm").get("measurementsEnabled")).size());
+
+ assertEquals(SessionStatus.NOT_ACTIVE.name(),
+ node.get("dm").get("sessionStatus").asText());
+ assertEquals("PT0.000101S",
+ node.get("dm").get("frameDelayTwoWay").asText());
+ assertEquals("PT0.000102S",
+ node.get("dm").get("frameDelayForward").asText());
+ assertEquals("PT0.000103S",
+ node.get("dm").get("frameDelayBackward").asText());
+ assertEquals("PT0.000104S",
+ node.get("dm").get("interFrameDelayVariationTwoWay").asText());
+ assertEquals("PT0.000105S",
+ node.get("dm").get("interFrameDelayVariationForward").asText());
+ assertEquals("PT0.000106S",
+ node.get("dm").get("interFrameDelayVariationBackward").asText());
+
+ }
+
+ @Test
+ public void testEncodeIterableOfDelayMeasurementEntryCodecContext()
+ throws SoamConfigException {
+ DmEntryBuilder builder2 = DefaultDelayMeasurementEntry
+ .builder(SoamId.valueOf(14), DmType.DM1DMRX,
+ Version.Y17312011, MepId.valueOf((short) 16), Priority.PRIO5);
+ builder2.addToMeasurementsEnabled(MeasurementOption.FRAME_DELAY_BACKWARD_MIN);
+ builder2.addToMeasurementsEnabled(MeasurementOption.FRAME_DELAY_TWO_WAY_MIN);
+ builder2.addToMeasurementsEnabled(MeasurementOption.INTER_FRAME_DELAY_VARIATION_BACKWARD_MIN);
+
+ Collection<DelayMeasurementEntry> dmEntries = new ArrayList<>();
+ dmEntries.add(dmEntry1);
+ dmEntries.add(builder2.build());
+ ObjectNode node = mapper.createObjectNode();
+ node.set("dm", context.codec(DelayMeasurementEntry.class)
+ .encode(dmEntries, context));
+
+ assertEquals(2, ((ArrayNode) node.get("dm")).size());
+ }
+
+}
diff --git a/apps/cfm/src/test/java/org/onosproject/soam/web/DmMeasurementOptionCodecTest.java b/apps/cfm/src/test/java/org/onosproject/soam/web/DmMeasurementOptionCodecTest.java
new file mode 100644
index 0000000..4986d5a
--- /dev/null
+++ b/apps/cfm/src/test/java/org/onosproject/soam/web/DmMeasurementOptionCodecTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.soam.web;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.cfm.CfmCodecContext;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+public class DmMeasurementOptionCodecTest {
+ ObjectMapper mapper;
+ CfmCodecContext context;
+
+ @Before
+ public void setUp() throws Exception {
+ mapper = new ObjectMapper();
+ context = new CfmCodecContext();
+ }
+
+ @Test
+ public void testEncodeIterableOfMeasurementOptionCodecContext() {
+ List<MeasurementOption> moList = new ArrayList<>();
+ moList.add(MeasurementOption.FRAME_DELAY_BACKWARD_MAX);
+ moList.add(MeasurementOption.FRAME_DELAY_FORWARD_BINS);
+
+ ArrayNode an =
+ context.codec(MeasurementOption.class).encode(moList, context);
+
+ assertEquals(MeasurementOption.FRAME_DELAY_BACKWARD_MAX.toString(),
+ an.get(0).asText());
+ assertEquals(MeasurementOption.FRAME_DELAY_FORWARD_BINS.toString(),
+ an.get(1).asText());
+ }
+
+ @Test
+ public void testDecodeArrayNodeCodecContext()
+ throws JsonProcessingException, IOException {
+ String moStr = "{\"measurementsEnabled\": " +
+ "[\"FRAME_DELAY_RANGE_BACKWARD_AVERAGE\", " +
+ "\"INTER_FRAME_DELAY_VARIATION_FORWARD_AVERAGE\"]}";
+ InputStream input = new ByteArrayInputStream(
+ moStr.getBytes(StandardCharsets.UTF_8));
+ JsonNode cfg = mapper.readTree(input);
+ Iterable<MeasurementOption> moIter = context
+ .codec(MeasurementOption.class)
+ .decode((ArrayNode) cfg.get("measurementsEnabled"), context);
+
+ Iterator<MeasurementOption> source = moIter.iterator();
+ List<MeasurementOption> moList = new ArrayList<>();
+ source.forEachRemaining(moList::add);
+
+ assertEquals(MeasurementOption.FRAME_DELAY_RANGE_BACKWARD_AVERAGE.toString(),
+ moList.get(0).name());
+ assertEquals(MeasurementOption.INTER_FRAME_DELAY_VARIATION_FORWARD_AVERAGE.toString(),
+ moList.get(1).name());
+ }
+
+}