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);
}
}
}