DATAGEODE-219 - Invoke SmartLifecycle callbacks when defining Regions based on Caching annotations.

This commit is contained in:
John Blum
2019-08-16 00:41:29 -07:00
parent 715cbb2e9e
commit 2a7e9d28db
6 changed files with 454 additions and 12 deletions

View File

@@ -0,0 +1,126 @@
/*
* Copyright 2019 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
*
* https://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.data.gemfire.config.annotation;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.util.Arrays;
import javax.annotation.Resource;
import org.apache.geode.cache.InterestResultPolicy;
import org.apache.geode.cache.Region;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.Lifecycle;
import org.springframework.context.annotation.Bean;
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
import org.springframework.data.gemfire.client.Interest;
import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects;
import org.springframework.data.gemfire.util.ArrayUtils;
import org.springframework.stereotype.Service;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Integration Tests asserting that caching-defined {@link Region Regions} receive a {@link Lifecycle#start()} callback
* to register interests.
*
* @author John Blum
* @see org.junit.Test
* @see org.apache.geode.cache.Region
* @see org.springframework.cache.annotation.Cacheable
* @see org.springframework.context.Lifecycle
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
* @see org.springframework.data.gemfire.client.Interest
* @see org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringRunner
* @see <a href="https://jira.spring.io/browse/DATAGEODE-219">DATAGEODE-219</a>
* @since 2.2.0
*/
@RunWith(SpringRunner.class)
@ContextConfiguration
@SuppressWarnings({ "unchecked", "unused" })
public class CachingDefinedRegionsRegistersInterestsIntegrationTests {
private static final Interest testInterest =
new Interest<>("TestKey", InterestResultPolicy.KEYS_VALUES, false, true);
@Resource(name = "CacheOne")
private Region cacheOne;
@Resource(name = "CacheTwo")
private Region cacheTwo;
@Test
public void cachesRegisterInterestInTestKey() {
assertThat(this.cacheOne).isNotNull();
assertThat(this.cacheOne.getName()).isEqualTo("CacheOne");
assertThat(this.cacheTwo).isNotNull();
assertThat(this.cacheTwo.getName()).isEqualTo("CacheTwo");
Arrays.asList(this.cacheOne, this.cacheTwo).forEach(cache -> {
verify(cache, times(1))
.registerInterest(eq(testInterest.getKey()), eq(testInterest.getPolicy()), eq(testInterest.isDurable()),
eq(testInterest.isReceiveValues()));
});
}
@ClientCacheApplication
@EnableCachingDefinedRegions
@EnableGemFireMockObjects
static class TestConfiguration {
@Bean
RegionConfigurer interestsRegisteringRegionConfigurer() {
return new RegionConfigurer() {
@Override
public void configure(String beanName, ClientRegionFactoryBean<?, ?> bean) {
bean.setInterests(ArrayUtils.asArray(testInterest));
}
};
}
@Bean
CacheableServiceObject cacheableServiceObject() {
return new CacheableServiceObject();
}
}
@Service
static class CacheableServiceObject {
@Cacheable("CacheOne")
public Object cacheableOperationOne(String input) {
return "FROM-CACHE-ONE";
}
@Cacheable("CacheTwo")
public Object cacheableOperationTwo(String input) {
return "FROM-CACHE-TWO";
}
}
}

View File

@@ -0,0 +1,178 @@
/*
* Copyright 2019 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
*
* https://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.data.gemfire.support;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
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.springframework.context.Lifecycle;
/**
* Unit Tests for {@link CompositeLifecycle}.
*
* @author John Blum
* @see org.junit.Test
* @see org.mockito.Mockito
* @see org.springframework.context.Lifecycle
* @see org.springframework.data.gemfire.support.CompositeLifecycle
* @since 2.2.0
*/
public class CompositeLifecycleUnitTests {
private CompositeLifecycle compositeLifecycle;
@Before
public void setup() {
this.compositeLifecycle = new CompositeLifecycle();
}
@Test
public void addLifecycleObjectToCompositeReturnsTrue() {
Lifecycle mockLifecycle = mock(Lifecycle.class);
assertThat(this.compositeLifecycle.add(mockLifecycle)).isTrue();
assertThat(this.compositeLifecycle).isNotEmpty();
assertThat(this.compositeLifecycle).hasSize(1);
assertThat(this.compositeLifecycle).containsExactly(mockLifecycle);
}
@Test
public void addNullReturnsFalse() {
assertThat(this.compositeLifecycle.add(null)).isFalse();
assertThat(this.compositeLifecycle).isEmpty();
assertThat(this.compositeLifecycle).hasSize(0);
}
@Test
public void removeLifecycleObjectReturnsTrue() {
Lifecycle mockLifecycle = mock(Lifecycle.class);
assertThat(this.compositeLifecycle.add(mockLifecycle)).isTrue();
assertThat(this.compositeLifecycle).isNotEmpty();
assertThat(this.compositeLifecycle).hasSize(1);
assertThat(this.compositeLifecycle.remove(mockLifecycle)).isTrue();
assertThat(this.compositeLifecycle).isEmpty();
assertThat(this.compositeLifecycle).hasSize(0);
}
@Test
public void removeNullReturnsFalse() {
assertThat(this.compositeLifecycle).isEmpty();
assertThat(this.compositeLifecycle).hasSize(0);
assertThat(this.compositeLifecycle.remove(null)).isFalse();
}
@Test
public void isAutoStartupReturnsTrue() {
assertThat(this.compositeLifecycle.isAutoStartup()).isTrue();
}
@Test
public void isRunningWithAllRunningLifecycleObjectsReturnsTrue() {
Lifecycle mockLifecycleOne = mock(Lifecycle.class);
Lifecycle mockLifecycleTwo = mock(Lifecycle.class);
when(mockLifecycleOne.isRunning()).thenReturn(true);
assertThat(this.compositeLifecycle.add(mockLifecycleOne)).isTrue();
assertThat(this.compositeLifecycle.add(mockLifecycleTwo)).isTrue();
assertThat(this.compositeLifecycle.isRunning()).isTrue();
verify(mockLifecycleOne, times(1)).isRunning();
verify(mockLifecycleTwo, never()).isRunning();
}
@Test
public void isRunningWithNoLifecycleObjectReturnsFalse() {
assertThat(this.compositeLifecycle.isRunning()).isFalse();
}
@Test
public void isRunningWithNoRunningLifecycleObjectsReturnsFalse() {
Lifecycle mockLifecycleOne = mock(Lifecycle.class);
Lifecycle mockLifecycleTwo = mock(Lifecycle.class);
when(mockLifecycleOne.isRunning()).thenReturn(false);
when(mockLifecycleTwo.isRunning()).thenReturn(false);
assertThat(this.compositeLifecycle.add(mockLifecycleOne)).isTrue();
assertThat(this.compositeLifecycle.add(mockLifecycleTwo)).isTrue();
assertThat(this.compositeLifecycle.isRunning()).isFalse();
verify(mockLifecycleOne, times(1)).isRunning();
verify(mockLifecycleTwo, times(1)).isRunning();
}
@Test
public void isRunningWithOneRunningLifecycleObjectsReturnsTrue() {
Lifecycle mockLifecycleOne = mock(Lifecycle.class);
Lifecycle mockLifecycleTwo = mock(Lifecycle.class);
when(mockLifecycleOne.isRunning()).thenReturn(false);
when(mockLifecycleTwo.isRunning()).thenReturn(true);
assertThat(this.compositeLifecycle.add(mockLifecycleOne)).isTrue();
assertThat(this.compositeLifecycle.add(mockLifecycleTwo)).isTrue();
assertThat(this.compositeLifecycle.isRunning()).isTrue();
verify(mockLifecycleOne, times(1)).isRunning();
verify(mockLifecycleTwo, times(1)).isRunning();
}
@Test
public void startStartsAllLifecycleObjects() {
Lifecycle mockLifecycleOne = mock(Lifecycle.class);
Lifecycle mockLifecycleTwo = mock(Lifecycle.class);
assertThat(this.compositeLifecycle.add(mockLifecycleOne)).isTrue();
assertThat(this.compositeLifecycle.add(mockLifecycleTwo)).isTrue();
this.compositeLifecycle.start();
verify(mockLifecycleOne, times(1)).start();
verify(mockLifecycleTwo, times(1)).start();
}
@Test
public void stopStopsAllLifecycleObjects() {
Lifecycle mockLifecycleOne = mock(Lifecycle.class);
Lifecycle mockLifecycleTwo = mock(Lifecycle.class);
assertThat(this.compositeLifecycle.add(mockLifecycleOne)).isTrue();
assertThat(this.compositeLifecycle.add(mockLifecycleTwo)).isTrue();
this.compositeLifecycle.stop();
verify(mockLifecycleOne, times(1)).stop();
verify(mockLifecycleTwo, times(1)).stop();
}
}