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