Fix NoSuchElementException reported in ONOS-4763 and ONOS-4757
Change-Id: I973b6c33f02defac3463b6e53ea177056f1f9714
diff --git a/core/store/dist/src/main/java/org/onosproject/store/resource/impl/EncodableDiscreteResources.java b/core/store/dist/src/main/java/org/onosproject/store/resource/impl/EncodableDiscreteResources.java
index 7ec9de0..a6a7d08 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/resource/impl/EncodableDiscreteResources.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/resource/impl/EncodableDiscreteResources.java
@@ -98,14 +98,25 @@
public DiscreteResources difference(DiscreteResources other) {
if (other instanceof EncodableDiscreteResources) {
EncodableDiscreteResources cast = (EncodableDiscreteResources) other;
- Map<Class<?>, EncodedDiscreteResources> newMap =
- Stream.concat(this.map.entrySet().stream(), cast.map.entrySet().stream())
- .filter(entry -> this.map.containsKey(entry.getKey()))
- .collect(Collectors.toMap(
- Map.Entry::getKey,
- Map.Entry::getValue,
- EncodedDiscreteResources::difference,
- LinkedHashMap::new));
+
+ Map<Class<?>, EncodedDiscreteResources> newMap = new LinkedHashMap<>();
+ for (Class<?> key : this.map.keySet()) {
+ EncodedDiscreteResources thisValues = this.map.get(key);
+ if (!cast.map.containsKey(key)) {
+ newMap.put(key, thisValues);
+ continue;
+ }
+ EncodedDiscreteResources otherValues = cast.map.get(key);
+ EncodedDiscreteResources diff = thisValues.difference(otherValues);
+ // omit empty resources from a new resource set
+ // empty EncodedDiscreteResources can't deserialize due to
+ // inability to reproduce a Class<?> instance from the serialized data
+ if (diff.isEmpty()) {
+ continue;
+ }
+ newMap.put(key, diff);
+ }
+
return of(parent, newMap);
} else if (other instanceof EmptyDiscreteResources) {
return this;
diff --git a/core/store/dist/src/test/java/org/onosproject/store/resource/impl/EncodableDiscreteResourcesTest.java b/core/store/dist/src/test/java/org/onosproject/store/resource/impl/EncodableDiscreteResourcesTest.java
index 40f20b6..31285d94 100644
--- a/core/store/dist/src/test/java/org/onosproject/store/resource/impl/EncodableDiscreteResourcesTest.java
+++ b/core/store/dist/src/test/java/org/onosproject/store/resource/impl/EncodableDiscreteResourcesTest.java
@@ -18,16 +18,19 @@
import com.google.common.collect.ImmutableSet;
import org.junit.Test;
+import org.onlab.packet.VlanId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.resource.DiscreteResource;
import org.onosproject.net.resource.Resources;
import org.onosproject.store.service.Serializer;
+import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
+import java.util.stream.Stream;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
@@ -83,6 +86,30 @@
}
@Test
+ public void testSerializeInstanceContainingEmptyEncodedDiscreteResources() {
+ DiscreteResource device = Resources.discrete(DeviceId.deviceId("a")).resource();
+ List<PortNumber> ports = IntStream.range(0, 1)
+ .mapToObj(PortNumber::portNumber)
+ .collect(Collectors.toList());
+ List<VlanId> vlans = IntStream.range(0, 2)
+ .mapToObj(x -> VlanId.vlanId((short) x))
+ .collect(Collectors.toList());
+
+ Set<DiscreteResource> originalResources = Stream.concat(ports.stream(), vlans.stream())
+ .map(device::child)
+ .collect(Collectors.toSet());
+ DiscreteResources sut = EncodableDiscreteResources.of(originalResources);
+
+ Set<DiscreteResource> portOnlyResources = ports.stream().map(device::child).collect(Collectors.toSet());
+ DiscreteResources other = EncodableDiscreteResources.of(portOnlyResources);
+
+ DiscreteResources diff = sut.difference(other);
+
+ byte[] bytes = serializer.encode(diff);
+ assertThat(serializer.decode(bytes), is(diff));
+ }
+
+ @Test
public void testIfDifferenceIsNotEmpty() {
DiscreteResource res1 = Resources.discrete(DeviceId.deviceId("a"), PortNumber.portNumber(1)).resource();
DiscreteResource res2 = Resources.discrete(DeviceId.deviceId("a"), PortNumber.portNumber(2)).resource();