From c0496e36b3b6ae89ca8e90b8da3527dc8b0494a9 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Mon, 25 Apr 2022 17:26:31 +0200 Subject: [PATCH] Seal YangInstanceIdentifier We only allow two implementations, make sure we express that to the runtime. Change-Id: I3e4f2208d30682a9a0d23d2e1114d9d5d790e9b7 Signed-off-by: Robert Varga --- .../yang/data/api/YangInstanceIdentifier.java | 19 ++--- .../tree/spi/DataTreeCandidateNodesTest.java | 24 +++---- .../data/tree/spi/DataTreeCandidatesTest.java | 69 ++++++++----------- 3 files changed, 47 insertions(+), 65 deletions(-) diff --git a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/YangInstanceIdentifier.java b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/YangInstanceIdentifier.java index f0d9627fe8..e45d760faa 100644 --- a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/YangInstanceIdentifier.java +++ b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/YangInstanceIdentifier.java @@ -75,8 +75,8 @@ import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; * * @see RFC6020 */ -// FIXME: sealed once we have JDK17+ -public abstract class YangInstanceIdentifier implements HierarchicalIdentifier { +public abstract sealed class YangInstanceIdentifier implements HierarchicalIdentifier + permits FixedYangInstanceIdentifier, StackedYangInstanceIdentifier { private static final long serialVersionUID = 4L; private static final VarHandle TO_STRING_CACHE; private static final VarHandle HASH; @@ -233,7 +233,7 @@ public abstract class YangInstanceIdentifier implements HierarchicalIdentifier otherChildNames = other.getPossibleChildNames(); int thisSize = childNames.size(); int otherSize = otherChildNames.size(); diff --git a/data/yang-data-tree-spi/src/test/java/org/opendaylight/yangtools/yang/data/tree/spi/DataTreeCandidateNodesTest.java b/data/yang-data-tree-spi/src/test/java/org/opendaylight/yangtools/yang/data/tree/spi/DataTreeCandidateNodesTest.java index 0c8bfcc219..c664b682b1 100644 --- a/data/yang-data-tree-spi/src/test/java/org/opendaylight/yangtools/yang/data/tree/spi/DataTreeCandidateNodesTest.java +++ b/data/yang-data-tree-spi/src/test/java/org/opendaylight/yangtools/yang/data/tree/spi/DataTreeCandidateNodesTest.java @@ -18,10 +18,11 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import java.util.Collection; import java.util.List; import java.util.Optional; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -29,6 +30,7 @@ import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateNode; import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModificationCursor; import org.opendaylight.yangtools.yang.data.tree.api.ModificationType; +@RunWith(MockitoJUnitRunner.StrictStubs.class) public class DataTreeCandidateNodesTest { @Test public void testFromNormalizedNode() { @@ -80,9 +82,8 @@ public class DataTreeCandidateNodesTest { doReturn(ModificationType.DELETE).when(mockedChildNode3ChildNode).getModificationType(); doReturn(List.of(mockedChildNode3ChildNode)).when(mockedChildNode3).getChildNodes(); - final Collection childNodes = List.of(mockedChildNode1, mockedChildNode2, - mockedChildNode3); - doReturn(childNodes).when(mockedDataTreeCandidateNode).getChildNodes(); + doReturn(List.of(mockedChildNode1, mockedChildNode2, mockedChildNode3)) + .when(mockedDataTreeCandidateNode).getChildNodes(); DataTreeCandidateNodes.applyToCursor(mockedCursor, mockedDataTreeCandidateNode); verify(mockedCursor, times(2)).enter((PathArgument) isNull()); @@ -104,31 +105,30 @@ public class DataTreeCandidateNodesTest { @Test public void testApplyRootedNodeToCursorWithWriteModificationType() { final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class); - final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class); final DataTreeModificationCursor mockedCursor = mock(DataTreeModificationCursor.class); doReturn(ModificationType.WRITE).when(mockedDataTreeCandidateNode).getModificationType(); final NormalizedNode mockedNormalizedNode = mock(NormalizedNode.class); doReturn(Optional.of(mockedNormalizedNode)).when(mockedDataTreeCandidateNode).getDataAfter(); - DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, mockedRootPath, mockedDataTreeCandidateNode); + DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, YangInstanceIdentifier.empty(), + mockedDataTreeCandidateNode); verify(mockedCursor, times(1)).write(isNull(), any(NormalizedNode.class)); } @Test public void testApplyRootedNodeToCursorWithDeleteModificationType() { final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class); - final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class); final DataTreeModificationCursor mockedCursor = mock(DataTreeModificationCursor.class); doReturn(ModificationType.DELETE).when(mockedDataTreeCandidateNode).getModificationType(); - DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, mockedRootPath, mockedDataTreeCandidateNode); + DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, YangInstanceIdentifier.empty(), + mockedDataTreeCandidateNode); verify(mockedCursor, times(1)).delete(isNull()); } @Test public void testApplyRootedNodeToCursorWithSubtreeModifiedModificationType() { final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class); - final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class); final DataTreeModificationCursor mockedCursor = mock(DataTreeModificationCursor.class); doReturn(ModificationType.SUBTREE_MODIFIED).when(mockedDataTreeCandidateNode).getModificationType(); @@ -137,7 +137,8 @@ public class DataTreeCandidateNodesTest { doReturn(ModificationType.DELETE).when(mockedChildNode1).getModificationType(); doReturn(List.of(mockedChildNode1)).when(mockedDataTreeCandidateNode).getChildNodes(); - DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, mockedRootPath, mockedDataTreeCandidateNode); + DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, YangInstanceIdentifier.empty(), + mockedDataTreeCandidateNode); verify(mockedCursor, times(1)).enter((PathArgument) isNull()); verify(mockedCursor, times(1)).delete(isNull()); } @@ -145,12 +146,11 @@ public class DataTreeCandidateNodesTest { @Test public void testApplyRootedNodeToCursorWithUnsupportedModificationType() { final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class); - final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class); final DataTreeModificationCursor mockedCursor = mock(DataTreeModificationCursor.class); doReturn(ModificationType.APPEARED).when(mockedDataTreeCandidateNode).getModificationType(); final IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, - () -> DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, mockedRootPath, + () -> DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, YangInstanceIdentifier.empty(), mockedDataTreeCandidateNode)); assertThat(ex.getMessage(), containsString("Unsupported modification")); } diff --git a/data/yang-data-tree-spi/src/test/java/org/opendaylight/yangtools/yang/data/tree/spi/DataTreeCandidatesTest.java b/data/yang-data-tree-spi/src/test/java/org/opendaylight/yangtools/yang/data/tree/spi/DataTreeCandidatesTest.java index 561004f72c..5be065cb40 100644 --- a/data/yang-data-tree-spi/src/test/java/org/opendaylight/yangtools/yang/data/tree/spi/DataTreeCandidatesTest.java +++ b/data/yang-data-tree-spi/src/test/java/org/opendaylight/yangtools/yang/data/tree/spi/DataTreeCandidatesTest.java @@ -8,11 +8,11 @@ package org.opendaylight.yangtools.yang.data.tree.spi; import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doReturn; @@ -23,7 +23,11 @@ import static org.mockito.Mockito.verify; import java.util.List; import java.util.Optional; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; +import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.tree.api.CursorAwareDataTreeModification; @@ -33,34 +37,32 @@ import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification; import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModificationCursor; import org.opendaylight.yangtools.yang.data.tree.api.ModificationType; +@RunWith(MockitoJUnitRunner.StrictStubs.class) public class DataTreeCandidatesTest { + private static final NodeIdentifier FOO = new NodeIdentifier(QName.create("foo", "foo")); @Test public void testNewDataTreeCandidate() { - final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class); final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class); - final DataTreeCandidate dataTreeCandidate = DataTreeCandidates.newDataTreeCandidate(mockedRootPath, - mockedDataTreeCandidateNode); + final DataTreeCandidate dataTreeCandidate = DataTreeCandidates.newDataTreeCandidate( + YangInstanceIdentifier.empty(), mockedDataTreeCandidateNode); - assertNotNull(dataTreeCandidate); - assertTrue(dataTreeCandidate instanceof DefaultDataTreeCandidate); - assertEquals(mockedRootPath, dataTreeCandidate.getRootPath()); + assertThat(dataTreeCandidate, instanceOf(DefaultDataTreeCandidate.class)); + assertSame(YangInstanceIdentifier.empty(), dataTreeCandidate.getRootPath()); assertEquals(mockedDataTreeCandidateNode, dataTreeCandidate.getRootNode()); - assertTrue(dataTreeCandidate.toString().contains( - "DefaultDataTreeCandidate{rootPath=/, rootNode=Mock for DataTreeCandidateNode, hashCode: ")); + assertThat(dataTreeCandidate.toString(), + containsString("DefaultDataTreeCandidate{rootPath=/, rootNode=Mock for DataTreeCandidateNode, hashCode: ")); } @Test public void testFromNormalizedNode() { - final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class); final NormalizedNode mockedNormalizedNode = mock(NormalizedNode.class); - final DataTreeCandidate dataTreeCandidate = DataTreeCandidates.fromNormalizedNode(mockedRootPath, - mockedNormalizedNode); + final DataTreeCandidate dataTreeCandidate = DataTreeCandidates.fromNormalizedNode( + YangInstanceIdentifier.empty(), mockedNormalizedNode); - assertNotNull(dataTreeCandidate); - assertTrue(dataTreeCandidate instanceof DefaultDataTreeCandidate); - assertEquals(mockedRootPath, dataTreeCandidate.getRootPath()); - assertTrue(dataTreeCandidate.getRootNode() instanceof NormalizedNodeDataTreeCandidateNode); + assertThat(dataTreeCandidate, instanceOf(DefaultDataTreeCandidate.class)); + assertSame(YangInstanceIdentifier.empty(), dataTreeCandidate.getRootPath()); + assertThat(dataTreeCandidate.getRootNode(), instanceOf(NormalizedNodeDataTreeCandidateNode.class)); } @Test @@ -80,32 +82,26 @@ public class DataTreeCandidatesTest { final DataTreeCandidate mockedDataTreeCandidate = mock(DataTreeCandidate.class); final CursorAwareDataTreeModification mockedModification = mock(CursorAwareDataTreeModification.class); - final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class); - doReturn(mockedRootPath).when(mockedDataTreeCandidate).getRootPath(); - final YangInstanceIdentifier mockedRootPathParent = mock(YangInstanceIdentifier.class); - doReturn(mockedRootPathParent).when(mockedRootPath).getParent(); + doReturn(YangInstanceIdentifier.create(FOO)).when(mockedDataTreeCandidate).getRootPath(); final DataTreeModificationCursor mockedCursor = mock(DataTreeModificationCursor.class); - doReturn(Optional.of(mockedCursor)).when(mockedModification).openCursor(mockedRootPathParent); + doReturn(Optional.of(mockedCursor)).when(mockedModification).openCursor(YangInstanceIdentifier.empty()); final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class); doReturn(mockedDataTreeCandidateNode).when(mockedDataTreeCandidate).getRootNode(); doReturn(ModificationType.DELETE).when(mockedDataTreeCandidateNode).getModificationType(); DataTreeCandidates.applyToModification(mockedModification, mockedDataTreeCandidate); - verify(mockedRootPath, times(1)).getParent(); - verify(mockedModification, times(1)).openCursor(mockedRootPathParent); - verify(mockedCursor, times(1)).delete(isNull()); + verify(mockedModification, times(1)).openCursor(YangInstanceIdentifier.empty()); + verify(mockedCursor, times(1)).delete(FOO); } @Test public void testApplyToCursorAwareModificationRoot() { final DataTreeCandidate mockedDataTreeCandidate = mock(DataTreeCandidate.class); final CursorAwareDataTreeModification mockedModification = mock(CursorAwareDataTreeModification.class); - final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class); final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class); - doReturn(mockedRootPath).when(mockedDataTreeCandidate).getRootPath(); - doReturn(null).when(mockedRootPath).getParent(); + doReturn(YangInstanceIdentifier.empty()).when(mockedDataTreeCandidate).getRootPath(); doReturn(mockedDataTreeCandidateNode).when(mockedDataTreeCandidate).getRootNode(); doReturn(ModificationType.DELETE).when(mockedDataTreeCandidateNode).getModificationType(); @@ -121,13 +117,12 @@ public class DataTreeCandidatesTest { final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class); doReturn(mockedDataTreeCandidateNode).when(mockedDataTreeCandidate).getRootNode(); - final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class); - doReturn(mockedRootPath).when(mockedDataTreeCandidate).getRootPath(); + doReturn(YangInstanceIdentifier.empty()).when(mockedDataTreeCandidate).getRootPath(); doReturn(ModificationType.DELETE).when(mockedDataTreeCandidateNode).getModificationType(); DataTreeCandidates.applyToModification(mockedModification, mockedDataTreeCandidate); - verify(mockedModification, times(1)).delete(any(YangInstanceIdentifier.class)); + verify(mockedModification, times(1)).delete(YangInstanceIdentifier.empty()); } @Test @@ -137,8 +132,7 @@ public class DataTreeCandidatesTest { final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class); doReturn(mockedDataTreeCandidateNode).when(mockedDataTreeCandidate).getRootNode(); - final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class); - doReturn(mockedRootPath).when(mockedDataTreeCandidate).getRootPath(); + doReturn(YangInstanceIdentifier.empty()).when(mockedDataTreeCandidate).getRootPath(); final NormalizedNode mockedNormalizedNode = mock(NormalizedNode.class); doReturn(Optional.of(mockedNormalizedNode)).when(mockedDataTreeCandidateNode).getDataAfter(); @@ -155,8 +149,7 @@ public class DataTreeCandidatesTest { final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class); doReturn(mockedDataTreeCandidateNode).when(mockedDataTreeCandidate).getRootNode(); - final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class); - doReturn(mockedRootPath).when(mockedDataTreeCandidate).getRootPath(); + doReturn(YangInstanceIdentifier.empty()).when(mockedDataTreeCandidate).getRootPath(); doReturn(ModificationType.SUBTREE_MODIFIED).when(mockedDataTreeCandidateNode).getModificationType(); @@ -174,11 +167,10 @@ public class DataTreeCandidatesTest { final DataTreeCandidateNode mockedChildNode3 = mock(DataTreeCandidateNode.class); doReturn(ModificationType.SUBTREE_MODIFIED).when(mockedChildNode3).getModificationType(); - final PathArgument mockedPathArgument3 = mock(PathArgument.class); - doReturn(mockedPathArgument3).when(mockedChildNode3).getIdentifier(); final DataTreeCandidateNode mockedChildNode3ChildNode = mock(DataTreeCandidateNode.class); doReturn(ModificationType.DELETE).when(mockedChildNode3ChildNode).getModificationType(); final PathArgument mockedPathArgument31 = mock(PathArgument.class); + final PathArgument mockedPathArgument3 = mock(PathArgument.class); doReturn(mockedPathArgument3).when(mockedChildNode3).getIdentifier(); doReturn(mockedPathArgument31).when(mockedChildNode3ChildNode).getIdentifier(); doReturn(List.of(mockedChildNode3ChildNode)).when(mockedChildNode3).getChildNodes(); @@ -198,8 +190,7 @@ public class DataTreeCandidatesTest { final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class); doReturn(mockedDataTreeCandidateNode).when(mockedDataTreeCandidate).getRootNode(); - final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class); - doReturn(mockedRootPath).when(mockedDataTreeCandidate).getRootPath(); + doReturn(YangInstanceIdentifier.empty()).when(mockedDataTreeCandidate).getRootPath(); doReturn(ModificationType.APPEARED).when(mockedDataTreeCandidateNode).getModificationType(); -- 2.36.6