@Test(expectedExceptions = IllegalArgumentException.class) public void nullInstrumentationPoint() { String name = "method"; String desc = "()V"; boolean enhancedExceptionSensor = false; factory.getMethodVisitor(null, superMethodVisitor, 0, name, desc, enhancedExceptionSensor); }
/** * {@inheritDoc} */ @Override public void onApplicationEvent(AgentMessagesReceivedEvent event) { if (event == null) { if (log.isDebugEnabled()) { log.debug("A 'null' event will not be processed."); } return; } // When we update to Spring v4, we should use @Conditional that the RetransformationManager // is not running if retransformation is not used. if (!Agent.agent.isUsingRetransformation()) { if (log.isInfoEnabled()) { log.info("Retransformation is disabled by the used retransformation strategy."); } return; } List<InstrumentationDefinition> instrumentationDefinitions = getInstrumentatioDefinitions(event.getAgentMessages()); if (CollectionUtils.isEmpty(instrumentationDefinitions)) { return; } // remove out-dated duplicates Collection<InstrumentationDefinition> cleanedInstrumentationDefinitions = removeOutdatedInstrumentationDefinitions(instrumentationDefinitions); processInstrumentationDefinitions(cleanedInstrumentationDefinitions); }
/** * {@inheritDoc} */ @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { // calling super to ensure the visitor pattern MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); MethodInstrumentationConfig instrumentationConfig = shouldInstrument(name, desc); if (null != instrumentationConfig) { // using JSR inliner adapter in order to remove JSR/RET instructions // see http://mail-archive.ow2.org/asm/2008-11/msg00008.html // using only if we add byte code methodVisitor = new JSRInlinerAdapter(methodVisitor, access, name, desc, signature, exceptions); // go over all instrumentation points and create the method visitor for (IMethodInstrumentationPoint instrumentationPoint : instrumentationConfig.getAllInstrumentationPoints()) { // note that here we create a chain of method visitor by passing the current one to // the one being created, thus following the visitor pattern of ASM MethodVisitor mv = instrumenterFactory.getMethodVisitor(instrumentationPoint, methodVisitor, access, name, desc, enhancedExceptionSensor); // safety for the null returned method visitor if (null != mv) { methodVisitor = mv; } } // add to list so that we know which are applied appliedInstrumentationConfigs.add(instrumentationConfig); } return methodVisitor; }
@Test public void floatNullParameter() throws Exception { String methodName = "floatNullParameter"; long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockMethod(config, InstrumentationTestClass.class, methodName); doAnswer(METHOD_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); // now call this method Object testClass = this.createInstance(TEST_CLASS_FQN, b); this.callMethod(testClass, methodName, null); verify(hookDispatcher).dispatchMethodBeforeBody(methodId, testClass, new Object[0]); verify(hookDispatcher).dispatchFirstMethodAfterBody(methodId, testClass, new Object[0], Float.MAX_VALUE, false); verify(hookDispatcher).dispatchSecondMethodAfterBody(methodId, testClass, new Object[0], Float.MAX_VALUE, false); verifyNoMoreInteractions(hookDispatcher); }
@Test public void staticConstructor() throws Exception { long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockConstructor(config, InstrumentationTestClass.class, true); doAnswer(CONSTRUCTOR_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); // create instance this.createInstance(TEST_CLASS_FQN, b); verify(hookDispatcher).dispatchConstructorBeforeBody(methodId, new Object[0]); verify(hookDispatcher).dispatchConstructorAfterBody(methodId, null, new Object[0]); verifyNoMoreInteractions(hookDispatcher); }
@Test public void method() { long id = 7L; String name = "method"; String desc = "()V"; boolean enhancedExceptionSensor = false; when(sensorInstrumentationPoint.isConstructor()).thenReturn(false); when(sensorInstrumentationPoint.getId()).thenReturn(id); MethodVisitor methodVisitor = factory.getMethodVisitor(sensorInstrumentationPoint, superMethodVisitor, 0, name, desc, enhancedExceptionSensor); assertThat(methodVisitor, is(instanceOf(MethodInstrumenter.class))); MethodInstrumenter methodInstrumenter = (MethodInstrumenter) methodVisitor; assertThat(methodInstrumenter.getMethodId(), is(id)); assertThat(methodInstrumenter.isEnhancedExceptionSensor(), is(enhancedExceptionSensor)); }
@Test public void constructor() { long id = 7L; String name = "method"; String desc = "()V"; boolean enhancedExceptionSensor = false; when(sensorInstrumentationPoint.isConstructor()).thenReturn(true); when(sensorInstrumentationPoint.getId()).thenReturn(id); MethodVisitor methodVisitor = factory.getMethodVisitor(sensorInstrumentationPoint, superMethodVisitor, 0, name, desc, enhancedExceptionSensor); assertThat(methodVisitor, is(instanceOf(ConstructorInstrumenter.class))); ConstructorInstrumenter methodInstrumenter = (ConstructorInstrumenter) methodVisitor; assertThat(methodInstrumenter.getMethodId(), is(id)); assertThat(methodInstrumenter.isEnhancedExceptionSensor(), is(enhancedExceptionSensor)); }
@Test public void nullEvent() throws UnmodifiableClassException { when(instrumentation.getAllLoadedClasses()).thenReturn(new Class[] { Object.class, String.class }); retransformManager.onApplicationEvent(null); verifyZeroInteractions(instrumentation, classHashHelper, threadTransformHelper, agent); }
@Test public void charNullParameter() throws Exception { String methodName = "charNullParameter"; long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockMethod(config, InstrumentationTestClass.class, methodName); doAnswer(METHOD_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); // now call this method Object testClass = this.createInstance(TEST_CLASS_FQN, b); this.callMethod(testClass, methodName, null); verify(hookDispatcher).dispatchMethodBeforeBody(methodId, testClass, new Object[0]); verify(hookDispatcher).dispatchFirstMethodAfterBody(methodId, testClass, new Object[0], '\u1234', false); verify(hookDispatcher).dispatchSecondMethodAfterBody(methodId, testClass, new Object[0], '\u1234', false); verifyNoMoreInteractions(hookDispatcher); }
@Test public void constructorNullParameter() throws Exception { long methodId = 9L; when(sip.getId()).thenReturn(methodId); prepareConfigurationMockConstructor(config, InstrumentationTestClass.class, false); doAnswer(CONSTRUCTOR_INSTRUMENTER_ANSWER).when(instrumenterFactory).getMethodVisitor(eq(sip), Matchers.<MethodVisitor> any(), anyInt(), anyString(), anyString(), anyBoolean()); when(config.getAllInstrumentationPoints()).thenReturn(Collections.<IMethodInstrumentationPoint> singleton(sip)); ClassReader cr = new ClassReader(TEST_CLASS_FQN); prepareWriter(cr, null, false, config); cr.accept(classInstrumenter, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); assertThat(classInstrumenter.isByteCodeAdded(), is(true)); byte b[] = classWriter.toByteArray(); // create instance Object instance = this.createInstance(TEST_CLASS_FQN, b); verify(hookDispatcher).dispatchConstructorBeforeBody(methodId, new Object[0]); verify(hookDispatcher).dispatchConstructorAfterBody(methodId, instance, new Object[0]); verifyNoMoreInteractions(hookDispatcher); }
@Test public void methodEnchancedExceptionSensor() { long id = 7L; String name = "method"; String desc = "()V"; boolean enhancedExceptionSensor = true; when(sensorInstrumentationPoint.isConstructor()).thenReturn(false); when(sensorInstrumentationPoint.getId()).thenReturn(id); MethodVisitor methodVisitor = factory.getMethodVisitor(sensorInstrumentationPoint, superMethodVisitor, 0, name, desc, enhancedExceptionSensor); assertThat(methodVisitor, is(instanceOf(MethodInstrumenter.class))); MethodInstrumenter methodInstrumenter = (MethodInstrumenter) methodVisitor; assertThat(methodInstrumenter.getMethodId(), is(id)); assertThat(methodInstrumenter.isEnhancedExceptionSensor(), is(enhancedExceptionSensor)); }
@Test public void constructorEnchancedExceptionSensor() { long id = 7L; String name = "method"; String desc = "()V"; boolean enhancedExceptionSensor = true; when(sensorInstrumentationPoint.isConstructor()).thenReturn(true); when(sensorInstrumentationPoint.getId()).thenReturn(id); MethodVisitor methodVisitor = factory.getMethodVisitor(sensorInstrumentationPoint, superMethodVisitor, 0, name, desc, enhancedExceptionSensor); assertThat(methodVisitor, is(instanceOf(ConstructorInstrumenter.class))); ConstructorInstrumenter methodInstrumenter = (ConstructorInstrumenter) methodVisitor; assertThat(methodInstrumenter.getMethodId(), is(id)); assertThat(methodInstrumenter.isEnhancedExceptionSensor(), is(enhancedExceptionSensor)); }
@Test(expectedExceptions = IllegalArgumentException.class) public void unknownInstrumentationPoint() { IMethodInstrumentationPoint instrumentationPoint = mock(IMethodInstrumentationPoint.class); String name = "method"; String desc = "()V"; boolean enhancedExceptionSensor = false; factory.getMethodVisitor(instrumentationPoint, superMethodVisitor, 0, name, desc, enhancedExceptionSensor); }
@Test public void unknownMessageClass() throws UnmodifiableClassException { IAgentMessage<?> message = mock(IAgentMessage.class); AgentMessagesReceivedEvent event = new AgentMessagesReceivedEvent(eventSource, Arrays.<IAgentMessage<?>> asList(message)); when(instrumentation.getAllLoadedClasses()).thenReturn(new Class[] { Object.class, String.class }); when(agent.isUsingRetransformation()).thenReturn(true); retransformManager.onApplicationEvent(event); verifyZeroInteractions(instrumentation, classHashHelper, threadTransformHelper); }
@Test public void specialMethod() { long id = 7L; String name = "method"; String desc = "()V"; boolean enhancedExceptionSensor = false; SubstitutionDescriptor substitutionDescriptor = mock(SubstitutionDescriptor.class); when(specialInstrumentationPoint.getId()).thenReturn(id); when(specialInstrumentationPoint.getSubstitutionDescriptor()).thenReturn(substitutionDescriptor); MethodVisitor methodVisitor = factory.getMethodVisitor(specialInstrumentationPoint, superMethodVisitor, 0, name, desc, enhancedExceptionSensor); assertThat(methodVisitor, is(instanceOf(SpecialMethodInstrumenter.class))); }
@Test public void noInstrumentationDefinitions() throws UnmodifiableClassException { IAgentMessage<?> message = new UpdatedInstrumentationMessage(); AgentMessagesReceivedEvent event = new AgentMessagesReceivedEvent(eventSource, Arrays.<IAgentMessage<?>> asList(message)); when(instrumentation.getAllLoadedClasses()).thenReturn(new Class[] { Object.class, String.class }); when(agent.isUsingRetransformation()).thenReturn(true); retransformManager.onApplicationEvent(event); verifyZeroInteractions(instrumentation, classHashHelper, threadTransformHelper); }
@Test public void retransformationDisabled() throws UnmodifiableClassException { InstrumentationDefinition objectDefinition = mock(InstrumentationDefinition.class); when(objectDefinition.getClassName()).thenReturn("java.lang.Object"); IAgentMessage<?> message = new UpdatedInstrumentationMessage(); ((UpdatedInstrumentationMessage) message).getMessageContent().add(objectDefinition); AgentMessagesReceivedEvent event = new AgentMessagesReceivedEvent(eventSource, Arrays.<IAgentMessage<?>> asList(message)); when(agent.isUsingRetransformation()).thenReturn(false); retransformManager.onApplicationEvent(event); verifyZeroInteractions(instrumentation, classHashHelper, threadTransformHelper); } }
@Test public void unknownInstrumentationClass() throws UnmodifiableClassException { InstrumentationDefinition iDefinition = mock(InstrumentationDefinition.class); when(iDefinition.getClassName()).thenReturn("unknown.Class"); IAgentMessage<?> message = new UpdatedInstrumentationMessage(); ((UpdatedInstrumentationMessage) message).getMessageContent().add(iDefinition); AgentMessagesReceivedEvent event = new AgentMessagesReceivedEvent(eventSource, Arrays.<IAgentMessage<?>> asList(message)); when(instrumentation.getAllLoadedClasses()).thenReturn(new Class[] { Object.class, String.class }); when(agent.isUsingRetransformation()).thenReturn(true); retransformManager.onApplicationEvent(event); verify(classHashHelper).registerInstrumentationDefinition(eq("unknown.Class"), eq(iDefinition)); verify(instrumentation).getAllLoadedClasses(); verify(instrumentation, times(2)).isModifiableClass(any(Class.class)); verifyNoMoreInteractions(instrumentation, classHashHelper); verifyZeroInteractions(threadTransformHelper); }
@Test public void unmodifiableClass() throws UnmodifiableClassException { InstrumentationDefinition iDefinition = mock(InstrumentationDefinition.class); when(iDefinition.getClassName()).thenReturn("java.lang.Object"); IAgentMessage<?> message = new UpdatedInstrumentationMessage(); ((UpdatedInstrumentationMessage) message).getMessageContent().add(iDefinition); AgentMessagesReceivedEvent event = new AgentMessagesReceivedEvent(eventSource, Arrays.<IAgentMessage<?>> asList(message)); when(instrumentation.getAllLoadedClasses()).thenReturn(new Class[] { Object.class, String.class }); when(instrumentation.isModifiableClass(eq(Object.class))).thenReturn(false); when(agent.isUsingRetransformation()).thenReturn(true); retransformManager.onApplicationEvent(event); verify(classHashHelper).registerInstrumentationDefinition(eq("java.lang.Object"), eq(iDefinition)); verify(instrumentation).getAllLoadedClasses(); verify(instrumentation, times(2)).isModifiableClass(any(Class.class)); verifyNoMoreInteractions(instrumentation, classHashHelper); verifyZeroInteractions(threadTransformHelper); }
@Test @SuppressWarnings("unchecked") public void instrumentationThrowsOneException() throws UnmodifiableClassException { InstrumentationDefinition iDefinition = mock(InstrumentationDefinition.class); when(iDefinition.getClassName()).thenReturn("java.lang.Object"); IAgentMessage<?> message = new UpdatedInstrumentationMessage(); ((UpdatedInstrumentationMessage) message).getMessageContent().add(iDefinition); AgentMessagesReceivedEvent event = new AgentMessagesReceivedEvent(eventSource, Arrays.<IAgentMessage<?>> asList(message)); when(instrumentation.getAllLoadedClasses()).thenReturn(new Class[] { Object.class, String.class }); when(instrumentation.isModifiableClass(any(Class.class))).thenReturn(true).thenThrow(RuntimeException.class); when(agent.isUsingRetransformation()).thenReturn(true); retransformManager.onApplicationEvent(event); verify(classHashHelper).registerInstrumentationDefinition(eq("java.lang.Object"), eq(iDefinition)); verify(instrumentation).getAllLoadedClasses(); verify(instrumentation).retransformClasses(eq(Object.class)); verify(instrumentation, times(2)).isModifiableClass(any(Class.class)); InOrder inOrder = inOrder(threadTransformHelper); inOrder.verify(threadTransformHelper).setThreadTransformDisabled(false); inOrder.verify(threadTransformHelper).setThreadTransformDisabled(true); verifyNoMoreInteractions(instrumentation, classHashHelper, threadTransformHelper); }