mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-21 20:31:00 +02:00
[ONOS-4016] Add Region codec with unit test for Region REST API
Change-Id: Ib7d6daa3adf8b23bea681e7bd3ef64839be65d13
This commit is contained in:
parent
8b0fdaafe9
commit
b68b9a8177
@ -58,6 +58,7 @@ import org.onosproject.net.mcast.McastRoute;
|
|||||||
import org.onosproject.net.meter.Band;
|
import org.onosproject.net.meter.Band;
|
||||||
import org.onosproject.net.meter.Meter;
|
import org.onosproject.net.meter.Meter;
|
||||||
import org.onosproject.net.meter.MeterRequest;
|
import org.onosproject.net.meter.MeterRequest;
|
||||||
|
import org.onosproject.net.region.Region;
|
||||||
import org.onosproject.net.statistic.Load;
|
import org.onosproject.net.statistic.Load;
|
||||||
import org.onosproject.net.topology.Topology;
|
import org.onosproject.net.topology.Topology;
|
||||||
import org.onosproject.net.topology.TopologyCluster;
|
import org.onosproject.net.topology.TopologyCluster;
|
||||||
@ -121,6 +122,7 @@ public class CodecManager implements CodecService {
|
|||||||
registerCodec(NextObjective.class, new NextObjectiveCodec());
|
registerCodec(NextObjective.class, new NextObjectiveCodec());
|
||||||
registerCodec(McastRoute.class, new McastRouteCodec());
|
registerCodec(McastRoute.class, new McastRouteCodec());
|
||||||
registerCodec(DeviceKey.class, new DeviceKeyCodec());
|
registerCodec(DeviceKey.class, new DeviceKeyCodec());
|
||||||
|
registerCodec(Region.class, new RegionCodec());
|
||||||
log.info("Started");
|
log.info("Started");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 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.codec.impl;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import com.google.common.collect.BiMap;
|
||||||
|
import com.google.common.collect.HashBiMap;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import org.onosproject.cluster.NodeId;
|
||||||
|
import org.onosproject.codec.CodecContext;
|
||||||
|
import org.onosproject.codec.JsonCodec;
|
||||||
|
import org.onosproject.net.region.DefaultRegion;
|
||||||
|
import org.onosproject.net.region.Region;
|
||||||
|
import org.onosproject.net.region.RegionId;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.onlab.util.Tools.nullIsIllegal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Codec for the Region class.
|
||||||
|
*/
|
||||||
|
public class RegionCodec extends JsonCodec<Region> {
|
||||||
|
|
||||||
|
// JSON field names
|
||||||
|
private static final String REGION_ID = "id";
|
||||||
|
private static final String NAME = "name";
|
||||||
|
private static final String TYPE = "type";
|
||||||
|
private static final String MASTERS = "masters";
|
||||||
|
private static final String NODE_ID = "nodeId";
|
||||||
|
private static final String REGION_NOT_NULL_MSG = "Region cannot be null";
|
||||||
|
private static final String MISSING_MEMBER_MESSAGE = " member is required in Region";
|
||||||
|
|
||||||
|
private static final BiMap<String, Region.Type> REGION_TYPE_MAP = HashBiMap.create();
|
||||||
|
|
||||||
|
static {
|
||||||
|
// key is String representation of Region.Type
|
||||||
|
// value is Region.Type
|
||||||
|
REGION_TYPE_MAP.put("CONTINENT", Region.Type.CONTINENT);
|
||||||
|
REGION_TYPE_MAP.put("COUNTRY", Region.Type.COUNTRY);
|
||||||
|
REGION_TYPE_MAP.put("METRO", Region.Type.METRO);
|
||||||
|
REGION_TYPE_MAP.put("CAMPUS", Region.Type.CAMPUS);
|
||||||
|
REGION_TYPE_MAP.put("BUILDING", Region.Type.BUILDING);
|
||||||
|
REGION_TYPE_MAP.put("FLOOR", Region.Type.FLOOR);
|
||||||
|
REGION_TYPE_MAP.put("ROOM", Region.Type.ROOM);
|
||||||
|
REGION_TYPE_MAP.put("RACK", Region.Type.RACK);
|
||||||
|
REGION_TYPE_MAP.put("LOGICAL_GROUP", Region.Type.LOGICAL_GROUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectNode encode(Region region, CodecContext context) {
|
||||||
|
checkNotNull(region, REGION_NOT_NULL_MSG);
|
||||||
|
|
||||||
|
ObjectNode result = context.mapper().createObjectNode()
|
||||||
|
.put(REGION_ID, region.id().toString())
|
||||||
|
.put(NAME, region.name())
|
||||||
|
.put(TYPE, region.type().toString());
|
||||||
|
|
||||||
|
ArrayNode masters = context.mapper().createArrayNode();
|
||||||
|
|
||||||
|
region.masters().forEach(sets -> {
|
||||||
|
ArrayNode setsJson = context.mapper().createArrayNode();
|
||||||
|
sets.forEach(nodeId -> setsJson.add(nodeId.toString()));
|
||||||
|
masters.add(setsJson);
|
||||||
|
});
|
||||||
|
result.set(MASTERS, masters);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Region decode(ObjectNode json, CodecContext context) {
|
||||||
|
if (json == null || !json.isObject()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse masters
|
||||||
|
List<Set<NodeId>> masters = new ArrayList<>();
|
||||||
|
JsonNode mastersJson = json.get(MASTERS);
|
||||||
|
checkNotNull(mastersJson);
|
||||||
|
|
||||||
|
if (mastersJson != null) {
|
||||||
|
IntStream.range(0, mastersJson.size()).forEach(i -> {
|
||||||
|
ObjectNode setsJson = get(mastersJson, i);
|
||||||
|
final Set<NodeId> nodeIds = Sets.newHashSet();
|
||||||
|
if (setsJson != null && setsJson.isArray()) {
|
||||||
|
Set<NodeId> localNodeIds = Sets.newHashSet();
|
||||||
|
IntStream.range(0, mastersJson.size()).forEach(j -> {
|
||||||
|
ObjectNode nodeIdJson = get(setsJson, j);
|
||||||
|
localNodeIds.add(decodeNodeId(nodeIdJson));
|
||||||
|
});
|
||||||
|
nodeIds.addAll(localNodeIds);
|
||||||
|
}
|
||||||
|
masters.add(nodeIds);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse region id
|
||||||
|
RegionId regionId = RegionId.regionId(nullIsIllegal(json.get(REGION_ID),
|
||||||
|
REGION_ID + MISSING_MEMBER_MESSAGE).asText());
|
||||||
|
|
||||||
|
// parse region name
|
||||||
|
String name = nullIsIllegal(json.get(NAME), NAME +
|
||||||
|
MISSING_MEMBER_MESSAGE).asText();
|
||||||
|
|
||||||
|
// parse region type
|
||||||
|
String typeText = nullIsIllegal(json.get(TYPE), TYPE +
|
||||||
|
MISSING_MEMBER_MESSAGE).asText();
|
||||||
|
|
||||||
|
Region.Type type = REGION_TYPE_MAP.get(typeText);
|
||||||
|
|
||||||
|
return new DefaultRegion(regionId, name, type, masters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes node id json to node id object.
|
||||||
|
*
|
||||||
|
* @param json json object
|
||||||
|
* @return decoded node id object
|
||||||
|
*/
|
||||||
|
private NodeId decodeNodeId(ObjectNode json) {
|
||||||
|
NodeId nodeId = NodeId.nodeId(nullIsIllegal(json, NODE_ID +
|
||||||
|
MISSING_MEMBER_MESSAGE).asText());
|
||||||
|
|
||||||
|
return nodeId;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 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.codec.impl;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import org.hamcrest.MatcherAssert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.onosproject.cluster.NodeId;
|
||||||
|
import org.onosproject.codec.JsonCodec;
|
||||||
|
import org.onosproject.core.CoreService;
|
||||||
|
import org.onosproject.net.region.DefaultRegion;
|
||||||
|
import org.onosproject.net.region.Region;
|
||||||
|
import org.onosproject.net.region.RegionId;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.easymock.EasyMock.createMock;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.onosproject.codec.impl.RegionJsonMatcher.matchesRegion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for region codec.
|
||||||
|
*/
|
||||||
|
public class RegionCodecTest {
|
||||||
|
|
||||||
|
MockCodecContext context;
|
||||||
|
JsonCodec<Region> regionCodec;
|
||||||
|
final CoreService mockCoreService = createMock(CoreService.class);
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
context = new MockCodecContext();
|
||||||
|
regionCodec = context.codec(Region.class);
|
||||||
|
assertThat(regionCodec, notNullValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests encoding of a Region object.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRegionEncode() {
|
||||||
|
NodeId nodeId1 = NodeId.nodeId("1");
|
||||||
|
NodeId nodeId2 = NodeId.nodeId("2");
|
||||||
|
NodeId nodeId3 = NodeId.nodeId("3");
|
||||||
|
NodeId nodeId4 = NodeId.nodeId("4");
|
||||||
|
|
||||||
|
Set<NodeId> set1 = ImmutableSet.of(nodeId1);
|
||||||
|
Set<NodeId> set2 = ImmutableSet.of(nodeId1, nodeId2);
|
||||||
|
Set<NodeId> set3 = ImmutableSet.of(nodeId1, nodeId2, nodeId3);
|
||||||
|
Set<NodeId> set4 = ImmutableSet.of(nodeId1, nodeId2, nodeId3, nodeId4);
|
||||||
|
List<Set<NodeId>> masters = ImmutableList.of(set1, set2, set3, set4);
|
||||||
|
|
||||||
|
RegionId regionId = RegionId.regionId("1");
|
||||||
|
String name = "foo";
|
||||||
|
Region.Type type = Region.Type.ROOM;
|
||||||
|
|
||||||
|
Region region = new DefaultRegion(regionId, name, type, masters);
|
||||||
|
|
||||||
|
ObjectNode regionJson = regionCodec.encode(region, context);
|
||||||
|
assertThat(regionJson, matchesRegion(region));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests decoding of a json object.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRegionDecode() throws IOException {
|
||||||
|
Region region = getRegion("Region.json");
|
||||||
|
checkCommonData(region);
|
||||||
|
|
||||||
|
assertThat(region.masters().size(), is(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that the data shared by all the resource is correct for a given region.
|
||||||
|
*
|
||||||
|
* @param region region to check
|
||||||
|
*/
|
||||||
|
private void checkCommonData(Region region) {
|
||||||
|
assertThat(region.id().toString(), is("1"));
|
||||||
|
assertThat(region.type().toString(), is("ROOM"));
|
||||||
|
assertThat(region.name(), is("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads in a region from the given resource and decodes it.
|
||||||
|
*
|
||||||
|
* @param resourceName resource to use to read the JSON for the rule
|
||||||
|
* @return decoded region
|
||||||
|
* @throws IOException if processing the resource fails
|
||||||
|
*/
|
||||||
|
private Region getRegion(String resourceName) throws IOException {
|
||||||
|
InputStream jsonStream = RegionCodecTest.class.getResourceAsStream(resourceName);
|
||||||
|
JsonNode json = context.mapper().readTree(jsonStream);
|
||||||
|
MatcherAssert.assertThat(json, notNullValue());
|
||||||
|
Region region = regionCodec.decode((ObjectNode) json, context);
|
||||||
|
assertThat(region, notNullValue());
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 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.codec.impl;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import org.hamcrest.Description;
|
||||||
|
import org.hamcrest.TypeSafeDiagnosingMatcher;
|
||||||
|
import org.onosproject.net.region.Region;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hamcrest matcher for region.
|
||||||
|
*/
|
||||||
|
public final class RegionJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
|
||||||
|
|
||||||
|
private final Region region;
|
||||||
|
|
||||||
|
private RegionJsonMatcher(Region region) {
|
||||||
|
this.region = region;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean matchesSafely(JsonNode jsonRegion, Description description) {
|
||||||
|
// check id
|
||||||
|
String jsonRegionId = jsonRegion.get("id").asText();
|
||||||
|
String regionId = region.id().toString();
|
||||||
|
if (!jsonRegionId.equals(regionId)) {
|
||||||
|
description.appendText("region id was " + jsonRegionId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check type
|
||||||
|
String jsonType = jsonRegion.get("type").asText();
|
||||||
|
String type = region.type().toString();
|
||||||
|
if (!jsonType.equals(type)) {
|
||||||
|
description.appendText("type was " + jsonType);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check name
|
||||||
|
String jsonName = jsonRegion.get("name").asText();
|
||||||
|
String name = region.name();
|
||||||
|
if (!jsonName.equals(name)) {
|
||||||
|
description.appendText("name was " + jsonName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check size of master array
|
||||||
|
JsonNode jsonMasters = jsonRegion.get("masters");
|
||||||
|
if (jsonMasters.size() != region.masters().size()) {
|
||||||
|
description.appendText("masters size was " + jsonMasters.size());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check the content inside masters
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void describeTo(Description description) {
|
||||||
|
description.appendText(region.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory to allocate a region matcher.
|
||||||
|
*
|
||||||
|
* @param region region object we are looking for
|
||||||
|
* @return matcher
|
||||||
|
*/
|
||||||
|
public static RegionJsonMatcher matchesRegion(Region region) {
|
||||||
|
return new RegionJsonMatcher(region);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"type": "ROOM",
|
||||||
|
"name": "foo",
|
||||||
|
"masters": [
|
||||||
|
[
|
||||||
|
"1"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"1", "2"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user