001
014
015 package com.liferay.portal.kernel.test;
016
017 import com.liferay.portal.kernel.process.ClassPathUtil;
018 import com.liferay.portal.kernel.util.StringUtil;
019
020 import java.lang.reflect.Constructor;
021 import java.lang.reflect.InvocationTargetException;
022 import java.lang.reflect.Method;
023
024 import java.net.URL;
025 import java.net.URLClassLoader;
026
027 import java.util.ArrayList;
028 import java.util.Arrays;
029 import java.util.List;
030
031 import org.junit.rules.TestRule;
032 import org.junit.runner.Description;
033 import org.junit.runners.model.Statement;
034
035
038 public class CodeCoverageAssertor implements TestRule {
039
040 public CodeCoverageAssertor() {
041 this(null, null, true);
042 }
043
044 public CodeCoverageAssertor(
045 String[] includes, String[] excludes, boolean includeInnerClasses) {
046
047 _includes = includes;
048 _excludes = excludes;
049 _includeInnerClasses = includeInnerClasses;
050 }
051
052 public void appendAssertClasses(List<Class<?>> assertClasses) {
053 }
054
055 @Override
056 public Statement apply(
057 final Statement statement, final Description description) {
058
059 return new Statement() {
060
061 @Override
062 public void evaluate() throws Throwable {
063 String className = description.getClassName();
064
065 if (className.endsWith("Test")) {
066 className = className.substring(0, className.length() - 4);
067 }
068
069 String[] includes = _includes;
070
071 if (includes == null) {
072 includes = _generateIncludes(className);
073 }
074
075 try {
076 _dynamicallyInstrumentMethod.invoke(
077 null, includes, _excludes);
078 }
079 catch (InvocationTargetException ite) {
080 throw ite.getCause();
081 }
082
083 try {
084 statement.evaluate();
085 }
086 finally {
087 List<Class<?>> assertClasses = new ArrayList<Class<?>>();
088
089 ClassLoader classLoader = getClassLoader();
090
091 Class<?> clazz = classLoader.loadClass(className);
092
093 assertClasses.add(clazz);
094
095 appendAssertClasses(assertClasses);
096
097 try {
098 _assertCoverageMethod.invoke(
099 null, _includeInnerClasses,
100 assertClasses.toArray(
101 new Class<?>[assertClasses.size()]));
102 }
103 catch (InvocationTargetException ite) {
104 throw ite.getCause();
105 }
106 }
107 }
108
109 };
110 }
111
112 protected ClassLoader getClassLoader() {
113 Class<?> clazz = getClass();
114
115 return clazz.getClassLoader();
116 }
117
118 private String[] _generateIncludes(String mainClassName) throws Exception {
119 List<Class<?>> assertClasses = new ArrayList<Class<?>>();
120
121 String jvmClassPath = ClassPathUtil.getJVMClassPath(false);
122
123 URL[] urls = ClassPathUtil.getClassPathURLs(jvmClassPath);
124
125 ClassLoader classLoader = new URLClassLoader(urls, null);
126
127 Class<?> mainClass = classLoader.loadClass(mainClassName);
128
129 assertClasses.add(mainClass);
130
131 if (_includeInnerClasses) {
132 assertClasses.addAll(Arrays.asList(mainClass.getDeclaredClasses()));
133 }
134
135 if (getClass() != CodeCoverageAssertor.class) {
136 Class<?> reloadedClass = classLoader.loadClass(
137 getClass().getName());
138
139 Method appendAssertClassesMethod = reloadedClass.getMethod(
140 "appendAssertClasses", List.class);
141
142 appendAssertClassesMethod.setAccessible(true);
143
144 Constructor<?> constructor = reloadedClass.getDeclaredConstructor();
145
146 constructor.setAccessible(true);
147
148 Object reloadedObject = constructor.newInstance();
149
150 appendAssertClassesMethod.invoke(reloadedObject, assertClasses);
151 }
152
153 String[] includes = new String[assertClasses.size()];
154
155 for (int i = 0; i < assertClasses.size(); i++) {
156 Class<?> assertClass = assertClasses.get(i);
157
158 includes[i] = StringUtil.replace(
159 assertClass.getName(), new String[] {".", "$"},
160 new String[] {"/", "\\$"});
161 }
162
163 return includes;
164 }
165
166 private static final Method _assertCoverageMethod;
167 private static final Method _dynamicallyInstrumentMethod;
168
169 private final String[] _excludes;
170 private final boolean _includeInnerClasses;
171 private final String[] _includes;
172
173 static {
174 ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
175
176 try {
177 Class<?> instrumentationAgentClass = systemClassLoader.loadClass(
178 "net.sourceforge.cobertura.instrument.InstrumentationAgent");
179
180 _assertCoverageMethod = instrumentationAgentClass.getMethod(
181 "assertCoverage", boolean.class, Class[].class);
182 _dynamicallyInstrumentMethod = instrumentationAgentClass.getMethod(
183 "dynamicallyInstrument", String[].class, String[].class);
184 }
185 catch (Exception e) {
186 throw new ExceptionInInitializerError(e);
187 }
188 }
189
190 }