| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package groovy.util.logging |
| |
| import groovy.test.GroovyTestCase |
| |
| import java.lang.reflect.Field |
| import java.lang.reflect.Modifier |
| |
| import static groovy.test.GroovyAssert.isAtLeastJdk |
| |
| /** |
| * Unit test for the commons logging @Log based annotation. |
| */ |
| class CommonsTest extends GroovyTestCase { |
| |
| PrintStream savedSystemOut |
| ByteArrayOutputStream redirectedSystemOut |
| |
| void setUp() { |
| super.setUp() |
| savedSystemOut = System.out |
| redirectedSystemOut = new ByteArrayOutputStream() |
| System.out = new PrintStream(redirectedSystemOut) |
| } |
| |
| void tearDown() { |
| super.tearDown() |
| System.out = savedSystemOut |
| } |
| |
| void testPrivateFinalStaticLogFieldAppears() { |
| Class clazz = new GroovyClassLoader().parseClass(''' |
| @groovy.util.logging.Commons |
| class MyClass { |
| } ''') |
| |
| assert clazz.declaredFields.find { Field field -> |
| field.name == "log" && |
| Modifier.isPrivate(field.getModifiers()) && |
| Modifier.isStatic(field.getModifiers()) && |
| Modifier.isTransient(field.getModifiers()) && |
| Modifier.isFinal(field.getModifiers()) |
| } |
| } |
| |
| void testExplicitPrivateFinalStaticLogFieldAppears() { |
| Class clazz = new GroovyClassLoader().parseClass(''' |
| import static groovy.transform.options.Visibility.* |
| @groovy.transform.VisibilityOptions(value = PRIVATE) |
| @groovy.util.logging.Commons |
| class MyClass { |
| } |
| ''') |
| |
| assert clazz.declaredFields.find { Field field -> |
| field.name == "log" && |
| Modifier.isPrivate(field.getModifiers()) && |
| Modifier.isStatic(field.getModifiers()) && |
| Modifier.isTransient(field.getModifiers()) && |
| Modifier.isFinal(field.getModifiers()) |
| } |
| } |
| |
| void testPackagePrivateFinalStaticLogFieldAppears() { |
| Class clazz = new GroovyClassLoader().parseClass(''' |
| import static groovy.transform.options.Visibility.* |
| @groovy.transform.VisibilityOptions(value = PACKAGE_PRIVATE) |
| @groovy.util.logging.Commons |
| class MyClass { |
| } |
| ''') |
| |
| assert clazz.declaredFields.find { Field field -> |
| field.name == "log" && |
| !Modifier.isPrivate(field.getModifiers()) && |
| !Modifier.isProtected(field.getModifiers()) && |
| !Modifier.isPublic(field.getModifiers()) && |
| Modifier.isStatic(field.getModifiers()) && |
| Modifier.isTransient(field.getModifiers()) && |
| Modifier.isFinal(field.getModifiers()) |
| } |
| } |
| |
| void testProtectedFinalStaticLogFieldAppears() { |
| Class clazz = new GroovyClassLoader().parseClass(''' |
| import static groovy.transform.options.Visibility.* |
| @groovy.transform.VisibilityOptions(value = PROTECTED) |
| @groovy.util.logging.Commons |
| class MyClass { |
| } |
| ''') |
| |
| assert clazz.declaredFields.find { Field field -> |
| field.name == "log" && |
| Modifier.isProtected(field.getModifiers()) && |
| Modifier.isStatic(field.getModifiers()) && |
| Modifier.isTransient(field.getModifiers()) && |
| Modifier.isFinal(field.getModifiers()) |
| } |
| } |
| |
| void testPublicFinalStaticLogFieldAppears() { |
| Class clazz = new GroovyClassLoader().parseClass(''' |
| import static groovy.transform.options.Visibility.* |
| @groovy.transform.VisibilityOptions(value = PUBLIC) |
| @groovy.util.logging.Commons |
| class MyClass { |
| } |
| ''') |
| |
| assert clazz.declaredFields.find { Field field -> |
| field.name == "log" && |
| Modifier.isPublic(field.getModifiers()) && |
| Modifier.isStatic(field.getModifiers()) && |
| Modifier.isTransient(field.getModifiers()) && |
| Modifier.isFinal(field.getModifiers()) |
| } |
| } |
| |
| void testPrivateFinalStaticNamedLogFieldAppears() { |
| Class clazz = new GroovyClassLoader().parseClass(''' |
| @groovy.util.logging.Commons('logger') |
| class MyClass { |
| } ''') |
| |
| assert clazz.declaredFields.find { Field field -> |
| field.name == "logger" && |
| Modifier.isPrivate(field.getModifiers()) && |
| Modifier.isStatic(field.getModifiers()) && |
| Modifier.isTransient(field.getModifiers()) && |
| Modifier.isFinal(field.getModifiers()) |
| } |
| } |
| |
| void testClassAlreadyHasLogField() { |
| shouldFail { |
| Class clazz = new GroovyClassLoader().parseClass(''' |
| @groovy.util.logging.Commons |
| class MyClass { |
| String log |
| } ''') |
| |
| assert clazz.newInstance() |
| } |
| } |
| |
| void testClassAlreadyHasNamedLogField() { |
| shouldFail { |
| Class clazz = new GroovyClassLoader().parseClass(''' |
| @groovy.util.logging.Commons('logger') |
| class MyClass { |
| String logger |
| } ''') |
| |
| assert clazz.newInstance() |
| } |
| } |
| |
| void testLogLevelDebug() { |
| Class clazz = new GroovyClassLoader().parseClass(''' |
| @groovy.util.logging.Commons |
| class MyClass { |
| |
| def loggingMethod() { |
| log.error ("error called") |
| log.warn ("warn called") |
| log.info ("info called") |
| log.debug ("debug called") |
| } |
| } |
| new MyClass().loggingMethod() ''') |
| |
| clazz.newInstance().run() |
| |
| String log = redirectedSystemOut.toString() |
| assert log.contains("error called") |
| assert log.contains("warn called") |
| assert log.contains("info called") |
| assert log.contains("debug called") |
| } |
| |
| void testLogFromStaticMethods() { |
| Class clazz = new GroovyClassLoader().parseClass(""" |
| @groovy.util.logging.Commons |
| class MyClass { |
| static loggingMethod() { |
| log.info ("(static) info called") |
| } |
| } |
| MyClass.loggingMethod()""") |
| |
| clazz.newInstance().run() |
| |
| String log = redirectedSystemOut.toString() |
| assert log.contains("(static) info called") |
| } |
| |
| void testNamedLogger() { |
| Class clazz = new GroovyClassLoader().parseClass(''' |
| @groovy.util.logging.Commons('logger') |
| class MyClass { |
| |
| def loggingMethod() { |
| logger.error ("error called") |
| logger.warn ("warn called") |
| logger.info ("info called") |
| logger.debug ("debug called") |
| } |
| } |
| new MyClass().loggingMethod() ''') |
| |
| clazz.newInstance().run() |
| |
| String log = redirectedSystemOut.toString() |
| assert log.contains("error called") |
| assert log.contains("warn called") |
| assert log.contains("info called") |
| assert log.contains("debug called") |
| } |
| |
| void testLogGuards() { |
| // JDK12+ doesn't allow adjusting static final fields even via reflection |
| // so skip this test on such JDK versions - it is only this test which is affected |
| // and currently we have coverage from builds with lower JDK versions. |
| if (isAtLeastJdk('12')) return |
| |
| Class clazz = new GroovyClassLoader().parseClass(''' |
| class LogDecorator extends groovy.util.Proxy { |
| boolean isTraceEnabled() { false } |
| } |
| |
| @groovy.util.logging.Commons |
| class MyClass { |
| boolean traceCalled = false |
| |
| def loggingMethod() { |
| overrideLog() |
| log.trace (traceCalled = true) |
| } |
| |
| def overrideLog() { |
| def field = MyClass.getDeclaredField('log') |
| field.accessible = true |
| def modifiersField = java.lang.reflect.Field.getDeclaredField("modifiers") |
| modifiersField.accessible = true |
| modifiersField.setInt(field, field.modifiers & ~java.lang.reflect.Modifier.FINAL) |
| field.set(null, new LogDecorator().wrap(log) as org.apache.commons.logging.Log) |
| } |
| } |
| def o = new MyClass() |
| o.loggingMethod() |
| o.traceCalled''') |
| |
| Script s = (Script) clazz.newInstance() |
| def result = s.run() |
| assert !result |
| } |
| |
| void testDefaultCategory() { |
| Class clazz = new GroovyClassLoader().parseClass(""" |
| @groovy.util.logging.Commons |
| class MyClass { |
| static loggingMethod() { |
| log.error("error called") |
| } |
| }""") |
| |
| clazz.newInstance().loggingMethod() |
| |
| assert redirectedSystemOut.toString().contains('MyClass') |
| } |
| |
| void testCustomCategory() { |
| Class clazz = new GroovyClassLoader().parseClass(""" |
| @groovy.util.logging.Commons(category='customCategory') |
| class MyClass { |
| static loggingMethod() { |
| log.error("error called") |
| } |
| }""") |
| |
| clazz.newInstance().loggingMethod() |
| |
| assert redirectedSystemOut.toString().contains('customCategory') |
| } |
| } |