/** * The MIT License * Copyright © 2018 Twinformatics GmbH * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package at.twinformatics.eureka.adapter.consul.controller; import at.twinformatics.eureka.adapter.consul.mapper.MetadataMapper; import at.twinformatics.eureka.adapter.consul.mapper.NodeMetadataMapper; import at.twinformatics.eureka.adapter.consul.mapper.ServiceMetadataMapper; import at.twinformatics.eureka.adapter.consul.service.RegistrationService; import at.twinformatics.eureka.adapter.consul.service.ServiceChangeDetector; import at.twinformatics.eureka.adapter.consul.mapper.InstanceInfoMapper; import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.shared.Application; import com.netflix.discovery.shared.Applications; import com.netflix.eureka.registry.PeerAwareInstanceRegistry; import lombok.extern.slf4j.Slf4j; import net.minidev.json.JSONArray; import org.hamcrest.Matchers; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @Slf4j @RunWith(SpringRunner.class) @WebMvcTest(controllers = { ServiceController.class, ServiceChangeDetector.class, InstanceInfoMapper.class, RegistrationService.class, MetadataMapper.class }) public class ServiceControllerTest { private MockMvc mockMvc; @MockBean private PeerAwareInstanceRegistry registry; @Autowired private ServiceChangeDetector serviceChangeDetector; @Autowired private ServiceController controller; @Autowired private InstanceInfoMapper instanceInfoMapper; private ExecutorService executorService1; @Before public void setUp() { executorService1 = Executors.newSingleThreadExecutor(); serviceChangeDetector.reset(); mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); } @After public void tearDown() throws InterruptedException { executorService1.shutdown(); executorService1.awaitTermination(10, TimeUnit.SECONDS); } @Test public void services_noServices_emptyObj() throws Exception { Mockito.when(registry.getApplications()).thenReturn(new Applications()); performAsync("/v1/catalog/services?wait=1ms") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(content().string("{}")); } @Test public void services_1Service_serviceObj() throws Exception { Applications applications = mock2Applications(); Mockito.when(registry.getApplications()).thenReturn(applications); performAsync("/v1/catalog/services?wait=1ms") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$.ms1", Matchers.is(new JSONArray()))) .andExpect(jsonPath("$.ms2", Matchers.is(new JSONArray()))); } @Test public void services_syncChangesToMs1_interruptOnChange() throws Exception { Applications applications = mock2Applications(); Mockito.when(registry.getApplications()).thenReturn(applications); performAsync("/v1/catalog/services?wait=1ms") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(header().string("X-Consul-Index", "1")) .andExpect(jsonPath("$.ms1", Matchers.is(new JSONArray()))) .andExpect(jsonPath("$.ms2", Matchers.is(new JSONArray()))); serviceChangeDetector.publish("ms1", 2); performAsync("/v1/catalog/services?wait=1ms&index=1") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(header().string("X-Consul-Index", "2")) .andExpect(jsonPath("$.ms1", Matchers.is(new JSONArray()))) .andExpect(jsonPath("$.ms2", Matchers.is(new JSONArray()))); performAsync("/v1/catalog/services?wait=1ms&index=2") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(header().string("X-Consul-Index", "2")) .andExpect(jsonPath("$.ms1", Matchers.is(new JSONArray()))) .andExpect(jsonPath("$.ms2", Matchers.is(new JSONArray()))); serviceChangeDetector.publish("ms1", 3); performAsync("/v1/catalog/services?wait=1ms&index=2") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(header().string("X-Consul-Index", "3")) .andExpect(jsonPath("$.ms1", Matchers.is(new JSONArray()))) .andExpect(jsonPath("$.ms2", Matchers.is(new JSONArray()))); } private ResultActions performAsync(String url) throws Exception { MvcResult mvcResult = this.mockMvc.perform(get(url)) .andExpect(status().isOk()) .andReturn(); return this.mockMvc.perform(asyncDispatch(mvcResult)); } @Test(timeout = 10000) public void services_asyncChangesToMs1_interruptOnChange() throws Exception { Applications applications = mock2Applications(); Mockito.when(registry.getApplications()).thenReturn(applications); startThread(() -> { sleepFor(1000); serviceChangeDetector.publish("ms1", 2); sleepFor(1000); serviceChangeDetector.publish("ms1", 3); }); performAsync("/v1/catalog/services?wait=30s") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(header().string("X-Consul-Index", "1")) .andExpect(jsonPath("$.ms1", Matchers.is(new JSONArray()))) .andExpect(jsonPath("$.ms2", Matchers.is(new JSONArray()))); performAsync("/v1/catalog/services?wait=30s&index=1") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(header().string("X-Consul-Index", "2")) .andExpect(jsonPath("$.ms1", Matchers.is(new JSONArray()))) .andExpect(jsonPath("$.ms2", Matchers.is(new JSONArray()))); } @Test(timeout = 10000) public void services_asyncChangesToMs1AndMs2_interruptOnChange() throws Exception { Applications applications = mock2Applications(); Mockito.when(registry.getApplications()).thenReturn(applications); startThread(() -> { sleepFor(1000); serviceChangeDetector.publish("ms1", 2); sleepFor(1000); Applications newApplications = new Applications(); newApplications.addApplication(new Application("ms1")); Mockito.when(registry.getApplications()).thenReturn(newApplications); serviceChangeDetector.publish("ms2", 4); sleepFor(1000); }); performAsync("/v1/catalog/services?wait=30s") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(header().string("X-Consul-Index", "1")) .andExpect(jsonPath("$.ms1", Matchers.is(new JSONArray()))) .andExpect(jsonPath("$.ms2", Matchers.is(new JSONArray()))); performAsync("/v1/catalog/services?wait=30s&index=1") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(header().string("X-Consul-Index", "2")) .andExpect(jsonPath("$.ms1", Matchers.is(new JSONArray()))) .andExpect(jsonPath("$.ms2", Matchers.is(new JSONArray()))); performAsync("/v1/catalog/services?wait=30s&index=2") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(header().string("X-Consul-Index", "4")) .andExpect(jsonPath("$.ms1", Matchers.is(new JSONArray()))) .andExpect(jsonPath("$.ms2").doesNotExist()); } @Test public void service_sampleService_jsonObject() throws Exception { Applications applications = mock2Applications(); Mockito.when(registry.getApplications()).thenReturn(applications); Application ms1 = applications.getRegisteredApplications().get(0); InstanceInfo instance1 = mock1Instance(); ms1.addInstance(instance1); Mockito.when(registry.getApplication("ms1")).thenReturn(ms1); MetadataMapper metadataMapper = new ServiceMetadataMapper(); instanceInfoMapper.setMetadataMapper(metadataMapper); performAsync("/v1/catalog/service/ms1?wait=1ms") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$[0].Address", Matchers.is("1.2.3.4"))) .andExpect(jsonPath("$[0].Node", Matchers.is("ms1"))) .andExpect(jsonPath("$[0].ServiceAddress", Matchers.is("1.2.3.4"))) .andExpect(jsonPath("$[0].ServiceName", Matchers.is("ms1"))) .andExpect(jsonPath("$[0].ServiceID", Matchers.is("1"))) .andExpect(jsonPath("$[0].ServicePort", Matchers.is(80))) .andExpect(jsonPath("$[0].NodeMeta").isEmpty()) .andExpect(jsonPath("$[0].ServiceMeta").isEmpty()) .andExpect(jsonPath("$[0].ServiceTags", Matchers.is(new JSONArray()))); InstanceInfo instance2 = mock1Instance("2","1.2.3.5", "ms2.com", 81, true); Map<String, String> md = new HashMap<>(); md.put("k1", "v1"); md.put("k2", "v2"); Mockito.when(instance2.getMetadata()).thenReturn(md); ms1.addInstance(instance2); performAsync("/v1/catalog/service/ms1?wait=1ms") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$[0].Address", Matchers.is("1.2.3.4"))) .andExpect(jsonPath("$[0].Node", Matchers.is("ms1"))) .andExpect(jsonPath("$[0].ServiceAddress", Matchers.is("1.2.3.4"))) .andExpect(jsonPath("$[0].ServiceName", Matchers.is("ms1"))) .andExpect(jsonPath("$[0].ServiceID", Matchers.is("1"))) .andExpect(jsonPath("$[0].ServicePort", Matchers.is(80))) .andExpect(jsonPath("$[0].NodeMeta").isEmpty()) .andExpect(jsonPath("$[0].ServiceMeta").isEmpty()) .andExpect(jsonPath("$[0].ServiceTags", Matchers.is(new JSONArray()))) .andExpect(jsonPath("$[1].Address", Matchers.is("1.2.3.5"))) .andExpect(jsonPath("$[1].Node", Matchers.is("ms1"))) .andExpect(jsonPath("$[1].ServiceAddress", Matchers.is("1.2.3.5"))) .andExpect(jsonPath("$[1].ServiceName", Matchers.is("ms1"))) .andExpect(jsonPath("$[1].ServiceID", Matchers.is("2"))) .andExpect(jsonPath("$[1].ServicePort", Matchers.is(443))) .andExpect(jsonPath("$[1].NodeMeta").isEmpty()) .andExpect(jsonPath("$[1].ServiceMeta.k1", Matchers.is("v1"))) .andExpect(jsonPath("$[1].ServiceMeta.k2", Matchers.is("v2"))) .andExpect(jsonPath("$[1].ServiceTags", Matchers.is(new JSONArray()))); } @Test public void service_sampleService_jsonObject_nodeMetadataMapper() throws Exception{ Applications applications = mock2Applications(); Mockito.when(registry.getApplications()).thenReturn(applications); Application ms1 = applications.getRegisteredApplications().get(0); InstanceInfo instance = mock1Instance(); ms1.addInstance(instance); Mockito.when(registry.getApplication("ms1")).thenReturn(ms1); String nodeMetaPrefix = "nodeMeta_"; MetadataMapper metadataMapper = new NodeMetadataMapper(nodeMetaPrefix); instanceInfoMapper.setMetadataMapper(metadataMapper); Map<String, String> md = new HashMap<>(); md.put("k1", "v1"); md.put("k2", "v2"); md.put("nodeMeta_k1", "nv1"); md.put("nodeMeta_k2", "nv2"); Mockito.when(instance.getMetadata()).thenReturn(md); performAsync("/v1/catalog/service/ms1?wait=1ms") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$[0].Address", Matchers.is("1.2.3.4"))) .andExpect(jsonPath("$[0].Node", Matchers.is("ms1"))) .andExpect(jsonPath("$[0].ServiceAddress", Matchers.is("1.2.3.4"))) .andExpect(jsonPath("$[0].ServiceName", Matchers.is("ms1"))) .andExpect(jsonPath("$[0].ServiceID", Matchers.is("1"))) .andExpect(jsonPath("$[0].ServicePort", Matchers.is(80))) .andExpect(jsonPath("$[0].NodeMeta.k1", Matchers.is("nv1"))) .andExpect(jsonPath("$[0].NodeMeta.k2", Matchers.is("nv2"))) .andExpect(jsonPath("$[0].ServiceMeta.k1", Matchers.is("v1"))) .andExpect(jsonPath("$[0].ServiceMeta.k2", Matchers.is("v2"))) .andExpect(jsonPath("$[0].ServiceTags", Matchers.is(new JSONArray()))); nodeMetaPrefix = ""; metadataMapper = new NodeMetadataMapper(nodeMetaPrefix); instanceInfoMapper.setMetadataMapper(metadataMapper); performAsync("/v1/catalog/service/ms1?wait=1ms") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$[0].Address", Matchers.is("1.2.3.4"))) .andExpect(jsonPath("$[0].Node", Matchers.is("ms1"))) .andExpect(jsonPath("$[0].ServiceAddress", Matchers.is("1.2.3.4"))) .andExpect(jsonPath("$[0].ServiceName", Matchers.is("ms1"))) .andExpect(jsonPath("$[0].ServiceID", Matchers.is("1"))) .andExpect(jsonPath("$[0].ServicePort", Matchers.is(80))) .andExpect(jsonPath("$[0].NodeMeta.k1", Matchers.is("v1"))) .andExpect(jsonPath("$[0].NodeMeta.k2", Matchers.is("v2"))) .andExpect(jsonPath("$[0].NodeMeta.nodeMeta_k1", Matchers.is("nv1"))) .andExpect(jsonPath("$[0].NodeMeta.nodeMeta_k2", Matchers.is("nv2"))) .andExpect(jsonPath("$[0].ServiceMeta").isEmpty()) .andExpect(jsonPath("$[0].ServiceTags", Matchers.is(new JSONArray()))); } @Test public void service_sampleService_jsonObject_preferHostName() throws Exception { Applications applications = mock2Applications(); Mockito.when(registry.getApplications()).thenReturn(applications); Application ms1 = applications.getRegisteredApplications().get(0); InstanceInfo instance1 = mock1Instance(); ms1.addInstance(instance1); InstanceInfo instance2 = mock1Instance("2","1.2.3.5", "2.ms1.com", 81, true); ms1.addInstance(instance2); Mockito.when(registry.getApplication("ms1")).thenReturn(ms1); instanceInfoMapper.setPreferHostName(true); performAsync("/v1/catalog/service/ms1?wait=1ms") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$[0].Address", Matchers.is("ms1.com"))) .andExpect(jsonPath("$[0].ServiceAddress", Matchers.is("ms1.com"))) .andExpect(jsonPath("$[1].Address", Matchers.is("2.ms1.com"))) .andExpect(jsonPath("$[1].ServiceAddress", Matchers.is("2.ms1.com"))); } @Test public void service_healthEndpoint_jsonObject() throws Exception { Applications applications = mock2Applications(); Mockito.when(registry.getApplications()).thenReturn(applications); Application ms1 = applications.getRegisteredApplications().get(0); InstanceInfo instance1 = mock1Instance(); ms1.addInstance(instance1); Mockito.when(registry.getApplication("ms1")).thenReturn(ms1); MetadataMapper metadataMapper = new ServiceMetadataMapper(); instanceInfoMapper.setMetadataMapper(metadataMapper); performAsync("/v1/health/service/ms1?wait=1ms") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$[0].Node.Node", Matchers.is("ms1"))) .andExpect(jsonPath("$[0].Node.Address", Matchers.is("1.2.3.4"))) .andExpect(jsonPath("$[0].Node.Meta").isEmpty()) .andExpect(jsonPath("$[0].Service.ID", Matchers.is("1"))) .andExpect(jsonPath("$[0].Service.Service", Matchers.is("ms1"))) .andExpect(jsonPath("$[0].Service.Address", Matchers.is("1.2.3.4"))) .andExpect(jsonPath("$[0].Service.Port", Matchers.is(80))) .andExpect(jsonPath("$[0].Service.Meta").isEmpty()) .andExpect(jsonPath("$[0].Service.Tags", Matchers.is(new JSONArray()))) .andExpect(jsonPath("$[0].Checks[0].Node", Matchers.is("ms1"))) .andExpect(jsonPath("$[0].Checks[0].CheckID", Matchers.is("service:1"))) .andExpect(jsonPath("$[0].Checks[0].Name", Matchers.is("Service '1' check"))) .andExpect(jsonPath("$[0].Checks[0].Status", Matchers.is("UP"))); InstanceInfo instance2 = mock1Instance("2","1.2.3.5", "ms2.com", 81, true); Map<String, String> md = new HashMap<>(); md.put("k1", "v1"); md.put("k2", "v2"); Mockito.when(instance2.getMetadata()).thenReturn(md); ms1.addInstance(instance2); performAsync("/v1/health/service/ms1?wait=1ms") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$[0].Node.Node", Matchers.is("ms1"))) .andExpect(jsonPath("$[0].Node.Address", Matchers.is("1.2.3.4"))) .andExpect(jsonPath("$[0].Node.Meta").isEmpty()) .andExpect(jsonPath("$[0].Service.ID", Matchers.is("1"))) .andExpect(jsonPath("$[0].Service.Service", Matchers.is("ms1"))) .andExpect(jsonPath("$[0].Service.Address", Matchers.is("1.2.3.4"))) .andExpect(jsonPath("$[0].Service.Port", Matchers.is(80))) .andExpect(jsonPath("$[0].Service.Meta").isEmpty()) .andExpect(jsonPath("$[0].Service.Tags", Matchers.is(new JSONArray()))) .andExpect(jsonPath("$[0].Checks[0].Node", Matchers.is("ms1"))) .andExpect(jsonPath("$[0].Checks[0].CheckID", Matchers.is("service:1"))) .andExpect(jsonPath("$[0].Checks[0].Name", Matchers.is("Service '1' check"))) .andExpect(jsonPath("$[0].Checks[0].Status", Matchers.is("UP"))) .andExpect(jsonPath("$[1].Node.Node", Matchers.is("ms1"))) .andExpect(jsonPath("$[1].Node.Address", Matchers.is("1.2.3.5"))) .andExpect(jsonPath("$[1].Node.Meta").isEmpty()) .andExpect(jsonPath("$[1].Service.ID", Matchers.is("2"))) .andExpect(jsonPath("$[1].Service.Service", Matchers.is("ms1"))) .andExpect(jsonPath("$[1].Service.Address", Matchers.is("1.2.3.5"))) .andExpect(jsonPath("$[1].Service.Port", Matchers.is(443))) .andExpect(jsonPath("$[1].Service.Meta.k1", Matchers.is("v1"))) .andExpect(jsonPath("$[1].Service.Meta.k2", Matchers.is("v2"))) .andExpect(jsonPath("$[1].Service.Tags", Matchers.is(new JSONArray()))) .andExpect(jsonPath("$[1].Checks[0].Node", Matchers.is("ms1"))) .andExpect(jsonPath("$[1].Checks[0].CheckID", Matchers.is("service:2"))) .andExpect(jsonPath("$[1].Checks[0].Name", Matchers.is("Service '2' check"))) .andExpect(jsonPath("$[1].Checks[0].Status", Matchers.is("UP"))); } @Test(timeout = 10000) public void service_serviceChangesToOtherServices_interruptOnCorrectService() throws Exception { Applications applications = mock2Applications(); Mockito.when(registry.getApplications()).thenReturn(applications); Application ms1 = applications.getRegisteredApplications().get(0); InstanceInfo instance1 = mock1Instance(); ms1.addInstance(instance1); Mockito.when(registry.getApplication("ms1")).thenReturn(ms1); startThread(() -> { sleepFor(1000); serviceChangeDetector.publish("ms1", 2); sleepFor(500); serviceChangeDetector.publish("ms2", 1); serviceChangeDetector.publish("ms3", 1); serviceChangeDetector.publish("ms4", 1); sleepFor(500); Mockito.when(instance1.getIPAddr()).thenReturn("8.8.8.8"); serviceChangeDetector.publish("ms1", 3); }); performAsync("/v1/catalog/service/ms1?wait=30s") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(header().string("X-Consul-Index", "1")) .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$[0].Address", Matchers.is("1.2.3.4"))); performAsync("/v1/catalog/service/ms1?wait=30s&index=1") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(header().string("X-Consul-Index", "2")) .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$[0].Address", Matchers.is("1.2.3.4"))); performAsync("/v1/catalog/service/ms1?wait=30s&index=2") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(header().string("X-Consul-Index", "3")) .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$[0].Address", Matchers.is("8.8.8.8"))); } @Test(timeout = 3000) public void service_eventInterruptsRequestError_isResolved() throws Exception { Applications applications = mock2Applications(); Mockito.when(registry.getApplications()).thenReturn(applications); Application ms1 = applications.getRegisteredApplications().get(0); InstanceInfo instance1 = mock1Instance(); ms1.addInstance(instance1); Mockito.when(registry.getApplication("ms1")).thenReturn(ms1); startThread(() -> { sleepFor(500); serviceChangeDetector.publish("ms2", 1); sleepFor(500); serviceChangeDetector.publish("ms2", 2); sleepFor(500); serviceChangeDetector.publish("ms2", 3); sleepFor(500); serviceChangeDetector.publish("ms2", 4); sleepFor(500); serviceChangeDetector.publish("ms2", 5); }); long t1 = System.currentTimeMillis(); performAsync("/v1/catalog/service/ms1?wait=2s&index=1") .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(header().string("X-Consul-Index", "1")) .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$[0].Address", Matchers.is("1.2.3.4"))); Assert.assertThat(System.currentTimeMillis() - t1, Matchers.is(Matchers.greaterThan(2000L))); } private Applications mock2Applications() { Applications applications = new Applications(); Application app1 = new Application(); app1.setName("ms1"); applications.addApplication(app1); Application app2 = new Application(); app2.setName("ms2"); applications.addApplication(app2); return applications; } private void startThread(Runnable t) { executorService1.submit(t); } private InstanceInfo mock1Instance() { return mock1Instance("1", "1.2.3.4", "ms1.com", 80, false); } private InstanceInfo mock1Instance(String id, String ip, String hostName, int port, boolean securePort) { InstanceInfo instance1 = Mockito.mock(InstanceInfo.class); Mockito.when(instance1.getId()).thenReturn(id); Mockito.when(instance1.getAppName()).thenReturn("ms1"); Mockito.when(instance1.getHostName()).thenReturn(hostName); Mockito.when(instance1.getIPAddr()).thenReturn(ip); Mockito.when(instance1.getPort()).thenReturn(port); Mockito.when(instance1.isPortEnabled(InstanceInfo.PortType.SECURE)).thenReturn(securePort); Mockito.when(instance1.getSecurePort()).thenReturn(443); Mockito.when(instance1.getStatus()).thenReturn(InstanceInfo.InstanceStatus.UP); return instance1; } private void sleepFor(final int millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { Assert.fail(); } } }