package rocks.inspectit.server.instrumentation.config.applier; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; 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.util.Arrays; import java.util.Collections; import java.util.List; import org.mockito.ArgumentCaptor; import org.mockito.Matchers; import org.mockito.Mock; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import rocks.inspectit.shared.all.instrumentation.classcache.ClassType; import rocks.inspectit.shared.all.instrumentation.classcache.MethodType; import rocks.inspectit.shared.all.instrumentation.classcache.MethodType.Character; import rocks.inspectit.shared.all.instrumentation.config.impl.AgentConfig; import rocks.inspectit.shared.all.instrumentation.config.impl.ExceptionSensorTypeConfig; import rocks.inspectit.shared.all.instrumentation.config.impl.MethodInstrumentationConfig; import rocks.inspectit.shared.all.instrumentation.config.impl.SensorInstrumentationPoint; import rocks.inspectit.shared.all.instrumentation.config.impl.SpecialInstrumentationPoint; import rocks.inspectit.shared.all.testbase.TestBase; import rocks.inspectit.shared.cs.ci.Environment; import rocks.inspectit.shared.cs.ci.assignment.AbstractClassSensorAssignment; import rocks.inspectit.shared.cs.ci.sensor.method.IMethodSensorConfig; import rocks.inspectit.shared.cs.cmr.service.IRegistrationService; /** * @author Ivan Senic * */ @SuppressWarnings("PMD") public class AbstractSensorInstrumentationApplierTest extends TestBase { protected AbstractSensorInstrumentationApplier applier; @Mock protected Environment environment; @Mock protected IRegistrationService registrationService; @Mock protected ClassType classType; @Mock protected MethodType methodType; @BeforeMethod public void setup() { applier = new AbstractSensorInstrumentationApplier(environment, registrationService) { @Override public AbstractClassSensorAssignment<?> getSensorAssignment() { return null; } @Override protected boolean matches(ClassType classType) { return true; } @Override protected boolean matches(MethodType methodType) { return true; } @Override protected void applyAssignment(AgentConfig agentConfiguration, MethodType methodType, MethodInstrumentationConfig methodInstrumentationConfig) { // test both getOrCreateSensorInstrumentationPoint(agentConfiguration, methodType, methodInstrumentationConfig); getOrCreateSpecialInstrumentationPoint(agentConfiguration, methodType, methodInstrumentationConfig); } }; // class to return one method when(classType.getMethods()).thenReturn(Collections.singleton(methodType)); } public class AddInstrumentationPoints extends AbstractSensorInstrumentationApplierTest { @Test public void defaultPackage() { long agentId = 13L; long methodId = 17L; String sensorClassName = "sensorClassName"; when(registrationService.registerMethodIdent(eq(agentId), anyString(), anyString(), anyString(), Matchers.<List<String>> any(), anyString(), anyInt())).thenReturn(methodId); AgentConfig agentConfiguration = mock(AgentConfig.class); when(agentConfiguration.getPlatformId()).thenReturn(agentId); IMethodSensorConfig methodSensorConfig = mock(IMethodSensorConfig.class); when(methodSensorConfig.getClassName()).thenReturn(sensorClassName); when(environment.getMethodSensorTypeConfig(Matchers.<Class<? extends IMethodSensorConfig>> any())).thenReturn(methodSensorConfig); String packageName = ""; String className = "ClassName"; String methodName = "methodName"; String returnType = "returnType"; List<String> parameters = Arrays.asList(new String[] { "p1", "p2" }); int mod = 10; when(classType.getFQN()).thenReturn(className); when(methodType.getClassOrInterfaceType()).thenReturn(classType); when(methodType.getName()).thenReturn(methodName); when(methodType.getParameters()).thenReturn(parameters); when(methodType.getReturnType()).thenReturn(returnType); when(methodType.getMethodCharacter()).thenReturn(Character.METHOD); when(methodType.getModifiers()).thenReturn(mod); boolean changed = applier.addInstrumentationPoints(agentConfiguration, classType); // verify results assertThat(changed, is(true)); // verify registration service verify(registrationService, times(2)).registerMethodIdent(agentId, packageName, className, methodName, parameters, returnType, mod); verifyNoMoreInteractions(registrationService); // check RSC and instrumentation config ArgumentCaptor<MethodInstrumentationConfig> captor = ArgumentCaptor.forClass(MethodInstrumentationConfig.class); verify(methodType, times(1)).setMethodInstrumentationConfig(captor.capture()); MethodInstrumentationConfig instrumentationConfig = captor.getValue(); assertThat(instrumentationConfig.getTargetClassFqn(), is(className)); assertThat(instrumentationConfig.getTargetMethodName(), is(methodName)); assertThat(instrumentationConfig.getReturnType(), is(returnType)); assertThat(instrumentationConfig.getParameterTypes(), is(parameters)); assertThat(instrumentationConfig.getAllInstrumentationPoints(), hasSize(2)); SensorInstrumentationPoint rsc = instrumentationConfig.getSensorInstrumentationPoint(); assertThat(rsc.getId(), is(methodId)); assertThat(rsc.getSensorIds().length, is(0)); assertThat(rsc.isConstructor(), is(false)); SpecialInstrumentationPoint ssc = instrumentationConfig.getSpecialInstrumentationPoint(); assertThat(ssc.getId(), is(methodId)); assertThat(ssc.getSensorId(), is(0L)); } @Test public void constructor() { long agentId = 13L; long methodId = 17L; String sensorClassName = "sensorClassName"; when(registrationService.registerMethodIdent(eq(agentId), anyString(), anyString(), anyString(), Matchers.<List<String>> any(), anyString(), anyInt())).thenReturn(methodId); ExceptionSensorTypeConfig exceptionSensorTypeConfig = mock(ExceptionSensorTypeConfig.class); AgentConfig agentConfiguration = mock(AgentConfig.class); when(agentConfiguration.getPlatformId()).thenReturn(agentId); when(agentConfiguration.getExceptionSensorTypeConfig()).thenReturn(exceptionSensorTypeConfig); IMethodSensorConfig methodSensorConfig = mock(IMethodSensorConfig.class); when(methodSensorConfig.getClassName()).thenReturn(sensorClassName); when(environment.getMethodSensorTypeConfig(Matchers.<Class<? extends IMethodSensorConfig>> any())).thenReturn(methodSensorConfig); String packageName = "my.favorite.package"; String className = "ClassName"; String methodName = "methodName"; String returnType = "returnType"; List<String> parameters = Arrays.asList(new String[] { "p1", "p2" }); int mod = 10; when(classType.getFQN()).thenReturn(packageName + '.' + className); when(methodType.getClassOrInterfaceType()).thenReturn(classType); when(methodType.getName()).thenReturn(methodName); when(methodType.getParameters()).thenReturn(parameters); when(methodType.getReturnType()).thenReturn(returnType); when(methodType.getMethodCharacter()).thenReturn(Character.CONSTRUCTOR); when(methodType.getModifiers()).thenReturn(mod); boolean changed = applier.addInstrumentationPoints(agentConfiguration, classType); // verify results assertThat(changed, is(true)); // verify registration service verify(registrationService, times(2)).registerMethodIdent(agentId, packageName, className, methodName, parameters, returnType, mod); verifyNoMoreInteractions(registrationService); // check RSC and instrumentation config ArgumentCaptor<MethodInstrumentationConfig> captor = ArgumentCaptor.forClass(MethodInstrumentationConfig.class); verify(methodType, times(1)).setMethodInstrumentationConfig(captor.capture()); MethodInstrumentationConfig instrumentationConfig = captor.getValue(); assertThat(instrumentationConfig.getTargetClassFqn(), is(packageName + '.' + className)); assertThat(instrumentationConfig.getTargetMethodName(), is(methodName)); assertThat(instrumentationConfig.getReturnType(), is(returnType)); assertThat(instrumentationConfig.getParameterTypes(), is(parameters)); assertThat(instrumentationConfig.getAllInstrumentationPoints(), hasSize(2)); SensorInstrumentationPoint rsc = instrumentationConfig.getSensorInstrumentationPoint(); assertThat(rsc.getId(), is(methodId)); assertThat(rsc.getSensorIds().length, is(0)); assertThat(rsc.isConstructor(), is(true)); SpecialInstrumentationPoint ssc = instrumentationConfig.getSpecialInstrumentationPoint(); assertThat(ssc.getId(), is(methodId)); assertThat(ssc.getSensorId(), is(0L)); } } public class RemoveInstrumentationPoints extends AbstractSensorInstrumentationApplierTest { @Test public void remove() { // something to remove when(classType.getMethods()).thenReturn(Collections.singleton(methodType)); when(classType.hasInstrumentationPoints()).thenReturn(true); boolean result = applier.removeInstrumentationPoints(classType); assertThat(result, is(true)); verify(methodType, times(1)).setMethodInstrumentationConfig(null); } @Test public void removeNothing() { // nothing to remove when(classType.getMethods()).thenReturn(Collections.singleton(methodType)); when(classType.hasInstrumentationPoints()).thenReturn(false); boolean result = applier.removeInstrumentationPoints(classType); assertThat(result, is(false)); verifyZeroInteractions(methodType); } } }