topicName | No | string | | | the short name used by humans, and utilized to construct the `FQTN`
version | No | string | | | a hook for any versioning needed for managing a `Topic` over time
-Security
-~~~~~~~~
-As default security is in Dmaap Bus Controller disabled.
-
-Enable
-------
-Settings to turn on security is in file dmaapbc.properties. The file is located in OOM project in path: ./oom/kubernetes/dmaap/components/dmaap-bc/resources/config/dmaapbc.properties
-During deployment the the file is placed into ConfigMap XXX-dmaap-bus-controller-config (XXX depend on deployment setup). The config map is linked to volume with read only permission so it can not be changed from pod level.
-Ater updating ConfigMap the bus controller pod needs to be restarted.
-
-Settings
-++++++++
-
-In the dmaapbc.properties for security settings there is a main flag:
-
-1.UseAAF: true
-
-If set to true then creating topic also will create required perms in AAF. The perms will be created in org.onap.dmaap.mr.
-The last element -mr- is related to another setting - MR.projectID .
-
-Example:
- Topic name:
- aSimpleTopic
- Permitions
- org.onap.dmaap.mr.topic|:topic.org.onap.dmaap.mr.aSimpleTopic|pub
- org.onap.dmaap.mr.topic|:topic.org.onap.dmaap.mr.aSimpleTopic|sub
- org.onap.dmaap.mr.topic|:topic.org.onap.dmaap.mr.aSimpleTopic|view
-
-
-Hint: User defined in the certificate of cadi (property:cadi.properties, user:dmaap-bc@dmaap-bc.onap.org) needs to have permissions to create and view such topics (org.onap.dmaap.mr.topic|*|*).
-
-
-Authentication is using CADI
-
-CADI confilguration is stored in CADI files. Location of the files is defined in varaible:
-cadi.properties: /opt/app/osaaf/local/org.onap.dmaap-bc.props
-
-The configuration is a mandatory and missing parameter or file cause exception.
-
-Authorization is done by CADI - configuration is required as above
-
-Call to bus controller needs to have given user credentials. The user ich checked in AAF for permission to call topic.
-The check is done in org.onap.dmaap-bc.api according to ApiNamespace setting.
-
-Hint: User defined in the certificate of cadi (property:cadi.properties, user:dmaap-bc@dmaap-bc.onap.org) needs to have permission to read the namespace (org.onap.dmaap-bc.api.access|*|read).
-
-
-2.UseAAF: false
-
-For backward compatibility, if AAF flag is turned off the previous implementation is enabled based on AuthorizationFilter and ApiPermission class.
-This filter switching has been made due to the technology differences: Jersey filters do not implement directly servlet API, but CADI filter is based on it.
\ No newline at end of file
private String authMethod;
private String user;
private String encPwd;
+ private String unit_test;
private boolean hostnameVerify;
public MrProvConnection() {
authMethod = p.getProperty("MR.authentication", "none");
topicMgrCred = getCred();
hostnameVerify= "true".equalsIgnoreCase(p.getProperty("MR.hostnameVerify", "true"));
+ unit_test = p.getProperty( "UnitTest", "No" );
}
err.setFields( uc.getURL().getHost());
return new String( "500: " + uhe.getMessage());
}catch ( ConnectException ce ) {
- errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, "HTTP Connection Exception" );
- err.setCode(500);
- err.setMessage("HTTP Connection Exception");
- err.setFields( uc.getURL().getHost());
+ if ( unit_test.equals( "Yes" ) ) {
+ err.setCode(200);
+ err.setMessage( "simulated response");
+ logger.info( "artificial 200 response from doPostMessage because unit_test =" + unit_test );
+ } else {
+ errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, "HTTP Connection Exception" );
+ err.setCode(500);
+ err.setMessage("HTTP Connection Exception");
+ err.setFields( uc.getURL().getHost());
return new String( "500: " + ce.getMessage());
+ }
}
rc = uc.getResponseCode();
logger.info( "http response code:" + rc );
} catch (Exception e) {
if ( unit_test.equals( "Yes" ) ) {
- response.setCode(200);
+ response.setCode(201);
response.setMessage( "simulated response");
- logger.info( "artificial 200 response from doPostMessage because unit_test =" + unit_test );
+ logger.info( "artificial 201 response from doPostMessage because unit_test =" + unit_test );
} else {
response.setCode(500);
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.util.Properties;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
try {
String cadiPropertiesFile = dmaapConfig.getProperty(CADI_PROPERTIES);
if(cadiPropertiesFile != null && !cadiPropertiesFile.isEmpty()) {
- cadiFilter = new CadiFilter(new PropAccess(cadiPropertiesFile));
+ cadiFilter = new CadiFilter(loadCadiProperties(cadiPropertiesFile));
} else {
throw new ServletException("Cannot initialize CADI filter.CADI properties not available.");
}
}
}
+ private PropAccess loadCadiProperties(String propertiesFilePath) throws ServletException {
+ try {
+ Properties props = new Properties();
+ props.load(new FileInputStream(propertiesFilePath));
+ return new PropAccess(props);
+ } catch (IOException e) {
+ String msg = "Could not load CADI properties file: " + propertiesFilePath;
+ LOGGER.error(msg, e);
+ throw new ServletException(msg);
+ }
+ }
+
DmaapConfig getConfig() {
return (DmaapConfig) DmaapConfig.getConfig();
}
private static MrTopicConnection prov;
private static AafDecrypt decryptor;
+ static final String PROV_USER_PROPERTY = "MM.ProvUserMechId";
+ static final String PROV_PWD_PROPERTY = "MM.ProvUserPwd";
+ static final String PROV_PWD_DEFAULT = "pwdNotSet";
+ static final String SOURCE_REPLICATION_PORT_PROPERTY = "MR.SourceReplicationPort";
+ static final String SOURCE_REPLICATION_PORT_DEFAULT = "9092";
+ static final String TARGET_REPLICATION_PORT_PROPERTY = "MR.TargetReplicationPort";
+ static final String TARGET_REPLICATION_PORT_DEFAULT = "2181";
+
private static String provUser;
private static String provUserPwd;
private static String defaultProducerPort;
super();
decryptor = new AafDecrypt();
DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig();
- provUser = p.getProperty("MM.ProvUserMechId");
- provUserPwd = decryptor.decrypt(p.getProperty( "MM.ProvUserPwd", "notSet" ));
- defaultProducerPort = p.getProperty( "MR.SourceReplicationPort", "9092");
- defaultConsumerPort = p.getProperty( "MR.TargetReplicationPort", "2181");
+ provUser = p.getProperty(PROV_USER_PROPERTY);
+ provUserPwd = decryptor.decrypt(p.getProperty( PROV_PWD_PROPERTY, PROV_PWD_DEFAULT ));
+ defaultProducerPort = p.getProperty( SOURCE_REPLICATION_PORT_PROPERTY, SOURCE_REPLICATION_PORT_DEFAULT );
+ defaultConsumerPort = p.getProperty( TARGET_REPLICATION_PORT_PROPERTY, TARGET_REPLICATION_PORT_DEFAULT );
centralFqdn = p.getProperty("MR.CentralCname", "notSet");
maxTopicsPerMM = Integer.valueOf( p.getProperty( "MaxTopicsPerMM", "5"));
mmPerMR = "true".equalsIgnoreCase(p.getProperty("MirrorMakerPerMR", "true"));
return ret;
}
- public MirrorMaker getNextMM( String source, String target, String fqtn ) {
+ public MirrorMaker findNextMM( String source, String target, String fqtn ) {
int i = 0;
MirrorMaker mm = null;
while( mm == null ) {
int last = whitelist.size() - 1;
String topic = whitelist.get(last);
whitelist.remove(last);
- MirrorMaker mm = this.getNextMM( source, target, "aValueThatShouldNotMatchAnything" );
+ MirrorMaker mm = this.findNextMM( source, target, "aValueThatShouldNotMatchAnything" );
mm.addTopic(topic);
this.updateMirrorMaker(mm);
}
return orig;
}
+
+ public static String getProvUser() {
+ return provUser;
+ }
+
+ public static void setProvUser(String provUser) {
+ MirrorMakerService.provUser = provUser;
+ }
+
+ public static String getProvUserPwd() {
+ return provUserPwd;
+ }
+
+ public static void setProvUserPwd(String provUserPwd) {
+ MirrorMakerService.provUserPwd = provUserPwd;
+ }
+
+ public static String getDefaultProducerPort() {
+ return defaultProducerPort;
+ }
+
+ public static void setDefaultProducerPort(String defaultProducerPort) {
+ MirrorMakerService.defaultProducerPort = defaultProducerPort;
+ }
+
+ public static String getDefaultConsumerPort() {
+ return defaultConsumerPort;
+ }
+
+ public static void setDefaultConsumerPort(String defaultConsumerPort) {
+ MirrorMakerService.defaultConsumerPort = defaultConsumerPort;
+ }
}
public Topic checkForBridge( Topic topic, ApiError err ) {
logger.info( "checkForBridge: entry");
- logger.info( "fqtn=" + topic.getFqtn() + "replicatonType=" + topic.getReplicationCase());
+ logger.info( "fqtn=" + topic.getFqtn() + " replicatonType=" + topic.getReplicationCase());
if ( topic.getReplicationCase() == ReplicationType.REPLICATION_NONE ) {
topic.setStatus( DmaapObject_Status.VALID);
return topic;
logger.info( "loc=" + loc );
DcaeLocation location = locations.getDcaeLocation(loc);
MR_Cluster cluster = clusters.getMr_ClusterByLoc(loc);
- logger.info( "cluster=" + cluster );
+ logger.info( "cluster=" + cluster + " at "+ cluster.getDcaeLocationName() );
+ logger.info( "location.isCentral()="+location.isCentral() + " getCentralLoc()=" + graph.getCentralLoc() );
case REPLICATION_EDGE_TO_CENTRAL_TO_GLOBAL: // NOTE: this is for E2C portion only
source = cluster.getFqdn();
target = (mmPerMR)? groupCentralCluster.getFqdn() : centralCname;
+ logger.info( "REPLICATION_EDGE_TO_CENTRAL: source=" + source + " target=" +target );
break;
case REPLICATION_CENTRAL_TO_EDGE:
case REPLICATION_GLOBAL_TO_CENTRAL_TO_EDGE: // NOTE: this is for C2E portion only
if ( source != null && target != null ) {
try {
logger.info( "Create a MM from " + source + " to " + target );
- MirrorMaker mm = bridge.getNextMM( source, target, topic.getFqtn());
+ MirrorMaker mm = bridge.findNextMM( source, target, topic.getFqtn());
mm.addTopic(topic.getFqtn());
bridge.updateMirrorMaker(mm);
} catch ( Exception ex ) {
}
@Test
- public void init_shouldInitializeCADI_whenAafIsUsed_andCadiPropertiesSet() throws Exception {
+ public void init_shouldFail_whenAafIsUsed_andInvalidCadiPropertiesSet() throws Exception {
//given
+ String invalidFilePath = "src/test/resources/notExisting.properties";
doReturn("true").when(dmaapConfig).getProperty(eq(AAFAuthenticationFilter.AAF_AUTHN_FLAG), anyString());
- doReturn("cadi.properties").when(dmaapConfig).getProperty(AAFAuthenticationFilter.CADI_PROPERTIES);
+ doReturn(invalidFilePath).when(dmaapConfig).getProperty(AAFAuthenticationFilter.CADI_PROPERTIES);
+
+ //then
+ thrown.expect(ServletException.class);
+ thrown.expectMessage("Could not load CADI properties file: "+invalidFilePath);
+
+ //when
+ filter.init(filterConfig);
+ }
+
+ @Test
+ public void init_shouldInitializeCADI_whenAafIsUsed_andValidCadiPropertiesSet() throws Exception {
+ //given
+ doReturn("true").when(dmaapConfig).getProperty(eq(AAFAuthenticationFilter.AAF_AUTHN_FLAG), anyString());
+ doReturn("src/test/resources/cadi.properties").when(dmaapConfig).getProperty(AAFAuthenticationFilter.CADI_PROPERTIES);
//when
filter.init(filterConfig);
private void initCADIFilter() throws Exception{
doReturn("true").when(dmaapConfig).getProperty(eq(AAFAuthenticationFilter.AAF_AUTHN_FLAG), anyString());
- doReturn("cadi.properties").when(dmaapConfig).getProperty(AAFAuthenticationFilter.CADI_PROPERTIES);
+ doReturn("src/test/resources/cadi.properties").when(dmaapConfig).getProperty(AAFAuthenticationFilter.CADI_PROPERTIES);
filter.init(filterConfig);
filter.setCadiFilter(cadiFilterMock);
}
private static final String fmt = "%24s: %s%n";
+ private boolean is2xx(int val ) {
+ if ( val >= 200 && val < 300 ) {
+ return true;
+ }
+ return false;
+ }
@Before
public void preTest() throws Exception {
Dmaap dmaap = factory.genDmaap();
Entity<Dmaap> reqEntity = Entity.entity( dmaap, MediaType.APPLICATION_JSON );
- Response resp = target( "dmaap").request().put( reqEntity, Response.class );
- System.out.println( resp.getStatus() );
- assertTrue( resp.getStatus() == 200 );
+ Response resp = target( "dmaap").request().post( reqEntity, Response.class );
+ System.out.println( "POST dmaap resp=" + resp.getStatus() );
+ assertTrue( is2xx( resp.getStatus()) );
+
}catch (Exception e ) {
}
try {
Response resp = target( "dcaeLocations").request().post( reqEntity, Response.class );
System.out.println( "POST dcaeLocation resp=" + resp.getStatus() + " " + resp.readEntity( String.class ));
if ( resp.getStatus() != 409 ) {
- assertTrue( resp.getStatus() == 201 );
+ assertTrue( is2xx( resp.getStatus()) );
}
} catch (Exception e ) {
}
Response resp = target( "mr_clusters").request().post( reqEntity, Response.class );
System.out.println( "POST MR_Cluster resp=" + resp.getStatus() + " " + resp.readEntity( String.class ) );
if (resp.getStatus() != 409 ) {
- assertTrue( resp.getStatus() == 200 );
+ assertTrue( is2xx( resp.getStatus()) );
}
} catch (Exception e ) {
if ( nTopic != null ) {
assertTrue( nTopic.getTopicName().equals( topic.getTopicName() ));
}
- String[] actions = { "pub", "view" };
+
MR_Client c = factory.genPublisher( "edge", topic.getFqtn() );
c = cls.addMr_Client( c, topic, err );
}
@Test
- public void test5() {
+ public void AddSubscriberToTopic() {
Topic topic = factory.genSimpleTopic( "test5" );
ApiError err = new ApiError();
Topic nTopic = ts.addTopic( topic, err, false );
MR_Client c = factory.genPublisher( "central", topic.getFqtn() );
c = cls.addMr_Client( c, topic, err );
- if ( c != null ) {
- c = factory.genSubscriber( "central", topic.getFqtn() );
- c = cls.updateMr_Client( c, err );
- assertTrue( err.getCode() == 200 );
- }
- }
+ assertTrue( c != null );
+ c = factory.genSubscriber( "central", topic.getFqtn() );
+ c = cls.addMr_Client( c, topic, err );
+ assertTrue( err.getCode() == 200 );
+
+
+ }
+
}
--- /dev/null
+/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.dmaap
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dmaap.dbcapi.service;
+
+import org.onap.dmaap.dbcapi.model.*;
+import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory;
+import org.onap.dmaap.dbcapi.testframework.ReflectionHarness;
+
+import static org.junit.Assert.*;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import java.util.List;
+import java.util.ArrayList;
+
+public class MirrorMakerServiceTest {
+
+ private static final String fmt = "%24s: %s%n";
+ private static DmaapObjectFactory factory = new DmaapObjectFactory();
+ ReflectionHarness rh = new ReflectionHarness();
+
+ private MirrorMakerService mms;
+ private TopicService ts;
+ private MR_ClusterService mcs;
+ private MR_ClientService cls;
+ private DcaeLocationService dls;
+
+ private Topic replicationTopic;
+
+
+ DmaapService ds;
+ String locname;
+
+ @Before
+ public void setUp() throws Exception {
+ mms = new MirrorMakerService();
+ ts = new TopicService();
+ assert( ts != null );
+ mcs = new MR_ClusterService();
+ assert( mcs != null );
+ Dmaap nd = factory.genDmaap();
+ ds = new DmaapService();
+ ds.addDmaap( nd );
+ ts = new TopicService();
+ mcs = new MR_ClusterService();
+ cls = new MR_ClientService();
+
+ dls = new DcaeLocationService();
+ DcaeLocation loc = factory.genDcaeLocation( "central" );
+ locname = loc.getDcaeLocationName();
+ dls.addDcaeLocation( loc );
+ loc = factory.genDcaeLocation( "edge");
+ dls.addDcaeLocation( loc );
+
+ ApiError err = new ApiError();
+
+ MR_Cluster node = factory.genMR_Cluster( "central" );
+ mcs.addMr_Cluster( node, err);
+ node = factory.genMR_Cluster("edge" );
+ mcs.addMr_Cluster(node, err);
+
+
+ String t = "org.onap.dmaap.bridgingTopic";
+ replicationTopic = factory.genSimpleTopic(t);
+ replicationTopic.setReplicationCase( ReplicationType.REPLICATION_EDGE_TO_CENTRAL );
+
+ String c = "publisher";
+ String[] a = { "sub", "view" };
+ MR_Client sub = factory.genMR_Client("central", replicationTopic.getFqtn(), c, a );
+ String[] b = { "pub", "view" };
+ MR_Client pub = factory.genMR_Client( "edge", replicationTopic.getFqtn(), c, b );
+ ArrayList<MR_Client> clients = new ArrayList<MR_Client>();
+
+ clients.add( sub );
+ clients.add( pub );
+
+ replicationTopic.setClients( clients );
+
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+
+// @Test
+// public void test_getters() {
+//
+//
+// rh.reflect( "org.onap.dmaap.dbcapi.service.MirrorMakerService", "get", null );
+//
+// }
+
+ @Test
+ public void test_setters() {
+ String v = "Validate";
+ rh.reflect( "org.onap.dmaap.dbcapi.service.MirrorMakerService", "set", v );
+
+ }
+
+
+
+ @Test
+ public void CreateMirrorMakerWithSingleTopic() {
+ ApiError err = new ApiError();
+
+
+ Topic nTopic = ts.addTopic(replicationTopic, err, true );
+
+ assertTrue( err.getCode() == 200 );
+
+ List<String> mma = mms.getAllMirrorMakers();
+ }
+
+ @Test
+ public void DeleteMirrorMakerWithSingleTopic() {
+
+ ApiError err = new ApiError();
+ Topic nTopic = ts.addTopic(replicationTopic, err, true );
+ replicationTopic.setTopicDescription("modified topic");
+ nTopic = ts.updateTopic( replicationTopic, err );
+
+ assertTrue( err.getCode() == 200 );
+
+
+ List<String> mma = mms.getAllMirrorMakers();
+
+ int nMM = mma.size();
+ assertTrue( nMM >= 1);
+
+ String name = mma.get(0);
+
+ MirrorMaker mm = mms.getMirrorMaker(name);
+
+ mms.delMirrorMaker(mm);
+
+ mma = mms.getAllMirrorMakers();
+
+ assertTrue( mma.size() == (nMM-1) );
+ }
+
+ @Test
+ public void SplitMirrorMakerWithSingleTopic() {
+
+ ApiError err = new ApiError();
+
+
+ Topic nTopic = ts.addTopic( replicationTopic, err, true );
+ replicationTopic.setTopicDescription("modified topic");
+ nTopic = ts.updateTopic( replicationTopic, err );
+
+
+ assertTrue( err.getCode() == 200 );
+ List<String> mma = mms.getAllMirrorMakers();
+
+ int nMM = mma.size();
+ assertTrue( nMM >= 1);
+
+ String name = mma.get(0);
+
+ MirrorMaker mm = mms.getMirrorMaker(name);
+
+ MirrorMaker mm2 = mms.splitMM(mm);
+
+ }
+
+}
--- /dev/null
+/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.dmaap
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dmaap.dbcapi.service;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.aaf.cadi.filter.CadiFilter;
+import org.onap.dmaap.dbcapi.model.MirrorMaker;
+import org.onap.dmaap.dbcapi.util.DmaapConfig;
+
+@RunWith(MockitoJUnitRunner.class)
+public class MirrorMakerServiceTestMockito {
+
+ @Spy
+ private MirrorMakerService service;
+
+ @Mock
+ private CadiFilter cadiFilterMock;
+ @Mock
+ private HttpServletRequest servletRequest;
+ @Mock
+ private HttpServletResponse servletResponse;
+
+ @Mock
+ private DmaapConfig dmaapConfig;
+
+ @Mock
+ private MirrorMaker mm = new MirrorMaker();
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Before
+ public void setUp() throws Exception {
+
+ }
+
+ @Test
+ public void init_normalConstructor() throws Exception {
+ //given
+
+
+ //when
+
+
+ //then
+ assertEquals( MirrorMakerService.getProvUserPwd(), MirrorMakerService.PROV_PWD_DEFAULT);
+ assertEquals( MirrorMakerService.getDefaultConsumerPort(), MirrorMakerService.TARGET_REPLICATION_PORT_DEFAULT);
+ assertEquals( MirrorMakerService.getDefaultProducerPort(), MirrorMakerService.SOURCE_REPLICATION_PORT_DEFAULT);
+ }
+
+ // Todo: learn how to make more tests in Mockito
+
+
+}