1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package net.grinder.util.weave.j2se6;
23
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertNull;
27 import static org.junit.Assert.assertSame;
28 import static org.junit.Assert.fail;
29 import static org.mockito.Matchers.isA;
30 import static org.mockito.Mockito.doThrow;
31 import static org.mockito.Mockito.times;
32 import static org.mockito.Mockito.verify;
33 import static org.mockito.Mockito.verifyNoMoreInteractions;
34 import static org.mockito.Mockito.when;
35
36 import java.lang.instrument.ClassFileTransformer;
37 import java.lang.instrument.Instrumentation;
38 import java.lang.instrument.UnmodifiableClassException;
39 import java.lang.reflect.Constructor;
40 import java.lang.reflect.Method;
41 import java.util.List;
42 import java.util.Map;
43
44 import net.grinder.util.weave.Weaver;
45 import net.grinder.util.weave.WeavingException;
46 import net.grinder.util.weave.Weaver.TargetSource;
47 import net.grinder.util.weave.j2se6.DCRWeaver.ClassFileTransformerFactory;
48
49 import org.junit.Before;
50 import org.junit.Test;
51 import org.mockito.ArgumentCaptor;
52 import org.mockito.Captor;
53 import org.mockito.Mock;
54 import org.mockito.MockitoAnnotations;
55
56
57
58
59
60
61
62
63 public class TestDCRWeaver {
64
65 @Mock private ClassFileTransformerFactory m_classFileTransformerFactory;
66 @Mock private ClassFileTransformer m_transformer;
67 @Mock private Instrumentation m_instrumentation;
68 @Captor private ArgumentCaptor<PointCutRegistry> m_pointCutRegistryCaptor;
69
70 @SuppressWarnings("unused")
71 private void myMethod() {
72 }
73
74 @SuppressWarnings("unused")
75 private void myOtherMethod() {
76 }
77
78 @Before public void setUp() {
79 MockitoAnnotations.initMocks(this);
80
81 when(m_classFileTransformerFactory.create(isA(PointCutRegistry.class)))
82 .thenReturn(m_transformer);
83 }
84
85 @Test public void testMethodRegistration() throws Exception {
86 final Weaver weaver = new DCRWeaver(m_classFileTransformerFactory,
87 m_instrumentation);
88
89 verify(m_classFileTransformerFactory)
90 .create(m_pointCutRegistryCaptor.capture());
91 verify(m_instrumentation).addTransformer(m_transformer, true);
92
93 final Method method = getClass().getDeclaredMethod("myMethod");
94
95 final String l1 = weaver.weave(method, TargetSource.FIRST_PARAMETER);
96 final String l2 = weaver.weave(method, TargetSource.FIRST_PARAMETER);
97 assertEquals(l1, l2);
98
99 weaver.weave(method, TargetSource.FIRST_PARAMETER);
100
101 final PointCutRegistry pointCutRegistry =
102 m_pointCutRegistryCaptor.getValue();
103
104 final String internalClassName = getClass().getName().replace('.', '/');
105
106 final Map<Constructor<?>, List<WeavingDetails>> constructorPointCuts =
107 pointCutRegistry.getConstructorPointCutsForClass(internalClassName);
108
109 assertNull(constructorPointCuts);
110
111 final Map<Method, List<WeavingDetails>> methodPointCuts =
112 pointCutRegistry.getMethodPointCutsForClass(internalClassName);
113
114 assertEquals(1, methodPointCuts.size());
115
116 final List<WeavingDetails> locations1 = methodPointCuts.get(method);
117 assertEquals(1, locations1.size());
118 final String location1 = locations1.get(0).getLocation();
119 assertNotNull(location1);
120
121 final Method method2 = getClass().getDeclaredMethod("myOtherMethod");
122
123 weaver.weave(method, TargetSource.FIRST_PARAMETER);
124 weaver.weave(method2, TargetSource.FIRST_PARAMETER);
125
126 final Map<Method, List<WeavingDetails>> pointCuts2 =
127 pointCutRegistry.getMethodPointCutsForClass(internalClassName);
128
129 assertEquals(2, pointCuts2.size());
130
131 final List<WeavingDetails> locations2 = pointCuts2.get(method);
132 assertEquals(1, locations2.size());
133
134 assertEquals(new WeavingDetails(location1, TargetSource.FIRST_PARAMETER),
135 locations2.get(0));
136 assertNotNull(pointCuts2.get(method2));
137
138 verifyNoMoreInteractions(m_classFileTransformerFactory, m_instrumentation);
139 }
140
141 @Test public void testConstructorRegistration() throws Exception {
142 final Weaver weaver = new DCRWeaver(m_classFileTransformerFactory,
143 m_instrumentation);
144
145
146 verify(m_classFileTransformerFactory)
147 .create(m_pointCutRegistryCaptor.capture());
148
149 final Constructor<?> constructor = getClass().getDeclaredConstructor();
150
151 final String l1 = weaver.weave(constructor);
152 final String l2 = weaver.weave(constructor);
153 assertEquals(l1, l2);
154
155 weaver.weave(constructor);
156
157 final PointCutRegistry pointCutRegistry =
158 m_pointCutRegistryCaptor.getValue();
159
160 final String internalClassName = getClass().getName().replace('.', '/');
161
162 final Map<Constructor<?>, List<WeavingDetails>> constructorPointCuts =
163 pointCutRegistry.getConstructorPointCutsForClass(internalClassName);
164
165 assertEquals(1, constructorPointCuts.size());
166
167 final Map<Method, List<WeavingDetails>> methodPointCuts =
168 pointCutRegistry.getMethodPointCutsForClass(internalClassName);
169
170 assertNull(methodPointCuts);
171
172 final List<WeavingDetails> locations1 =
173 constructorPointCuts.get(constructor);
174
175 assertEquals(1, locations1.size());
176
177 final String location1 = locations1.get(0).getLocation();
178 assertNotNull(location1);
179 }
180
181 @Test public void testWeavingWithInstrumentation() throws Exception {
182 final Weaver weaver = new DCRWeaver(m_classFileTransformerFactory,
183 m_instrumentation);
184
185 verify(m_classFileTransformerFactory)
186 .create(m_pointCutRegistryCaptor.capture());
187 verify(m_instrumentation).addTransformer(m_transformer, true);
188
189 final Method method = getClass().getDeclaredMethod("myMethod");
190 weaver.weave(method, TargetSource.FIRST_PARAMETER);
191
192 weaver.applyChanges();
193
194 verify(m_instrumentation).retransformClasses(new Class[] { getClass(),});
195
196 weaver.weave(method, TargetSource.FIRST_PARAMETER);
197 weaver.applyChanges();
198
199 verifyNoMoreInteractions(m_classFileTransformerFactory,
200 m_instrumentation);
201 }
202
203
204 @Test public void testWeavingWithInstrumentation2() throws Exception {
205 final Weaver weaver = new DCRWeaver(m_classFileTransformerFactory,
206 m_instrumentation);
207
208 verify(m_classFileTransformerFactory)
209 .create(m_pointCutRegistryCaptor.capture());
210 verify(m_instrumentation).addTransformer(m_transformer, true);
211
212 final Method method = getClass().getDeclaredMethod("myMethod");
213
214 weaver.weave(method, TargetSource.FIRST_PARAMETER);
215 weaver.applyChanges();
216 weaver.weave(method, TargetSource.CLASS);
217 weaver.applyChanges();
218
219 verify(m_instrumentation, times(2))
220 .retransformClasses(new Class[] { getClass(),});
221
222 verifyNoMoreInteractions(m_classFileTransformerFactory,
223 m_instrumentation);
224 }
225
226 @Test public void testWeavingWithBadInstrumentation() throws Exception {
227 final Weaver weaver = new DCRWeaver(m_classFileTransformerFactory,
228 m_instrumentation);
229
230 final Method method = getClass().getDeclaredMethod("myMethod");
231
232 weaver.weave(method, TargetSource.FIRST_PARAMETER);
233 weaver.weave(method, TargetSource.FIRST_PARAMETER);
234
235 final Exception uce = new UnmodifiableClassException();
236
237 doThrow(uce)
238 .when(m_instrumentation).retransformClasses(isA(Class.class));
239
240 try {
241 weaver.applyChanges();
242 verifyNoMoreInteractions(m_instrumentation);
243 fail("Expected WeavingException");
244 }
245 catch (WeavingException e) {
246 assertSame(e.getCause(), uce);
247 }
248 }
249
250 @Test(expected=WeavingException.class)
251 public void testInsufficientParameters() throws Exception {
252 final Weaver weaver = new DCRWeaver(m_classFileTransformerFactory,
253 m_instrumentation);
254
255 final Method method = getClass().getDeclaredMethod("myMethod");
256
257 weaver.weave(method, TargetSource.SECOND_PARAMETER);
258 }
259 }