1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package io.earcam.instrumental.agent.defy;
20
21 import static io.earcam.instrumental.proxy.handler.NoopInvocationHandler.NOOP_INVOCATION_HANDLER;
22 import static org.hamcrest.MatcherAssert.assertThat;
23 import static org.hamcrest.Matchers.equalTo;
24 import static org.hamcrest.Matchers.is;
25 import static org.junit.jupiter.api.Assertions.assertFalse;
26 import static org.junit.jupiter.api.Assertions.assertTrue;
27 import static org.junit.jupiter.api.Assertions.fail;
28
29 import java.lang.instrument.Instrumentation;
30 import java.lang.reflect.Modifier;
31
32 import org.junit.jupiter.api.Test;
33
34 import io.earcam.acme.a.FinalClass;
35 import io.earcam.acme.a.InterfaceWithFinalField;
36 import io.earcam.acme.b.FinalClassB;
37 import io.earcam.acme.c.FinalClassC;
38 import io.earcam.instrumental.agent.junit.extension.AgentClass;
39 import io.earcam.instrumental.proxy.Proxies;
40 import io.earcam.unexceptional.Exceptional;
41
42 @AgentClass(value = Agent.class, arguments = "io.earcam.acme.a,io.earcam.acme.c")
43 public final class AgentTest {
44
45 public static final Instrumentation MOCK_INSTRUMENTATION = Proxies.proxy(NOOP_INVOCATION_HANDLER, Instrumentation.class);
46
47
48 @Test
49 public void finalClassShouldNotBeFinal()
50 {
51 Class<?> clazz = loadClass("io.earcam.acme.a.FinalClass");
52 assertFalse(Modifier.isFinal(clazz.getModifiers()));
53 }
54
55
56 @Test
57 public void loadedFinalClassShouldNotBeFinal()
58 {
59 Class<?> clazz = FinalClass.class;
60 assertFalse(Modifier.isFinal(clazz.getModifiers()));
61 }
62
63
64 private Class<?> loadClass(String name)
65 {
66 return Exceptional.apply(ClassLoader::loadClass, AgentTest.class.getClassLoader(), name);
67 }
68
69
70 @Test
71 public void finalMethodShouldNotBeFinal() throws NoSuchMethodException, SecurityException
72 {
73 Class<?> clazz = loadClass("io.earcam.acme.a.FinalClass");
74 assertFalse(Modifier.isFinal(clazz.getMethod("sayFoo").getModifiers()));
75 }
76
77
78 @Test
79 public void finalFieldShouldNotBeFinal() throws NoSuchFieldException, SecurityException
80 {
81 Class<?> clazz = loadClass("io.earcam.acme.a.FinalClass");
82 assertFalse(Modifier.isFinal(clazz.getField("field").getModifiers()));
83 }
84
85
86 @Test
87 public void doesNotProduceInvalidInterfaces() throws NoSuchFieldException, SecurityException
88 {
89 assertTrue(Modifier.isFinal(InterfaceWithFinalField.class.getField("field").getModifiers()));
90 }
91
92
93 @Test
94 public void finalSystemClassWillStillBeFinal()
95 {
96 Class<?> clazz = loadClass("java.lang.String");
97 assertTrue(Modifier.isFinal(clazz.getModifiers()));
98 }
99
100
101 @Test
102 public void otherFinalClassMatchedByPatternIsDefinalised()
103 {
104 Class<?> clazz = FinalClassC.class;
105 assertFalse(Modifier.isFinal(clazz.getModifiers()));
106 }
107
108
109 @Test
110 public void otherFinalClassNotMatchedByPatternIsStillFinal()
111 {
112 Class<?> clazz = FinalClassB.class;
113 assertTrue(Modifier.isFinal(clazz.getModifiers()));
114 }
115
116
117 @Test
118 public void agentThrowsIfArgumentIsNull()
119 {
120 try {
121 Agent.premain(null, MOCK_INSTRUMENTATION);
122 fail();
123 } catch(IllegalArgumentException e) {}
124 }
125
126
127 @Test
128 public void agentThrowsIfArgumentContainIllegalCharacters()
129 {
130 try {
131 Agent.premain("com.acme.*", MOCK_INSTRUMENTATION);
132 fail();
133 } catch(IllegalArgumentException e) {}
134 }
135
136
137 @Test
138 public void agentHoldsReferenceToInstrumentation()
139 {
140 Agent.premain("com.acme.boo", MOCK_INSTRUMENTATION);
141
142 assertThat(Agent.instrumentation, is(equalTo(MOCK_INSTRUMENTATION)));
143 }
144 }