diff --git a/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDiscoveryWithDyingDependenciesISpec.groovy b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDiscoveryWithDyingDependenciesISpec.groovy deleted file mode 100644 index 8b6f1bd9..00000000 --- a/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDiscoveryWithDyingDependenciesISpec.groovy +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2013-2015 the original author or authors. - * - * 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. - */ -package org.springframework.cloud.zookeeper.discovery.dependency - -import org.apache.curator.test.TestingServer -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.boot.builder.SpringApplicationBuilder -import org.springframework.cloud.client.discovery.EnableDiscoveryClient -import org.springframework.cloud.zookeeper.discovery.PollingUtils -import org.springframework.cloud.zookeeper.discovery.test.TestRibbonClient -import org.springframework.context.ApplicationContext -import org.springframework.context.ConfigurableApplicationContext -import org.springframework.context.annotation.Configuration -import org.springframework.context.annotation.Import -import org.springframework.util.SocketUtils -import spock.lang.Issue -import spock.lang.Specification -import spock.util.concurrent.PollingConditions -import spock.util.environment.RestoreSystemProperties - -class ZookeeperDiscoveryWithDyingDependenciesISpec extends Specification implements PollingUtils { - - PollingConditions pollingConditions = new PollingConditions() - - @Issue("#45") - @RestoreSystemProperties - def "should refresh a dependency in Ribbon when the dependency has de-registered and registered in Zookeeper"() { - given: - int zookeeperPort = SocketUtils.findAvailableTcpPort() - TestingServer testingServer = new TestingServer(zookeeperPort) - System.setProperty('spring.jmx.enabled', 'false') - System.setProperty('spring.cloud.zookeeper.connectString', "127.0.0.1:$zookeeperPort") - and: - ConfigurableApplicationContext serverContext = contextWithProfile('server') - ConfigurableApplicationContext clientContext = contextWithProfile('client') - and: - Integer serverPortBeforeDying = callServiceAtPortEndpoint(clientContext) - and: - serverContext = restartContext(serverContext, 'server') - expect: - pollingConditions.within 5, willPass { - assert callServiceAtPortEndpoint(clientContext) != serverPortBeforeDying - } - - cleanup: - serverContext?.close() - clientContext?.close() - testingServer?.close() - } - - private ConfigurableApplicationContext contextWithProfile(String profile) { - return new SpringApplicationBuilder(Config).profiles(profile).build().run() - } - - private ConfigurableApplicationContext restartContext(ConfigurableApplicationContext configurableApplicationContext, String profile) { - configurableApplicationContext.close() - return contextWithProfile(profile) - } - - private Integer callServiceAtPortEndpoint(ApplicationContext applicationContext) { - return applicationContext.getBean(TestRibbonClient).callService('testInstance', 'port', Integer) - } - - @Configuration - @EnableDiscoveryClient - @EnableAutoConfiguration - @Import(DependencyConfig) - static class Config { - } - -} \ No newline at end of file diff --git a/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDiscoveryWithDyingDependenciesTests.java b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDiscoveryWithDyingDependenciesTests.java new file mode 100644 index 00000000..c9a11a10 --- /dev/null +++ b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDiscoveryWithDyingDependenciesTests.java @@ -0,0 +1,108 @@ +package org.springframework.cloud.zookeeper.discovery.dependency; + +import java.io.Closeable; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.curator.test.TestingServer; +import org.assertj.core.api.BDDAssertions; +import org.junit.After; +import org.junit.Test; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.zookeeper.discovery.test.TestRibbonClient; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.util.SocketUtils; + +import static com.jayway.awaitility.Awaitility.await; + +/** + * @author Marcin Grzejszczak + */ +public class ZookeeperDiscoveryWithDyingDependenciesTests { + + private static final Log log = LogFactory.getLog(ZookeeperDiscoveryWithDyingDependenciesTests.class); + + ConfigurableApplicationContext serverContext; + ConfigurableApplicationContext clientContext; + TestingServer testingServer; + + // Issue: #45 + @Test public void should_refresh_a_dependency_in_Ribbon_when_the_dependency_has_deregistered_and_registered_in_Zookeeper() + throws Exception { + //given: + int zookeeperPort = SocketUtils.findAvailableTcpPort(); + this.testingServer = new TestingServer(zookeeperPort); + System.setProperty("spring.jmx.enabled", "false"); + System.setProperty("spring.cloud.zookeeper.connectString", "127.0.0.1:"+zookeeperPort); + //and: + this.serverContext = contextWithProfile("server"); + this.clientContext = contextWithProfile("client"); + //and: + final Integer serverPortBeforeDying = callServiceAtPortEndpoint(this.clientContext); + //and: + this.serverContext = restartContext(this.serverContext, "server"); + //expect: + await().atMost(5, TimeUnit.SECONDS).until( + applicationHasStartedOnANewPort(ZookeeperDiscoveryWithDyingDependenciesTests.this.clientContext, serverPortBeforeDying) + ); + } + + @After + public void cleanup() throws Exception { + //cleanup: + close(this.serverContext); + close(this.clientContext); + close(this.testingServer); + System.setProperty("spring.jmx.enabled", "false"); + System.setProperty("spring.cloud.zookeeper.connectString", ""); + } + + private Callable applicationHasStartedOnANewPort( + final ConfigurableApplicationContext clientContext, + final Integer serverPortBeforeDying) { + return new Callable() { + @Override public Boolean call() throws Exception { + try { + BDDAssertions.then(callServiceAtPortEndpoint(clientContext)).isNotEqualTo(serverPortBeforeDying); + } catch (Exception e) { + log.error("Exception occurred while trying to call the server", e); + return false; + } + return true; + } + }; + } + + private void close(Closeable closeable) throws IOException { + if(closeable != null) { + closeable.close(); + } + } + + private ConfigurableApplicationContext contextWithProfile(String profile) { + return new SpringApplicationBuilder(Config.class).profiles(profile).build().run(); + } + + private ConfigurableApplicationContext restartContext(ConfigurableApplicationContext configurableApplicationContext, String profile) { + configurableApplicationContext.close(); + return contextWithProfile(profile); + } + + private Integer callServiceAtPortEndpoint(ApplicationContext applicationContext) { + return applicationContext.getBean(TestRibbonClient.class).callService("testInstance", "port", Integer.class); + } + + @Configuration + @EnableDiscoveryClient + @EnableAutoConfiguration + @Import(DependencyConfig.class) + static class Config { } +} diff --git a/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/presence/DefaultDependencyPresenceOnStartupVerifierSpec.groovy b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/presence/DefaultDependencyPresenceOnStartupVerifierSpec.groovy deleted file mode 100644 index 0a682f3e..00000000 --- a/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/presence/DefaultDependencyPresenceOnStartupVerifierSpec.groovy +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2013-2015 the original author or authors. - * - * 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. - */ -package org.springframework.cloud.zookeeper.discovery.watcher.presence - -import org.apache.curator.x.discovery.ServiceCache -import org.codehaus.groovy.runtime.StackTraceUtils -import spock.lang.Specification - -class DefaultDependencyPresenceOnStartupVerifierSpec extends Specification { - - private static final String SERVICE_NAME = 'service01' - - def 'should throw exception if obligatory dependencies are missing'() { - given: - DefaultDependencyPresenceOnStartupVerifier dependencyVerifier = new DefaultDependencyPresenceOnStartupVerifier() - ServiceCache serviceCache = Mock() - serviceCache.instances >> [] - when: - dependencyVerifier.verifyDependencyPresence(SERVICE_NAME, serviceCache, true) - then: - Throwable thrown = thrown(Throwable) - StackTraceUtils.extractRootCause(thrown).class == NoInstancesRunningException - } - -} diff --git a/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/presence/DefaultDependencyPresenceOnStartupVerifierTests.java b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/presence/DefaultDependencyPresenceOnStartupVerifierTests.java new file mode 100644 index 00000000..cf3beaa8 --- /dev/null +++ b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/presence/DefaultDependencyPresenceOnStartupVerifierTests.java @@ -0,0 +1,34 @@ +package org.springframework.cloud.zookeeper.discovery.watcher.presence; + +import java.util.Collections; + +import org.apache.curator.x.discovery.ServiceCache; +import org.assertj.core.api.BDDAssertions; +import org.junit.Assert; +import org.junit.Test; + +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +/** + * @author Marcin Grzejszczak + */ +public class DefaultDependencyPresenceOnStartupVerifierTests { + + private static final String SERVICE_NAME = "service01"; + + @Test public void should_throw_exception_if_obligatory_dependencies_are_missing() { + //given: + DefaultDependencyPresenceOnStartupVerifier dependencyVerifier = new DefaultDependencyPresenceOnStartupVerifier(); + ServiceCache serviceCache = mock(ServiceCache.class); + given(serviceCache.getInstances()).willReturn(Collections.emptyList()); + //when: + try { + dependencyVerifier.verifyDependencyPresence(SERVICE_NAME, serviceCache, true); + Assert.fail("Should throw no instances running exception"); + } catch (Exception e) { + //then: + BDDAssertions.then(e).isInstanceOf(NoInstancesRunningException.class); + } + } +}