Skip to content

Commit 0154cd3

Browse files
committed
Added Unit test for DefineClassInstrumentation
1 parent dc26c83 commit 0154cd3

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.internal.classloader;
7+
8+
import static org.mockito.ArgumentMatchers.eq;
9+
import static org.mockito.ArgumentMatchers.same;
10+
import static org.mockito.Mockito.verify;
11+
12+
import io.opentelemetry.javaagent.bootstrap.DefineClassHelper;
13+
import java.io.ByteArrayOutputStream;
14+
import java.io.IOException;
15+
import java.io.InputStream;
16+
import java.lang.reflect.Field;
17+
import java.security.ProtectionDomain;
18+
import org.apache.commons.compress.utils.IOUtils;
19+
import org.junit.jupiter.params.ParameterizedTest;
20+
import org.junit.jupiter.params.provider.ValueSource;
21+
import org.mockito.Mockito;
22+
23+
class DefineClassInstrumentationTest {
24+
25+
public static class DefiningClassLoader extends ClassLoader {
26+
27+
public DefiningClassLoader() {
28+
super(null);
29+
}
30+
31+
// Suppressing warnings to force testing of deprecated method
32+
@SuppressWarnings("deprecation")
33+
public Class<?> doDefineClass(byte[] b, int off, int len) {
34+
return defineClass(b, off, len);
35+
}
36+
37+
public Class<?> doDefineClass(String name, byte[] b, int off, int len) {
38+
return defineClass(name, b, off, len);
39+
}
40+
41+
public Class<?> doDefineClass(
42+
String name, byte[] b, int off, int len, ProtectionDomain protectionDomain) {
43+
return defineClass(name, b, off, len, protectionDomain);
44+
}
45+
}
46+
47+
@ParameterizedTest
48+
@ValueSource(ints = {3, 4, 5})
49+
@SuppressWarnings("DirectInvocationOnMock")
50+
void ensureDefineClassInstrumented(int argCount) throws IOException {
51+
String className = Dummy.class.getName();
52+
String resource = className.replace('.', '/') + ".class";
53+
ByteArrayOutputStream byteCodeStream = new ByteArrayOutputStream();
54+
try (InputStream classfile = getClass().getResourceAsStream("/" + resource)) {
55+
IOUtils.copy(classfile, byteCodeStream, 1024);
56+
}
57+
byte[] bytecode = byteCodeStream.toByteArray();
58+
59+
DefiningClassLoader cl = new DefiningClassLoader();
60+
61+
DefineClassHelper.Handler mockHandler = Mockito.mock(DefineClassHelper.Handler.class);
62+
// We need to initialize mockHandler by invoking it early, otherwise this leads to problems
63+
mockHandler.beforeDefineClass(cl, className, bytecode, 0, bytecode.length);
64+
Mockito.reset(mockHandler);
65+
66+
DefineClassHelper.Handler originalHandler = forceSetDefineClassHelper(mockHandler);
67+
String expectedClassName;
68+
try {
69+
switch (argCount) {
70+
case 3:
71+
expectedClassName = null;
72+
cl.doDefineClass(bytecode, 0, bytecode.length);
73+
break;
74+
case 4:
75+
expectedClassName = className;
76+
cl.doDefineClass(className, bytecode, 0, bytecode.length);
77+
break;
78+
case 5:
79+
expectedClassName = className;
80+
cl.doDefineClass(className, bytecode, 0, bytecode.length, null);
81+
break;
82+
default:
83+
throw new IllegalStateException();
84+
}
85+
} finally {
86+
forceSetDefineClassHelper(originalHandler);
87+
}
88+
89+
verify(mockHandler)
90+
.beforeDefineClass(
91+
same(cl), eq(expectedClassName), eq(bytecode), eq(0), eq(bytecode.length));
92+
verify(mockHandler).afterDefineClass(eq(null));
93+
}
94+
95+
private static DefineClassHelper.Handler forceSetDefineClassHelper(
96+
DefineClassHelper.Handler newHandler) {
97+
try {
98+
Field handler = DefineClassHelper.class.getDeclaredField("handler");
99+
handler.setAccessible(true);
100+
DefineClassHelper.Handler previous = (DefineClassHelper.Handler) handler.get(null);
101+
handler.set(null, newHandler);
102+
return previous;
103+
} catch (Exception e) {
104+
throw new IllegalStateException(e);
105+
}
106+
}
107+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.internal.classloader;
7+
8+
class Dummy {}

0 commit comments

Comments
 (0)