package rocks.inspectit.server.instrumentation.config.job;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
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.rmi.RemoteException;
import java.util.Collection;
import java.util.Collections;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.slf4j.Logger;
import org.springframework.context.ApplicationEventPublisher;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import rocks.inspectit.server.ci.event.ClassInstrumentationChangedEvent;
import rocks.inspectit.server.ci.event.EnvironmentUpdateEvent;
import rocks.inspectit.server.instrumentation.classcache.ClassCache;
import rocks.inspectit.server.instrumentation.classcache.ClassCacheInstrumentation;
import rocks.inspectit.server.instrumentation.config.AgentCacheEntry;
import rocks.inspectit.server.instrumentation.config.ClassCacheSearchNarrower;
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.shared.all.exception.BusinessException;
import rocks.inspectit.shared.all.instrumentation.classcache.ClassType;
import rocks.inspectit.shared.all.instrumentation.classcache.ImmutableClassType;
import rocks.inspectit.shared.all.instrumentation.config.impl.AgentConfig;
import rocks.inspectit.shared.all.instrumentation.config.impl.InstrumentationDefinition;
import rocks.inspectit.shared.all.testbase.TestBase;
import rocks.inspectit.shared.cs.ci.Environment;
import rocks.inspectit.shared.cs.ci.assignment.impl.MethodSensorAssignment;
import rocks.inspectit.shared.cs.ci.factory.SpecialMethodSensorAssignmentFactory;
@SuppressWarnings({ "all", "unchecked" })
public class EnvironmentUpdateJobTest extends TestBase {
protected static final long PLATFORM_ID = 10L;
protected static final String ENVIRONMENT_ID = "env";
@InjectMocks
protected EnvironmentUpdateJob job;
@Mock
protected Logger log;
@Mock
protected ClassCacheSearchNarrower classCacheSearchNarrower;
@Mock
protected AgentCacheEntry agentCacheEntry;
@Mock
protected ConfigurationHolder configurationHolder;
@Mock
protected AgentConfig agentConfiguration;
@Mock
protected Environment environment;
@Mock
protected Environment updateEnvironment;
@Mock
protected ConfigurationResolver configurationResolver;
@Mock
protected ClassCache classCache;
@Mock
protected ClassCacheInstrumentation instrumentationService;
@Mock
protected MethodSensorAssignment sensorAssignment;
@Mock
protected IInstrumentationApplier instrumentationApplier;
@Mock
protected IInstrumentationApplier holdedInstrumentationApplier;
@Mock
protected ClassType classType;
@Mock
protected ImmutableClassType immutableClassType;
@Mock
protected SpecialMethodSensorAssignmentFactory functionalAssignmentFactory;
@Mock
protected EnvironmentUpdateEvent event;
@Mock
protected ApplicationEventPublisher eventPublisher;
@BeforeMethod
public void setup() throws Exception {
when(configurationHolder.getAgentConfiguration()).thenReturn(agentConfiguration);
when(configurationHolder.getEnvironment()).thenReturn(environment);
when(configurationHolder.getInstrumentationAppliers()).thenReturn(Collections.singletonList(holdedInstrumentationApplier));
when(agentCacheEntry.getConfigurationHolder()).thenReturn(configurationHolder);
when(agentCacheEntry.getClassCache()).thenReturn(classCache);
when(agentCacheEntry.getId()).thenReturn(PLATFORM_ID);
when(classCache.getInstrumentationService()).thenReturn(instrumentationService);
when(classType.isClass()).thenReturn(true);
when(classType.castToClass()).thenReturn(immutableClassType);
when(classType.getFQN()).thenReturn("fqn");
when(event.getAfter()).thenReturn(updateEnvironment);
}
public class Run extends EnvironmentUpdateJobTest {
@Test
public void onlyConfigurationUpdate() throws RemoteException, BusinessException {
job.setEnvironmentUpdateEvent(event);
job.run();
verify(configurationHolder, times(1)).update(updateEnvironment, PLATFORM_ID);
verify(agentConfiguration, times(0)).setInitialInstrumentationResults(Matchers.anyMap());
verify(agentConfiguration, times(0)).setClassCacheExistsOnCmr(Matchers.anyBoolean());
verifyZeroInteractions(classCache, environment, classCacheSearchNarrower, agentConfiguration, instrumentationService, eventPublisher);
}
@Test
public void addedAssignment() throws RemoteException, BusinessException {
Collection<ClassType> types = Collections.singleton(classType);
doReturn(instrumentationApplier).when(configurationResolver).getInstrumentationApplier(sensorAssignment, environment);
doReturn(types).when(classCacheSearchNarrower).narrowByClassSensorAssignment(classCache, sensorAssignment);
doReturn(types).when(instrumentationService).addInstrumentationPoints(eq(types), eq(agentConfiguration), Matchers.<Collection<IInstrumentationApplier>> any());
doReturn(Collections.singletonList(sensorAssignment)).when(event).getAddedSensorAssignments(functionalAssignmentFactory);
job.setEnvironmentUpdateEvent(event);
job.run();
verify(configurationHolder, times(1)).update(updateEnvironment, PLATFORM_ID);
ArgumentCaptor<Collection> captor = ArgumentCaptor.forClass(Collection.class);
verify(instrumentationService, times(1)).addInstrumentationPoints(eq(types), eq(agentConfiguration), captor.capture());
assertThat((Collection<IInstrumentationApplier>) captor.getValue(), hasSize(1));
assertThat(((Collection<IInstrumentationApplier>) captor.getValue()).iterator().next(), is(instrumentationApplier));
ArgumentCaptor<ClassInstrumentationChangedEvent> eventCaptor = ArgumentCaptor.forClass(ClassInstrumentationChangedEvent.class);
verify(eventPublisher).publishEvent(eventCaptor.capture());
assertThat(eventCaptor.getValue().getAgentId(), is(equalTo(PLATFORM_ID)));
assertThat(eventCaptor.getValue().getInstrumentationDefinitions(), contains(org.hamcrest.Matchers.<InstrumentationDefinition> hasProperty("className", equalTo("fqn"))));
verifyNoMoreInteractions(eventPublisher);
verifyZeroInteractions(environment, agentConfiguration);
}
@Test
public void removedAssignment() throws RemoteException, BusinessException {
Collection<ClassType> types = Collections.singleton(classType);
doReturn(instrumentationApplier).when(configurationResolver).getInstrumentationApplier(sensorAssignment, environment);
doReturn(types).when(classCacheSearchNarrower).narrowByClassSensorAssignment(classCache, sensorAssignment);
doReturn(types).when(instrumentationService).removeInstrumentationPoints(eq(types), Matchers.<Collection<IInstrumentationApplier>> any());
doReturn(Collections.singletonList(sensorAssignment)).when(event).getRemovedSensorAssignments(functionalAssignmentFactory);
job.setEnvironmentUpdateEvent(event);
job.run();
verify(configurationHolder, times(1)).update(updateEnvironment, PLATFORM_ID);
verify(instrumentationService, times(1)).removeInstrumentationPoints(types, Collections.singleton(instrumentationApplier));
ArgumentCaptor<Collection> captor = ArgumentCaptor.forClass(Collection.class);
Collection<IInstrumentationApplier> appliers = configurationHolder.getInstrumentationAppliers();
verify(instrumentationService, times(1)).addInstrumentationPoints(captor.capture(), eq(agentConfiguration), eq(appliers));
assertThat((Collection<ClassType>) captor.getValue(), hasSize(1));
assertThat(((Collection<ClassType>) captor.getValue()).iterator().next(), is(classType));
ArgumentCaptor<ClassInstrumentationChangedEvent> eventCaptor = ArgumentCaptor.forClass(ClassInstrumentationChangedEvent.class);
verify(eventPublisher).publishEvent(eventCaptor.capture());
assertThat(eventCaptor.getValue().getAgentId(), is(equalTo(PLATFORM_ID)));
assertThat(eventCaptor.getValue().getInstrumentationDefinitions(), contains(org.hamcrest.Matchers.<InstrumentationDefinition> hasProperty("className", equalTo("fqn"))));
verifyNoMoreInteractions(eventPublisher);
verifyZeroInteractions(environment, agentConfiguration);
}
@Test
public void removedAssignmentNoChange() {
Collection<ClassType> types = Collections.singleton(classType);
doReturn(instrumentationApplier).when(configurationResolver).getInstrumentationApplier(sensorAssignment, environment);
doReturn(types).when(classCacheSearchNarrower).narrowByClassSensorAssignment(classCache, sensorAssignment);
doReturn(Collections.emptyList()).when(instrumentationService).removeInstrumentationPoints(eq(types), Matchers.<Collection<IInstrumentationApplier>> any());
doReturn(Collections.singletonList(sensorAssignment)).when(event).getRemovedSensorAssignments(functionalAssignmentFactory);
job.setEnvironmentUpdateEvent(event);
job.run();
verify(configurationHolder, times(1)).update(updateEnvironment, PLATFORM_ID);
ArgumentCaptor<Collection> captor = ArgumentCaptor.forClass(Collection.class);
verify(instrumentationService, times(1)).removeInstrumentationPoints(types, Collections.singleton(instrumentationApplier));
verifyNoMoreInteractions(instrumentationService);
verifyZeroInteractions(environment, agentConfiguration, eventPublisher);
}
}
}