package rocks.inspectit.server.instrumentation;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.slf4j.Logger;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import rocks.inspectit.server.event.AgentRegisteredEvent;
import rocks.inspectit.server.instrumentation.classcache.ClassCache;
import rocks.inspectit.server.instrumentation.classcache.ClassCacheInstrumentation;
import rocks.inspectit.server.instrumentation.classcache.ClassCacheLookup;
import rocks.inspectit.server.instrumentation.classcache.ClassCacheModification;
import rocks.inspectit.server.instrumentation.classcache.ClassCacheModificationException;
import rocks.inspectit.server.instrumentation.config.ConfigurationHolder;
import rocks.inspectit.server.instrumentation.config.ConfigurationResolver;
import rocks.inspectit.server.instrumentation.config.applier.IInstrumentationApplier;
import rocks.inspectit.server.instrumentation.config.applier.JmxMonitoringApplier;
import rocks.inspectit.shared.all.exception.BusinessException;
import rocks.inspectit.shared.all.instrumentation.classcache.ClassType;
import rocks.inspectit.shared.all.instrumentation.classcache.ImmutableType;
import rocks.inspectit.shared.all.instrumentation.classcache.Type;
import rocks.inspectit.shared.all.instrumentation.config.impl.AgentConfig;
import rocks.inspectit.shared.all.instrumentation.config.impl.InstrumentationDefinition;
import rocks.inspectit.shared.all.instrumentation.config.impl.JmxAttributeDescriptor;
import rocks.inspectit.shared.all.testbase.TestBase;
import rocks.inspectit.shared.cs.ci.Environment;
import rocks.inspectit.shared.cs.cmr.service.IRegistrationService;
/**
* @author Ivan Senic
*
*/
@SuppressWarnings({ "PMD", "unchecked" })
public class NextGenInstrumentationManagerTest extends TestBase {
@InjectMocks
NextGenInstrumentationManager manager;
@Mock
Logger log;
@Mock
ObjectFactory<ClassCache> classCacheFactory;
@Mock
ObjectFactory<ConfigurationHolder> configurationHolderFactory;
@Mock
IRegistrationService registrationService;
@Mock
ConfigurationResolver configurationResolver;
@Mock
ExecutorService executor;
@Mock
ClassCache classCache;
@Mock
ConfigurationHolder configurationHolder;
@Mock
ClassCacheInstrumentation instrumentationService;
@Mock
ClassCacheLookup lookupService;
@Mock
ClassCacheModification modificationService;
@Mock
ApplicationEventPublisher eventPublisher;
@BeforeMethod
public void setup() {
when(classCacheFactory.getObject()).thenReturn(classCache);
when(configurationHolderFactory.getObject()).thenReturn(configurationHolder);
when(classCache.getInstrumentationService()).thenReturn(instrumentationService);
when(classCache.getLookupService()).thenReturn(lookupService);
when(classCache.getModificationService()).thenReturn(modificationService);
doAnswer(new Answer<Future<?>>() {
@Override
public Future<?> answer(InvocationOnMock invocation) throws Throwable {
Runnable runnable = (Runnable) invocation.getArguments()[0];
runnable.run();
return null;
}
}).when(executor).submit(any(Runnable.class));
}
public class Register extends NextGenInstrumentationManagerTest {
@Test(expectedExceptions = BusinessException.class)
public void noMappingsForAgent() throws BusinessException {
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
when(configurationResolver.getEnvironmentForAgent(definedIPs, agentName)).thenThrow(new BusinessException(null));
manager.register(definedIPs, agentName, version);
}
@Test
public void newAgent() throws BusinessException {
long id = 10;
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
final AgentConfig configuration = mock(AgentConfig.class);
Environment environment = mock(Environment.class);
when(configurationResolver.getEnvironmentForAgent(definedIPs, agentName)).thenReturn(environment);
when(registrationService.registerPlatformIdent(definedIPs, agentName, version)).thenReturn(id);
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
when(configurationHolder.getAgentConfiguration()).thenReturn(configuration);
return null;
}
}).when(configurationHolder).update(environment, id);
AgentConfig result = manager.register(definedIPs, agentName, version);
assertThat(result, is(configuration));
ArgumentCaptor<AgentRegisteredEvent> eventCaptor = ArgumentCaptor.forClass(AgentRegisteredEvent.class);
verify(eventPublisher).publishEvent(eventCaptor.capture());
assertThat(eventCaptor.getValue().getPlatformId(), is(equalTo(id)));
verify(configurationResolver).getEnvironmentForAgent(definedIPs, agentName);
verify(registrationService).registerPlatformIdent(definedIPs, agentName, version);
verify(configurationHolder).update(environment, id);
verify(configurationHolder).getEnvironment();
verify(configurationHolder).getAgentConfiguration();
verify(configurationHolder).isInitialized();
verify(executor).submit(any(Runnable.class));
verifyNoMoreInteractions(configurationResolver, registrationService, configurationHolder, eventPublisher, executor);
verifyZeroInteractions(classCache);
}
@Test
public void existingAgent() throws BusinessException {
long id = 10;
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
final AgentConfig configuration = mock(AgentConfig.class);
Environment environment = mock(Environment.class);
when(configurationResolver.getEnvironmentForAgent(definedIPs, agentName)).thenReturn(environment);
when(registrationService.registerPlatformIdent(definedIPs, agentName, version)).thenReturn(id);
when(configurationHolder.isInitialized()).thenReturn(true);
when(configurationHolder.getEnvironment()).thenReturn(environment);
when(configurationHolder.getAgentConfiguration()).thenReturn(configuration);
Map<Collection<String>, InstrumentationDefinition> initialInstrumentations = mock(Map.class);
when(instrumentationService.getInstrumentationResultsWithHashes()).thenReturn(initialInstrumentations);
AgentConfig result = manager.register(definedIPs, agentName, version);
assertThat(result, is(configuration));
verify(configurationResolver).getEnvironmentForAgent(definedIPs, agentName);
verify(registrationService).registerPlatformIdent(definedIPs, agentName, version);
verify(configurationHolder).getEnvironment();
verify(configurationHolder).getAgentConfiguration();
verify(configurationHolder).isInitialized();
verify(configuration).setInitialInstrumentationResults(initialInstrumentations);
verify(configuration).setClassCacheExistsOnCmr(true);
verify(classCache).getInstrumentationService();
verify(instrumentationService).getInstrumentationResultsWithHashes();
verifyNoMoreInteractions(configurationResolver, registrationService, configurationHolder, instrumentationService, classCache);
}
@Test
public void existingAgentNoEnvironment() throws BusinessException {
long id = 10;
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
final AgentConfig configuration = mock(AgentConfig.class);
Environment environment = mock(Environment.class);
when(configurationResolver.getEnvironmentForAgent(definedIPs, agentName)).thenReturn(environment);
when(registrationService.registerPlatformIdent(definedIPs, agentName, version)).thenReturn(id);
when(configurationHolder.isInitialized()).thenReturn(false);
when(configurationHolder.getEnvironment()).thenReturn(environment);
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
when(configurationHolder.getAgentConfiguration()).thenReturn(configuration);
return null;
}
}).when(configurationHolder).update(environment, id);
AgentConfig result = manager.register(definedIPs, agentName, version);
assertThat(result, is(configuration));
verify(configurationResolver).getEnvironmentForAgent(definedIPs, agentName);
verify(registrationService).registerPlatformIdent(definedIPs, agentName, version);
verify(configurationHolder).update(environment, id);
verify(configurationHolder).getEnvironment();
verify(configurationHolder).getAgentConfiguration();
verify(configurationHolder).isInitialized();
verifyNoMoreInteractions(configurationResolver, registrationService, configurationHolder);
verifyZeroInteractions(classCache);
}
@Test
public void existingAgentDifferentEnvironment() throws BusinessException {
long id = 10;
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
final AgentConfig configuration = mock(AgentConfig.class);
Environment environment = mock(Environment.class);
Environment newEnvironment = mock(Environment.class);
when(configurationResolver.getEnvironmentForAgent(definedIPs, agentName)).thenReturn(newEnvironment);
when(registrationService.registerPlatformIdent(definedIPs, agentName, version)).thenReturn(id);
when(configurationHolder.isInitialized()).thenReturn(true);
when(configurationHolder.getEnvironment()).thenReturn(environment);
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
when(configurationHolder.getAgentConfiguration()).thenReturn(configuration);
return null;
}
}).when(configurationHolder).update(newEnvironment, id);
AgentConfig result = manager.register(definedIPs, agentName, version);
assertThat(result, is(configuration));
verify(configurationResolver).getEnvironmentForAgent(definedIPs, agentName);
verify(registrationService).registerPlatformIdent(definedIPs, agentName, version);
verify(configurationHolder).update(newEnvironment, id);
verify(configurationHolder).getEnvironment();
verify(configurationHolder).getAgentConfiguration();
verify(configurationHolder).isInitialized();
verifyNoMoreInteractions(configurationResolver, registrationService, configurationHolder);
verifyZeroInteractions(classCache);
}
}
public class Unregister extends NextGenInstrumentationManagerTest {
@Test
public void unregister() throws Exception {
long platformId = 10L;
manager.unregister(platformId);
verify(registrationService).unregisterPlatformIdent(platformId);
}
}
public class Analyze extends NextGenInstrumentationManagerTest {
@Mock
private Type type;
private final static String HASH = "hash";
private final static long ID = 10;
@Test(expectedExceptions = BusinessException.class)
public void agentNotRegistered() throws BusinessException {
manager.analyze(ID, HASH, type);
}
@Test
public void nonExistingNonClassType() throws BusinessException, ClassCacheModificationException {
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
when(registrationService.registerPlatformIdent(definedIPs, agentName, version)).thenReturn(ID);
manager.register(definedIPs, agentName, version);
ImmutableType typeFromClassCache = mock(ImmutableType.class);
when(typeFromClassCache.isClass()).thenReturn(false);
when(lookupService.findByHash(HASH)).thenReturn(null, typeFromClassCache);
InstrumentationDefinition result = manager.analyze(ID, HASH, type);
assertThat(result, is(nullValue()));
verify(modificationService).merge(type);
verifyNoMoreInteractions(modificationService);
verifyZeroInteractions(instrumentationService);
}
@Test
public void existingNonClassType() throws BusinessException, ClassCacheModificationException {
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
when(registrationService.registerPlatformIdent(definedIPs, agentName, version)).thenReturn(ID);
manager.register(definedIPs, agentName, version);
ImmutableType typeFromClassCache = mock(ImmutableType.class);
when(typeFromClassCache.isClass()).thenReturn(false);
when(lookupService.findByHash(HASH)).thenReturn(typeFromClassCache);
InstrumentationDefinition result = manager.analyze(ID, HASH, type);
assertThat(result, is(nullValue()));
verifyZeroInteractions(modificationService, instrumentationService);
}
@Test
public void existingClassTypeConfigurationNotInitialized() throws BusinessException, ClassCacheModificationException {
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
when(registrationService.registerPlatformIdent(definedIPs, agentName, version)).thenReturn(ID);
manager.register(definedIPs, agentName, version);
ClassType classType = mock(ClassType.class);
when(classType.isClass()).thenReturn(true);
when(classType.castToClass()).thenReturn(classType);
when(lookupService.findByHash(HASH)).thenReturn(classType);
when(configurationHolder.isInitialized()).thenReturn(false);
InstrumentationDefinition result = manager.analyze(ID, HASH, type);
assertThat(result, is(nullValue()));
verifyZeroInteractions(modificationService, instrumentationService);
}
@Test
public void existingClassTypeInstrumented() throws BusinessException, ClassCacheModificationException {
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
when(registrationService.registerPlatformIdent(definedIPs, agentName, version)).thenReturn(ID);
manager.register(definedIPs, agentName, version);
ClassType classType = mock(ClassType.class);
when(classType.isClass()).thenReturn(true);
when(classType.castToClass()).thenReturn(classType);
when(lookupService.findByHash(HASH)).thenReturn(classType);
when(configurationHolder.isInitialized()).thenReturn(true);
AgentConfig configuration = mock(AgentConfig.class);
Collection<IInstrumentationApplier> appliers = mock(Collection.class);
InstrumentationDefinition instrumentationResult = mock(InstrumentationDefinition.class);
when(configurationHolder.getAgentConfiguration()).thenReturn(configuration);
when(configurationHolder.getInstrumentationAppliers()).thenReturn(appliers);
when(instrumentationService.addAndGetInstrumentationResult(classType, configuration, appliers)).thenReturn(instrumentationResult);
InstrumentationDefinition result = manager.analyze(ID, HASH, type);
assertThat(result, is(instrumentationResult));
verify(instrumentationService).addAndGetInstrumentationResult(classType, configuration, appliers);
verifyNoMoreInteractions(instrumentationService);
verifyZeroInteractions(modificationService);
}
}
public class AnalyzeJmxAttributes extends NextGenInstrumentationManagerTest {
private final static long ID = 10;
@Mock
JmxAttributeDescriptor descriptor;
@Mock
JmxMonitoringApplier applier;
@Test(expectedExceptions = BusinessException.class)
public void agentNotRegistered() throws BusinessException {
manager.analyzeJmxAttributes(ID, Collections.singleton(descriptor));
}
@Test
public void nothingSent() throws BusinessException, ClassCacheModificationException {
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
when(registrationService.registerPlatformIdent(definedIPs, agentName, version)).thenReturn(ID);
manager.register(definedIPs, agentName, version);
Collection<JmxAttributeDescriptor> toMonitor = manager.analyzeJmxAttributes(ID, Collections.<JmxAttributeDescriptor> emptyList());
assertThat(toMonitor, is(empty()));
}
@Test
public void configurationHolderNotInitialized() throws BusinessException, ClassCacheModificationException {
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
when(registrationService.registerPlatformIdent(definedIPs, agentName, version)).thenReturn(ID);
manager.register(definedIPs, agentName, version);
when(configurationHolder.isInitialized()).thenReturn(false);
Collection<JmxAttributeDescriptor> toMonitor = manager.analyzeJmxAttributes(ID, Collections.singleton(descriptor));
assertThat(toMonitor, is(empty()));
}
@Test
public void configurationHolderHasNoAppliers() throws BusinessException, ClassCacheModificationException {
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
when(registrationService.registerPlatformIdent(definedIPs, agentName, version)).thenReturn(ID);
manager.register(definedIPs, agentName, version);
when(configurationHolder.isInitialized()).thenReturn(true);
when(configurationHolder.getJmxMonitoringAppliers()).thenReturn(null);
Collection<JmxAttributeDescriptor> toMonitor = manager.analyzeJmxAttributes(ID, Collections.singleton(descriptor));
assertThat(toMonitor, is(empty()));
}
@Test
public void applierDoesNothing() throws BusinessException, ClassCacheModificationException {
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
when(registrationService.registerPlatformIdent(definedIPs, agentName, version)).thenReturn(ID);
manager.register(definedIPs, agentName, version);
AgentConfig configuration = mock(AgentConfig.class);
when(configurationHolder.isInitialized()).thenReturn(true);
when(configurationHolder.getAgentConfiguration()).thenReturn(configuration);
when(configurationHolder.getJmxMonitoringAppliers()).thenReturn(Collections.singleton(applier));
when(applier.addMonitoringPoint(configuration, descriptor)).thenReturn(false);
Collection<JmxAttributeDescriptor> toMonitor = manager.analyzeJmxAttributes(ID, Collections.singleton(descriptor));
assertThat(toMonitor, is(empty()));
verify(applier).addMonitoringPoint(configuration, descriptor);
}
@Test
public void applierAddsMonitoringPoint() throws BusinessException, ClassCacheModificationException {
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
when(registrationService.registerPlatformIdent(definedIPs, agentName, version)).thenReturn(ID);
manager.register(definedIPs, agentName, version);
AgentConfig configuration = mock(AgentConfig.class);
when(configurationHolder.isInitialized()).thenReturn(true);
when(configurationHolder.getAgentConfiguration()).thenReturn(configuration);
when(configurationHolder.getJmxMonitoringAppliers()).thenReturn(Collections.singleton(applier));
when(applier.addMonitoringPoint(configuration, descriptor)).thenReturn(true);
Collection<JmxAttributeDescriptor> toMonitor = manager.analyzeJmxAttributes(ID, Collections.singleton(descriptor));
assertThat(toMonitor, hasSize(1));
assertThat(toMonitor, hasItem(descriptor));
verify(applier).addMonitoringPoint(configuration, descriptor);
}
@Test
public void ensureNoDoubleRegistration() throws BusinessException, ClassCacheModificationException {
List<String> definedIPs = mock(List.class);
String agentName = "agentName";
String version = "v1";
when(registrationService.registerPlatformIdent(definedIPs, agentName, version)).thenReturn(ID);
manager.register(definedIPs, agentName, version);
AgentConfig configuration = mock(AgentConfig.class);
when(configurationHolder.isInitialized()).thenReturn(true);
when(configurationHolder.getAgentConfiguration()).thenReturn(configuration);
List<JmxMonitoringApplier> appliers = new ArrayList<>();
appliers.add(applier);
appliers.add(applier);
when(configurationHolder.getJmxMonitoringAppliers()).thenReturn(appliers);
when(applier.addMonitoringPoint(configuration, descriptor)).thenReturn(true);
Collection<JmxAttributeDescriptor> toMonitor = manager.analyzeJmxAttributes(ID, Collections.singleton(descriptor));
assertThat(toMonitor, hasSize(1));
assertThat(toMonitor, hasItem(descriptor));
verify(applier).addMonitoringPoint(configuration, descriptor);
}
}
}