]> git.somenet.org - pub/jan/dst18.git/blob - ass2-aop/src/test/java/dst/ass2/aop/tests/Ass2_4_2Test.java
Add template for assignment 2
[pub/jan/dst18.git] / ass2-aop / src / test / java / dst / ass2 / aop / tests / Ass2_4_2Test.java
1 package dst.ass2.aop.tests;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertNotNull;
5 import static org.junit.Assert.assertSame;
6 import static org.junit.Assert.assertTrue;
7
8 import java.io.ByteArrayOutputStream;
9 import java.io.PrintStream;
10 import java.lang.reflect.Method;
11 import java.util.List;
12 import java.util.Map;
13
14 import dst.ass2.aop.IPluginExecutable;
15 import dst.ass2.aop.event.Event;
16 import dst.ass2.aop.event.EventBus;
17 import dst.ass2.aop.event.EventType;
18 import dst.ass2.aop.sample.InvisiblePluginExecutable;
19 import dst.ass2.aop.sample.LoggingPluginExecutable;
20 import dst.ass2.aop.sample.SystemOutPluginExecutable;
21 import dst.ass2.aop.util.PluginUtils;
22 import org.aspectj.lang.annotation.After;
23 import org.aspectj.lang.annotation.Around;
24 import org.aspectj.lang.annotation.Aspect;
25 import org.aspectj.lang.annotation.Before;
26 import org.aspectj.weaver.internal.tools.PointcutExpressionImpl;
27 import org.aspectj.weaver.tools.ShadowMatch;
28 import org.junit.Test;
29 import org.springframework.aop.PointcutAdvisor;
30 import org.springframework.aop.framework.Advised;
31 import org.springframework.core.annotation.AnnotationUtils;
32 import org.springframework.util.ReflectionUtils;
33
34 import dst.ass2.aop.logging.Invisible;
35 import dst.ass2.aop.logging.LoggingAspect;
36
37 public class Ass2_4_2Test {
38     final EventBus eventBus = EventBus.getInstance();
39
40     @org.junit.Before
41     @org.junit.After
42     public void beforeAndAfter() {
43         eventBus.reset();
44     }
45
46     /**
47      * Verifies that the {@link LoggingAspect} is a valid AspectJ aspect i.e., {@link Aspect @Aspect} as well as
48      * {@link Around @Around} or {@link Before @Before} / {@link After @After}.
49      */
50     @Test
51     public void loggingAspect_isValid() {
52         Aspect aspect = AnnotationUtils.findAnnotation(LoggingAspect.class, Aspect.class);
53         assertNotNull("LoggingAspect is not annotated with @Aspect", aspect);
54
55         Map<Method, Around> around = PluginUtils.findMethodAnnotation(LoggingAspect.class, Around.class);
56         Map<Method, Before> before = PluginUtils.findMethodAnnotation(LoggingAspect.class, Before.class);
57         Map<Method, After> after = PluginUtils.findMethodAnnotation(LoggingAspect.class, After.class);
58
59         boolean found = !around.isEmpty() || (!before.isEmpty() && !after.isEmpty());
60         assertTrue("LoggingAspect does not contain methods annotated with @Around OR @Before / @After", found);
61     }
62
63     /**
64      * Verifies that the pointcut expression of the {@link LoggingAspect} does not match any method except the
65      * {@link IPluginExecutable#execute()} method.
66      */
67     @Test
68     public void pointcutExpression_matchesCorrectly() {
69         IPluginExecutable executable = PluginUtils.getExecutable(LoggingPluginExecutable.class, LoggingAspect.class);
70         assertTrue("Executable must implement the Advised interface", executable instanceof Advised);
71         Advised advised = (Advised) executable;
72
73         PointcutAdvisor pointcutAdvisor = PluginUtils.getPointcutAdvisor(advised);
74         assertNotNull("PointcutAdvisor not found because there is no pointcut or the pointcut does not match", pointcutAdvisor);
75
76         String expression = PluginUtils.getBestExpression(advised);
77         assertTrue("Pointcut expression must include '" + IPluginExecutable.class.getName() + "'", expression.contains(IPluginExecutable.class.getName()));
78         assertTrue("Pointcut expression must include '" + PluginUtils.EXECUTE_METHOD.getName() + "'", expression.contains(PluginUtils.EXECUTE_METHOD.getName()));
79
80         PointcutExpressionImpl pointcutExpression = PluginUtils.getPointcutExpression(advised);
81         ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(PluginUtils.EXECUTE_METHOD);
82         assertTrue("Pointcut does not match IPluginExecute.execute()", shadowMatch.alwaysMatches());
83
84         shadowMatch = pointcutExpression.matchesMethodExecution(PluginUtils.INTERRUPTED_METHOD);
85         assertTrue("Pointcut must not match IPluginExecute.interrupted()", shadowMatch.neverMatches());
86
87         shadowMatch = pointcutExpression.matchesMethodExecution(ReflectionUtils.findMethod(getClass(), PluginUtils.EXECUTE_METHOD.getName()));
88         assertTrue("Pointcut must not match LoggingPluginTest.execute()", shadowMatch.neverMatches());
89     }
90
91     /**
92      * Verifies that the pointcut expression of the LoggingAspect contains the {@link Invisible @Invisible} annotation.
93      */
94     @Test
95     public void pointcutExpression_containsInvisibleAnnotation() {
96         IPluginExecutable executable = PluginUtils.getExecutable(LoggingPluginExecutable.class, LoggingAspect.class);
97         Advised advised = (Advised) executable;
98
99         String expression = PluginUtils.getBestExpression(advised);
100         String annotationName = Invisible.class.getName();
101         assertTrue("Pointcut expression does not contain " + annotationName, expression.contains(annotationName));
102     }
103
104     /**
105      * Verifies that the pointcut expression of the {@link LoggingAspect} does not match any method annotated with
106      * {@link Invisible @Invisible}.
107      */
108     @Test
109     public void pointcutExpression_doesNotMatchInvisible() {
110         IPluginExecutable executable = PluginUtils.getExecutable(LoggingPluginExecutable.class, LoggingAspect.class);
111         Advised advised = (Advised) executable;
112
113         PointcutExpressionImpl pointcutExpression = PluginUtils.getPointcutExpression(advised);
114
115         Method loggingMethod = ReflectionUtils.findMethod(LoggingPluginExecutable.class, PluginUtils.EXECUTE_METHOD.getName());
116         ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(loggingMethod);
117         assertTrue("Pointcut does not match LoggingPluginExecutable.execute()", shadowMatch.alwaysMatches());
118
119         Method invisibleMethod = ReflectionUtils.findMethod(InvisiblePluginExecutable.class, PluginUtils.EXECUTE_METHOD.getName());
120         shadowMatch = pointcutExpression.matchesMethodExecution(invisibleMethod);
121         assertTrue("Pointcut matches InvisiblePluginExecutable.execute()", shadowMatch.neverMatches());
122     }
123
124     /**
125      * Tests if the {@link LoggingAspect} uses the {@link java.util.logging.Logger Logger} defined in the plugin.
126      */
127     @Test
128     public void loggingAspect_usesLogger() {
129         IPluginExecutable executable = PluginUtils.getExecutable(LoggingPluginExecutable.class, LoggingAspect.class);
130         Advised advised = (Advised) executable;
131
132         // Add handler end check that there are no events
133         PluginUtils.addBusHandlerIfNecessary(advised);
134         assertEquals("EventBus must be empty", 0, eventBus.count(EventType.INFO));
135
136         // Execute plugin and check that there are 2 events
137         executable.execute();
138         List<Event> events = eventBus.getEvents(EventType.INFO);
139         assertEquals("EventBus must exactly contain 2 INFO events", 2, events.size());
140
141         // Check if the logger contains the correct class name
142         events = eventBus.getEvents(EventType.INFO);
143         for (Event event : events) {
144             assertEquals("Event message must contain the name of the " + LoggingAspect.class.getSimpleName(), LoggingAspect.class.getName(), event.getMessage());
145             assertSame("Event must be logged for " + LoggingPluginExecutable.class.getSimpleName(), LoggingPluginExecutable.class, event.getPluginClass());
146         }
147     }
148
149     /**
150      * Tests if the {@link LoggingAspect} uses {@code System.out} if the plugin does not contain a
151      * {@link java.util.logging.Logger Logger} field.
152      *
153      * @throws IllegalAccessException if {@code System.out} cannot be modified (must not happen)
154      */
155     @Test
156     public void loggingAspect_usesSystemOut() throws IllegalAccessException {
157         // Redirect System.out
158         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
159         PrintStream out = PluginUtils.setStaticFinalField(System.class, "out", new PrintStream(byteArrayOutputStream));
160         try {
161             // Execute plugin
162             IPluginExecutable executable = PluginUtils.getExecutable(SystemOutPluginExecutable.class, LoggingAspect.class);
163             assertEquals("EventBus must be empty", 0, eventBus.size());
164             executable.execute();
165             assertEquals("EventBus must exactly contain 2 events", 2, eventBus.size());
166
167             // Verify that the log output contains the class name of the executed plugin
168             String output = byteArrayOutputStream.toString();
169             assertTrue(String.format("Log output must contain %s\n\tbut was%s", SystemOutPluginExecutable.class.getName(), output),
170                     output.contains(SystemOutPluginExecutable.class.getName()));
171         } finally {
172             // Reset System.out
173             PluginUtils.setStaticFinalField(System.class, "out", out);
174         }
175     }
176
177     public void execute() {
178
179     }
180 }