001
014
015 package com.liferay.portal.test.rule.callback;
016
017 import com.liferay.portal.kernel.test.rule.callback.BaseTestCallback;
018 import com.liferay.portal.kernel.util.StringPool;
019 import com.liferay.portal.test.log.CaptureAppender;
020 import com.liferay.portal.test.log.Log4JLoggerTestUtil;
021 import com.liferay.portal.test.rule.ExpectedLog;
022 import com.liferay.portal.test.rule.ExpectedLogs;
023 import com.liferay.portal.test.rule.ExpectedType;
024 import com.liferay.portal.test.rule.LogAssertionAppender;
025 import com.liferay.portal.test.rule.LogAssertionHandler;
026
027 import java.util.Map;
028 import java.util.concurrent.ConcurrentHashMap;
029 import java.util.logging.Logger;
030
031 import org.apache.log4j.Level;
032 import org.apache.log4j.spi.LoggingEvent;
033
034 import org.junit.Assert;
035 import org.junit.runner.Description;
036
037
040 public class LogAssertionTestCallback
041 extends BaseTestCallback<CaptureAppender, CaptureAppender> {
042
043 public static final LogAssertionTestCallback INSTANCE =
044 new LogAssertionTestCallback();
045
046 public static void caughtFailure(Error error) {
047 Thread currentThread = Thread.currentThread();
048
049 if (currentThread != _thread) {
050 _concurrentFailures.put(currentThread, error);
051
052 _thread.interrupt();
053 }
054 else {
055 throw error;
056 }
057 }
058
059 public static void endAssert(
060 ExpectedLogs expectedLogs, CaptureAppender captureAppender) {
061
062 if (expectedLogs != null) {
063 try {
064 for (LoggingEvent loggingEvent :
065 captureAppender.getLoggingEvents()) {
066
067 String renderedMessage = loggingEvent.getRenderedMessage();
068
069 if (!isExpected(expectedLogs, renderedMessage)) {
070 Assert.fail(renderedMessage);
071 }
072 }
073 }
074 finally {
075 captureAppender.close();
076 }
077 }
078
079 _thread = null;
080
081 try {
082 for (Map.Entry<Thread, Error> entry :
083 _concurrentFailures.entrySet()) {
084
085 Thread thread = entry.getKey();
086 Error error = entry.getValue();
087
088 Assert.fail(
089 "Thread " + thread + " caught concurrent failure: " +
090 error);
091
092 throw error;
093 }
094 }
095 finally {
096 _concurrentFailures.clear();
097 }
098 }
099
100 public static CaptureAppender startAssert(ExpectedLogs expectedLogs) {
101 _thread = Thread.currentThread();
102
103 CaptureAppender captureAppender = null;
104
105 if (expectedLogs != null) {
106 Class<?> clazz = expectedLogs.loggerClass();
107
108 captureAppender = Log4JLoggerTestUtil.configureLog4JLogger(
109 clazz.getName(), Level.toLevel(expectedLogs.level()));
110 }
111
112 installJdk14Handler();
113 installLog4jAppender();
114
115 return captureAppender;
116 }
117
118 @Override
119 public void doAfterClass(
120 Description description, CaptureAppender captureAppender) {
121
122 ExpectedLogs expectedLogs = description.getAnnotation(
123 ExpectedLogs.class);
124
125 endAssert(expectedLogs, captureAppender);
126 }
127
128 @Override
129 public void doAfterMethod(
130 Description description, CaptureAppender captureAppender,
131 Object target) {
132
133 doAfterClass(description, captureAppender);
134 }
135
136 @Override
137 public CaptureAppender doBeforeClass(Description description) {
138 ExpectedLogs expectedLogs = description.getAnnotation(
139 ExpectedLogs.class);
140
141 return startAssert(expectedLogs);
142 }
143
144 @Override
145 public CaptureAppender doBeforeMethod(
146 Description description, Object target) {
147
148 return doBeforeClass(description);
149 }
150
151 protected static void installJdk14Handler() {
152 Logger logger = Logger.getLogger(StringPool.BLANK);
153
154 logger.removeHandler(LogAssertionHandler.INSTANCE);
155
156 logger.addHandler(LogAssertionHandler.INSTANCE);
157 }
158
159 protected static void installLog4jAppender() {
160 org.apache.log4j.Logger logger =
161 org.apache.log4j.Logger.getRootLogger();
162
163 logger.removeAppender(LogAssertionAppender.INSTANCE);
164
165 logger.addAppender(LogAssertionAppender.INSTANCE);
166 }
167
168 protected static boolean isExpected(
169 ExpectedLogs expectedLogs, String renderedMessage) {
170
171 for (ExpectedLog expectedLog : expectedLogs.expectedLogs()) {
172 ExpectedType expectedType = expectedLog.expectedType();
173
174 if (expectedType == ExpectedType.EXACT) {
175 if (renderedMessage.equals(expectedLog.expectedLog())) {
176 return true;
177 }
178 }
179 else if (expectedType == ExpectedType.POSTFIX) {
180 if (renderedMessage.endsWith(expectedLog.expectedLog())) {
181 return true;
182 }
183 }
184 else if (expectedType == ExpectedType.PREFIX) {
185 if (renderedMessage.startsWith(expectedLog.expectedLog())) {
186 return true;
187 }
188 }
189 }
190
191 return false;
192 }
193
194 private LogAssertionTestCallback() {
195 }
196
197 private static final Map<Thread, Error> _concurrentFailures =
198 new ConcurrentHashMap<>();
199 private static volatile Thread _thread;
200
201 }