e4cd37995ae411b20541cdec008efc0fc9385456
[sdc.git] /
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.logging.aspects;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.UUID;
23 import java.util.concurrent.atomic.AtomicInteger;
24 import java.util.function.Predicate;
25 import org.aspectj.lang.ProceedingJoinPoint;
26 import org.aspectj.lang.Signature;
27 import org.aspectj.lang.reflect.SourceLocation;
28 import org.aspectj.runtime.internal.AroundClosure;
29 import org.easymock.EasyMock;
30 import org.openecomp.sdc.logging.api.AuditData;
31 import org.openecomp.sdc.logging.api.Logger;
32 import org.openecomp.sdc.logging.api.LoggerFactory;
33 import org.powermock.api.easymock.PowerMock;
34 import org.powermock.core.classloader.annotations.PrepareForTest;
35 import org.powermock.modules.testng.PowerMockTestCase;
36 import org.testng.Assert;
37 import org.testng.annotations.Test;
38
39 /**
40  * Unit-tests metrics aspect (AOP) behavior.
41  *
42  * @author evitaliy
43  * @since 17 Aug 2016
44  */
45 @PrepareForTest(LoggerFactory.class)
46 public class MetricsAspectTest extends PowerMockTestCase {
47
48     private static final Object OBJ_TO_RETURN = new Object();
49     private static final String EXPECTED_MESSAGE = "'{}' took {} milliseconds";
50
51     @Test
52     public void testLogExecutionTime() throws Throwable {
53
54         String className = UUID.randomUUID().toString();
55         String methodName = UUID.randomUUID().toString();
56
57         TestLogger logger = initLogging(className, true);
58
59         MetricsAspect aspect = new MetricsAspect();
60         MockProceedingJoinPoint pjp = new MockProceedingJoinPoint(className, methodName);
61         Object returned = aspect.logExecutionTime(pjp);
62
63         Assert.assertEquals(OBJ_TO_RETURN, returned);
64         assertExecution(methodName, pjp, logger);
65     }
66
67     private TestLogger initLogging(String className, boolean enabled) {
68         TestLogger logger = new TestLogger(enabled);
69         PowerMock.mockStatic(LoggerFactory.class);
70         EasyMock.expect(LoggerFactory.getLogger(className)).andReturn(logger);
71         PowerMock.replay(LoggerFactory.class);
72         return logger;
73     }
74
75     private void assertExecution(String methodName, MockProceedingJoinPoint pjp, TestLogger logger) {
76
77         Assert.assertEquals(1, pjp.getCount());
78         Assert.assertTrue(logger.contains(
79                 (event) -> (event != null) && (event.length == 3) && EXPECTED_MESSAGE.equals(event[0]) && methodName
80                         .equals(event[1]) && (event[2] instanceof Long)));
81     }
82
83     @Test
84     public void testMetricsDisabled() throws Throwable {
85
86         String className = UUID.randomUUID().toString();
87         String methodName = UUID.randomUUID().toString();
88
89         TestLogger logger = initLogging(className, false);
90
91         MetricsAspect aspect = new MetricsAspect();
92         MockProceedingJoinPoint pjp = new MockProceedingJoinPoint(className, methodName);
93         Object returned = aspect.logExecutionTime(pjp);
94
95         Assert.assertEquals(OBJ_TO_RETURN, returned);
96         Assert.assertEquals(1, pjp.getCount());
97         // return any event - must be empty
98         Assert.assertFalse(logger.contains((event) -> true));
99     }
100
101     @Test(expectedExceptions = IllegalArgumentException.class)
102     public void testThrowingError() throws Throwable {
103
104         String className = UUID.randomUUID().toString();
105         String methodName = UUID.randomUUID().toString();
106
107         final TestLogger logger = initLogging(className, true);
108
109         MetricsAspect aspect = new MetricsAspect();
110         MockProceedingJoinPoint pjp = new MockProceedingJoinPointWithException(className, methodName);
111
112         try {
113             aspect.logExecutionTime(pjp);
114         } finally {
115             assertExecution(methodName, pjp, logger);
116         }
117     }
118
119     private static class MockSignature implements Signature {
120
121         private final String className;
122         private final String methodName;
123
124         private MockSignature(String className, String methodName) {
125             this.className = className;
126             this.methodName = methodName;
127         }
128
129         @Override
130         public String toShortString() {
131             return null;
132         }
133
134         @Override
135         public String toLongString() {
136             return null;
137         }
138
139         @Override
140         public String getName() {
141             return methodName;
142         }
143
144         @Override
145         public int getModifiers() {
146             return 0;
147         }
148
149         @Override
150         public Class getDeclaringType() {
151             return null;
152         }
153
154         @Override
155         public String getDeclaringTypeName() {
156             return className;
157         }
158     }
159
160     private static class MockProceedingJoinPoint implements ProceedingJoinPoint {
161
162         private final AtomicInteger count = new AtomicInteger(0);
163         private final Signature signature;
164
165         MockProceedingJoinPoint(String className, String methodName) {
166             this.signature = new MockSignature(className, methodName);
167         }
168
169         int getCount() {
170             return count.get();
171         }
172
173         @Override
174         public void set$AroundClosure(AroundClosure aroundClosure) {
175
176         }
177
178         @Override
179         public Object proceed() throws Throwable {
180             count.incrementAndGet();
181             return OBJ_TO_RETURN;
182         }
183
184         @Override
185         public Object proceed(Object[] objects) {
186             return null;
187         }
188
189         @Override
190         public String toShortString() {
191             return null;
192         }
193
194         @Override
195         public String toLongString() {
196             return null;
197         }
198
199         @Override
200         public Object getThis() {
201             return null;
202         }
203
204         @Override
205         public Object getTarget() {
206             return null;
207         }
208
209         @Override
210         public Object[] getArgs() {
211             return new Object[0];
212         }
213
214         @Override
215         public Signature getSignature() {
216             return this.signature;
217         }
218
219         @Override
220         public SourceLocation getSourceLocation() {
221             return null;
222         }
223
224         @Override
225         public String getKind() {
226             return null;
227         }
228
229         @Override
230         public StaticPart getStaticPart() {
231             return null;
232         }
233     }
234
235     private static class MockProceedingJoinPointWithException extends MockProceedingJoinPoint {
236
237         MockProceedingJoinPointWithException(String className, String methodName) {
238             super(className, methodName);
239         }
240
241         @Override
242         public Object proceed() throws Throwable {
243             super.proceed();
244             throw new IllegalArgumentException();
245         }
246     }
247
248     private class TestLogger implements Logger {
249
250         private final boolean enabled;
251         private final List<Object[]> events = Collections.synchronizedList(new ArrayList<>(10));
252
253         TestLogger(boolean enabled) {
254             this.enabled = enabled;
255         }
256
257         @Override
258         public String getName() {
259             throw new RuntimeException("Not implemented");
260         }
261
262         @Override
263         public boolean isMetricsEnabled() {
264             return this.enabled;
265         }
266
267         @Override
268         public void metrics(String var1) {
269             throw new RuntimeException("Not implemented");
270         }
271
272         @Override
273         public void metrics(String var1, Object var2) {
274             throw new RuntimeException("Not implemented");
275         }
276
277         @Override
278         public void metrics(String var1, Object var2, Object var3) {
279
280             if (this.enabled) {
281                 events.add(new Object[] {var1, var2, var3});
282             }
283         }
284
285         @Override
286         public void metrics(String var1, Object... var2) {
287             throw new RuntimeException("Not implemented");
288         }
289
290         @Override
291         public void metrics(String var1, Throwable throwable) {
292             throw new RuntimeException("Not implemented");
293         }
294
295         @Override
296         public boolean isAuditEnabled() {
297             throw new RuntimeException("Not implemented");
298         }
299
300         @Override
301         public void audit(AuditData var1) {
302             throw new RuntimeException("Not implemented");
303         }
304
305         @Override
306         public boolean isDebugEnabled() {
307             throw new RuntimeException("Not implemented");
308         }
309
310         @Override
311         public void debug(String var1) {
312             throw new RuntimeException("Not implemented");
313         }
314
315         @Override
316         public void debug(String var1, Object var2) {
317             throw new RuntimeException("Not implemented");
318         }
319
320         @Override
321         public void debug(String var1, Object var2, Object var3) {
322             throw new RuntimeException("Not implemented");
323         }
324
325         @Override
326         public void debug(String var1, Object... var2) {
327             throw new RuntimeException("Not implemented");
328         }
329
330         @Override
331         public void debug(String var1, Throwable throwable) {
332             throw new RuntimeException("Not implemented");
333         }
334
335         @Override
336         public boolean isInfoEnabled() {
337             throw new RuntimeException("Not implemented");
338         }
339
340         @Override
341         public void info(String var1) {
342             throw new RuntimeException("Not implemented");
343         }
344
345         @Override
346         public void info(String var1, Object var2) {
347             throw new RuntimeException("Not implemented");
348         }
349
350         @Override
351         public void info(String var1, Object var2, Object var3) {
352             throw new RuntimeException("Not implemented");
353         }
354
355         @Override
356         public void info(String var1, Object... var2) {
357             throw new RuntimeException("Not implemented");
358         }
359
360         @Override
361         public void info(String var1, Throwable throwable) {
362             throw new RuntimeException("Not implemented");
363         }
364
365         @Override
366         public boolean isWarnEnabled() {
367             throw new RuntimeException("Not implemented");
368         }
369
370         @Override
371         public void warn(String var1) {
372             throw new RuntimeException("Not implemented");
373         }
374
375         @Override
376         public void warn(String var1, Object var2) {
377             throw new RuntimeException("Not implemented");
378         }
379
380         @Override
381         public void warn(String var1, Object... var2) {
382             throw new RuntimeException("Not implemented");
383         }
384
385         @Override
386         public void warn(String var1, Object var2, Object var3) {
387             throw new RuntimeException("Not implemented");
388         }
389
390         @Override
391         public void warn(String var1, Throwable throwable) {
392             throw new RuntimeException("Not implemented");
393         }
394
395         @Override
396         public boolean isErrorEnabled() {
397             throw new RuntimeException("Not implemented");
398         }
399
400         @Override
401         public void error(String var1) {
402             throw new RuntimeException("Not implemented");
403         }
404
405         @Override
406         public void error(String var1, Object var2) {
407             throw new RuntimeException("Not implemented");
408         }
409
410         @Override
411         public void error(String var1, Object var2, Object var3) {
412             throw new RuntimeException("Not implemented");
413         }
414
415         @Override
416         public void error(String var1, Object... var2) {
417             throw new RuntimeException("Not implemented");
418         }
419
420         @Override
421         public void error(String var1, Throwable throwable) {
422             throw new RuntimeException("Not implemented");
423         }
424
425         boolean contains(Predicate<Object[]> predicate) {
426             return events.stream().anyMatch(predicate);
427         }
428     }
429 }