Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

No commit message

  • Loading branch information...
commit f3e0d0e2049e31b52459bf6242e3a0df36b49d42 1 parent 6b14665
schuler authored
View
9 build.xml
@@ -125,4 +125,13 @@
</java>
</target>
+ <target name="showMutationResults" description="prints all mutation results to console">
+ <java classname="org.softevo.mutation.run.PrintResults" maxmemory="1024m" fork="true">
+ <classpath>
+ <path refid="mutation.classpath" />
+ <path location="target/classes" />
+ </classpath>
+ </java>
+ </target>
+
</project>
View
42 src/main/java/org/softevo/mutation/bytecodeMutations/BytecodeTasks.java
@@ -14,11 +14,23 @@
*/
public class BytecodeTasks {
- boolean insertNoops;
+ private static final boolean PRINT_STATEMENTS_ENABLED = true;
private BytecodeTasks() {
}
+ /**
+ * Inserts a mutation. The inserted code is like this:
+ * <code>if(System.getProperty(mutationID)){
+ * execute mutated code
+ * }
+ * else{
+ * execute unmutated code
+ * }
+ * @param mv MethodVisitor where the code is inserted.
+ * @param unMutated code that should be used when no mutation is applied.
+ * @param mutations code that should be used when one of the mutations is applied.
+ */
public static void insertIfElse(MethodVisitor mv, MutationCode unMutated,
MutationCode[] mutations) {
RicMethodAdapter.mutationForLine++;
@@ -35,14 +47,11 @@ public static void insertIfElse(MethodVisitor mv, MutationCode unMutated,
mv.visitJumpInsn(Opcodes.IFNULL, l1);
Label l2 = new Label();
mv.visitLabel(l2);
- BytecodeTasks.insertPrintStatements(mv, "Mutation "
- + mutation.getMutationVariable() + " - "
- + mutation.getMutationType() + " is enabled");
+ insertMutationTouchedCode(mv, mutation);
mutationCode.insertCodeBlock(mv);
mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(l1);
}
-
Label mutationEndLabel = new Label();
mutationEndLabel.info = new MutationMarker(false);
mv.visitLabel(mutationEndLabel);
@@ -51,6 +60,27 @@ public static void insertIfElse(MethodVisitor mv, MutationCode unMutated,
}
+ private static void insertMutationTouchedCode(MethodVisitor mv,
+ Mutation mutation) {
+ if (PRINT_STATEMENTS_ENABLED) {
+ BytecodeTasks.insertPrintStatements(mv, "Mutation "
+ + mutation.getMutationVariable() + " - "
+ + mutation.getMutationType() + " is enabled");
+ }
+ mv.visitLdcInsn(mutation.getId());
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC,
+ "org/softevo/mutation/testsuite/ResultReporter", "touch",
+ "(I)V");
+ }
+
+ /**
+ * Inserts bytecode that prints the given message.
+ *
+ * @param mv
+ * The MethodVisitor for which teh code is added.
+ * @param message
+ * The text to be printed to System.out .
+ */
public static void insertPrintStatements(MethodVisitor mv, String message) {
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "err",
"Ljava/io/PrintStream;");
@@ -59,6 +89,4 @@ public static void insertPrintStatements(MethodVisitor mv, String message) {
"println", "(Ljava/lang/String;)V");
}
-
-
}
View
9 src/main/java/org/softevo/mutation/bytecodeMutations/MutationTransformer.java
@@ -11,13 +11,18 @@
public class MutationTransformer extends BytecodeTransformer {
+ private static final boolean DEBUG = false;
+
private static Logger logger = Logger.getLogger(MutationTransformer.class);
@Override
protected ClassVisitor classVisitorFactory(ClassWriter cw) {
- ClassVisitor cc = new CheckClassAdapter(cw);
+ ClassVisitor cv = new CheckClassAdapter(cw);
logger.info("Mutation Transformer");
- return new MutationsClassAdapter(new TraceClassVisitor(cc, new PrintWriter(System.out)));
+ if (DEBUG) {
+ cv = new TraceClassVisitor(cv, new PrintWriter(System.out));
+ }
+ return new MutationsClassAdapter(cv);
}
}
View
60 src/main/java/org/softevo/mutation/results/SingleTestResult.java
@@ -3,6 +3,8 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
@@ -27,6 +29,11 @@
private int runs;
+ /**
+ * True if the mutation was touched by at least one TestCase;
+ */
+ boolean touched;
+
@OneToMany(cascade = CascadeType.ALL)
@OrderBy("testCaseName")
@IndexColumn(name = "failure_list_id")
@@ -36,30 +43,56 @@
@JoinTable(name = "SINGLETESTRESULT_ERRORS", joinColumns = { @JoinColumn(name = "singletestresult_id") }, inverseJoinColumns = @JoinColumn(name = "testmessage_id"))
private List<TestMessage> errors = new ArrayList<TestMessage>();
+ @OneToMany(cascade = CascadeType.ALL)
+ @JoinTable(name = "SINGLETESTRESULT_PASSING", joinColumns = { @JoinColumn(name = "singletestresult_id") }, inverseJoinColumns = @JoinColumn(name = "testmessage_id"))
+ private List<TestMessage> passing = new ArrayList<TestMessage>();
+
private SingleTestResult() {
}
public SingleTestResult(TestResult mutationTestResult,
- MutationTestListener mutationTestListener) {
+ MutationTestListener mutationTestListener,
+ Set<String> touchingTestCases) {
this.runs = mutationTestResult.runCount();
this.failures = mutationTestListener.getFailureMessages();
this.errors = mutationTestListener.getErrorMessages();
+ this.passing = mutationTestListener.getPassingMessages();
+ if (touchingTestCases != null && touchingTestCases.size() > 0) {
+ updateTouched(touchingTestCases, failures);
+ updateTouched(touchingTestCases, errors);
+ updateTimes(mutationTestListener.getDurations());
+ touched = true;
+ }
+ }
+
+ private void updateTimes(Map<String, Long> durations) {
+ // TODO
+ }
+
+ private static void updateTouched(Set<String> touchingTestCases,
+ List<TestMessage> testMessages) {
+ for (TestMessage tm : testMessages) {
+ if (touchingTestCases.contains(tm.getTestCaseName())) {
+ tm.setHasTouched(true);
+ }
+ }
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder( String.format("Runs: %d Failures: %d Errors: %d", runs,
- failures.size(), errors.size()));
- if(failures.size() >0){
+ StringBuilder sb = new StringBuilder(String.format(
+ "Runs: %d Failures: %d Errors: %d LineTouched: %s", runs, failures.size(),
+ errors.size(), touched ? "yes" : "no "));
+ if (failures.size() > 0) {
sb.append("Failures:\n");
- for(TestMessage tm : failures){
+ for (TestMessage tm : failures) {
sb.append(tm);
sb.append('\n');
}
}
- if(errors.size() >0){
+ if (errors.size() > 0) {
sb.append("Errors:\n");
- for(TestMessage tm : errors){
+ for (TestMessage tm : errors) {
sb.append(tm);
sb.append('\n');
}
@@ -135,5 +168,18 @@ public void setFailures(List<TestMessage> failures) {
this.failures = failures;
}
+ /**
+ * @return the passing
+ */
+ public List<TestMessage> getPassing() {
+ return passing;
+ }
+
+ /**
+ * @param passing the passing to set
+ */
+ public void setPassing(List<TestMessage> passing) {
+ this.passing = passing;
+ }
}
View
63 src/main/java/org/softevo/mutation/results/TestMessage.java
@@ -4,6 +4,13 @@
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
+/**
+ *
+ * Class that holds the result of one single TestCase.
+ *
+ * @author David Schuler
+ *
+ */
@Entity
public class TestMessage {
@@ -11,16 +18,39 @@
@GeneratedValue
private Long id;
+ /**
+ * name of the TestCases
+ */
private String testCaseName;
+ /**
+ * Failure or error message of the TestCase.
+ */
private String message;
+ /**
+ * True, if test case has touched the mutation.
+ */
+ private boolean hasTouched;
+
+ /**
+ * Time a testCase needed to execute.
+ */
+ private long duration;
+
public TestMessage(String testCaseName, String message) {
super();
this.testCaseName = testCaseName;
this.message = message;
}
+ public TestMessage(String testCaseName, String message, long duration) {
+ super();
+ this.testCaseName = testCaseName;
+ this.message = message;
+ this.duration = duration;
+ }
+
public TestMessage() {
}
@@ -71,6 +101,37 @@ public void setTestCaseName(String testCaseName) {
@Override
public String toString() {
- return String.format("TestCase: %s Reason: %s",testCaseName, message);
+ return String.format("TestCase: %s Touched: %s Reason: %s",
+ testCaseName, hasTouched ? "yes" : "no", message);
+ }
+
+ /**
+ * @return the hasTouched
+ */
+ public boolean isHasTouched() {
+ return hasTouched;
+ }
+
+ /**
+ * @param hasTouched
+ * the hasTouched to set
+ */
+ public void setHasTouched(boolean hasTouched) {
+ this.hasTouched = hasTouched;
+ }
+
+ /**
+ * @return the duration
+ */
+ public long getDuration() {
+ return duration;
+ }
+
+ /**
+ * @param duration
+ * the duration to set
+ */
+ public void setDuration(long duration) {
+ this.duration = duration;
}
}
View
4 src/main/java/org/softevo/mutation/results/persistence/QueryManager.java
@@ -64,10 +64,8 @@ public static void updateMutation(Mutation mutation,
session.save(tm);
}
session.save(mutationTestResult);
+ logger.info("mutation updated " + m2);
m2.setMutationResult(mutationTestResult);
- // logger.info("ID" + mutation.getId());
- // logger.info(mutationTestResult);
- // session.update(m2);
tx.commit();
session.close();
}
View
2  src/main/java/org/softevo/mutation/testsuite/MutationSwitcher.java
@@ -77,6 +77,7 @@ public void switchOn() {
+ actualMutation.getLineNumber() + " - "
+ actualMutation.toString());
System.setProperty(actualMutation.getMutationVariable(), "1");
+ ResultReporter.setActualMutation(actualMutation);
}
}
@@ -85,6 +86,7 @@ public void switchOff() {
System.clearProperty(actualMutation.getMutationVariable());
logger.info("disabling mutation: "
+ actualMutation.getMutationVariable());
+ ResultReporter.setActualMutation(null);
}
}
View
37 src/main/java/org/softevo/mutation/testsuite/MutationTestListener.java
@@ -1,8 +1,11 @@
package org.softevo.mutation.testsuite;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import org.apache.log4j.Logger;
import org.softevo.mutation.results.TestMessage;
import junit.framework.AssertionFailedError;
@@ -11,25 +14,39 @@
public class MutationTestListener implements TestListener {
+ private static Logger logger = Logger.getLogger(MutationTestListener.class);
+
+ private long start;
+
private List<TestMessage> errorMessages = new ArrayList<TestMessage>();
private List<TestMessage> failureMessages = new ArrayList<TestMessage>();
+ private List<TestMessage> passingMessages = new ArrayList<TestMessage>();
+
+ private Map<String, Long> durations = new HashMap<String, Long>();
+
public void addError(Test test, Throwable t) {
+ logger.info("Error added");
errorMessages.add(new TestMessage(test.toString(), t.toString()));
}
public void addFailure(Test test, AssertionFailedError t) {
+ logger.info("Failure added");
failureMessages.add(new TestMessage(test.toString(), t.toString()));
-
}
public void endTest(Test test) {
-
+ long duration = System.currentTimeMillis() - start;
+ durations.put(test.toString(), duration);
+ passingMessages.add(new TestMessage(test.toString(), "test passed",
+ duration));
+ logger.info("Test ended");
}
public void startTest(Test test) {
-
+ logger.info("Test started");
+ start = System.currentTimeMillis();
}
public List<TestMessage> getErrorMessages() {
@@ -40,4 +57,18 @@ public void startTest(Test test) {
return failureMessages;
}
+ /**
+ * @return the durations
+ */
+ public Map<String, Long> getDurations() {
+ return durations;
+ }
+
+ /**
+ * @return the passingMessages
+ */
+ public List<TestMessage> getPassingMessages() {
+ return passingMessages;
+ }
+
}
View
70 src/main/java/org/softevo/mutation/testsuite/ResultReporter.java
@@ -1,10 +1,13 @@
package org.softevo.mutation.testsuite;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import junit.framework.TestResult;
+import org.apache.log4j.Logger;
import org.softevo.mutation.results.Mutation;
import org.softevo.mutation.results.OldMutationResult;
import org.softevo.mutation.results.SingleTestResult;
@@ -12,12 +15,24 @@
public class ResultReporter {
+ private static Logger logger = Logger.getLogger(ResultReporter.class);
+
+ private static Mutation actualMutation;
+
+ private static Set<String> touchingTestCases = new HashSet<String>();
+
+ private static String actualTestCase;
+
private List<OldMutationResult> mutationResults = new ArrayList<OldMutationResult>();
- public void report(
- TestResult mutationTestResult, Mutation mutation, MutationTestListener mutationTestListener) {
- SingleTestResult mutated = new SingleTestResult(mutationTestResult , mutationTestListener);
+ public void report(TestResult mutationTestResult, Mutation mutation,
+ MutationTestListener mutationTestListener) {
+ SingleTestResult mutated = new SingleTestResult(mutationTestResult,
+ mutationTestListener, touchingTestCases);
QueryManager.updateMutation(mutation, mutated);
+ touchingTestCases.clear();
+ actualMutation = null;
+ actualTestCase = null;
}
@Override
@@ -30,17 +45,44 @@ public String toString() {
return sb.toString();
}
+ public static void touch(int mutationID) {
+ logger.info("Touch called by mutated code");
+ long expectedID = actualMutation.getId();
+ if (mutationID != expectedID) {
+ throw new RuntimeException("Expected ID did not match reported ID"
+ + actualMutation.getId() + " " + mutationID);
+ } else {
+ touchingTestCases.add(actualTestCase);
+ }
+ }
+
+ /**
+ * @return the actualTestCase
+ */
+ public static String getActualTestCase() {
+ return actualTestCase;
+ }
+
+ /**
+ * @param actualTestCase
+ * the actualTestCase to set
+ */
+ public static void setActualTestCase(String actualTestCase) {
+ ResultReporter.actualTestCase = actualTestCase;
+ }
+
/**
- * Save collected results to database
+ * @return the actualMutation
*/
-// public void toDb() {
-// Session session = HibernateUtil.getSessionFactory().openSession();
-// Transaction tx = session.beginTransaction();
-// for (OldMutationResult mr : mutationResults) {
-// session.save(mr);
-// }
-// tx.commit();
-// session.close();
-//
-// }
+ public static Mutation getActualMutation() {
+ return actualMutation;
+ }
+
+ /**
+ * @param actualMutation
+ * the actualMutation to set
+ */
+ public static void setActualMutation(Mutation actualMutation) {
+ ResultReporter.actualMutation = actualMutation;
+ }
}
View
80 src/main/java/org/softevo/mutation/testsuite/SelectiveTestSuite.java
@@ -36,7 +36,22 @@
private ResultReporter resultReporter = new ResultReporter();
+ private MutationTestListener actualListener;
+
+ private Mutation actualMutation;
+
+ private TestResult actualMutationTestResult;
+
+ private Thread shutDownHook;
+
+ private Test actualTest;
+
static {
+ staticLogMessage();
+ // setSecurityManager();
+ }
+
+ private static void staticLogMessage() {
System.out.println("Selective Test Suite");
if (TESTMODE) {
logger.info("TESTMODE");
@@ -46,12 +61,38 @@
.info("$LastChangedDate$ a");
}
+ private void addShutdownHook() {
+ shutDownHook = new Thread() {
+ public void run() {
+ logger.info("Shutdownhook activated");
+
+ actualListener.addError(actualTest, new RuntimeException("JVM shut down because of mutation"));
+ resultReporter.report(actualMutationTestResult, actualMutation,
+ actualListener);
+ }
+ };
+ Runtime.getRuntime().addShutdownHook(shutDownHook);
+ }
+
public SelectiveTestSuite() {
super();
+ addShutdownHook();
+ }
+
+ private static void setSecurityManager() {
+ try {
+ System.setSecurityManager(new ExitSecurityManager());
+ logger.info("SecurityManager set");
+ } catch (SecurityException se) {
+ logger.info("SecurityManager already set!");
+ se.printStackTrace();
+ }
+
}
public SelectiveTestSuite(String name) {
super(name);
+ addShutdownHook();
}
@Override
@@ -63,7 +104,7 @@ public void run(TestResult result) {
return;
}
logger.info("Not Running scanner");
- logger.info("DDD");
+ logger.info("eee");
Map<String, TestCase> allTests = getAllTests(this);
logger.log(Level.INFO, "All Tests collected");
mutationSwitcher = new MutationSwitcher(
@@ -75,12 +116,12 @@ public void run(TestResult result) {
break;
}
}
- Mutation mutation = mutationSwitcher.next();
+ actualMutation = mutationSwitcher.next();
try {
@SuppressWarnings("unused")
- Class c = Class.forName(mutation.getClassName());
+ Class c = Class.forName(actualMutation.getClassName());
} catch (ClassNotFoundException e) {
- logger.info("Class " + mutation.getClassName()
+ logger.info("Class " + actualMutation.getClassName()
+ " not on classpath");
continue;
}
@@ -88,20 +129,23 @@ public void run(TestResult result) {
break;
Set<String> testsForThisRun = mutationSwitcher.getTests();
if (testsForThisRun == null) {
- logger.info("No tests for " + mutation);
+ logger.info("No tests for " + actualMutation);
continue;
}
- TestResult mutationTestResult = new TestResult();
+ actualMutationTestResult = new TestResult();
mutationSwitcher.switchOn();
- MutationTestListener listener = new MutationTestListener();
- mutationTestResult.addListener(listener);
- runTests(allTests, mutationTestResult, testsForThisRun);
+ actualListener = new MutationTestListener();
+ actualMutationTestResult.addListener(actualListener);
+ runTests(allTests, actualMutationTestResult, testsForThisRun);
mutationSwitcher.switchOff();
- resultReporter.report(mutationTestResult, mutation, listener);
+ resultReporter.report(actualMutationTestResult, actualMutation,
+ actualListener);
logger.info(String.format("runs: %d failures:%d errors:%d ",
- mutationTestResult.runCount(), mutationTestResult
- .failureCount(), mutationTestResult.errorCount()));
+ actualMutationTestResult.runCount(),
+ actualMutationTestResult.failureCount(),
+ actualMutationTestResult.errorCount()));
}
+ Runtime.getRuntime().removeShutdownHook(shutDownHook);
logger.log(Level.INFO, "Test Runs finished");
}
@@ -123,6 +167,8 @@ private void runTests(Map<String, TestCase> allTests,
TestResult testResult, Set<String> testsForThisRun) {
for (String testName : testsForThisRun) {
TestCase test = allTests.get(testName);
+ actualTest = test;
+ ResultReporter.setActualTestCase(getFullTestCaseName(test));
if (test == null) {
// throw new RuntimeException("Test not found " + testName
// + "\n All Tests: " + allTests);
@@ -134,6 +180,7 @@ private void runTests(Map<String, TestCase> allTests,
logger.warn(String.format(
"Exception thrown by test %s Exception: %s", test
.toString(), e.toString()));
+ logger.info("Exception caught");
testResult.addError(test, e);
}
}
@@ -170,4 +217,13 @@ private static String getFullTestCaseName(TestCase testCase) {
+ testCase.getName();
return fullTestName;
}
+
+ /**
+ * @return the actualMutation
+ */
+ public Mutation getActualMutation() {
+ return actualMutation;
+ }
+
+
}
View
6 src/main/resources/log4j.properties
@@ -4,9 +4,9 @@ log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-5p [%M - %C] - %m%n
-#log4j.logger.org.softevo.mutation.testsuite=WARN
-#log4j.logger.org.hibernate=WARN
-#log4j.logger.org.softevo.mutation.results.persistence.QueryManager=WARN
+log4j.logger.org.softevo.mutation.bytecodeMutations=WARN
+log4j.logger.org.hibernate=WARN
+log4j.logger.org.softevo.mutation.results.persistence.QueryManager=WARN
log4j.appender.Chainsaw=org.apache.log4j.net.SocketAppender
log4j.appender.Chainsaw.remoteHost=127.0.0.1
View
2  src/test/java/org/softevo/mutation/results/QueryManagerTestClass.java
@@ -72,7 +72,7 @@ public void testUpdate() {
Mutation resultMutation = QueryManager.getMutation(testMutation);
Assert.assertNull(resultMutation.getMutationResult());
QueryManager.updateMutation(resultMutation, new SingleTestResult(
- new TestResult(), new MutationTestListener()));
+ new TestResult(), new MutationTestListener(), null));
Mutation checkMutation = QueryManager.getMutation(testMutation);
Assert.assertNotNull(checkMutation.getMutationResult());
}
Please sign in to comment.
Something went wrong with that request. Please try again.