blob: b140ad745e611cb5b203d61ec10f9cf1f399d439 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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.apache.geode.internal.cache;
import static org.apache.geode.distributed.internal.InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS_PROPERTY;
import static org.apache.geode.internal.cache.InternalCacheBuilderAllowsMultipleSystemsTest.CacheState.CLOSED;
import static org.apache.geode.internal.cache.InternalCacheBuilderAllowsMultipleSystemsTest.CacheState.OPEN;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import java.util.Properties;
import java.util.function.Consumer;
import java.util.function.Supplier;
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
import org.assertj.core.api.ThrowableAssert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.RestoreSystemProperties;
import org.mockito.Mock;
import org.apache.geode.cache.CacheExistsException;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.cache.InternalCacheBuilder.InternalCacheConstructor;
import org.apache.geode.internal.cache.InternalCacheBuilder.InternalDistributedSystemConstructor;
import org.apache.geode.internal.metrics.CompositeMeterRegistryFactory;
/**
* Unit tests for {@link InternalCacheBuilder} when
* {@code InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS} is set to true.
*/
public class InternalCacheBuilderAllowsMultipleSystemsTest {
@Rule
public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
private static final int ANY_SYSTEM_ID = 12;
private static final String ANY_MEMBER_NAME = "a-member-name";
private static final String ANY_HOST_NAME = "a-host-name";
private static final Supplier<InternalDistributedSystem> THROWING_SYSTEM_SUPPLIER =
() -> {
throw new AssertionError("throwing system supplier");
};
private static final Supplier<InternalCache> THROWING_CACHE_SUPPLIER =
() -> {
throw new AssertionError("throwing cache supplier");
};
private static final InternalDistributedSystemConstructor THROWING_SYSTEM_CONSTRUCTOR =
(a, b) -> {
throw new AssertionError("throwing system constructor");
};
private static final InternalCacheConstructor THROWING_CACHE_CONSTRUCTOR =
(a, b, c, d, e, f, g, addedMeterSubregistries) -> {
throw new AssertionError("throwing cache constructor");
};
@Mock
private CompositeMeterRegistryFactory compositeMeterRegistryFactory;
@Mock
private Consumer<CompositeMeterRegistry> metricsSessionInitializer;
@Before
public void setUp() {
initMocks(this);
System.setProperty(ALLOW_MULTIPLE_SYSTEMS_PROPERTY, "true");
}
@Test
public void create_throwsNullPointerException_ifConfigPropertiesIsNull() {
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
null, new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, constructorOf(constructedSystem()),
THROWING_CACHE_SUPPLIER, constructorOf(constructedCache()));
Throwable thrown = catchThrowable(() -> internalCacheBuilder
.create());
assertThat(thrown).isInstanceOf(NullPointerException.class);
}
@Test
public void create_throwsNullPointerException_andCacheConfigIsNull() {
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), null,
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, constructorOf(constructedSystem()),
THROWING_CACHE_SUPPLIER, constructorOf(constructedCache()));
Throwable thrown = catchThrowable(() -> internalCacheBuilder
.create());
assertThat(thrown).isInstanceOf(NullPointerException.class);
}
@Test
public void create_constructsSystem_withGivenProperties_ifNoSystemExists() {
InternalCache constructedCache = constructedCache();
InternalDistributedSystemConstructor systemConstructor = constructorOf(constructedSystem());
Properties configProperties = new Properties();
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
configProperties, new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, systemConstructor,
THROWING_CACHE_SUPPLIER, constructorOf(constructedCache));
internalCacheBuilder.create();
verify(systemConstructor).construct(same(configProperties), any());
}
@Test
public void create_returnsConstructedCache_ifNoSystemExists() {
InternalCache constructedCache = constructedCache();
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, constructorOf(constructedSystem()),
THROWING_CACHE_SUPPLIER, constructorOf(constructedCache));
InternalCache result = internalCacheBuilder.create();
assertThat(result).isSameAs(constructedCache);
}
@Test
public void create_setsConstructedCache_onConstructedSystem_ifNoSystemExists() {
InternalDistributedSystem constructedSystem = constructedSystem();
InternalCache constructedCache = constructedCache();
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, constructorOf(constructedSystem),
THROWING_CACHE_SUPPLIER, constructorOf(constructedCache));
internalCacheBuilder.create();
verify(constructedSystem).setCache(same(constructedCache));
}
@Test
public void create_setsConstructedSystem_onConstructedCache_ifNoSystemExists() {
InternalDistributedSystem constructedSystem = constructedSystem();
InternalCacheConstructor cacheConstructor = constructorOf(constructedCache());
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, constructorOf(constructedSystem),
THROWING_CACHE_SUPPLIER, cacheConstructor);
internalCacheBuilder.create();
verify(cacheConstructor).construct(anyBoolean(), any(), same(constructedSystem), any(),
anyBoolean(), any(), any(), any());
}
@Test
public void createWithSystem_throwsNullPointerException_ifSystemIsNull() {
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, THROWING_SYSTEM_CONSTRUCTOR,
THROWING_CACHE_SUPPLIER, THROWING_CACHE_CONSTRUCTOR);
Throwable thrown = catchThrowable(() -> internalCacheBuilder.create(null));
assertThat(thrown).isInstanceOf(NullPointerException.class);
}
@Test
public void createWithSystem_returnsConstructedCache_ifSystemCacheDoesNotExist() {
InternalCache constructedCache = constructedCache();
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, THROWING_SYSTEM_CONSTRUCTOR,
THROWING_CACHE_SUPPLIER, constructorOf(constructedCache));
InternalCache result = internalCacheBuilder
.create(givenSystem());
assertThat(result).isSameAs(constructedCache);
}
@Test
public void createWithSystem_setsConstructedCache_onGivenSystem_ifSystemCacheDoesNotExist() {
InternalDistributedSystem givenSystem = givenSystem();
InternalCache constructedCache = constructedCache();
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, THROWING_SYSTEM_CONSTRUCTOR,
THROWING_CACHE_SUPPLIER, constructorOf(constructedCache));
internalCacheBuilder
.create(givenSystem);
verify(givenSystem).setCache(same(constructedCache));
}
@Test
public void createWithSystem_setsGivenSystem_onConstructedCache_ifSystemCacheDoesNotExist() {
InternalDistributedSystem givenSystem = givenSystem();
InternalCacheConstructor cacheConstructor = constructorOf(constructedCache());
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, THROWING_SYSTEM_CONSTRUCTOR,
THROWING_CACHE_SUPPLIER, cacheConstructor);
internalCacheBuilder
.create(givenSystem);
verify(cacheConstructor).construct(anyBoolean(), any(), same(givenSystem), any(),
anyBoolean(), any(), any(), any());
}
@Test
public void createWithSystem_returnsConstructedCache_ifSystemCacheIsClosed() {
InternalDistributedSystem givenSystem = givenSystemWithCache(CLOSED);
InternalCache constructedCache = constructedCache();
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, THROWING_SYSTEM_CONSTRUCTOR,
THROWING_CACHE_SUPPLIER, constructorOf(constructedCache));
InternalCache result = internalCacheBuilder
.create(givenSystem);
assertThat(result).isSameAs(constructedCache);
}
@Test
public void createWithSystem_setsConstructedCache_onGivenSystem_ifSystemCacheIsClosed() {
InternalDistributedSystem givenSystem = givenSystemWithCache(CLOSED);
InternalCache constructedCache = constructedCache();
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, THROWING_SYSTEM_CONSTRUCTOR,
THROWING_CACHE_SUPPLIER, constructorOf(constructedCache));
internalCacheBuilder
.create(givenSystem);
verify(givenSystem).setCache(same(constructedCache));
}
@Test
public void createWithSystem_setsGivenSystem_onConstructedCache_ifSystemCacheIsClosed() {
InternalDistributedSystem givenSystem = givenSystemWithCache(CLOSED);
InternalCacheConstructor cacheConstructor = constructorOf(constructedCache());
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, THROWING_SYSTEM_CONSTRUCTOR,
THROWING_CACHE_SUPPLIER, cacheConstructor);
internalCacheBuilder
.create(givenSystem);
verify(cacheConstructor).construct(anyBoolean(), any(), same(givenSystem), any(),
anyBoolean(), any(), any(), any());
}
@Test
public void createWithSystem_throwsCacheExistsException_ifSystemCacheIsOpen_butExistingNotOk() {
InternalDistributedSystem givenSystem = givenSystemWithCache(OPEN);
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, THROWING_SYSTEM_CONSTRUCTOR,
THROWING_CACHE_SUPPLIER, THROWING_CACHE_CONSTRUCTOR);
Throwable thrown = catchThrowable(() -> internalCacheBuilder
.setIsExistingOk(false)
.create(givenSystem));
assertThat(thrown).isInstanceOf(CacheExistsException.class);
}
@Test
public void createWithSystem_doesNotSetSystemCache_onGivenSystem__ifSystemCacheIsOpen_butExistingNotOk() {
InternalDistributedSystem givenSystem = givenSystemWithCache(OPEN);
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, THROWING_SYSTEM_CONSTRUCTOR,
THROWING_CACHE_SUPPLIER, THROWING_CACHE_CONSTRUCTOR);
ignoreThrowable(() -> internalCacheBuilder
.setIsExistingOk(false)
.create(givenSystem));
verify(givenSystem, never()).setCache(any());
}
@Test
public void createWithSystem_propagatesCacheConfigException_ifSystemCacheIsOpen_andExistingOk_butCacheIsIncompatible() {
InternalDistributedSystem givenSystem = givenSystemWithCache(OPEN);
Throwable thrownByCacheConfig = new IllegalStateException("incompatible");
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), throwingCacheConfig(thrownByCacheConfig),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, THROWING_SYSTEM_CONSTRUCTOR,
THROWING_CACHE_SUPPLIER, THROWING_CACHE_CONSTRUCTOR);
Throwable thrown = catchThrowable(() -> internalCacheBuilder
.setIsExistingOk(true)
.create(givenSystem));
assertThat(thrown).isSameAs(thrownByCacheConfig);
}
@Test
public void createWithSystem_doesNotSetSystemCache_onGivenSystem_ifSystemCacheIsOpen_andExistingOk_butCacheIsNotCompatible() {
InternalDistributedSystem givenSystem = givenSystemWithCache(OPEN);
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), throwingCacheConfig(new IllegalStateException("incompatible")),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, THROWING_SYSTEM_CONSTRUCTOR,
THROWING_CACHE_SUPPLIER, THROWING_CACHE_CONSTRUCTOR);
ignoreThrowable(() -> internalCacheBuilder
.setIsExistingOk(true)
.create(givenSystem));
verify(givenSystem, never()).setCache(any());
}
@Test
public void createWithSystem_returnsSystemCache_ifSystemCacheIsOpen_andExistingOk_andCacheIsCompatible() {
InternalDistributedSystem givenSystem = givenSystem();
InternalCache systemCache = systemCache(givenSystem, OPEN);
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, THROWING_SYSTEM_CONSTRUCTOR,
THROWING_CACHE_SUPPLIER, THROWING_CACHE_CONSTRUCTOR);
InternalCache result = internalCacheBuilder
.setIsExistingOk(true)
.create(givenSystem);
assertThat(result).isSameAs(systemCache);
}
@Test
public void createWithSystem_setsSystemCache_onGivenSystem_ifSystemCacheIsOpen_andExistingOk_andCacheIsCompatible() {
InternalDistributedSystem givenSystem = givenSystem();
InternalCache systemCache = systemCache(givenSystem, OPEN);
InternalCacheBuilder internalCacheBuilder = new InternalCacheBuilder(
new Properties(), new CacheConfig(),
compositeMeterRegistryFactory, metricsSessionInitializer,
THROWING_SYSTEM_SUPPLIER, THROWING_SYSTEM_CONSTRUCTOR,
THROWING_CACHE_SUPPLIER, THROWING_CACHE_CONSTRUCTOR);
internalCacheBuilder
.setIsExistingOk(true)
.create(givenSystem);
verify(givenSystem).setCache(same(systemCache));
}
private InternalDistributedSystem constructedSystem() {
return systemWith("constructedSystem", ANY_SYSTEM_ID, ANY_MEMBER_NAME, ANY_HOST_NAME);
}
private InternalDistributedSystem givenSystem() {
return systemWith("givenSystem", ANY_SYSTEM_ID, ANY_MEMBER_NAME, ANY_HOST_NAME);
}
private InternalDistributedSystem systemWith(String mockName, int systemId, String memberName,
String hostName) {
InternalDistributedSystem system = mock(InternalDistributedSystem.class, mockName);
DistributionConfig distributionConfig = mock(DistributionConfig.class);
InternalDistributedMember distributedMember = mock(InternalDistributedMember.class);
when(distributionConfig.getDistributedSystemId()).thenReturn(systemId);
when(distributedMember.getHost()).thenReturn(hostName);
when(system.getConfig()).thenReturn(distributionConfig);
when(system.getDistributedMember()).thenReturn(distributedMember);
when(system.getName()).thenReturn(memberName);
return system;
}
private InternalDistributedSystem givenSystemWithCache(CacheState state) {
InternalDistributedSystem system =
systemWith("givenSystemWithCache", ANY_SYSTEM_ID, ANY_MEMBER_NAME, ANY_HOST_NAME);
systemCache(system, state);
return system;
}
private static InternalCache constructedCache() {
return cache("constructedCache", OPEN);
}
private static InternalCache systemCache(InternalDistributedSystem givenSystem,
CacheState state) {
InternalCache cache = cache("systemCache", state);
when(givenSystem.getCache()).thenReturn(cache);
return cache;
}
private static InternalCache cache(String name, CacheState state) {
InternalCache cache = mock(InternalCache.class, name);
when(cache.isClosed()).thenReturn(state.isClosed());
doThrow(new CacheExistsException(cache, "cache exists"))
.when(cache).throwCacheExistsException();
return cache;
}
private static InternalDistributedSystemConstructor constructorOf(
InternalDistributedSystem constructedSystem) {
InternalDistributedSystemConstructor constructor =
mock(InternalDistributedSystemConstructor.class, "internal distributed system constructor");
when(constructor.construct(any(), any())).thenReturn(constructedSystem);
return constructor;
}
private static InternalCacheConstructor constructorOf(InternalCache constructedCache) {
InternalCacheConstructor constructor =
mock(InternalCacheConstructor.class, "internal cache constructor");
when(
constructor.construct(anyBoolean(), any(), any(), any(), anyBoolean(), any(), any(), any()))
.thenReturn(constructedCache);
return constructor;
}
private static CacheConfig throwingCacheConfig(Throwable throwable) {
CacheConfig cacheConfig = mock(CacheConfig.class);
doThrow(throwable).when(cacheConfig).validateCacheConfig(any());
return cacheConfig;
}
private static void ignoreThrowable(ThrowableAssert.ThrowingCallable shouldRaiseThrowable) {
try {
shouldRaiseThrowable.call();
} catch (Throwable ignored) {
}
}
enum CacheState {
OPEN(false),
CLOSED(true);
private final boolean isClosed;
CacheState(boolean isClosed) {
this.isClosed = isClosed;
}
boolean isClosed() {
return isClosed;
}
}
}