From 7ad501cc747a9307c547a160f3f8357a2dcb0562 Mon Sep 17 00:00:00 2001
From: Martin Goik <goik@hdm-stuttgart.de>
Date: Fri, 11 Mar 2016 20:31:22 +0100
Subject: [PATCH] Unit Marking library

---
 ws/unitmarking/.gitignore                     |   4 +
 ws/unitmarking/pom.xml                        |  53 +++++++++
 .../mi/exam/unitmarking/DummyPrintStream.java |  25 ++++
 .../mi/exam/unitmarking/Marking.java          |  14 +++
 .../mi/exam/unitmarking/MarkingListener.java  | 108 ++++++++++++++++++
 .../mi/exam/unitmarking/RunTests.java         |  43 +++++++
 ws/unitmarking/src/main/resources/log4j2.xml  |  21 ++++
 7 files changed, 268 insertions(+)
 create mode 100644 ws/unitmarking/.gitignore
 create mode 100644 ws/unitmarking/pom.xml
 create mode 100644 ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/DummyPrintStream.java
 create mode 100644 ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/Marking.java
 create mode 100644 ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/MarkingListener.java
 create mode 100644 ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/RunTests.java
 create mode 100644 ws/unitmarking/src/main/resources/log4j2.xml

diff --git a/ws/unitmarking/.gitignore b/ws/unitmarking/.gitignore
new file mode 100644
index 000000000..a1c3ab4d0
--- /dev/null
+++ b/ws/unitmarking/.gitignore
@@ -0,0 +1,4 @@
+/target/
+/.settings/
+.classpath
+.project
diff --git a/ws/unitmarking/pom.xml b/ws/unitmarking/pom.xml
new file mode 100644
index 000000000..28290cde7
--- /dev/null
+++ b/ws/unitmarking/pom.xml
@@ -0,0 +1,53 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  
+  <groupId>de.hdm_stuttgart.mi.exam</groupId>
+  <artifactId>unitmarking</artifactId>
+  <version>0.9</version>
+  <packaging>jar</packaging>
+  
+  <name>unitmarking</name>
+
+  <url>http://www.mi.hdm-stuttgart.de/freedocs/topic/de.hdm_stuttgart.mi.lectures/sd1SectUsingMaven.html</url>
+  
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+  
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.12</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+      <version>2.4</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <version>2.4</version>
+    </dependency>
+
+  </dependencies>
+  
+  <build>
+    <plugins>
+
+        <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.3</version>
+        <configuration>
+          <source>1.8</source>
+          <target>1.8</target>
+        </configuration>
+      </plugin>
+
+    </plugins>
+  </build>
+</project>
diff --git a/ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/DummyPrintStream.java b/ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/DummyPrintStream.java
new file mode 100644
index 000000000..ff56453a7
--- /dev/null
+++ b/ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/DummyPrintStream.java
@@ -0,0 +1,25 @@
+package de.hdm_stuttgart.mi.exam.unitmarking;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+public class DummyPrintStream extends PrintStream {
+   
+   public DummyPrintStream() {
+      super(new OutputStream() {
+
+      @Override
+      public void write(int b) throws IOException {}
+
+      @Override
+      public void write(byte[] b) throws IOException {}
+
+      @Override
+      public void write(byte[] b, int off, int len) throws IOException {}
+   });
+   }
+   
+   static public final DummyPrintStream out = new  DummyPrintStream();
+   static public final PrintStream systemDotOut = System.out;
+}
diff --git a/ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/Marking.java b/ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/Marking.java
new file mode 100644
index 000000000..236ebfc79
--- /dev/null
+++ b/ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/Marking.java
@@ -0,0 +1,14 @@
+package de.hdm_stuttgart.mi.exam.unitmarking;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+@Retention( value = RetentionPolicy.RUNTIME)
+@Target( value = { ElementType.METHOD})
+public @interface Marking {
+
+	int points ();
+}
diff --git a/ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/MarkingListener.java b/ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/MarkingListener.java
new file mode 100644
index 000000000..3db9ec899
--- /dev/null
+++ b/ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/MarkingListener.java
@@ -0,0 +1,108 @@
+package de.hdm_stuttgart.mi.exam.unitmarking;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+public class MarkingListener extends RunListener {
+
+   private Map<String, Values> valuesByClassname = new HashMap<>();
+   
+   class Values {
+      
+      int points = 0,
+          reachablePoints = 0,
+          currentPoints;
+
+      public int getPoints() {
+         return points;
+      }
+
+      public int getReachablePoints() {
+         return reachablePoints;
+      }
+   }
+
+   @Override
+   public void testFinished(final Description description) throws Exception {
+      super.testFinished(description);
+
+      final Values values = addDescription(description);
+      values.points += values.currentPoints;
+      values.reachablePoints += values.currentPoints;
+   }
+
+   @Override
+   public void testFailure(final Failure failure) throws Exception {
+      super.testFailure(failure);
+      
+      final Values values = addDescription(failure.getDescription());
+      values.reachablePoints += values.currentPoints;
+   }
+
+   Values addDescription(final Description description) {
+      final String[] components = description.getClassName().split("\\.");
+      
+      final String testClassName = components[components.length - 1];
+      Values values = valuesByClassname.get(testClassName);
+      if (null == values) {
+         values = new Values();
+         valuesByClassname.put(testClassName, values);
+      }
+      final Marking marking = description.getAnnotation(Marking.class);
+      if (null == marking) {
+         values.currentPoints = 1;
+      } else {
+         values.currentPoints = marking.points();
+      }
+      return values;
+   }
+
+   
+   public String getPointSumms() {
+      final StringBuffer ret = new StringBuffer();
+      
+      for (Map.Entry<String, Values> entry: valuesByClassname.entrySet()) {
+         ret.append(entry.getKey());
+         ret.append(": ");
+         final Values value = entry.getValue();
+         ret.append(value.points);
+         ret.append('/');
+         ret.append(value.reachablePoints);
+         ret.append("  ");
+      }
+      return ret.toString();
+   }
+//      @Override
+//      public void testRunStarted(Description description) throws Exception {
+//         super.testRunStarted(description);
+//         System.out.println("testRunStarted" + description);
+//      }
+   //
+   //   @Override
+   //   public void testRunFinished(Result result) throws Exception {
+   //      super.testRunFinished(result);
+   //      System.out.println("testRunFinished");
+   //   }
+   //
+   //   @Override
+   //   public void testStarted(Description description) throws Exception {
+   //      super.testStarted(description);
+   //      System.out.println("testStarted");
+   //   }
+   //
+   //   @Override
+   //   public void testAssumptionFailure(Failure failure) {
+   //      super.testAssumptionFailure(failure);
+   //      System.out.println("testAssumptionFailure");
+   //   }
+   //
+   //   @Override
+   //   public void testIgnored(Description description) throws Exception {
+   //      super.testIgnored(description);
+   //      System.out.println("testIgnored");
+   //   }   
+}
diff --git a/ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/RunTests.java b/ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/RunTests.java
new file mode 100644
index 000000000..c0aafd7f9
--- /dev/null
+++ b/ws/unitmarking/src/main/java/de/hdm_stuttgart/mi/exam/unitmarking/RunTests.java
@@ -0,0 +1,43 @@
+package de.hdm_stuttgart.mi.exam.unitmarking;
+
+import java.util.Set;
+
+import org.junit.runner.JUnitCore;
+
+public class RunTests {
+   
+   static public final MarkingListener markingListener = new MarkingListener();
+   
+   @SafeVarargs
+   public static void exec(Class<? extends Object> ... classz) {
+      
+      final JUnitCore jc = new JUnitCore();
+      jc.addListener(markingListener);
+      
+      System.setOut(DummyPrintStream.out);
+      jc.run(classz);
+      System.setOut(DummyPrintStream.systemDotOut);
+      killStillRunningJUnitTestcaseThreads();
+      System.out.println(RunTests.getMarking());
+    }
+    static public String getMarking() {
+       return markingListener.getPointSumms();
+    }
+    
+    @SuppressWarnings("deprecation")
+    static public void killStillRunningJUnitTestcaseThreads() {
+        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
+        for (Thread thread : threadSet) {
+            if (!(thread.isDaemon())) {
+                final StackTraceElement[] threadStackTrace = thread.getStackTrace();
+                if (threadStackTrace.length > 1) {
+                    StackTraceElement firstMethodInvocation = threadStackTrace[threadStackTrace.length - 1];
+                    if (firstMethodInvocation.getClassName().startsWith("org.junit")) {
+                        // HACK: must use deprecated method
+                        thread.stop();
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/ws/unitmarking/src/main/resources/log4j2.xml b/ws/unitmarking/src/main/resources/log4j2.xml
new file mode 100644
index 000000000..aabaeda1a
--- /dev/null
+++ b/ws/unitmarking/src/main/resources/log4j2.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration>
+    <Appenders>
+        <File name="A1" fileName="A1.log" append="false">
+            <PatternLayout pattern="%t %-5p %c{2} - %m%n"/>
+        </File>
+        <Console name="STDOUT" target="SYSTEM_OUT">
+            <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
+        </Console>
+    </Appenders>
+    <Loggers>
+
+        <!-- You my want to define class or package level per-logger rules -->
+        <Logger name="de.hdm_stuttgart.mi.exam.unitmarking.App" level="debug">
+            <AppenderRef ref="A1"/>
+        </Logger>
+        <Root level="info">
+            <AppenderRef ref="STDOUT"/>
+        </Root>
+    </Loggers>
+</Configuration>
\ No newline at end of file
-- 
GitLab