Merge "BUG-5006: rework SouthboundProviderTest, clean up"
authorSam Hague <shague@redhat.com>
Fri, 19 Feb 2016 17:16:22 +0000 (17:16 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 19 Feb 2016 17:16:22 +0000 (17:16 +0000)
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManager.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbDataChangeListener.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundProvider.java
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/SouthboundMapperTest.java
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/SouthboundProviderTest.java

index 5c9c121b6e6871e1868be9af24be1e22529ae3f9..153bab5fc3fa3955d7f1582413b50c73c26fb840 100644 (file)
@@ -212,7 +212,7 @@ public class OvsdbConnectionManager implements OvsdbConnectionListener, AutoClos
     }
 */
     @Override
-    public void close() throws Exception {
+    public void close() {
         if (ovsdbDeviceEntityOwnershipListener != null) {
             ovsdbDeviceEntityOwnershipListener.close();
         }
index 8b2859317224fd62ce678a1cc3ce305049f4ea8c..9e2c5e7f30da82aeee0af88519136fb90f8947b1 100644 (file)
@@ -64,7 +64,7 @@ public class OvsdbDataChangeListener implements ClusteredDataChangeListener, Aut
     }
 
     @Override
-    public void close() throws Exception {
+    public void close() {
         registration.close();
     }
 
index bfd3c9e9a9a21c51af142640c4c02d2ba3e66c72..a331a2ab5d6c83661d9df46d35a148ad9e70b757 100644 (file)
@@ -97,7 +97,7 @@ public class SouthboundProvider implements BindingAwareProvider, AutoCloseable {
     }
 
     @Override
-    public void close() throws Exception {
+    public void close() {
         LOG.info("SouthboundProvider Closed");
         cm.close();
         ovsdbDataChangeListener.close();
index 430240248cbe8429b0e0307792963ccb69d88128..b4baa98bb5e93608e60959122db57134cb0c6c22 100644 (file)
@@ -11,8 +11,6 @@ package org.opendaylight.ovsdb.southbound;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -32,7 +30,6 @@ import org.junit.Test;
 import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
-import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
 import org.opendaylight.ovsdb.lib.OvsdbClient;
 import org.opendaylight.ovsdb.lib.notation.Column;
 import org.opendaylight.ovsdb.lib.notation.UUID;
@@ -62,15 +59,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.powermock.api.mockito.PowerMockito;
 
-public class SouthboundMapperTest extends AbstractDataBrokerTest {
+public class SouthboundMapperTest {
 
     @Test
     public void testCreateIpAddress() throws Exception {
@@ -315,8 +310,6 @@ public class SouthboundMapperTest extends AbstractDataBrokerTest {
     @Test
     public void testCreateConnectionInfo() throws Exception {
         OvsdbClient client = mock(OvsdbClient.class, Mockito.RETURNS_DEEP_STUBS);
-        ConnectionInfoBuilder connectionInfoBuilder = mock(ConnectionInfoBuilder.class);
-        PowerMockito.whenNew(ConnectionInfoBuilder.class).withNoArguments().thenReturn(connectionInfoBuilder);
 
         InetAddress remoteAddress = InetAddress.getByAddress(new byte[] {1, 2, 3, 4});
         when(client.getConnectionInfo().getRemoteAddress()).thenReturn(remoteAddress);
@@ -435,14 +428,6 @@ public class SouthboundMapperTest extends AbstractDataBrokerTest {
         Column<GenericTableSchema, Boolean> isConnectedColumn = mock(Column.class);
         when(manager.getIsConnectedColumn()).thenReturn(isConnectedColumn);
         when(isConnectedColumn.getData()).thenReturn(true);
-        ManagerEntryBuilder managerEntryBuilder = mock(ManagerEntryBuilder.class);
-        PowerMockito.whenNew(ManagerEntryBuilder.class).withNoArguments().thenReturn(managerEntryBuilder);
-        PowerMockito.whenNew(Uri.class).withAnyArguments().thenReturn(mock(Uri.class));
-        when(managerEntryBuilder.setTarget(any(Uri.class))).thenReturn(managerEntryBuilder);
-        when(managerEntryBuilder.setNumberOfConnections(any(Long.class))).thenReturn(managerEntryBuilder);
-        when(managerEntryBuilder.setConnected(true)).thenReturn(managerEntryBuilder);
-
-        when(managerEntryBuilder.build()).thenReturn(managerEntry);
 
         assertEquals(Collections.singletonList(new ManagerEntryBuilder()
                 .setConnected(true)
@@ -463,15 +448,16 @@ public class SouthboundMapperTest extends AbstractDataBrokerTest {
     @Test
     public void testGetInstanceIdentifier() throws Exception {
         OpenVSwitch ovs = mock(OpenVSwitch.class);
-        InstanceIdentifier<Node> iid = mock(InstanceIdentifier.class);
+        InstanceIdentifier iid = InstanceIdentifier.create(Node.class);
         Column<GenericTableSchema, Map<String, String>> externalIdColumn = mock(Column.class);
         when(ovs.getExternalIdsColumn()).thenReturn(externalIdColumn);
         Map<String, String> externalIdMap = new HashMap<>();
         when(externalIdColumn.getData()).thenReturn(externalIdMap);
         // if true
         externalIdMap.put(SouthboundConstants.IID_EXTERNAL_ID_KEY, "test");
-        PowerMockito.mockStatic(SouthboundUtil.class);
-        when((InstanceIdentifier<Node>) SouthboundUtil.deserializeInstanceIdentifier(anyString())).thenReturn(iid);
+        InstanceIdentifierCodec iidc = mock(InstanceIdentifierCodec.class);
+        when(iidc.bindingDeserializer("test")).thenReturn(iid);
+        SouthboundUtil.setInstanceIdentifierCodec(iidc);
         assertEquals("Incorrect Instance Identifier received", iid, SouthboundMapper.getInstanceIdentifier(ovs));
         // if false
         externalIdMap.clear();
index 1e935351d918b4f6c81609c75f04c668350a3e9f..85989d3e51008635279c574da376930b8063b6cb 100644 (file)
@@ -8,21 +8,21 @@
 
 package org.opendaylight.ovsdb.southbound;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import org.junit.Before;
 import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
@@ -34,147 +34,102 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.ovsdb.lib.OvsdbConnection;
-import org.opendaylight.ovsdb.southbound.transactions.md.TransactionInvoker;
-import org.opendaylight.ovsdb.southbound.transactions.md.TransactionInvokerImpl;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.api.support.membermodification.MemberMatcher;
-import org.powermock.api.support.membermodification.MemberModifier;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-import org.powermock.reflect.Whitebox;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 
 import com.google.common.base.Optional;
-import com.google.common.util.concurrent.CheckedFuture;
-
-@PrepareForTest({SouthboundProvider.class, InstanceIdentifier.class, LogicalDatastoreType.class})
-@RunWith(PowerMockRunner.class)
-public class SouthboundProviderTest {
-    @Mock private DataBroker db;
-    @Mock private OvsdbConnectionManager cm;
-    @Mock private TransactionInvoker txInvoker;
-    @Mock private OvsdbDataChangeListener ovsdbDataChangeListener;
-    @Mock private SouthboundProvider southboundProvider;
-    @Mock private EntityOwnershipService entityOwnershipService;
-    @Mock private EntityOwnershipCandidateRegistration registration;
-    @Mock private EntityOwnershipListener entityOwnershipListener;
-    @Mock private OvsdbConnection ovsdbConnection;
+
+public class SouthboundProviderTest extends AbstractDataBrokerTest {
+    private EntityOwnershipService entityOwnershipService;
 
     @Before
-    public void setUp() throws Exception {
-        southboundProvider = PowerMockito.mock(SouthboundProvider.class, Mockito.CALLS_REAL_METHODS);
-        MemberModifier.field(SouthboundProvider.class, "cm").set(southboundProvider, cm);
-        MemberModifier.field(SouthboundProvider.class, "ovsdbDataChangeListener").set(southboundProvider, ovsdbDataChangeListener);
-        MemberModifier.field(SouthboundProvider.class, "db").set(southboundProvider, db);
-        MemberModifier.field(SouthboundProvider.class, "entityOwnershipService").set(southboundProvider, entityOwnershipService);
-        MemberModifier.field(SouthboundProvider.class, "registration").set(southboundProvider, registration);
-        MemberModifier.field(SouthboundProvider.class, "ovsdbConnection").set(southboundProvider, ovsdbConnection);
+    public void setUp() throws CandidateAlreadyRegisteredException {
+        entityOwnershipService = mock(EntityOwnershipService.class);
+        when(entityOwnershipService.registerListener(anyString(), any(EntityOwnershipListener.class))).thenReturn(
+                mock(EntityOwnershipListenerRegistration.class));
+        when(entityOwnershipService.registerCandidate(any(Entity.class))).thenReturn(mock(
+                EntityOwnershipCandidateRegistration.class));
     }
 
     @Test
-    public void testOnSessionInitiated() throws Exception {
+    public void testOnSessionInitiated() throws CandidateAlreadyRegisteredException {
         ProviderContext session = mock(ProviderContext.class);
-        when(session.getSALService(DataBroker.class)).thenReturn(db);
-        TransactionInvokerImpl transactionInvokerImpl = mock(TransactionInvokerImpl.class);
-        PowerMockito.whenNew(TransactionInvokerImpl.class).withArguments(any(DataBroker.class)).thenReturn(transactionInvokerImpl);
-        PowerMockito.whenNew(OvsdbConnectionManager.class).withArguments(any(DataBroker.class), any(TransactionInvoker.class), any(EntityOwnershipService.class), any(OvsdbConnection.class)).thenReturn(cm);
-        PowerMockito.whenNew(OvsdbDataChangeListener.class).withArguments(any(DataBroker.class), any(OvsdbConnectionManager.class)).thenReturn(ovsdbDataChangeListener);
+        when(session.getSALService(DataBroker.class)).thenReturn(getDataBroker());
 
-        when(entityOwnershipService.registerListener(anyString(), any(EntityOwnershipListener.class))).thenReturn(mock(EntityOwnershipListenerRegistration.class));
-        when(entityOwnershipService.registerCandidate(any(Entity.class))).thenReturn(registration);
-        EntityOwnershipState entityOwnershipState = mock(EntityOwnershipState.class);
-        when(entityOwnershipService.getOwnershipState(any(Entity.class))).thenReturn(Optional.of(entityOwnershipState));
+        // Indicate that this is the owner
+        when(entityOwnershipService.getOwnershipState(any(Entity.class))).thenReturn(
+                Optional.of(new EntityOwnershipState(true, true)));
 
-        southboundProvider.onSessionInitiated(session);
+        try (SouthboundProvider southboundProvider = new SouthboundProvider(entityOwnershipService,
+                mock(OvsdbConnection.class))) {
+            // Initiate the session
+            southboundProvider.onSessionInitiated(session);
 
-        verify(entityOwnershipService, times(2)).registerListener(anyString(), any(EntityOwnershipListener.class));
-        verify(entityOwnershipService).registerCandidate(any(Entity.class));
-    }
+            // Verify that at least one listener was registered
+            verify(entityOwnershipService, atLeastOnce()).registerListener(anyString(),
+                    any(EntityOwnershipListener.class));
 
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testInitializeTopology() throws Exception {
-        InstanceIdentifier<NetworkTopology> path = mock(InstanceIdentifier.class);
-        PowerMockito.mockStatic(InstanceIdentifier.class);
-        when(InstanceIdentifier.create(NetworkTopology.class)).thenReturn(path);
-
-        CheckedFuture<Optional<NetworkTopology>, ReadFailedException> topology = mock(CheckedFuture.class);
-        ReadWriteTransaction transaction = mock(ReadWriteTransaction.class);
-        when(db.newReadWriteTransaction()).thenReturn(transaction);
-        when(transaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))).thenReturn(topology);
-
-        Optional<NetworkTopology> optNetTopo = mock(Optional.class);
-        when(topology.get()).thenReturn(optNetTopo);
-        when(optNetTopo.isPresent()).thenReturn(false);
-        NetworkTopologyBuilder ntb = mock(NetworkTopologyBuilder.class);
-        PowerMockito.whenNew(NetworkTopologyBuilder.class).withNoArguments().thenReturn(ntb);
-        NetworkTopology networkTopology = mock(NetworkTopology.class);
-        when(ntb.build()).thenReturn(networkTopology);
-        doNothing().when(transaction).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(NetworkTopology.class));
-        when(transaction.submit()).thenReturn(mock(CheckedFuture.class));
-
-        LogicalDatastoreType type = PowerMockito.mock(LogicalDatastoreType.class);
-        Whitebox.invokeMethod(southboundProvider, "initializeTopology", type);
-        verify(ntb).build();
+            // Verify that a candidate was registered
+            verify(entityOwnershipService).registerCandidate(any(Entity.class));
+        }
     }
 
-    @SuppressWarnings("unchecked")
     @Test
-    public void testInitializeOvsdbTopology() throws Exception {
-        ReadWriteTransaction transaction = mock(ReadWriteTransaction.class);
-        when(db.newReadWriteTransaction()).thenReturn(transaction);
-
-        //suppress calls to initializeTopology()
-        MemberModifier.suppress(MemberMatcher.method(SouthboundProvider.class, "initializeTopology", LogicalDatastoreType.class));
-
-        CheckedFuture<Optional<Topology>, ReadFailedException> ovsdbTp = mock(CheckedFuture.class);
-        when(transaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))).thenReturn(ovsdbTp);
-
-        //true case
-        Optional<Topology> optTopo = mock(Optional.class);
-        when(ovsdbTp.get()).thenReturn(optTopo);
-        when(optTopo.isPresent()).thenReturn(false);
-        TopologyBuilder tpb = mock(TopologyBuilder.class);
-        PowerMockito.whenNew(TopologyBuilder.class).withNoArguments().thenReturn(tpb);
-        when(tpb.setTopologyId(any(TopologyId.class))).thenReturn(tpb);
-        Topology data = mock(Topology.class);
-        when(tpb.build()).thenReturn(data);
-        doNothing().when(transaction).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(Topology.class));
-        when(transaction.submit()).thenReturn(mock(CheckedFuture.class));
-
-        LogicalDatastoreType type = PowerMockito.mock(LogicalDatastoreType.class);
-        Whitebox.invokeMethod(southboundProvider, "initializeOvsdbTopology", type);
-        PowerMockito.verifyPrivate(southboundProvider).invoke("initializeTopology", any(LogicalDatastoreType.class));
-        verify(tpb).setTopologyId(any(TopologyId.class));
-        verify(tpb).build();
-
-        //false case
-        when(optTopo.isPresent()).thenReturn(false);
-        when(transaction.cancel()).thenReturn(true);
-        Whitebox.invokeMethod(southboundProvider, "initializeOvsdbTopology", type);
-        PowerMockito.verifyPrivate(southboundProvider, times(2)).invoke("initializeTopology", any(LogicalDatastoreType.class));
+    public void testGetDb() {
+        ProviderContext session = mock(ProviderContext.class);
+        when(session.getSALService(DataBroker.class)).thenReturn(getDataBroker());
+        when(entityOwnershipService.getOwnershipState(any(Entity.class))).thenReturn(
+                Optional.of(new EntityOwnershipState(true, true)));
+        try (SouthboundProvider southboundProvider = new SouthboundProvider(entityOwnershipService,
+                mock(OvsdbConnection.class))) {
+            southboundProvider.onSessionInitiated(session);
+
+            assertEquals(getDataBroker(), SouthboundProvider.getDb());
+        }
     }
 
     @Test
-    public void testHandleOwnershipChange() throws Exception {
-        EntityOwnershipChange entityOwner = mock(EntityOwnershipChange.class);
-        //suppress calls to initializeOvsdbTopology()
-        MemberModifier.suppress(MemberMatcher.method(SouthboundProvider.class, "initializeOvsdbTopology", LogicalDatastoreType.class));
-        doNothing().when(ovsdbConnection).registerConnectionListener(any(OvsdbConnectionManager.class));
-        when(ovsdbConnection.startOvsdbManager(any(Integer.class))).thenReturn(false);
-        // Entity ownership given to this instance.
-        when(entityOwner.isOwner()).thenReturn(true);
-        Whitebox.invokeMethod(southboundProvider, "handleOwnershipChange", entityOwner);
-        PowerMockito.verifyPrivate(southboundProvider, times(2)).invoke("initializeOvsdbTopology", any(LogicalDatastoreType.class));
-        // Entity ownership not awarded to this instance.
-        when(entityOwner.isOwner()).thenReturn(false);
-        Whitebox.invokeMethod(southboundProvider, "handleOwnershipChange", entityOwner);
-        PowerMockito.verifyPrivate(southboundProvider, times(2)).invoke("initializeOvsdbTopology", any(LogicalDatastoreType.class));
-        verify(ovsdbConnection, times(2)).registerConnectionListener(any(OvsdbConnectionManager.class));
+    public void testHandleOwnershipChange() throws ReadFailedException {
+        // Start as slave
+        ProviderContext session = mock(ProviderContext.class);
+        when(session.getSALService(DataBroker.class)).thenReturn(getDataBroker());
+        when(entityOwnershipService.getOwnershipState(any(Entity.class))).thenReturn(
+                Optional.of(new EntityOwnershipState(false, true)));
+        Entity entity = new Entity("ovsdb-southbound-provider", "ovsdb-southbound-provider");
+        KeyedInstanceIdentifier<Topology, TopologyKey> topologyIid = InstanceIdentifier
+                .create(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
+
+        try (SouthboundProvider southboundProvider = new SouthboundProvider(entityOwnershipService,
+                mock(OvsdbConnection.class))) {
+            southboundProvider.onSessionInitiated(session);
+
+            // At this point the OVSDB topology must not be present in either tree
+            assertFalse(getDataBroker().newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION,
+                    topologyIid).checkedGet().isPresent());
+            assertFalse(getDataBroker().newReadOnlyTransaction().read(LogicalDatastoreType.OPERATIONAL,
+                    topologyIid).checkedGet().isPresent());
+
+            // Become owner
+            southboundProvider.handleOwnershipChange(new EntityOwnershipChange(entity, false, true, true));
+
+            // Now the OVSDB topology must be present in both trees
+            assertTrue(getDataBroker().newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION,
+                    topologyIid).checkedGet().isPresent());
+            assertTrue(getDataBroker().newReadOnlyTransaction().read(LogicalDatastoreType.OPERATIONAL,
+                    topologyIid).checkedGet().isPresent());
+
+            // Verify idempotency
+            southboundProvider.handleOwnershipChange(new EntityOwnershipChange(entity, false, true, true));
+
+            // The OVSDB topology must be present in both trees
+            assertTrue(getDataBroker().newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION,
+                    topologyIid).checkedGet().isPresent());
+            assertTrue(getDataBroker().newReadOnlyTransaction().read(LogicalDatastoreType.OPERATIONAL,
+                    topologyIid).checkedGet().isPresent());
+        }
     }
 }
\ No newline at end of file