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