Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- some low-hanging fruit - speed up admin tests with declaration failures with a `NoBackoffPolicy` or remove retry altogether - speed up some tests that were waiting 2 seconds for no message expected - Polishing Queue.clone() - decouple `LongRunningIntegrationTestCondition` from JUnit 4 - Add JUnit 5 log level adjuster; find @RabbitAvailable etc on test superclasses - Support @LogLevels at the method level - Make JUnit 4 an optional dependency - Remove annotation from method level context store - Fix typo in class name - Fix @SInCE Javadoc - Switch to the new Log4j2 logic from Spring Integration
- Loading branch information
1 parent
a22a1ce
commit 2c5d037
Showing
50 changed files
with
836 additions
and
637 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
170 changes: 170 additions & 0 deletions
170
spring-rabbit-junit/src/main/java/org/springframework/amqp/rabbit/junit/JUnitUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
/* | ||
* Copyright 2019 the original author or authors. | ||
* | ||
* Licensed 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 | ||
* | ||
* https://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 org.springframework.amqp.rabbit.junit; | ||
|
||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
import org.apache.commons.logging.Log; | ||
import org.apache.commons.logging.LogFactory; | ||
import org.apache.logging.log4j.Level; | ||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.core.Logger; | ||
import org.apache.logging.log4j.core.LoggerContext; | ||
import org.apache.logging.log4j.core.config.Configuration; | ||
import org.apache.logging.log4j.core.config.LoggerConfig; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* Utility methods for JUnit rules and conditions. | ||
* | ||
* @author Gary Russell | ||
* @since 2.2 | ||
* | ||
*/ | ||
public final class JUnitUtils { | ||
|
||
private static final Log LOGGER = LogFactory.getLog(JUnitUtils.class); | ||
|
||
private JUnitUtils() { | ||
super(); | ||
} | ||
|
||
/** | ||
* Return the parsed value if the provided property exists in the environment or system properties. | ||
* @param property the property name. | ||
* @return the parsed property value if it exists, false otherwise. | ||
*/ | ||
public static boolean parseBooleanProperty(String property) { | ||
for (String value: new String[] { System.getenv(property), System.getProperty(property) }) { | ||
if (Boolean.parseBoolean(value)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
public static LevelsContainer adjustLogLevels(String methodName, List<Class<?>> classes, List<String> categories, | ||
Level level) { | ||
|
||
LoggerContext ctx = (LoggerContext) LogManager.getContext(false); | ||
Configuration config = ctx.getConfiguration(); | ||
|
||
Map<Class<?>, Level> classLevels = new HashMap<>(); | ||
for (Class<?> cls : classes) { | ||
String className = cls.getName(); | ||
LoggerConfig loggerConfig = config.getLoggerConfig(className); | ||
LoggerConfig specificConfig = loggerConfig; | ||
|
||
// We need a specific configuration for this logger, | ||
// otherwise we would change the level of all other loggers | ||
// having the original configuration as parent as well | ||
|
||
if (!loggerConfig.getName().equals(className)) { | ||
specificConfig = new LoggerConfig(className, loggerConfig.getLevel(), true); | ||
specificConfig.setParent(loggerConfig); | ||
config.addLogger(className, specificConfig); | ||
} | ||
|
||
classLevels.put(cls, specificConfig.getLevel()); | ||
specificConfig.setLevel(level); | ||
} | ||
|
||
Map<String, Level> categoryLevels = new HashMap<>(); | ||
for (String category : categories) { | ||
LoggerConfig loggerConfig = config.getLoggerConfig(category); | ||
LoggerConfig specificConfig = loggerConfig; | ||
|
||
// We need a specific configuration for this logger, | ||
// otherwise we would change the level of all other loggers | ||
// having the original configuration as parent as well | ||
|
||
if (!loggerConfig.getName().equals(category)) { | ||
specificConfig = new LoggerConfig(category, loggerConfig.getLevel(), true); | ||
specificConfig.setParent(loggerConfig); | ||
config.addLogger(category, specificConfig); | ||
} | ||
|
||
categoryLevels.put(category, specificConfig.getLevel()); | ||
specificConfig.setLevel(level); | ||
} | ||
|
||
ctx.updateLoggers(); | ||
|
||
Map<String, ch.qos.logback.classic.Level> oldLbLevels = new HashMap<>(); | ||
categories.stream() | ||
.forEach(cat -> { | ||
ch.qos.logback.classic.Logger lbLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(cat); | ||
oldLbLevels.put(cat, lbLogger.getLevel()); | ||
lbLogger.setLevel(ch.qos.logback.classic.Level.toLevel(level.name())); | ||
}); | ||
LOGGER.info("++++++++++++++++++++++++++++ " | ||
+ "Overridden log level setting for: " | ||
+ classes.stream() | ||
.map(Class::getSimpleName) | ||
.collect(Collectors.toList()) | ||
+ " and " + categories.toString() | ||
+ " for test " + methodName); | ||
return new LevelsContainer(classLevels, categoryLevels, oldLbLevels); | ||
} | ||
|
||
public static void revertLevels(String methodName, LevelsContainer container) { | ||
LOGGER.info("++++++++++++++++++++++++++++ " | ||
+ "Restoring log level setting for test " + methodName); | ||
container.oldCatLevels.entrySet() | ||
.stream() | ||
.forEach(entry -> { | ||
if (!entry.getKey().contains("BrokerRunning")) { | ||
((Logger) LogManager.getLogger(entry.getKey())).setLevel(entry.getValue()); | ||
} | ||
}); | ||
container.oldLevels.entrySet() | ||
.stream() | ||
.forEach(entry -> { | ||
if (!entry.getKey().equals(BrokerRunning.class)) { | ||
((Logger) LogManager.getLogger(entry.getKey())).setLevel(entry.getValue()); | ||
} | ||
}); | ||
container.oldLbLevels.entrySet() | ||
.stream() | ||
.forEach(entry -> { | ||
((ch.qos.logback.classic.Logger) LoggerFactory.getLogger(entry.getKey())) | ||
.setLevel(entry.getValue()); | ||
}); | ||
} | ||
|
||
public static class LevelsContainer { | ||
|
||
final Map<Class<?>, Level> oldLevels; | ||
|
||
final Map<String, Level> oldCatLevels; | ||
|
||
final Map<String, ch.qos.logback.classic.Level> oldLbLevels; | ||
|
||
public LevelsContainer(Map<Class<?>, Level> oldLevels, Map<String, Level> oldCatLevels, | ||
Map<String, ch.qos.logback.classic.Level> oldLbLevels) { | ||
|
||
this.oldLevels = oldLevels; | ||
this.oldCatLevels = oldCatLevels; | ||
this.oldLbLevels = oldLbLevels; | ||
} | ||
|
||
} | ||
|
||
} |
87 changes: 87 additions & 0 deletions
87
...ng-rabbit-junit/src/main/java/org/springframework/amqp/rabbit/junit/LogLevelAdjuster.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* Copyright 2002-2019 the original author or authors. | ||
* | ||
* Licensed 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 | ||
* | ||
* https://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 org.springframework.amqp.rabbit.junit; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
import org.apache.logging.log4j.Level; | ||
import org.junit.rules.MethodRule; | ||
import org.junit.runners.model.FrameworkMethod; | ||
import org.junit.runners.model.Statement; | ||
|
||
import org.springframework.amqp.rabbit.junit.JUnitUtils.LevelsContainer; | ||
|
||
/** | ||
* A JUnit method @Rule that changes the logger level for a set of classes | ||
* while a test method is running. Useful for performance or scalability tests | ||
* where we don't want to generate a large log in a tight inner loop. | ||
* | ||
* As well as adjusting Log4j, this also adjusts loggers for logback. The amqp-client | ||
* library now uses slf4j. Since we have logback on the CP (for the appender) | ||
* we can't add the slf4j-log4j bridge as well. | ||
* | ||
* @author Dave Syer | ||
* @author Artem Bilan | ||
* @author Gary Russell | ||
* | ||
*/ | ||
public class LogLevelAdjuster implements MethodRule { | ||
|
||
private final List<Class<?>> classes; | ||
|
||
private List<String> categories; | ||
|
||
private final Level level; | ||
|
||
public LogLevelAdjuster(Level level, Class<?>... classes) { | ||
this.level = level; | ||
this.classes = new ArrayList<>(Arrays.asList(classes)); | ||
this.classes.add(getClass()); | ||
this.categories = Collections.emptyList(); | ||
} | ||
|
||
public LogLevelAdjuster categories(String... categoriesToAdjust) { | ||
this.categories = new ArrayList<>(Arrays.asList(categoriesToAdjust)); | ||
return this; | ||
} | ||
|
||
@Override | ||
public Statement apply(final Statement base, FrameworkMethod method, Object target) { | ||
return new Statement() { | ||
@Override | ||
public void evaluate() throws Throwable { | ||
LevelsContainer container = null; | ||
try { | ||
container = JUnitUtils.adjustLogLevels(method.getName(), | ||
LogLevelAdjuster.this.classes, LogLevelAdjuster.this.categories, | ||
LogLevelAdjuster.this.level); | ||
base.evaluate(); | ||
} | ||
finally { | ||
if (container != null) { | ||
JUnitUtils.revertLevels(method.getName(), container); | ||
} | ||
} | ||
} | ||
|
||
}; | ||
} | ||
|
||
} |
Oops, something went wrong.