package rocks.inspectit.server.instrumentation.config.job;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItems;
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.hamcrest.Matcher;
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 com.google.common.collect.ImmutableList;
import rocks.inspectit.server.ci.event.ClassInstrumentationChangedEvent;
import rocks.inspectit.server.ci.event.ProfileUpdateEvent;
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.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.AbstractClassSensorAssignment;
@SuppressWarnings({ "all", "unchecked" })
public class ProfileUpdateJobTest extends TestBase {
@InjectMocks
protected ProfileUpdateJob job;
@Mock
protected Logger log;
@Mock
protected ClassCacheSearchNarrower classCacheSearchNarrower;
@Mock
protected AgentCacheEntry agentCacheEntry;
@Mock
protected ClassCache classCache;
@Mock
protected ConfigurationHolder configurationHolder;
@Mock
protected AgentConfig agentConfiguration;
@Mock
protected Environment environment;
@Mock
protected ConfigurationResolver configurationResolver;
@Mock
protected ClassCacheInstrumentation instrumentationService;
@Mock
protected AbstractClassSensorAssignment<?> sensorAssignment;
@Mock
protected IInstrumentationApplier holdedInstrumentationApplier;
@Mock
protected IInstrumentationApplier instrumentationApplier;
@Mock
protected ClassType classTypeOne;
@Mock
protected ClassType classTypeTwo;
@Mock
protected ImmutableClassType immutableClassTypeOne;
@Mock
protected ImmutableClassType immutableClassTypeTwo;
@Mock
protected ProfileUpdateEvent 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(10L);
when(classCache.getInstrumentationService()).thenReturn(instrumentationService);
when(classTypeOne.isClass()).thenReturn(true);
when(classTypeTwo.isClass()).thenReturn(true);
when(classTypeOne.castToClass()).thenReturn(immutableClassTypeOne);
when(classTypeTwo.castToClass()).thenReturn(immutableClassTypeTwo);
when(immutableClassTypeOne.hasInstrumentationPoints()).thenReturn(true);
when(immutableClassTypeOne.hasInstrumentationPoints()).thenReturn(false);
when(classTypeOne.getFQN()).thenReturn("fqnOne");
when(classTypeTwo.getFQN()).thenReturn("fqnTwo");
}
public class Run extends ProfileUpdateJobTest {
@Test
public void noChanges() {
job.setProfileUpdateEvent(event);
job.run();
verifyZeroInteractions(classCache, environment, classCacheSearchNarrower, agentConfiguration, instrumentationService, eventPublisher);
}
@Test
public void addedAssignment() throws RemoteException {
Collection<ClassType> types = ImmutableList.of(classTypeOne, classTypeTwo);
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.singleton(sensorAssignment)).when(event).getAddedSensorAssignments();
job.setProfileUpdateEvent(event);
job.run();
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<Collection> typeCaptor = ArgumentCaptor.forClass(Collection.class);
verify(instrumentationService).getInstrumentationResults(typeCaptor.capture());
assertThat((Collection<ClassType>) typeCaptor.getValue(), hasItems(classTypeOne, classTypeTwo));
ArgumentCaptor<ClassInstrumentationChangedEvent> eventCaptor = ArgumentCaptor.forClass(ClassInstrumentationChangedEvent.class);
verify(eventPublisher).publishEvent(eventCaptor.capture());
assertThat(eventCaptor.getValue().getAgentId(), is(equalTo(10L)));
Matcher<InstrumentationDefinition> matcherOne = org.hamcrest.Matchers.<InstrumentationDefinition> hasProperty("className", equalTo("fqnOne"));
Matcher<InstrumentationDefinition> matcherTwo = org.hamcrest.Matchers.<InstrumentationDefinition> hasProperty("className", equalTo("fqnTwo"));
assertThat(eventCaptor.getValue().getInstrumentationDefinitions(), hasItems(matcherOne, matcherTwo));
verifyNoMoreInteractions(instrumentationService, eventPublisher);
verifyZeroInteractions(environment);
}
@Test
public void removedAssignment() throws RemoteException {
Collection<ClassType> types = ImmutableList.of(classTypeOne, classTypeTwo);
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.singleton(sensorAssignment)).when(event).getRemovedSensorAssignments();
job.setProfileUpdateEvent(event);
job.run();
ArgumentCaptor<Collection> captor = ArgumentCaptor.forClass(Collection.class);
verify(instrumentationService, times(1)).removeInstrumentationPoints(eq(types), captor.capture());
assertThat((Collection<IInstrumentationApplier>) captor.getValue(), hasSize(1));
assertThat(((Collection<IInstrumentationApplier>) captor.getValue()).iterator().next(), is(instrumentationApplier));
ArgumentCaptor<Collection> typeCaptor = ArgumentCaptor.forClass(Collection.class);
verify(instrumentationService).getInstrumentationResults(typeCaptor.capture());
assertThat((Collection<ClassType>) typeCaptor.getValue(), hasItems(classTypeOne, classTypeTwo));
Collection<IInstrumentationApplier> appliers = configurationHolder.getInstrumentationAppliers();
verify(instrumentationService, times(1)).addInstrumentationPoints(captor.capture(), eq(agentConfiguration), eq(appliers));
assertThat((Collection<ClassType>) captor.getValue(), hasSize(2));
assertThat(((Collection<ClassType>) captor.getValue()).iterator().next(), is(classTypeOne));
ArgumentCaptor<ClassInstrumentationChangedEvent> eventCaptor = ArgumentCaptor.forClass(ClassInstrumentationChangedEvent.class);
verify(eventPublisher).publishEvent(eventCaptor.capture());
assertThat(eventCaptor.getValue().getAgentId(), is(equalTo(10L)));
Matcher<InstrumentationDefinition> matcherOne = org.hamcrest.Matchers.<InstrumentationDefinition> hasProperty("className", equalTo("fqnOne"));
Matcher<InstrumentationDefinition> matcherTwo = org.hamcrest.Matchers.<InstrumentationDefinition> hasProperty("className", equalTo("fqnTwo"));
assertThat(eventCaptor.getValue().getInstrumentationDefinitions(), hasItems(matcherOne, matcherTwo));
verifyNoMoreInteractions(instrumentationService, eventPublisher);
verifyZeroInteractions(environment);
}
@Test
public void removedAssignmentNoChange() throws RemoteException {
Collection<ClassType> types = ImmutableList.of(classTypeOne, classTypeTwo);
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.singleton(sensorAssignment)).when(event).getRemovedSensorAssignments();
job.setProfileUpdateEvent(event);
job.run();
ArgumentCaptor<Collection> captor = ArgumentCaptor.forClass(Collection.class);
verify(instrumentationService, times(1)).removeInstrumentationPoints(eq(types), captor.capture());
assertThat((Collection<IInstrumentationApplier>) captor.getValue(), hasSize(1));
assertThat(((Collection<IInstrumentationApplier>) captor.getValue()).iterator().next(), is(instrumentationApplier));
verifyNoMoreInteractions(instrumentationService);
verifyZeroInteractions(environment, eventPublisher);
}
}
}