diff --git a/.gitignore b/.gitignore
index fa9bcb8820..a4f6f3d915 100644
--- a/.gitignore
+++ b/.gitignore
@@ -291,7 +291,6 @@ students/406400373/*
students/549739951/*
students/582161208/*
students/592146505/*
-students/740707954/*
students/844620174/*
students/87049319/*
students/183549495/*
diff --git a/dicegame.png b/dicegame.png
deleted file mode 100644
index 1c1a40821a..0000000000
Binary files a/dicegame.png and /dev/null differ
diff --git a/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/bridge/GraphicLibrary1.java b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/bridge/GraphicLibrary1.java
new file mode 100644
index 0000000000..798cfbc7f9
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/bridge/GraphicLibrary1.java
@@ -0,0 +1,11 @@
+package com.coderising.dp.bridge;
+
+public class GraphicLibrary1 {
+ public void draw_a_line(int x1,int y1,int x2,int y2){
+
+ }
+ public void draw_a_circle(int x,int y, int r){
+
+ }
+
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/bridge/GraphicLibrary2.java b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/bridge/GraphicLibrary2.java
new file mode 100644
index 0000000000..2e67a1220b
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/bridge/GraphicLibrary2.java
@@ -0,0 +1,11 @@
+package com.coderising.dp.bridge;
+
+public class GraphicLibrary2 {
+ public void drawLine(int x1,int x2,int y1,int y2){
+
+ }
+ public void drawCircle(int x,int y, int r){
+
+ }
+
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/builder/TagBuilder.java b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/builder/TagBuilder.java
index fe8673ec30..daa431f139 100644
--- a/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/builder/TagBuilder.java
+++ b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/builder/TagBuilder.java
@@ -1,30 +1,37 @@
package com.coderising.dp.builder;
public class TagBuilder {
-
+ private TagNode rootNode;
+ private TagNode currentNode;
+ private TagNode parentNode;
public TagBuilder(String rootTagName){
-
+ rootNode = new TagNode(rootTagName);
+ currentNode = rootNode;
+ parentNode = null;
}
public TagBuilder addChild(String childTagName){
-
- return null;
+ parentNode = this.currentNode;
+ this.currentNode = new TagNode(childTagName);
+ parentNode.add(currentNode);
+ return this;
}
public TagBuilder addSibling(String siblingTagName){
-
- return null;
+ this.currentNode = new TagNode(siblingTagName);
+ parentNode.add(this.currentNode);
+ return this;
}
public TagBuilder setAttribute(String name, String value){
-
- return null;
+ this.currentNode.setAttribute(name, value);
+ return this;
}
public TagBuilder setText(String value){
-
- return null;
+ this.currentNode.setValue(value);
+ return this;
}
public String toXML(){
- return null;
+ return this.rootNode.toXML();
}
}
diff --git a/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/builder/TagNode.java b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/builder/TagNode.java
index 7763ee9d0a..2ac26ad7b9 100644
--- a/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/builder/TagNode.java
+++ b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/builder/TagNode.java
@@ -19,6 +19,7 @@ public void setAttribute(String name, String value) {
Attribute attr = findAttribute(name);
if(attr != null){
attr.value = value;
+ return;
}
attributes.add(new Attribute(name,value));
diff --git a/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Line.java b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Line.java
new file mode 100644
index 0000000000..b3c769e63a
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Line.java
@@ -0,0 +1,11 @@
+package com.coderising.dp.composite;
+
+public class Line implements Shape {
+
+ @Override
+ public void draw() {
+
+
+ }
+
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Rectangle.java b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Rectangle.java
new file mode 100644
index 0000000000..2960351a35
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Rectangle.java
@@ -0,0 +1,11 @@
+package com.coderising.dp.composite;
+
+public class Rectangle implements Shape {
+
+ @Override
+ public void draw() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Shape.java b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Shape.java
new file mode 100644
index 0000000000..4562f10b12
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Shape.java
@@ -0,0 +1,5 @@
+package com.coderising.dp.composite;
+
+public interface Shape {
+ public void draw();
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Square.java b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Square.java
new file mode 100644
index 0000000000..f106d65fd8
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Square.java
@@ -0,0 +1,11 @@
+package com.coderising.dp.composite;
+
+public class Square implements Shape {
+
+ @Override
+ public void draw() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Text.java b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Text.java
new file mode 100644
index 0000000000..3543a08be3
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/com/coderising/dp/composite/Text.java
@@ -0,0 +1,11 @@
+package com.coderising.dp.composite;
+
+public class Text implements Shape {
+
+ @Override
+ public void draw() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/extension/RepeatedTest.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/extension/RepeatedTest.java
new file mode 100644
index 0000000000..f6250ee426
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/extension/RepeatedTest.java
@@ -0,0 +1,32 @@
+package org.litejunit.extension;
+
+import org.litejunit.v2.Test;
+import org.litejunit.v2.TestResult;
+
+/**
+ * A Decorator that runs a test repeatedly.
+ *
+ */
+public class RepeatedTest extends TestDecorator {
+ private int fTimesRepeat;
+
+ public RepeatedTest(Test test, int repeat) {
+ super(test);
+ if (repeat < 0)
+ throw new IllegalArgumentException("Repetition count must be > 0");
+ fTimesRepeat= repeat;
+ }
+ public int countTestCases() {
+ return super.countTestCases()*fTimesRepeat;
+ }
+ public void run(TestResult result) {
+ for (int i= 0; i < fTimesRepeat; i++) {
+ if (result.shouldStop())
+ break;
+ super.run(result);
+ }
+ }
+ public String toString() {
+ return super.toString()+"(repeated)";
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/extension/TestDecorator.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/extension/TestDecorator.java
new file mode 100644
index 0000000000..556d05cbbb
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/extension/TestDecorator.java
@@ -0,0 +1,40 @@
+package org.litejunit.extension;
+
+import org.litejunit.v2.Assert;
+import org.litejunit.v2.Test;
+import org.litejunit.v2.TestResult;
+
+/**
+ * A Decorator for Tests. Use TestDecorator as the base class
+ * for defining new test decorators. Test decorator subclasses
+ * can be introduced to add behaviour before or after a test
+ * is run.
+ *
+ */
+public class TestDecorator extends Assert implements Test {
+ protected Test test;
+
+ public TestDecorator(Test test) {
+ this.test= test;
+ }
+ /**
+ * The basic run behaviour.
+ */
+ public void basicRun(TestResult result) {
+ test.run(result);
+ }
+ public int countTestCases() {
+ return test.countTestCases();
+ }
+ public void run(TestResult result) {
+ basicRun(result);
+ }
+
+ public String toString() {
+ return test.toString();
+ }
+
+ public Test getTest() {
+ return test;
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/extension/TestSetup.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/extension/TestSetup.java
new file mode 100644
index 0000000000..7a133a798c
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/extension/TestSetup.java
@@ -0,0 +1,39 @@
+package org.litejunit.extension;
+
+import org.litejunit.v2.Protectable;
+import org.litejunit.v2.Test;
+import org.litejunit.v2.TestResult;
+
+/**
+ * A Decorator to set up and tear down additional fixture state.
+ * Subclass TestSetup and insert it into your tests when you want
+ * to set up additional state once before the tests are run.
+ */
+public class TestSetup extends TestDecorator {
+
+ public TestSetup(Test test) {
+ super(test);
+ }
+ public void run(final TestResult result) {
+ Protectable p= new Protectable() {
+ public void protect() throws Exception {
+ setUp();
+ basicRun(result);
+ tearDown();
+ }
+ };
+ result.runProtected(this, p);
+ }
+ /**
+ * Sets up the fixture. Override to set up additional fixture
+ * state.
+ */
+ protected void setUp() throws Exception {
+ }
+ /**
+ * Tears down the fixture. Override to tear down the additional
+ * fixture state.
+ */
+ protected void tearDown() throws Exception {
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/AllTest.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/AllTest.java
new file mode 100644
index 0000000000..2c4d6b3dca
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/AllTest.java
@@ -0,0 +1,43 @@
+package org.litejunit.sample;
+
+import org.litejunit.extension.RepeatedTest;
+import org.litejunit.extension.TestSetup;
+import org.litejunit.sample.calculator.CalculatorSuite;
+import org.litejunit.v2.Test;
+import org.litejunit.v2.TestSuite;
+
+
+public class AllTest {
+ /*public static Test suite(){
+
+ TestSuite suite= new TestSuite("All Test");
+ suite.addTest(CalculatorSuite.suite());
+ suite.addTestSuite(PersonTest.class);
+ return suite;
+
+ }*/
+
+ public static Test suite(){
+
+ TestSuite suite= new TestSuite("All Test");
+ suite.addTest(CalculatorSuite.suite());
+ suite.addTest(new RepeatedTest(new TestSuite(PersonTest.class), 2));
+ return new OverallTestSetup(suite);
+ }
+
+
+ static class OverallTestSetup extends TestSetup{
+
+ public OverallTestSetup(Test test) {
+ super(test);
+
+ }
+ protected void setUp() throws Exception {
+ System.out.println("this is overall testsetup");
+ }
+ protected void tearDown() throws Exception {
+ System.out.println("this is overall teardown");
+ }
+
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/PersonTest.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/PersonTest.java
new file mode 100644
index 0000000000..2e76ea26ae
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/PersonTest.java
@@ -0,0 +1,38 @@
+package org.litejunit.sample;
+
+import org.litejunit.v2.TestCase;
+
+public class PersonTest extends TestCase {
+
+ Person p = null;
+ protected void setUp() {
+ p = new Person("andy",30);
+ }
+ public PersonTest(String name) {
+ super(name);
+ }
+ public void testAge(){
+ this.assertEquals(30, p.getAge());
+ }
+ public void testName(){
+ this.assertEquals("andy", p.getName());
+ }
+}
+class Person{
+ private String name;
+ private int age;
+
+ public Person(String name, int age) {
+
+ this.name = name;
+ this.age = age;
+ }
+ public String getName() {
+ return name;
+ }
+ public int getAge() {
+ return age;
+ }
+
+
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/calculator/Calculator.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/calculator/Calculator.java
new file mode 100644
index 0000000000..ed0a69959a
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/calculator/Calculator.java
@@ -0,0 +1,22 @@
+package org.litejunit.sample.calculator;
+
+public class Calculator {
+
+ private int result = 0;
+ public void add(int x){
+ result += x;
+ }
+ public void subtract(int x){
+ result -=x;
+ }
+
+ public int getResult(){
+ return this.result;
+ }
+ public static void main(String[] args){
+ Calculator calculator = new Calculator();
+ calculator.add(10);
+ calculator.subtract(5);
+ System.out.println(calculator.getResult());
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/calculator/CalculatorSuite.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/calculator/CalculatorSuite.java
new file mode 100644
index 0000000000..1deec69c52
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/calculator/CalculatorSuite.java
@@ -0,0 +1,12 @@
+package org.litejunit.sample.calculator;
+
+import org.litejunit.v2.Test;
+import org.litejunit.v2.TestSuite;
+
+public class CalculatorSuite {
+ public static Test suite(){
+ TestSuite suite= new TestSuite("Calculator All Test");
+ suite.addTestSuite(CalculatorTest.class);
+ return suite;
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/calculator/CalculatorTest.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/calculator/CalculatorTest.java
new file mode 100644
index 0000000000..39f1d2433b
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/sample/calculator/CalculatorTest.java
@@ -0,0 +1,59 @@
+package org.litejunit.sample.calculator;
+
+import org.litejunit.v2.TestCase;
+
+public class CalculatorTest extends TestCase {
+ public CalculatorTest(String name) {
+ super(name);
+
+ }
+ Calculator calculator =null;
+ public void setUp(){
+ calculator = new Calculator();
+ }
+ public void tearDown(){
+ calculator = null;
+ }
+ public void testAdd(){
+
+ calculator.add(10);
+ assertEquals(5,calculator.getResult());
+ }
+ public void testSubtract(){
+ calculator.add(10);
+ calculator.subtract(5);
+ throw new RuntimeException("this is a test");
+ //assertEquals(5,calculator.getResult());
+ }
+
+ public static void main(String[] args){
+ /*{
+ TestCase tc1 = new CalculatorTest("testAdd"){
+ protected void runTest() {
+ testAdd();
+ }
+ };
+
+ TestCase tc2 = new CalculatorTest("testSubtract"){
+ protected void runTest() {
+ testSubtract();
+ }
+ };
+ tc1.run();
+ tc2.run();
+ }
+
+
+ TestSuite ts = new TestSuite();
+ ts.addTest(new CalculatorTest("testAdd"));
+ ts.addTest(new CalculatorTest("testSubtract"));
+
+
+ {
+ TestCase tc1 = new CalculatorTest("test1");
+ TestCase tc2 = new CalculatorTest("test2");
+ tc1.run();
+ tc2.run();
+ }*/
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/Assert.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/Assert.java
new file mode 100644
index 0000000000..07a3c1a22b
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/Assert.java
@@ -0,0 +1,225 @@
+package org.litejunit.v1;
+
+/**
+ * A set of assert methods.
+ */
+
+public class Assert {
+ /**
+ * Protect constructor since it is a static only class
+ */
+ protected Assert() {
+ }
+
+ /**
+ * Asserts that a condition is true. If it isn't it throws
+ * an AssertionFailedError with the given message.
+ */
+ static public void assertTrue(String message, boolean condition) {
+ if (!condition)
+ fail(message);
+ }
+ /**
+ * Asserts that a condition is true. If it isn't it throws
+ * an AssertionFailedError.
+ */
+ static public void assertTrue(boolean condition) {
+ assertTrue(null, condition);
+ }
+ /**
+ * Fails a test with the given message.
+ */
+ static public void fail(String message) {
+ throw new AssertionFailedError(message);
+ }
+ /**
+ * Fails a test with no message.
+ */
+ static public void fail() {
+ fail(null);
+ }
+ /**
+ * Asserts that two objects are equal. If they are not
+ * an AssertionFailedError is thrown.
+ */
+ static public void assertEquals(String message, Object expected, Object actual) {
+ if (expected == null && actual == null)
+ return;
+ if (expected != null && expected.equals(actual))
+ return;
+ failNotEquals(message, expected, actual);
+ }
+ /**
+ * Asserts that two objects are equal. If they are not
+ * an AssertionFailedError is thrown.
+ */
+ static public void assertEquals(Object expected, Object actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two doubles are equal concerning a delta. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(String message, double expected, double actual, double delta) {
+ // handle infinity specially since subtracting to infinite values gives NaN and the
+ // the following test fails
+ if (Double.isInfinite(expected)) {
+ if (!(expected == actual))
+ failNotEquals(message, new Double(expected), new Double(actual));
+ } else if (!(Math.abs(expected-actual) <= delta)) // Because comparison with NaN always returns false
+ failNotEquals(message, new Double(expected), new Double(actual));
+ }
+ /**
+ * Asserts that two doubles are equal concerning a delta. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(double expected, double actual, double delta) {
+ assertEquals(null, expected, actual, delta);
+ }
+ /**
+ * Asserts that two floats are equal concerning a delta. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(String message, float expected, float actual, float delta) {
+ // handle infinity specially since subtracting to infinite values gives NaN and the
+ // the following test fails
+ if (Float.isInfinite(expected)) {
+ if (!(expected == actual))
+ failNotEquals(message, new Float(expected), new Float(actual));
+ } else if (!(Math.abs(expected-actual) <= delta))
+ failNotEquals(message, new Float(expected), new Float(actual));
+ }
+ /**
+ * Asserts that two floats are equal concerning a delta. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(float expected, float actual, float delta) {
+ assertEquals(null, expected, actual, delta);
+ }
+ /**
+ * Asserts that two longs are equal.
+ */
+ static public void assertEquals(String message, long expected, long actual) {
+ assertEquals(message, new Long(expected), new Long(actual));
+ }
+ /**
+ * Asserts that two longs are equal.
+ */
+ static public void assertEquals(long expected, long actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two booleans are equal.
+ */
+ static public void assertEquals(String message, boolean expected, boolean actual) {
+ assertEquals(message, new Boolean(expected), new Boolean(actual));
+ }
+ /**
+ * Asserts that two booleans are equal.
+ */
+ static public void assertEquals(boolean expected, boolean actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two bytes are equal.
+ */
+ static public void assertEquals(String message, byte expected, byte actual) {
+ assertEquals(message, new Byte(expected), new Byte(actual));
+ }
+ /**
+ * Asserts that two bytes are equal.
+ */
+ static public void assertEquals(byte expected, byte actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two chars are equal.
+ */
+ static public void assertEquals(String message, char expected, char actual) {
+ assertEquals(message, new Character(expected), new Character(actual));
+ }
+ /**
+ * Asserts that two chars are equal.
+ */
+ static public void assertEquals(char expected, char actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two shorts are equal.
+ */
+ static public void assertEquals(String message, short expected, short actual) {
+ assertEquals(message, new Short(expected), new Short(actual));
+ }
+ /**
+ * Asserts that two shorts are equal.
+ */
+ static public void assertEquals(short expected, short actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two ints are equal.
+ */
+ static public void assertEquals(String message, int expected, int actual) {
+ assertEquals(message, new Integer(expected), new Integer(actual));
+ }
+ /**
+ * Asserts that two ints are equal.
+ */
+ static public void assertEquals(int expected, int actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that an object isn't null.
+ */
+ static public void assertNotNull(Object object) {
+ assertNotNull(null, object);
+ }
+ /**
+ * Asserts that an object isn't null.
+ */
+ static public void assertNotNull(String message, Object object) {
+ assertTrue(message, object != null);
+ }
+ /**
+ * Asserts that an object is null.
+ */
+ static public void assertNull(Object object) {
+ assertNull(null, object);
+ }
+ /**
+ * Asserts that an object is null.
+ */
+ static public void assertNull(String message, Object object) {
+ assertTrue(message, object == null);
+ }
+ /**
+ * Asserts that two objects refer to the same object. If they are not
+ * an AssertionFailedError is thrown.
+ */
+ static public void assertSame(String message, Object expected, Object actual) {
+ if (expected == actual)
+ return;
+ failNotSame(message, expected, actual);
+ }
+ /**
+ * Asserts that two objects refer to the same object. If they are not
+ * the same an AssertionFailedError is thrown.
+ */
+ static public void assertSame(Object expected, Object actual) {
+ assertSame(null, expected, actual);
+ }
+
+ static private void failNotEquals(String message, Object expected, Object actual) {
+ String formatted= "";
+ if (message != null)
+ formatted= message+" ";
+ fail(formatted+"expected:<"+expected+"> but was:<"+actual+">");
+ }
+
+ static private void failNotSame(String message, Object expected, Object actual) {
+ String formatted= "";
+ if (message != null)
+ formatted= message+" ";
+ fail(formatted+"expected same");
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/AssertionFailedError.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/AssertionFailedError.java
new file mode 100644
index 0000000000..05e786ea47
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/AssertionFailedError.java
@@ -0,0 +1,13 @@
+package org.litejunit.v1;
+
+/**
+ * Thrown when an assertion failed.
+ */
+public class AssertionFailedError extends Error {
+
+ public AssertionFailedError () {
+ }
+ public AssertionFailedError (String message) {
+ super (message);
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/Calculator.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/Calculator.java
new file mode 100644
index 0000000000..f1245ff3a6
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/Calculator.java
@@ -0,0 +1,22 @@
+package org.litejunit.v1;
+
+public class Calculator {
+
+ private int result = 0;
+ public void add(int x){
+ result += x;
+ }
+ public void subtract(int x){
+ result -=x;
+ }
+
+ public int getResult(){
+ return this.result;
+ }
+ public static void main(String[] args){
+ Calculator calculator = new Calculator();
+ calculator.add(10);
+ calculator.subtract(5);
+ System.out.println(calculator.getResult());
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/CalculatorTest.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/CalculatorTest.java
new file mode 100644
index 0000000000..3460528043
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/CalculatorTest.java
@@ -0,0 +1,65 @@
+package org.litejunit.v1;
+
+
+public class CalculatorTest extends TestCase {
+ public CalculatorTest(String name) {
+ super(name);
+
+ }
+ Calculator calculator =null;
+ public void setUp(){
+ calculator = new Calculator();
+ }
+ public void tearDown(){
+ calculator = null;
+ }
+ public void testAdd(){
+
+ calculator.add(10);
+ assertEquals(10,calculator.getResult());
+ }
+ public void testSubtract(){
+ calculator.add(10);
+ calculator.subtract(5);
+ assertEquals(4,calculator.getResult());
+ }
+
+ public static void main(String[] args){
+ TestSuite ts = new TestSuite(CalculatorTest.class);
+ TestResult tr = new TestResult();
+ ts.run(tr);
+ System.out.println(tr.wasSuccessful());
+ for(TestFailure failure : tr.failures){
+ System.err.println(failure);
+ }
+
+ /*{
+ TestCase tc1 = new CalculatorTest("testAdd"){
+ protected void runTest() {
+ testAdd();
+ }
+ };
+
+ TestCase tc2 = new CalculatorTest("testSubtract"){
+ protected void runTest() {
+ testSubtract();
+ }
+ };
+ tc1.run();
+ tc2.run();
+ }
+
+
+ TestSuite ts = new TestSuite();
+ ts.addTest(new CalculatorTest("testAdd"));
+ ts.addTest(new CalculatorTest("testSubtract"));
+
+
+ {
+ TestCase tc1 = new CalculatorTest("test1");
+ TestCase tc2 = new CalculatorTest("test2");
+ tc1.run();
+ tc2.run();
+ }*/
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/Test.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/Test.java
new file mode 100644
index 0000000000..3d870cf637
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/Test.java
@@ -0,0 +1,6 @@
+package org.litejunit.v1;
+
+public interface Test {
+ public abstract int countTestCases();
+ public void run(TestResult tr);
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/TestCase.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/TestCase.java
new file mode 100644
index 0000000000..d9cebd263b
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/TestCase.java
@@ -0,0 +1,63 @@
+package org.litejunit.v1;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+
+
+public abstract class TestCase extends Assert implements Test {
+ private String name;
+
+
+ public TestCase(String name) {
+ this.name = name;
+ }
+
+ public int countTestCases() {
+ return 1;
+ }
+
+ protected void runTest() throws Throwable{
+ Method runMethod= null;
+ try {
+ runMethod= getClass().getMethod(name, null);
+ } catch (NoSuchMethodException e) {
+ fail("Method \""+name+"\" not found");
+ }
+ if (!Modifier.isPublic(runMethod.getModifiers())) {
+ fail("Method \""+name+"\" should be public");
+ }
+
+ try {
+ runMethod.invoke(this, new Class[0]);
+ }
+ catch (InvocationTargetException e) {
+ e.fillInStackTrace();
+ throw e.getTargetException();
+ }
+ catch (IllegalAccessException e) {
+ e.fillInStackTrace();
+ throw e;
+ }
+ }
+
+ protected void setUp() {
+ }
+
+ protected void tearDown() {
+ }
+
+ public void run(TestResult tr) {
+ tr.run(this);
+ }
+ public void doRun() throws Throwable{
+ setUp();
+ try{
+ runTest();
+ }
+ finally{
+ tearDown();
+ }
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/TestFailure.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/TestFailure.java
new file mode 100644
index 0000000000..1ac44256a4
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/TestFailure.java
@@ -0,0 +1,39 @@
+package org.litejunit.v1;
+
+/**
+ * A TestFailure collects a failed test together with
+ * the caught exception.
+ * @see TestResult
+ */
+public class TestFailure {
+ protected Test failedTest;
+ protected Throwable thrownException;
+
+ /**
+ * Constructs a TestFailure with the given test and exception.
+ */
+ public TestFailure(Test failedTest, Throwable thrownException) {
+ this.failedTest= failedTest;
+ this.thrownException= thrownException;
+ }
+ /**
+ * Gets the failed test.
+ */
+ public Test failedTest() {
+ return failedTest;
+ }
+ /**
+ * Gets the thrown exception.
+ */
+ public Throwable thrownException() {
+ return thrownException;
+ }
+ /**
+ * Returns a short description of the failure.
+ */
+ public String toString() {
+ StringBuffer buffer= new StringBuffer();
+ buffer.append(failedTest+": "+thrownException.getMessage());
+ return buffer.toString();
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/TestResult.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/TestResult.java
new file mode 100644
index 0000000000..a9e8c2b439
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/TestResult.java
@@ -0,0 +1,95 @@
+package org.litejunit.v1;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+public class TestResult extends Object {
+ protected List failures;
+ protected List errors;
+
+ protected int testCount;
+ private boolean stop;
+
+ public TestResult() {
+ failures= new ArrayList<>();
+ errors= new ArrayList<>();
+
+ testCount= 0;
+ stop= false;
+ }
+
+ public void addError(Test test, Throwable t) {
+ errors.add(new TestFailure(test, t));
+ }
+
+ public void addFailure(Test test, AssertionFailedError t) {
+ failures.add(new TestFailure(test, t));
+ }
+
+ public void startTest(Test test) {
+ int count= test.countTestCases();
+ testCount+= count;
+ }
+ public void endTest(Test test) {
+ }
+
+ /**
+ * Runs a TestCase.
+ */
+ protected void run(final TestCase test) {
+ startTest(test);
+ try {
+ test.doRun();
+ }
+ catch (AssertionFailedError e) {
+ addFailure(test, e);
+ }
+ catch (Throwable e) {
+ addError(test, e);
+ }
+
+ endTest(test);
+ }
+ /**
+ * Gets the number of run tests.
+ */
+ public int runCount() {
+ return testCount;
+ }
+
+
+ public boolean shouldStop() {
+ return stop;
+ }
+
+ public void stop() {
+ stop= true;
+ }
+
+ public int errorCount() {
+ return errors.size();
+ }
+
+ public Iterator errors() {
+ return errors.iterator();
+ }
+
+ public int failureCount() {
+ return failures.size();
+ }
+
+ public Iterator failures() {
+ return failures.iterator();
+ }
+ /**
+ * Returns whether the entire test was successful or not.
+ */
+ public boolean wasSuccessful() {
+ return this.failureCount() == 0 && this.errorCount() == 0;
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/TestSuite.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/TestSuite.java
new file mode 100644
index 0000000000..ad0af20ffd
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v1/TestSuite.java
@@ -0,0 +1,130 @@
+package org.litejunit.v1;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+public class TestSuite extends Assert implements Test {
+ private List tests= new ArrayList<>(10);
+ private String name;
+ public TestSuite(){
+
+ }
+ public TestSuite(final Class> theClass) {
+ this.name= theClass.getName();
+ Constructor> constructor= null;
+ try {
+ constructor= getConstructor(theClass);
+ } catch (NoSuchMethodException e) {
+ addTest(warning("Class "+theClass.getName()+" has no public constructor TestCase(String name)"));
+ return;
+ }
+
+ if (!Modifier.isPublic(theClass.getModifiers())) {
+ addTest(warning("Class "+theClass.getName()+" is not public"));
+ return;
+ }
+
+ Vector names= new Vector<>();
+ Method[] methods= theClass.getDeclaredMethods();
+ for (int i= 0; i < methods.length; i++) {
+ addTestMethod(methods[i], names, constructor);
+ }
+
+ if (tests.size() == 0)
+ addTest(warning("No tests found in "+theClass.getName()));
+ }
+
+ private Constructor> getConstructor(Class> theClass) throws NoSuchMethodException {
+ Class>[] args= { String.class };
+ return theClass.getConstructor(args);
+ }
+ private void addTestMethod(Method m, Vector names, Constructor> constructor) {
+ String name= m.getName();
+ if (names.contains(name))
+ return;
+ if (isPublicTestMethod(m)) {
+ names.addElement(name);
+
+ Object[] args= new Object[]{name};
+ try {
+ addTest((Test)constructor.newInstance(args));
+ } catch (InstantiationException e) {
+ addTest(warning("Cannot instantiate test case: "+name+" ("+exceptionToString(e)+")"));
+ } catch (InvocationTargetException e) {
+ addTest(warning("Exception in constructor: "+name+" ("+exceptionToString(e.getTargetException())+")"));
+ } catch (IllegalAccessException e) {
+ addTest(warning("Cannot access test case: "+name+" ("+exceptionToString(e)+")"));
+ }
+
+ } else { // almost a test method
+ if (isTestMethod(m))
+ addTest(warning("Test method isn't public: "+m.getName()));
+ }
+ }
+ private boolean isPublicTestMethod(Method m) {
+ return isTestMethod(m) && Modifier.isPublic(m.getModifiers());
+ }
+ private boolean isTestMethod(Method m) {
+ String name= m.getName();
+ Class>[] parameters= m.getParameterTypes();
+ Class> returnType= m.getReturnType();
+ return parameters.length == 0 && name.startsWith("test") && returnType.equals(Void.TYPE);
+ }
+ public void addTest(Test test) {
+ tests.add(test);
+ }
+
+ private Test warning(final String message) {
+ return new TestCase("warning") {
+ public void doRun() {
+ fail(message);
+ }
+ };
+ }
+ private String exceptionToString(Throwable t) {
+ StringWriter stringWriter= new StringWriter();
+ PrintWriter writer= new PrintWriter(stringWriter);
+ t.printStackTrace(writer);
+ return stringWriter.toString();
+
+ }
+
+
+
+ @Override
+ public void run(TestResult result) {
+ for (Iterator e= tests(); e.hasNext(); ) {
+ if (result.shouldStop() ){
+ break;
+ }
+ Test test= (Test)e.next();
+ test.run(result);
+ }
+
+ }
+
+ public int countTestCases() {
+ int count= 0;
+
+ for (Iterator e= tests(); e.hasNext(); ) {
+ Test test= e.next();
+ count= count + test.countTestCases();
+ }
+ return count;
+ }
+ public Iterator tests() {
+ return tests.iterator();
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/Assert.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/Assert.java
new file mode 100644
index 0000000000..4e5a9920bd
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/Assert.java
@@ -0,0 +1,243 @@
+package org.litejunit.v2;
+
+/**
+ * A set of assert methods.
+ */
+
+public class Assert {
+ /**
+ * Protect constructor since it is a static only class
+ */
+ protected Assert() {
+ }
+ /**
+ * Asserts that a condition is true. If it isn't it throws
+ * an AssertionFailedError with the given message.
+ * @deprecated use assertTrue
+ */
+ /*static public void assert(String message, boolean condition) {
+ if (!condition)
+ fail(message);
+ }*/
+ /**
+ * Asserts that a condition is true. If it isn't it throws
+ * an AssertionFailedError.
+ * @deprecated use assertTrue
+ *
+ */
+ /*static public void assert(boolean condition) {
+ assert(null, condition);
+ }
+*/
+ /**
+ * Asserts that a condition is true. If it isn't it throws
+ * an AssertionFailedError with the given message.
+ */
+ static public void assertTrue(String message, boolean condition) {
+ if (!condition)
+ fail(message);
+ }
+ /**
+ * Asserts that a condition is true. If it isn't it throws
+ * an AssertionFailedError.
+ */
+ static public void assertTrue(boolean condition) {
+ assertTrue(null, condition);
+ }
+ /**
+ * Fails a test with the given message.
+ */
+ static public void fail(String message) {
+ throw new AssertionFailedError(message);
+ }
+ /**
+ * Fails a test with no message.
+ */
+ static public void fail() {
+ fail(null);
+ }
+ /**
+ * Asserts that two objects are equal. If they are not
+ * an AssertionFailedError is thrown.
+ */
+ static public void assertEquals(String message, Object expected, Object actual) {
+ if (expected == null && actual == null)
+ return;
+ if (expected != null && expected.equals(actual))
+ return;
+ failNotEquals(message, expected, actual);
+ }
+ /**
+ * Asserts that two objects are equal. If they are not
+ * an AssertionFailedError is thrown.
+ */
+ static public void assertEquals(Object expected, Object actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two doubles are equal concerning a delta. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(String message, double expected, double actual, double delta) {
+ // handle infinity specially since subtracting to infinite values gives NaN and the
+ // the following test fails
+ if (Double.isInfinite(expected)) {
+ if (!(expected == actual))
+ failNotEquals(message, new Double(expected), new Double(actual));
+ } else if (!(Math.abs(expected-actual) <= delta)) // Because comparison with NaN always returns false
+ failNotEquals(message, new Double(expected), new Double(actual));
+ }
+ /**
+ * Asserts that two doubles are equal concerning a delta. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(double expected, double actual, double delta) {
+ assertEquals(null, expected, actual, delta);
+ }
+ /**
+ * Asserts that two floats are equal concerning a delta. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(String message, float expected, float actual, float delta) {
+ // handle infinity specially since subtracting to infinite values gives NaN and the
+ // the following test fails
+ if (Float.isInfinite(expected)) {
+ if (!(expected == actual))
+ failNotEquals(message, new Float(expected), new Float(actual));
+ } else if (!(Math.abs(expected-actual) <= delta))
+ failNotEquals(message, new Float(expected), new Float(actual));
+ }
+ /**
+ * Asserts that two floats are equal concerning a delta. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(float expected, float actual, float delta) {
+ assertEquals(null, expected, actual, delta);
+ }
+ /**
+ * Asserts that two longs are equal.
+ */
+ static public void assertEquals(String message, long expected, long actual) {
+ assertEquals(message, new Long(expected), new Long(actual));
+ }
+ /**
+ * Asserts that two longs are equal.
+ */
+ static public void assertEquals(long expected, long actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two booleans are equal.
+ */
+ static public void assertEquals(String message, boolean expected, boolean actual) {
+ assertEquals(message, new Boolean(expected), new Boolean(actual));
+ }
+ /**
+ * Asserts that two booleans are equal.
+ */
+ static public void assertEquals(boolean expected, boolean actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two bytes are equal.
+ */
+ static public void assertEquals(String message, byte expected, byte actual) {
+ assertEquals(message, new Byte(expected), new Byte(actual));
+ }
+ /**
+ * Asserts that two bytes are equal.
+ */
+ static public void assertEquals(byte expected, byte actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two chars are equal.
+ */
+ static public void assertEquals(String message, char expected, char actual) {
+ assertEquals(message, new Character(expected), new Character(actual));
+ }
+ /**
+ * Asserts that two chars are equal.
+ */
+ static public void assertEquals(char expected, char actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two shorts are equal.
+ */
+ static public void assertEquals(String message, short expected, short actual) {
+ assertEquals(message, new Short(expected), new Short(actual));
+ }
+ /**
+ * Asserts that two shorts are equal.
+ */
+ static public void assertEquals(short expected, short actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two ints are equal.
+ */
+ static public void assertEquals(String message, int expected, int actual) {
+ assertEquals(message, new Integer(expected), new Integer(actual));
+ }
+ /**
+ * Asserts that two ints are equal.
+ */
+ static public void assertEquals(int expected, int actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that an object isn't null.
+ */
+ static public void assertNotNull(Object object) {
+ assertNotNull(null, object);
+ }
+ /**
+ * Asserts that an object isn't null.
+ */
+ static public void assertNotNull(String message, Object object) {
+ assertTrue(message, object != null);
+ }
+ /**
+ * Asserts that an object is null.
+ */
+ static public void assertNull(Object object) {
+ assertNull(null, object);
+ }
+ /**
+ * Asserts that an object is null.
+ */
+ static public void assertNull(String message, Object object) {
+ assertTrue(message, object == null);
+ }
+ /**
+ * Asserts that two objects refer to the same object. If they are not
+ * an AssertionFailedError is thrown.
+ */
+ static public void assertSame(String message, Object expected, Object actual) {
+ if (expected == actual)
+ return;
+ failNotSame(message, expected, actual);
+ }
+ /**
+ * Asserts that two objects refer to the same object. If they are not
+ * the same an AssertionFailedError is thrown.
+ */
+ static public void assertSame(Object expected, Object actual) {
+ assertSame(null, expected, actual);
+ }
+
+ static private void failNotEquals(String message, Object expected, Object actual) {
+ String formatted= "";
+ if (message != null)
+ formatted= message+" ";
+ fail(formatted+"expected:<"+expected+"> but was:<"+actual+">");
+ }
+
+ static private void failNotSame(String message, Object expected, Object actual) {
+ String formatted= "";
+ if (message != null)
+ formatted= message+" ";
+ fail(formatted+"expected same");
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/AssertionFailedError.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/AssertionFailedError.java
new file mode 100644
index 0000000000..49ebf0955e
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/AssertionFailedError.java
@@ -0,0 +1,13 @@
+package org.litejunit.v2;
+
+/**
+ * Thrown when an assertion failed.
+ */
+public class AssertionFailedError extends Error {
+
+ public AssertionFailedError () {
+ }
+ public AssertionFailedError (String message) {
+ super (message);
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/Protectable.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/Protectable.java
new file mode 100644
index 0000000000..f43f7d8e01
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/Protectable.java
@@ -0,0 +1,14 @@
+package org.litejunit.v2;
+
+/**
+ * A Protectable can be run and can throw a Throwable.
+ *
+ * @see TestResult
+ */
+public interface Protectable {
+
+ /**
+ * Run the the following method protected.
+ */
+ public abstract void protect() throws Throwable;
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/Test.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/Test.java
new file mode 100644
index 0000000000..73de6a2e25
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/Test.java
@@ -0,0 +1,6 @@
+package org.litejunit.v2;
+
+public interface Test {
+ public abstract int countTestCases();
+ public void run(TestResult tr);
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestCase.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestCase.java
new file mode 100644
index 0000000000..4f704d2866
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestCase.java
@@ -0,0 +1,64 @@
+package org.litejunit.v2;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+
+
+public abstract class TestCase extends Assert implements Test {
+ private String name;
+
+
+ public TestCase(String name) {
+ this.name = name;
+ }
+
+
+ public int countTestCases() {
+ return 1;
+ }
+
+ protected void runTest() throws Throwable{
+ Method runMethod= null;
+ try {
+ runMethod= getClass().getMethod(name, null);
+ } catch (NoSuchMethodException e) {
+ fail("Method \""+name+"\" not found");
+ }
+ if (!Modifier.isPublic(runMethod.getModifiers())) {
+ fail("Method \""+name+"\" should be public");
+ }
+
+ try {
+ runMethod.invoke(this, new Class[0]);
+ }
+ catch (InvocationTargetException e) {
+ e.fillInStackTrace();
+ throw e.getTargetException();
+ }
+ catch (IllegalAccessException e) {
+ e.fillInStackTrace();
+ throw e;
+ }
+ }
+
+ protected void setUp() {
+ }
+
+ protected void tearDown() {
+ }
+
+ public void run(TestResult tr) {
+ tr.run(this);
+ }
+ public void doRun() throws Throwable{
+ setUp();
+ try{
+ runTest();
+ }
+ finally{
+ tearDown();
+ }
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestFailure.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestFailure.java
new file mode 100644
index 0000000000..c40f6f89e0
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestFailure.java
@@ -0,0 +1,39 @@
+package org.litejunit.v2;
+
+/**
+ * A TestFailure collects a failed test together with
+ * the caught exception.
+ * @see TestResult
+ */
+public class TestFailure {
+ protected Test failedTest;
+ protected Throwable thrownException;
+
+ /**
+ * Constructs a TestFailure with the given test and exception.
+ */
+ public TestFailure(Test failedTest, Throwable thrownException) {
+ this.failedTest= failedTest;
+ this.thrownException= thrownException;
+ }
+ /**
+ * Gets the failed test.
+ */
+ public Test failedTest() {
+ return failedTest;
+ }
+ /**
+ * Gets the thrown exception.
+ */
+ public Throwable thrownException() {
+ return thrownException;
+ }
+ /**
+ * Returns a short description of the failure.
+ */
+ public String toString() {
+ StringBuffer buffer= new StringBuffer();
+ buffer.append(failedTest+": "+thrownException.getMessage());
+ return buffer.toString();
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestListener.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestListener.java
new file mode 100644
index 0000000000..412febcc55
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestListener.java
@@ -0,0 +1,15 @@
+package org.litejunit.v2;
+
+/**
+ * A Listener for test progress
+ */
+public interface TestListener {
+
+ public void addError(Test test, Throwable t);
+
+ public void addFailure(Test test, AssertionFailedError t);
+
+ public void endTest(Test test);
+
+ public void startTest(Test test);
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestResult.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestResult.java
new file mode 100644
index 0000000000..6fb789a495
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestResult.java
@@ -0,0 +1,121 @@
+package org.litejunit.v2;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class TestResult extends Object {
+ protected List failures;
+ protected List errors;
+ protected List listeners;
+ protected int testCount;
+ private boolean stop;
+
+ public TestResult() {
+ failures= new ArrayList<>();
+ errors= new ArrayList<>();
+ listeners = new ArrayList<>();
+ testCount= 0;
+ stop= false;
+ }
+
+ public void addError(Test test, Throwable t) {
+ errors.add(new TestFailure(test, t));
+ for(TestListener listener: listeners){
+ listener.addError(test, t);
+ }
+ }
+
+ public void addFailure(Test test, AssertionFailedError t) {
+ failures.add(new TestFailure(test, t));
+ for(TestListener listener: listeners){
+ listener.addFailure(test, t);
+ }
+ }
+
+ public void startTest(Test test) {
+ int count= test.countTestCases();
+ testCount+= count;
+ for(TestListener listener: listeners){
+ listener.startTest(test);
+ }
+ }
+ public void endTest(Test test) {
+ for(TestListener listener: listeners){
+ listener.endTest(test);
+ }
+ }
+
+ /**
+ * Runs a TestCase.
+ */
+ protected void run(final TestCase test) {
+ startTest(test);
+ try {
+ test.doRun();
+ }
+ catch (AssertionFailedError e) {
+ addFailure(test, e);
+ }
+ catch (Throwable e) {
+ addError(test, e);
+ }
+
+ endTest(test);
+ }
+ /**
+ * Gets the number of run tests.
+ */
+ public int runCount() {
+ return testCount;
+ }
+ public void runProtected(final Test test, Protectable p) {
+ try {
+ p.protect();
+ }
+ catch (AssertionFailedError e) {
+ addFailure(test, e);
+ }
+ catch (Throwable e) {
+ addError(test, e);
+ }
+ }
+
+ public boolean shouldStop() {
+ return stop;
+ }
+
+ public void stop() {
+ stop= true;
+ }
+
+ public int errorCount() {
+ return errors.size();
+ }
+
+ public Iterator errors() {
+ return errors.iterator();
+ }
+
+ public int failureCount() {
+ return failures.size();
+ }
+
+ public Iterator failures() {
+ return failures.iterator();
+ }
+ /**
+ * Returns whether the entire test was successful or not.
+ */
+ public boolean wasSuccessful() {
+ return this.failureCount() == 0 && this.errorCount() == 0;
+ }
+ public void addListener(TestListener listener) {
+ listeners.add(listener);
+ }
+
+ public void removeListener(TestListener listener) {
+ listeners.remove(listener);
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestSuite.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestSuite.java
new file mode 100644
index 0000000000..9ad0a05433
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/TestSuite.java
@@ -0,0 +1,137 @@
+package org.litejunit.v2;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+
+
+
+
+
+public class TestSuite extends Assert implements Test {
+ private List tests= new ArrayList<>(10);
+ private String name;
+ public TestSuite(){
+
+ }
+ public TestSuite(final Class> theClass) {
+ this.name= theClass.getName();
+ Constructor> constructor= null;
+ try {
+ constructor= getConstructor(theClass);
+ } catch (NoSuchMethodException e) {
+ addTest(warning("Class "+theClass.getName()+" has no public constructor TestCase(String name)"));
+ return;
+ }
+
+ if (!Modifier.isPublic(theClass.getModifiers())) {
+ addTest(warning("Class "+theClass.getName()+" is not public"));
+ return;
+ }
+
+ Vector names= new Vector<>();
+ Method[] methods= theClass.getDeclaredMethods();
+ for (int i= 0; i < methods.length; i++) {
+ addTestMethod(methods[i], names, constructor);
+ }
+
+ if (tests.size() == 0)
+ addTest(warning("No tests found in "+theClass.getName()));
+ }
+
+ public TestSuite(String name) {
+ this.name = name;
+ }
+ private Constructor> getConstructor(Class> theClass) throws NoSuchMethodException {
+ Class>[] args= { String.class };
+ return theClass.getConstructor(args);
+ }
+ private void addTestMethod(Method m, Vector names, Constructor> constructor) {
+ String name= m.getName();
+ if (names.contains(name))
+ return;
+ if (isPublicTestMethod(m)) {
+ names.addElement(name);
+
+ Object[] args= new Object[]{name};
+ try {
+ addTest((Test)constructor.newInstance(args));
+ } catch (InstantiationException e) {
+ addTest(warning("Cannot instantiate test case: "+name+" ("+exceptionToString(e)+")"));
+ } catch (InvocationTargetException e) {
+ addTest(warning("Exception in constructor: "+name+" ("+exceptionToString(e.getTargetException())+")"));
+ } catch (IllegalAccessException e) {
+ addTest(warning("Cannot access test case: "+name+" ("+exceptionToString(e)+")"));
+ }
+
+ } else { // almost a test method
+ if (isTestMethod(m))
+ addTest(warning("Test method isn't public: "+m.getName()));
+ }
+ }
+ private boolean isPublicTestMethod(Method m) {
+ return isTestMethod(m) && Modifier.isPublic(m.getModifiers());
+ }
+ private boolean isTestMethod(Method m) {
+ String name= m.getName();
+ Class>[] parameters= m.getParameterTypes();
+ Class> returnType= m.getReturnType();
+ return parameters.length == 0 && name.startsWith("test") && returnType.equals(Void.TYPE);
+ }
+ public void addTest(Test test) {
+ tests.add(test);
+ }
+ public void addTestSuite(Class testClass) {
+ addTest(new TestSuite(testClass));
+ }
+ private Test warning(final String message) {
+ return new TestCase("warning") {
+ public void doRun() {
+ fail(message);
+ }
+ };
+ }
+ private String exceptionToString(Throwable t) {
+ StringWriter stringWriter= new StringWriter();
+ PrintWriter writer= new PrintWriter(stringWriter);
+ t.printStackTrace(writer);
+ return stringWriter.toString();
+
+ }
+
+
+
+ @Override
+ public void run(TestResult result) {
+ for (Iterator e= tests(); e.hasNext(); ) {
+ if (result.shouldStop() ){
+ break;
+ }
+ Test test= (Test)e.next();
+ test.run(result);
+ }
+
+ }
+
+ public int countTestCases() {
+ int count= 0;
+
+ for (Iterator e= tests(); e.hasNext(); ) {
+ Test test= e.next();
+ count= count + test.countTestCases();
+ }
+ return count;
+ }
+ public Iterator tests() {
+ return tests.iterator();
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/runner/BaseTestRunner.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/runner/BaseTestRunner.java
new file mode 100644
index 0000000000..b6ff184b69
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/runner/BaseTestRunner.java
@@ -0,0 +1,85 @@
+package org.litejunit.v2.runner;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.text.NumberFormat;
+
+import org.litejunit.v2.Test;
+import org.litejunit.v2.TestListener;
+import org.litejunit.v2.TestSuite;
+
+
+public abstract class BaseTestRunner implements TestListener {
+ public static final String SUITE_METHODNAME= "suite";
+ /**
+ * Returns a filtered stack trace
+ */
+ public static String getFilteredTrace(Throwable t) {
+ StringWriter stringWriter= new StringWriter();
+ PrintWriter writer= new PrintWriter(stringWriter);
+ t.printStackTrace(writer);
+ StringBuffer buffer= stringWriter.getBuffer();
+ String trace= buffer.toString();
+ return trace;
+ //return BaseTestRunner.filterStack(trace);
+ }
+
+ public Test getTest(String suiteClassName) {
+ if (suiteClassName.length() <= 0) {
+ return null;
+ }
+ Class testClass= null;
+ try {
+ testClass= loadSuiteClass(suiteClassName);
+ } catch (ClassNotFoundException e) {
+ String clazz= e.getMessage();
+ if (clazz == null)
+ clazz= suiteClassName;
+ runFailed("Class not found \""+clazz+"\"");
+ return null;
+ } catch(Exception e) {
+ runFailed("Error: "+e.toString());
+ return null;
+ }
+ Method suiteMethod= null;
+ try {
+ suiteMethod= testClass.getMethod(SUITE_METHODNAME, new Class[0]);
+ } catch(Exception e) {
+ // try to extract a test suite automatically
+ //clearStatus();
+ return new TestSuite(testClass);
+ }
+ Test test= null;
+ try {
+ test= (Test)suiteMethod.invoke(null, new Class[0]); // static method
+ if (test == null)
+ return test;
+ }
+ catch (InvocationTargetException e) {
+ runFailed("Failed to invoke suite():" + e.getTargetException().toString());
+ return null;
+ }
+ catch (IllegalAccessException e) {
+ runFailed("Failed to invoke suite():" + e.toString());
+ return null;
+ }
+
+ //clearStatus();
+ return test;
+ }
+ protected Class> loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
+
+ //TODO
+ return Class.forName(suiteClassName);
+
+
+ //return getLoader().load(suiteClassName);
+ }
+ protected abstract void runFailed(String message);
+
+ public String elapsedTimeAsString(long runTime) {
+ return NumberFormat.getInstance().format((double)runTime/1000);
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/textui/TestRunner.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/textui/TestRunner.java
new file mode 100644
index 0000000000..0ffab6b747
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v2/textui/TestRunner.java
@@ -0,0 +1,202 @@
+package org.litejunit.v2.textui;
+
+
+import java.lang.reflect.*;
+import java.text.NumberFormat;
+import java.util.*;
+
+import org.litejunit.v2.AssertionFailedError;
+import org.litejunit.v2.Test;
+import org.litejunit.v2.TestFailure;
+import org.litejunit.v2.TestResult;
+import org.litejunit.v2.TestSuite;
+import org.litejunit.v2.runner.BaseTestRunner;
+
+import java.io.PrintStream;
+
+
+public class TestRunner extends BaseTestRunner {
+ PrintStream writer= System.out;
+ int column= 0;
+
+ /**
+ * Constructs a TestRunner.
+ */
+ public TestRunner() {
+ }
+
+
+ /**
+ * Always use the StandardTestSuiteLoader. Overridden from
+ * BaseTestRunner.
+ */
+ /*public TestSuiteLoader getLoader() {
+ return new StandardTestSuiteLoader();
+ }*/
+
+ public synchronized void addError(Test test, Throwable t) {
+ writer().print("E");
+ }
+
+ public synchronized void addFailure(Test test, AssertionFailedError t) {
+ writer().print("F");
+ }
+
+
+
+ public TestResult doRun(Test suite) {
+ TestResult result= new TestResult();
+ result.addListener(this);
+ long startTime= System.currentTimeMillis();
+ suite.run(result);
+ long endTime= System.currentTimeMillis();
+ long runTime= endTime-startTime;
+ writer().println();
+ writer().println("Time: "+elapsedTimeAsString(runTime));
+ print(result);
+
+ writer().println();
+
+
+ return result;
+ }
+
+
+
+ public synchronized void startTest(Test test) {
+ writer().print(".");
+ if (column++ >= 40) {
+ writer().println();
+ column= 0;
+ }
+ }
+
+ public void endTest(Test test) {
+ }
+
+ public static void main(String args[]) {
+ TestRunner testRunner= new TestRunner();
+ try {
+ TestResult r= testRunner.start(args);
+ if (!r.wasSuccessful())
+ System.exit(-1);
+ System.exit(0);
+ } catch(Exception e) {
+ System.err.println(e.getMessage());
+ System.exit(-2);
+ }
+ }
+ /**
+ * Prints failures to the standard output
+ */
+ public synchronized void print(TestResult result) {
+ printErrors(result);
+ printFailures(result);
+ printHeader(result);
+ }
+ /**
+ * Prints the errors to the standard output
+ */
+ public void printErrors(TestResult result) {
+ if (result.errorCount() != 0) {
+ if (result.errorCount() == 1)
+ writer().println("There was "+result.errorCount()+" error:");
+ else
+ writer().println("There were "+result.errorCount()+" errors:");
+
+ int i= 1;
+ for (Iterator e= result.errors(); e.hasNext(); i++) {
+ TestFailure failure= e.next();
+ writer().println(i+") "+failure.failedTest());
+ writer().print(getFilteredTrace(failure.thrownException()));
+ }
+ }
+ }
+ /**
+ * Prints failures to the standard output
+ */
+ public void printFailures(TestResult result) {
+ if (result.failureCount() != 0) {
+ if (result.failureCount() == 1)
+ writer().println("There was " + result.failureCount() + " failure:");
+ else
+ writer().println("There were " + result.failureCount() + " failures:");
+ int i = 1;
+ for (Iterator e= result.failures(); e.hasNext(); i++) {
+ TestFailure failure= (TestFailure) e.next();
+ writer().print(i + ") " + failure.failedTest());
+ Throwable t= failure.thrownException();
+ writer().print(getFilteredTrace(failure.thrownException()));
+ }
+ }
+ }
+ /**
+ * Prints the header of the report
+ */
+ public void printHeader(TestResult result) {
+ if (result.wasSuccessful()) {
+ writer().println();
+ writer().print("OK");
+ writer().println (" (" + result.runCount() + " tests)");
+
+ } else {
+ writer().println();
+ writer().println("FAILURES!!!");
+ writer().println("Tests run: "+result.runCount()+
+ ", Failures: "+result.failureCount()+
+ ", Errors: "+result.errorCount());
+ }
+ }
+
+
+ /**
+ * Starts a test run. Analyzes the command line arguments
+ * and runs the given test suite.
+ */
+ protected TestResult start(String args[]) throws Exception {
+ if(args.length == 0){
+ throw new Exception("Usage: TestRunner testCaseName");
+ }
+ String testCase= args[0];
+
+ try {
+ Test suite= getTest(testCase);
+ return doRun(suite);
+ }
+ catch(Exception e) {
+ throw new Exception("Could not create and run test suite: "+e);
+ }
+ }
+
+ protected void runFailed(String message) {
+ System.err.println(message);
+ System.exit(-1);
+ }
+
+ /**
+ * Runs a suite extracted from a TestCase subclass.
+ */
+ static public void run(Class testClass) {
+ run(new TestSuite(testClass));
+ }
+ /**
+ * Runs a single test and collects its results.
+ * This method can be used to start a test run
+ * from your program.
+ *
+ * public static void main (String[] args) {
+ * test.textui.TestRunner.run(suite());
+ * }
+ *
+ */
+ static public void run(Test suite) {
+ TestRunner aTestRunner= new TestRunner();
+ aTestRunner.doRun(suite);
+ }
+
+ protected PrintStream writer() {
+ return writer;
+ }
+
+
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/After.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/After.java
new file mode 100644
index 0000000000..f27496b8e1
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/After.java
@@ -0,0 +1,12 @@
+package org.litejunit.v3;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface After {
+}
+
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/AfterClass.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/AfterClass.java
new file mode 100644
index 0000000000..82618d7afc
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/AfterClass.java
@@ -0,0 +1,13 @@
+package org.litejunit.v3;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface AfterClass {
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/Assert.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/Assert.java
new file mode 100644
index 0000000000..6d1b7689f9
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/Assert.java
@@ -0,0 +1,269 @@
+package org.litejunit.v3;
+
+/**
+ * A set of assertion methods useful for writing tests. Only failed assertions are recorded.
+ * These methods can be used directly: Assert.assertEquals(...), however, they
+ * read better if they are referenced through static import:
+ *
+ * import static org.junit.Assert.*;
+ * ...
+ * assertEquals(...);
+ *
+ */
+
+public class Assert {
+ /**
+ * Protect constructor since it is a static only class
+ */
+ protected Assert() {
+ }
+
+ /**
+ * Asserts that a condition is true. If it isn't it throws an
+ * AssertionError with the given message.
+ */
+ static public void assertTrue(String message, boolean condition) {
+ if (!condition)
+ fail(message);
+ }
+
+ /**
+ * Asserts that a condition is true. If it isn't it throws an
+ * AssertionError.
+ */
+ static public void assertTrue(boolean condition) {
+ assertTrue(null, condition);
+ }
+
+ /**
+ * Asserts that a condition is false. If it isn't it throws an
+ * AssertionError with the given message.
+ */
+ static public void assertFalse(String message, boolean condition) {
+ assertTrue(message, !condition);
+ }
+
+ /**
+ * Asserts that a condition is false. If it isn't it throws an
+ * AssertionError.
+ */
+ static public void assertFalse(boolean condition) {
+ assertFalse(null, condition);
+ }
+
+ /**
+ * Fails a test with the given message.
+ */
+ static public void fail(String message) {
+ throw new AssertionError(message);
+ }
+
+ /**
+ * Fails a test with no message.
+ */
+ static public void fail() {
+ fail(null);
+ }
+
+ /**
+ * Asserts that two objects are equal. If they are not, an
+ * AssertionError is thrown with the given message.
+ */
+ static public void assertEquals(String message, Object expected, Object actual) {
+ if (expected == null && actual == null)
+ return;
+ if (expected != null && expected.equals(actual))
+ return;
+ if (expected instanceof String && actual instanceof String)
+ throw new ComparisonFailure(message, (String)expected, (String)actual);
+ else
+ failNotEquals(message, expected, actual);
+ }
+
+ /**
+ * Asserts that two objects are equal. If they are not, an
+ * AssertionError is thrown.
+ */
+ static public void assertEquals(Object expected, Object actual) {
+ assertEquals(null, expected, actual);
+ }
+
+ /**
+ * Asserts that two object arrays are equal. If they are not, an
+ * AssertionError is thrown with the given message.
+ */
+ public static void assertEquals(String message, Object[] expecteds, Object[] actuals) {
+ if (expecteds == actuals)
+ return;
+ String header = message == null ? "" : message + ": ";
+ if (expecteds == null)
+ fail(header + "expected array was null");
+ if (actuals == null)
+ fail(header + "actual array was null");
+ if (actuals.length != expecteds.length)
+ fail(header + "array lengths differed, expected.length=" + expecteds.length + " actual.length=" + actuals.length);
+
+ for (int i= 0; i < expecteds.length; i++) {
+ Object o1= expecteds[i];
+ Object o2= actuals[i];
+ if (o1.getClass().isArray() && o2.getClass().isArray()) {
+ Object[] expected= (Object[]) o1;
+ Object[] actual= (Object[]) o2;
+ assertEquals(header + "arrays first differed at element " + i + ";", expected, actual);
+ } else
+ assertEquals(header + "arrays first differed at element [" + i + "];", o1, o2);
+ }
+ }
+
+ /**
+ * Asserts that two object arrays are equal. If they are not, an
+ * AssertionError is thrown.
+ */
+ public static void assertEquals(Object[] expecteds, Object[] actuals) {
+ assertEquals(null, expecteds, actuals);
+ }
+
+ /**
+ * Asserts that two doubles are equal to within a positive delta. If they
+ * are not, an AssertionError is thrown with the given message. If the
+ * expected value is infinity then the delta value is ignored. NaNs are
+ * considered equal:
+ * assertEquals(Double.NaN, Double.NaN, *) passes
+ */
+ static public void assertEquals(String message, double expected, double actual, double delta) {
+ if (Double.compare(expected, actual) == 0)
+ return;
+ if (!(Math.abs(expected - actual) <= delta))
+ failNotEquals(message, new Double(expected), new Double(actual));
+ }
+
+ /**
+ * Asserts that two doubles are equal to within a positive delta. If they
+ * are not, an AssertionError is thrown. If the
+ * expected value is infinity then the delta value is ignored.NaNs are
+ * considered equal:
+ * assertEquals(Double.NaN, Double.NaN, *) passes
+ */
+ static public void assertEquals(double expected, double actual, double delta) {
+ assertEquals(null, expected, actual, delta);
+ }
+
+ /**
+ * Asserts that two floats are equal to within a positive delta. If they
+ * are not, an AssertionError is thrown with the given message. If the
+ * expected value is infinity then the delta value is ignored.NaNs are
+ * considered equal:
+ * assertEquals(Float.NaN, Float.NaN, *) passes
+ */
+ static public void assertEquals(String message, float expected, float actual, float delta) {
+ if (Float.compare(expected, actual) == 0)
+ return;
+ if (!(Math.abs(expected - actual) <= delta))
+ failNotEquals(message, new Float(expected), new Float(actual));
+ }
+
+ /**
+ * Asserts that two floats are equal to within a positive delta. If they
+ * are not, an AssertionError is thrown. If the
+ * expected value is infinity then the delta value is ignored.NaNs are
+ * considered equal:
+ * assertEquals(Float.NaN, Float.NaN, *) passes
+ */
+ static public void assertEquals(float expected, float actual, float delta) {
+ assertEquals(null, expected, actual, delta);
+ }
+
+ /**
+ * Asserts that an object isn't null. If it is an AssertionError is
+ * thrown with the given message.
+ */
+ static public void assertNotNull(String message, Object object) {
+ assertTrue(message, object != null);
+ }
+
+ /**
+ * Asserts that an object isn't null. If it is an AssertionError is
+ * thrown.
+ */
+ static public void assertNotNull(Object object) {
+ assertNotNull(null, object);
+ }
+
+ /**
+ * Asserts that an object is null. If it is not, an AssertionError is
+ * thrown with the given message.
+ */
+ static public void assertNull(String message, Object object) {
+ assertTrue(message, object == null);
+ }
+
+ /**
+ * Asserts that an object is null. If it isn't an AssertionError is
+ * thrown.
+ */
+ static public void assertNull(Object object) {
+ assertNull(null, object);
+ }
+
+ /**
+ * Asserts that two objects refer to the same object. If they are not, an
+ * AssertionError is thrown with the given message.
+ */
+ static public void assertSame(String message, Object expected, Object actual) {
+ if (expected == actual)
+ return;
+ failNotSame(message, expected, actual);
+ }
+
+ /**
+ * Asserts that two objects refer to the same object. If they are not the
+ * same, an AssertionError is thrown.
+ */
+ static public void assertSame(Object expected, Object actual) {
+ assertSame(null, expected, actual);
+ }
+
+ /**
+ * Asserts that two objects do not refer to the same object. If they do
+ * refer to the same object, an AssertionError is thrown with the given
+ * message.
+ */
+ static public void assertNotSame(String message, Object expected, Object actual) {
+ if (expected == actual)
+ failSame(message);
+ }
+
+ /**
+ * Asserts that two objects do not refer to the same object. If they do
+ * refer to the same object, an AssertionError is thrown.
+ */
+ static public void assertNotSame(Object expected, Object actual) {
+ assertNotSame(null, expected, actual);
+ }
+
+ static private void failSame(String message) {
+ String formatted= "";
+ if (message != null)
+ formatted= message + " ";
+ fail(formatted + "expected not same");
+ }
+
+ static private void failNotSame(String message, Object expected, Object actual) {
+ String formatted= "";
+ if (message != null)
+ formatted= message + " ";
+ fail(formatted + "expected same:<" + expected + "> was not:<" + actual + ">");
+ }
+
+ static private void failNotEquals(String message, Object expected, Object actual) {
+ fail(format(message, expected, actual));
+ }
+
+ static String format(String message, Object expected, Object actual) {
+ String formatted= "";
+ if (message != null)
+ formatted= message + " ";
+ return formatted + "expected:<" + expected + "> but was:<" + actual + ">";
+ }
+
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/Before.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/Before.java
new file mode 100644
index 0000000000..72e0e3beb2
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/Before.java
@@ -0,0 +1,13 @@
+package org.litejunit.v3;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Before {
+}
+
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/BeforeClass.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/BeforeClass.java
new file mode 100644
index 0000000000..6334ab45b2
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/BeforeClass.java
@@ -0,0 +1,11 @@
+package org.litejunit.v3;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface BeforeClass {
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/ComparisonFailure.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/ComparisonFailure.java
new file mode 100644
index 0000000000..77f9ea6f5f
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/ComparisonFailure.java
@@ -0,0 +1,124 @@
+package org.litejunit.v3;
+
+/**
+ * Thrown when an assertEquals(String, String) fails. Create and throw
+ * a ComparisonFailure manually if you want to show users the difference between two complex
+ * strings.
+ *
+ * Inspired by a patch from Alex Chaffee (alex@purpletech.com)
+ */
+public class ComparisonFailure extends AssertionError {
+ private static final int MAX_CONTEXT_LENGTH= 20;
+ private static final long serialVersionUID= 1L;
+
+ private String fExpected;
+ private String fActual;
+
+ /**
+ * Constructs a comparison failure.
+ * @param message the identifying message or null
+ * @param expected the expected string value
+ * @param actual the actual string value
+ */
+ public ComparisonFailure (String message, String expected, String actual) {
+ super (message);
+ fExpected= expected;
+ fActual= actual;
+ }
+
+ /**
+ * Returns "..." in place of common prefix and "..." in
+ * place of common suffix between expected and actual.
+ *
+ * @see java.lang.Throwable#getMessage()
+ */
+ @Override
+ public String getMessage() {
+ return new ComparisonCompactor(MAX_CONTEXT_LENGTH, fExpected, fActual).compact(super.getMessage());
+ }
+
+ /**
+ * Returns the actual value
+ * @return the actual string value
+ */
+ public String getActual() {
+ return fActual;
+ }
+ /**
+ * Returns the expected value
+ * @return the expected string value
+ */
+ public String getExpected() {
+ return fExpected;
+ }
+
+ private static class ComparisonCompactor {
+ private static final String ELLIPSIS= "...";
+ private static final String DELTA_END= "]";
+ private static final String DELTA_START= "[";
+
+ private int fContextLength;
+ private String fExpected;
+ private String fActual;
+ private int fPrefix;
+ private int fSuffix;
+
+ public ComparisonCompactor(int contextLength, String expected, String actual) {
+ fContextLength= contextLength;
+ fExpected= expected;
+ fActual= actual;
+ }
+
+ public String compact(String message) {
+ if (fExpected == null || fActual == null || areStringsEqual())
+ return Assert.format(message, fExpected, fActual);
+
+ findCommonPrefix();
+ findCommonSuffix();
+ String expected= compactString(fExpected);
+ String actual= compactString(fActual);
+ return Assert.format(message, expected, actual);
+ }
+
+ private String compactString(String source) {
+ String result= DELTA_START + source.substring(fPrefix, source.length() - fSuffix + 1) + DELTA_END;
+ if (fPrefix > 0)
+ result= computeCommonPrefix() + result;
+ if (fSuffix > 0)
+ result= result + computeCommonSuffix();
+ return result;
+ }
+
+ private void findCommonPrefix() {
+ fPrefix= 0;
+ int end= Math.min(fExpected.length(), fActual.length());
+ for (; fPrefix < end; fPrefix++) {
+ if (fExpected.charAt(fPrefix) != fActual.charAt(fPrefix))
+ break;
+ }
+ }
+
+ private void findCommonSuffix() {
+ int expectedSuffix= fExpected.length() - 1;
+ int actualSuffix= fActual.length() - 1;
+ for (; actualSuffix >= fPrefix && expectedSuffix >= fPrefix; actualSuffix--, expectedSuffix--) {
+ if (fExpected.charAt(expectedSuffix) != fActual.charAt(actualSuffix))
+ break;
+ }
+ fSuffix= fExpected.length() - expectedSuffix;
+ }
+
+ private String computeCommonPrefix() {
+ return (fPrefix > fContextLength ? ELLIPSIS : "") + fExpected.substring(Math.max(0, fPrefix - fContextLength), fPrefix);
+ }
+
+ private String computeCommonSuffix() {
+ int end= Math.min(fExpected.length() - fSuffix + 1 + fContextLength, fExpected.length());
+ return fExpected.substring(fExpected.length() - fSuffix + 1, end) + (fExpected.length() - fSuffix + 1 < fExpected.length() - fContextLength ? ELLIPSIS : "");
+ }
+
+ private boolean areStringsEqual() {
+ return fExpected.equals(fActual);
+ }
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/Ignore.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/Ignore.java
new file mode 100644
index 0000000000..1652ac2431
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/Ignore.java
@@ -0,0 +1,31 @@
+package org.litejunit.v3;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Sometimes you want to temporarily disable a test. Methods annotated with @Test
+ * that are also annotated with @Ignore will not be executed as tests. Native JUnit 4 test runners
+ * should report the number of ignored tests along with the number of tests that ran and the
+ * number of tests that failed.
+ *
+ * For example:
+ *
+ * @Ignore @Test public void something() { ...
+ *
+ * @Ignore takes an optional default parameter if you want to record why a test is being ignored:
+ *
+ * @Ignore("not ready yet") @Test public void something() { ...
+ *
+ *
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Ignore {
+ /**
+ * The optional reason why the test is ignored.
+ */
+ String value() default "";
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/Test.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/Test.java
new file mode 100644
index 0000000000..f390d10671
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/Test.java
@@ -0,0 +1,62 @@
+package org.litejunit.v3;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The Test annotation tells JUnit that the public void method
+ * to which it is attached can be run as a test case. To run the method,
+ * JUnit first constructs a fresh instance of the class then invokes the
+ * annotated method. Any exceptions thrown by the test will be reported
+ * by JUnit as a failure. If no exceptions are thrown, the test is assumed
+ * to have succeeded.
+ *
+ * A simple test looks like this:
+ *
+ * public class Example {
+ * @Test public void method() {
+ * System.out.println("Hello");
+ * }
+ * }
+ *
+ *
+ * The Test annotation supports two optional parameters.
+ * The first, expected, declares that a test method should throw
+ * an exception. If it doesn't throw an exception or if it throws a different exception
+ * than the one declared, the test fails. For example, the following test succeeds:
+ *
+ * @Test(expected=IndexOutOfBoundsException.class) public void outOfBounds() {
+ * new ArrayList<Object>().get(1);
+ * }
+ *
+ *
+ * The second optional parameter, timeout, causes a test to fail if it takes longer than a specified
+ * amount of clock time (measured in milliseconds). The following test fails:
+ *
+ * @Test(timeout=100) public void infinity() {
+ * for(;;);
+ * }
+ *
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Test {
+ static class None extends Throwable {
+ private static final long serialVersionUID= 1L;
+ private None() {
+ }
+ }
+
+ /**
+ * Optionally specify expected, a Throwable, to cause a test method to succeed iff
+ * an exception of the specified class is thrown by the method.
+ */
+ Class extends Throwable> expected() default None.class;
+
+ /**
+ * Optionally specify timeout in milliseconds to cause a test method to fail if it
+ * takes longer than that number of milliseconds.*/
+ long timeout() default 0L;
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/notification/Failure.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/notification/Failure.java
new file mode 100644
index 0000000000..2eb516b75f
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/notification/Failure.java
@@ -0,0 +1,78 @@
+package org.litejunit.v3.notification;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.litejunit.v3.runner.Description;
+
+
+/**
+ * A Failure holds a description of the failed test and the
+ * exception that was thrown while running it. In most cases the Description
+ * will be of a single test. However, if problems are encountered while constructing the
+ * test (for example, if a @BeforeClass method is not static), it may describe
+ * something other than a single test.
+ */
+public class Failure {
+ private final Description fDescription;
+ private Throwable fThrownException;
+
+ /**
+ * Constructs a Failure with the given description and exception.
+ * @param description a Description of the test that failed
+ * @param thrownException the exception that was thrown while running the test
+ */
+ public Failure(Description description, Throwable thrownException) {
+ fThrownException = thrownException;
+ fDescription= description;
+ }
+
+ /**
+ * @return a user-understandable label for the test
+ */
+ public String getTestHeader() {
+ return fDescription.getDisplayName();
+ }
+
+ /**
+ * @return the raw description of the context of the failure.
+ */
+ public Description getDescription() {
+ return fDescription;
+ }
+
+ /**
+ * @return the exception thrown
+ */
+
+ public Throwable getException() {
+ return fThrownException;
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buffer= new StringBuffer();
+ buffer.append(getTestHeader() + ": "+fThrownException.getMessage());
+ return buffer.toString();
+ }
+
+ /**
+ * Convenience method
+ * @return the printed form of the exception
+ */
+ public String getTrace() {
+ StringWriter stringWriter= new StringWriter();
+ PrintWriter writer= new PrintWriter(stringWriter);
+ getException().printStackTrace(writer);
+ StringBuffer buffer= stringWriter.getBuffer();
+ return buffer.toString();
+ }
+
+ /**
+ * Convenience method
+ * @return the message of the thrown exception
+ */
+ public String getMessage() {
+ return getException().getMessage();
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/notification/RunListener.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/notification/RunListener.java
new file mode 100644
index 0000000000..aa30aa9abf
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/notification/RunListener.java
@@ -0,0 +1,53 @@
+package org.litejunit.v3.notification;
+
+import org.litejunit.v3.runner.Description;
+import org.litejunit.v3.runner.Result;
+
+
+public class RunListener {
+
+ /**
+ * Called before any tests have been run.
+ * @param description describes the tests to be run
+ */
+ public void testRunStarted(Description description) throws Exception {
+ }
+
+ /**
+ * Called when all tests have finished
+ * @param result the summary of the test run, including all the tests that failed
+ */
+ public void testRunFinished(Result result) throws Exception {
+ }
+
+ /**
+ * Called when an atomic test is about to be started.
+ * @param description the description of the test that is about to be run (generally a class and method name)
+ */
+ public void testStarted(Description description) throws Exception {
+ }
+
+ /**
+ * Called when an atomic test has finished, whether the test succeeds or fails.
+ * @param description the description of the test that just ran
+ */
+ public void testFinished(Description description) throws Exception {
+ }
+
+ /**
+ * Called when an atomic test fails.
+ * @param failure describes the test that failed and the exception that was thrown
+ */
+ public void testFailure(Failure failure) throws Exception {
+ }
+
+ /**
+ * Called when a test will not be run, generally because a test method is annotated with @Ignored.
+ * @param description describes the test that will not be run
+ */
+ public void testIgnored(Description description) throws Exception {
+ }
+
+}
+
+
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/notification/RunNotifier.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/notification/RunNotifier.java
new file mode 100644
index 0000000000..d7d16e0677
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/notification/RunNotifier.java
@@ -0,0 +1,139 @@
+package org.litejunit.v3.notification;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.litejunit.v3.runner.Description;
+import org.litejunit.v3.runner.Result;
+
+
+
+/**
+ * If you write custom runners, you may need to notify JUnit of your progress running tests.
+ * Do this by invoking the RunNotifier passed to your implementation of
+ * Runner.run(RunNotifier notifier). Future evolution of this class is likely to
+ * move fireTestRunStarted() and fireTestRunFinished()
+ * to a separate class since they should only be called once per run.
+ */
+public class RunNotifier {
+ private List fListeners= new ArrayList();
+ private boolean fPleaseStop= false;
+
+ /** Internal use only
+ */
+ public void addListener(RunListener listener) {
+ fListeners.add(listener);
+ }
+
+ /** Internal use only
+ */
+ public void removeListener(RunListener listener) {
+ fListeners.remove(listener);
+ }
+
+ private abstract class SafeNotifier {
+ void run() {
+ for (Iterator all= fListeners.iterator(); all.hasNext();) {
+ try {
+ notifyListener(all.next());
+ } catch (Exception e) {
+ all.remove(); // Remove the offending listener first to avoid an infinite loop
+ fireTestFailure(new Failure(Description.TEST_MECHANISM, e));
+ }
+ }
+ }
+
+ abstract protected void notifyListener(RunListener each) throws Exception;
+ }
+
+ /**
+ * Do not invoke.
+ */
+ public void fireTestRunStarted(final Description description) {
+ new SafeNotifier() {
+ @Override
+ protected void notifyListener(RunListener each) throws Exception {
+ each.testRunStarted(description);
+ };
+ }.run();
+ }
+
+ /**
+ * Do not invoke.
+ */
+ public void fireTestRunFinished(final Result result) {
+ new SafeNotifier() {
+ @Override
+ protected void notifyListener(RunListener each) throws Exception {
+ each.testRunFinished(result);
+ };
+ }.run();
+ }
+
+ /**
+ * Invoke to tell listeners that an atomic test is about to start.
+ * @param description the description of the atomic test (generally a class and method name)
+ * @throws StoppedByUserException thrown if a user has requested that the test run stop
+ */
+ public void fireTestStarted(final Description description) throws StoppedByUserException {
+ if (fPleaseStop)
+ throw new StoppedByUserException();
+ new SafeNotifier() {
+ @Override
+ protected void notifyListener(RunListener each) throws Exception {
+ each.testStarted(description);
+ };
+ }.run();
+ }
+
+ /**
+ * Invoke to tell listeners that an atomic test failed.
+ * @param failure the description of the test that failed and the exception thrown
+ */
+ public void fireTestFailure(final Failure failure) {
+ new SafeNotifier() {
+ @Override
+ protected void notifyListener(RunListener each) throws Exception {
+ each.testFailure(failure);
+ };
+ }.run();
+ }
+
+ /**
+ * Invoke to tell listeners that an atomic test was ignored.
+ * @param description the description of the ignored test
+ */
+ public void fireTestIgnored(final Description description) {
+ new SafeNotifier() {
+ @Override
+ protected void notifyListener(RunListener each) throws Exception {
+ each.testIgnored(description);
+ };
+ }.run();
+ }
+
+ /**
+ * Invoke to tell listeners that an atomic test finished. Always invoke fireTestFinished()
+ * if you invoke fireTestStarted() as listeners are likely to expect them to come in pairs.
+ * @param description the description of the test that finished
+ */
+ public void fireTestFinished(final Description description) {
+ new SafeNotifier() {
+ @Override
+ protected void notifyListener(RunListener each) throws Exception {
+ each.testFinished(description);
+ };
+ }.run();
+ }
+
+ /**
+ * Ask that the tests run stop before starting the next test. Phrased politely because
+ * the test currently running will not be interrupted. It seems a little odd to put this
+ * functionality here, but the RunNotifier is the only object guaranteed
+ * to be shared amongst the many runners involved.
+ */
+ public void pleaseStop() {
+ fPleaseStop= true;
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/notification/StoppedByUserException.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/notification/StoppedByUserException.java
new file mode 100644
index 0000000000..829462445c
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/notification/StoppedByUserException.java
@@ -0,0 +1,11 @@
+package org.litejunit.v3.notification;
+
+/**
+ * Thrown when a user has requested that the test run stop. Writers of
+ * test running GUIs should be prepared to catch a StoppedByUserException.
+ *
+ * @see org.junit.runner.notification.RunNotifier
+ */
+public class StoppedByUserException extends RuntimeException {
+ private static final long serialVersionUID= 1L;
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/requests/ClassRequest.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/requests/ClassRequest.java
new file mode 100644
index 0000000000..315bbb6482
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/requests/ClassRequest.java
@@ -0,0 +1,48 @@
+/**
+ *
+ */
+package org.litejunit.v3.requests;
+
+import java.lang.reflect.Constructor;
+
+import org.litejunit.v3.runner.Request;
+import org.litejunit.v3.runner.Runner;
+import org.litejunit.v3.runners.TestClassRunner;
+
+
+public class ClassRequest extends Request {
+ private final Class> fTestClass;
+
+ public ClassRequest(Class> each) {
+ fTestClass= each;
+ }
+
+ @Override
+ public Runner getRunner() {
+ Class runnerClass= getRunnerClass(fTestClass);
+ try {
+ Constructor constructor= runnerClass.getConstructor(Class.class); // TODO good error message if no such constructor
+ Runner runner= (Runner) constructor
+ .newInstance(new Object[] { fTestClass });
+ return runner;
+ } catch (Exception e) {
+ return null;
+ //return Request.errorReport(fTestClass, e).getRunner();
+ }
+ }
+
+ Class getRunnerClass(Class> testClass) {
+ /*RunWith annotation= testClass.getAnnotation(RunWith.class);
+ if (annotation != null) {
+ return annotation.value();
+ } else if (isPre4Test(testClass)) {
+ return OldTestClassRunner.class;
+ } else {*/
+ return TestClassRunner.class;
+ /*}*/
+ }
+
+ /*boolean isPre4Test(Class> testClass) {
+ return junit.framework.TestCase.class.isAssignableFrom(testClass);
+ }*/
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/Description.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/Description.java
new file mode 100644
index 0000000000..db3610fd3f
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/Description.java
@@ -0,0 +1,127 @@
+package org.litejunit.v3.runner;
+
+import java.util.ArrayList;
+
+/**
+ * A Description describes a test which is to be run or has been run. Descriptions can
+ * be atomic (a single test) or compound (containing children tests). Descriptions are used
+ * to provide feedback about the tests that are about to run (for example, the tree view
+ * visible in many IDEs) or tests that have been run (for example, the failures view).
+ * Descriptions are implemented as a single class rather than a Composite because
+ * they are entirely informational. They contain no logic aside from counting their tests.
+ * In the past, we used the raw junit.framework.TestCases and junit.framework.TestSuites
+ * to display the tree of tests. This was no longer viable in JUnit 4 because atomic tests no longer have a superclass below Object.
+ * We needed a way to pass a class and name together. Description emerged from this.
+ *
+ * @see org.junit.runner.Request
+ * @see org.junit.runner.Runner
+ */
+public class Description {
+
+ /**
+ * Create a Description named name.
+ * Generally, you will add children to this Description.
+ * @param name The name of the Description
+ * @return A Description named name
+ */
+ public static Description createSuiteDescription(String name) {
+ return new Description(name);
+ }
+
+ /**
+ * Create a Description of a single test named name in the class clazz.
+ * Generally, this will be a leaf Description.
+ * @param clazz The class of the test
+ * @param name The name of the test (a method name for test annotated with @Test)
+ * @return A Description named name
+ */
+ public static Description createTestDescription(Class clazz, String name) {
+ return new Description(String.format("%s(%s)", name, clazz.getName()));
+ }
+
+ /**
+ * Create a generic Description that says there are tests in testClass.
+ * This is used as a last resort when you cannot precisely describe the individual tests in the class.
+ * @param testClass A Class containing tests
+ * @return A Description of testClass
+ */
+ public static Description createSuiteDescription(Class> testClass) {
+ return new Description(testClass.getName());
+ }
+
+ public static Description TEST_MECHANISM = new Description("Test mechanism");
+ private final ArrayList fChildren= new ArrayList();
+ private final String fDisplayName;
+
+ //TODO we seem to be using the static factories exclusively
+ private Description(final String displayName) {
+ fDisplayName= displayName;
+ }
+
+ /**
+ * @return a user-understandable label
+ */
+ public String getDisplayName() {
+ return fDisplayName;
+ }
+
+ /**
+ * Add description as a child of the receiver.
+ * @param description The soon-to-be child.
+ */
+ public void addChild(Description description) {
+ getChildren().add(description);
+ }
+
+ /**
+ * @return the receiver's children, if any
+ */
+ public ArrayList getChildren() {
+ return fChildren;
+ }
+
+ /**
+ * @return true if the receiver is a suite
+ */
+ public boolean isSuite() {
+ return !isTest();
+ }
+
+ /**
+ * @return true if the receiver is an atomic test
+ */
+ public boolean isTest() {
+ return getChildren().isEmpty();
+ }
+
+ /**
+ * @return the total number of atomic tests in the receiver
+ */
+ public int testCount() {
+ if (isTest())
+ return 1;
+ int result= 0;
+ for (Description child : getChildren())
+ result+= child.testCount();
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ return getDisplayName().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Description))
+ return false;
+ Description d = (Description) obj;
+ return getDisplayName().equals(d.getDisplayName())
+ && getChildren().equals(d.getChildren());
+ }
+
+ @Override
+ public String toString() {
+ return getDisplayName();
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/JUnitCore.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/JUnitCore.java
new file mode 100644
index 0000000000..662f5ffd0c
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/JUnitCore.java
@@ -0,0 +1,167 @@
+package org.litejunit.v3.runner;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.litejunit.v3.notification.RunListener;
+import org.litejunit.v3.notification.RunNotifier;
+import org.litejunit.v3.runners.InitializationError;
+import org.litejunit.v3.runners.TestClassRunner;
+import org.litejunit.v3.runners.TextListener;
+
+
+
+/**
+ * JUnitCore is a facade for running tests. It supports running JUnit 4 tests,
+ * JUnit 3.8.2 tests, and mixtures. To run tests from the command line, run java org.junit.runner.JUnitCore TestClass1 TestClass2 ....
+ * For one-shot test runs, use the static method runClasses(Class... classes)
+ * . If you want to add special listeners,
+ * create an instance of JUnitCore first and use it to run the tests.
+ *
+ * @see org.junit.runner.Result
+ * @see org.junit.runner.notification.RunListener
+ * @see org.junit.runner.Request
+ */
+public class JUnitCore {
+
+ private RunNotifier notifier;
+
+ /**
+ * Create a new JUnitCore to run tests.
+ */
+ public JUnitCore() {
+ notifier= new RunNotifier();
+ }
+
+ /**
+ * Run the tests contained in the classes named in the args.
+ * If all tests run successfully, exit with a status of 0. Otherwise exit with a status of 1.
+ * Write feedback while tests are running and write
+ * stack traces for all failed tests after the tests all complete.
+ * @param args names of classes in which to find tests to run
+ */
+ /*public static void main(String... args) {
+ Class> clz = null;
+ try {
+ clz = Class.forName(args[0]);
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ return;
+ }
+
+ Request request = Request.aClass(clz);
+
+ new JUnitCore().run(request);
+
+ Result result= new JUnitCore().runMain(args);
+ killAllThreads(result);
+ }*/
+ public static void runClass(Class> clz){
+ try {
+ TestClassRunner runner = new TestClassRunner(clz);
+ JUnitCore core = new JUnitCore();
+ core.addListener(new TextListener());
+ Result result = core.run(runner);
+
+ } catch (InitializationError e) {
+
+ e.printStackTrace();
+ }
+
+ }
+ /*private static void killAllThreads(Result result) {
+ System.exit(result.wasSuccessful() ? 0 : 1);
+ }*/
+
+ /**
+ * Run the tests contained in classes. Write feedback while the tests
+ * are running and write stack traces for all failed tests after all tests complete. This is
+ * similar to main(), but intended to be used programmatically.
+ * @param classes Classes in which to find tests
+ * @return a Result describing the details of the test run and the failed tests.
+ */
+ /*public static Result runClasses(Class... classes) {
+ return new JUnitCore().run(classes);
+ }*/
+
+ /**
+ * Do not use. Testing purposes only.
+ */
+ /*public Result runMain(String... args) {
+
+ List classes= new ArrayList();
+ for (String each : args)
+ try {
+ classes.add(Class.forName(each));
+ } catch (ClassNotFoundException e) {
+ System.out.println("Could not find class: " + each);
+ }
+ RunListener listener= new TextListener();
+ addListener(listener);
+ return run(classes.toArray(new Class[0]));
+ }*/
+
+
+
+ /**
+ * Run all the tests in classes.
+ * @param classes the classes containing tests
+ * @return a Result describing the details of the test run and the failed tests.
+ */
+ /*public Result run(Class... classes) {
+ return run(Request.classes("All", classes));
+ }*/
+
+ /**
+ * Run all the tests contained in request.
+ * @param request the request describing tests
+ * @return a Result describing the details of the test run and the failed tests.
+ */
+ /*public Result run(Request request) {
+ return run(request.getRunner());
+ }*/
+
+ /**
+ * Run all the tests contained in JUnit 3.8.x test. Here for backward compatibility.
+ * @param test the old-style test
+ * @return a Result describing the details of the test run and the failed tests.
+ */
+ /*public Result run(junit.framework.Test test) {
+ return run(new OldTestClassRunner(test));
+ }
+ */
+ /**
+ * Do not use. Testing purposes only.
+ */
+ public Result run(Runner runner) {
+ Result result= new Result();
+ RunListener listener= result.createListener();
+ addListener(listener);
+
+ try {
+ notifier.fireTestRunStarted(runner.getDescription());
+ runner.run(notifier);
+ notifier.fireTestRunFinished(result);
+ } finally {
+ removeListener(listener);
+ }
+ return result;
+ }
+
+ /**
+ * Add a listener to be notified as the tests run.
+ * @param listener the listener
+ * @see org.junit.runner.notification.RunListener
+ */
+ public void addListener(RunListener listener) {
+ notifier.addListener(listener);
+ }
+
+ /**
+ * Remove a listener.
+ * @param listener the listener to remove
+ */
+ public void removeListener(RunListener listener) {
+ notifier.removeListener(listener);
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/Request.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/Request.java
new file mode 100644
index 0000000000..02db808bb7
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/Request.java
@@ -0,0 +1,86 @@
+package org.litejunit.v3.runner;
+
+import org.litejunit.v3.requests.ClassRequest;
+
+
+
+/**
+ * A Request is an abstract description of tests to be run. Older versions of
+ * JUnit did not need such a concept--tests to be run were described either by classes containing
+ * tests or a tree of Tests. However, we want to support filtering and sorting,
+ * so we need a more abstract specification than the tests themselves and a richer
+ * specification than just the classes.
+ *
+ * The flow when JUnit runs tests is that a Request specifies some tests to be run ->
+ * a Runner is created for each class implied by the Request -> the Runner
+ * returns a detailed Description which is a tree structure of the tests to be run.
+ */
+public abstract class Request {
+ /**
+ * Create a Request that, when processed, will run a single test.
+ * This is done by filtering out all other tests. This method is used to support rerunning
+ * single tests.
+ * @param clazz the class of the test
+ * @param methodName the name of the test
+ * @return a Request that will cause a single test be run
+ */
+ /*public static Request method(Class> clazz, String methodName) {
+ Description method= Description.createTestDescription(clazz, methodName);
+ return Request.aClass(clazz).filterWith(method);
+ }*/
+
+ /**
+ * Create a Request that, when processed, will run all the tests
+ * in a class. The odd name is necessary because class is a reserved word.
+ * @param clazz the class containing the tests
+ * @return a Request that will cause all tests in the class to be run
+ */
+ public static Request aClass(Class> clazz) {
+ return new ClassRequest(clazz);
+ }
+
+ /**
+ * Create a Request that, when processed, will run all the tests
+ * in a set of classes.
+ * @param collectionName a name to identify this suite of tests
+ * @param classes the classes containing the tests
+ * @return a Request that will cause all tests in the classes to be run
+ */
+ /*public static Request classes(String collectionName, Class... classes) {
+ return new ClassesRequest(collectionName, classes);
+ }*/
+
+ /*public static Request errorReport(Class> klass, Throwable cause) {
+ return new ErrorReportingRequest(klass, cause);
+ }*/
+
+ public abstract Runner getRunner();
+
+ /*public Request filterWith(Filter filter) {
+ return new FilterRequest(this, filter);
+ }
+
+ public Request filterWith(final Description desiredDescription) {
+ return filterWith(new Filter() {
+ @Override
+ public boolean shouldRun(Description description) {
+ // TODO: test for equality even if we have children?
+ if (description.isTest())
+ return desiredDescription.equals(description);
+ for (Description each : description.getChildren())
+ if (shouldRun(each))
+ return true;
+ return false;
+ }
+
+ @Override
+ public String describe() {
+ return String.format("Method %s", desiredDescription.getDisplayName());
+ }
+ });
+ }
+
+ public Request sortWith(Comparator comparator) {
+ return new SortingRequest(this, comparator);
+ }*/
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/Result.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/Result.java
new file mode 100644
index 0000000000..591d083f71
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/Result.java
@@ -0,0 +1,98 @@
+package org.litejunit.v3.runner;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.litejunit.v3.notification.Failure;
+import org.litejunit.v3.notification.RunListener;
+
+
+/**
+ * A Result collects and summarizes information from running multiple
+ * tests. Since tests are expected to run correctly, successful tests are only noted in
+ * the count of tests that ran.
+ */
+public class Result {
+ private int fCount= 0;
+ private int fIgnoreCount= 0;
+ private List fFailures= new ArrayList();
+ private long fRunTime= 0;
+ private long fStartTime;
+
+ /**
+ * @return the number of tests run
+ */
+ public int getRunCount() {
+ return fCount;
+ }
+
+ /**
+ * @return the number of tests that failed during the run
+ */
+ public int getFailureCount() {
+ return fFailures.size();
+ }
+
+ /**
+ * @return the number of milliseconds it took to run the entire suite to run
+ */
+ public long getRunTime() {
+ return fRunTime;
+ }
+
+ /**
+ * @return the Failures describing tests that failed and the problems they encountered
+ */
+ public List getFailures() {
+ return fFailures;
+ }
+
+ /**
+ * @return the number of tests ignored during the run
+ */
+ public int getIgnoreCount() {
+ return fIgnoreCount;
+ }
+
+ /**
+ * @return true if all tests succeeded
+ */
+ public boolean wasSuccessful() {
+ return getFailureCount() == 0;
+ }
+
+ private class Listener extends RunListener {
+ @Override
+ public void testRunStarted(Description description) throws Exception {
+ fStartTime= System.currentTimeMillis();
+ }
+
+ @Override
+ public void testRunFinished(Result result) throws Exception {
+ long endTime= System.currentTimeMillis();
+ fRunTime+= endTime - fStartTime;
+ }
+
+ @Override
+ public void testStarted(Description description) throws Exception {
+ fCount++;
+ }
+
+ @Override
+ public void testFailure(Failure failure) throws Exception {
+ fFailures.add(failure);
+ }
+
+ @Override
+ public void testIgnored(Description description) throws Exception {
+ fIgnoreCount++;
+ }
+ }
+
+ /**
+ * Internal use only.
+ */
+ public RunListener createListener() {
+ return new Listener();
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/ResultPrinter.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/ResultPrinter.java
new file mode 100644
index 0000000000..de8a41717c
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/ResultPrinter.java
@@ -0,0 +1,72 @@
+package org.litejunit.v3.runner;
+
+import java.io.PrintStream;
+import java.text.NumberFormat;
+
+import org.litejunit.v3.notification.Failure;
+
+public class ResultPrinter {
+
+ private final PrintStream fWriter;
+
+ public ResultPrinter(){
+ fWriter = System.out;
+ }
+
+ public void print(Result result) {
+ printHeader(result.getRunTime());
+ printFailures(result);
+ printFooter(result);
+ }
+ protected void printHeader(long runTime) {
+ getWriter().println();
+ getWriter().println("Time: " + elapsedTimeAsString(runTime));
+ }
+
+ protected void printFailures(Result result) {
+ if (result.getFailureCount() == 0)
+ return;
+ if (result.getFailureCount() == 1)
+ getWriter().println("There was " + result.getFailureCount() + " failure:");
+ else
+ getWriter().println("There were " + result.getFailureCount() + " failures:");
+ int i= 1;
+ for (Failure each : result.getFailures())
+ printFailure(each, i++);
+ }
+
+ protected void printFailure(Failure failure, int count) {
+ printFailureHeader(failure, count);
+ printFailureTrace(failure);
+ }
+
+ protected void printFailureHeader(Failure failure, int count) {
+ getWriter().println(count + ") " + failure.getTestHeader());
+ }
+
+ protected void printFailureTrace(Failure failure) {
+ getWriter().print(failure.getTrace());
+ }
+
+ protected void printFooter(Result result) {
+ if (result.wasSuccessful()) {
+ getWriter().println();
+ getWriter().print("OK");
+ getWriter().println(" (" + result.getRunCount() + " test" + (result.getRunCount() == 1 ? "" : "s") + ")");
+
+ } else {
+ getWriter().println();
+ getWriter().println("FAILURES!!!");
+ getWriter().println("Tests run: " + result.getRunCount() + ", Failures: " + result.getFailureCount());
+ }
+ getWriter().println();
+ }
+ protected String elapsedTimeAsString(long runTime) {
+ return NumberFormat.getInstance().format((double) runTime / 1000);
+ }
+ private PrintStream getWriter() {
+ return fWriter;
+ }
+
+
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/RunWith.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/RunWith.java
new file mode 100644
index 0000000000..c8ed3d4ff5
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/RunWith.java
@@ -0,0 +1,24 @@
+package org.litejunit.v3.runner;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+//TODO add simple exampel
+/**
+ * When you annotate a class with @RunWith, JUnit will invoke
+ * the class it references to run the tests in that class instead of the runner
+ * built into JUnit. We added this feature late in development. While it
+ * seems powerful we expect the runner API to change as we learn how people
+ * really use it. Some of the classes that are currently internal will likely be refined
+ * and become public.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface RunWith {
+ /**
+ * @return a Runner class (must have a constructor that takes a single Class to run)
+ */
+ Class extends Runner> value();
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/Runner.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/Runner.java
new file mode 100644
index 0000000000..57ef0faf97
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runner/Runner.java
@@ -0,0 +1,24 @@
+package org.litejunit.v3.runner;
+
+import org.litejunit.v3.notification.RunNotifier;
+
+
+public abstract class Runner {
+ /**
+ * @return a Description showing the tests to be run by the receiver
+ */
+ public abstract Description getDescription();
+
+ /**
+ * Run the tests for this runner.
+ * @param notifier will be notified of events while tests are being run--tests being started, finishing, and failing
+ */
+ public abstract void run(RunNotifier notifier);
+
+ /**
+ * @return the number of tests to be run by the receiver
+ */
+ public int testCount() {
+ return getDescription().testCount();
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/BeforeAndAfterRunner.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/BeforeAndAfterRunner.java
new file mode 100644
index 0000000000..1bcbf40d79
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/BeforeAndAfterRunner.java
@@ -0,0 +1,76 @@
+package org.litejunit.v3.runners;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+
+public abstract class BeforeAndAfterRunner {
+ private static class FailedBefore extends Exception {
+ private static final long serialVersionUID= 1L;
+ }
+
+ private final Class extends Annotation> beforeAnnotation;
+
+ private final Class extends Annotation> afterAnnotation;
+
+ private TestIntrospector testIntrospector;
+
+ private Object test;
+
+ public BeforeAndAfterRunner(Class> testClass,
+ Class extends Annotation> beforeAnnotation,
+ Class extends Annotation> afterAnnotation,
+ Object test) {
+ this.beforeAnnotation= beforeAnnotation;
+ this.afterAnnotation= afterAnnotation;
+ this.testIntrospector= new TestIntrospector(testClass);
+ this.test= test;
+ }
+
+ public void runProtected() {
+ try {
+ runBefores();
+ runUnprotected();
+ } catch (FailedBefore e) {
+ } finally {
+ runAfters();
+ }
+ }
+
+ protected abstract void runUnprotected();
+
+ protected abstract void addFailure(Throwable targetException);
+
+ // Stop after first failed @Before
+ private void runBefores() throws FailedBefore {
+ try {
+ List befores= testIntrospector.getTestMethods(beforeAnnotation);
+ for (Method before : befores)
+ invokeMethod(before);
+ } catch (InvocationTargetException e) {
+ addFailure(e.getTargetException());
+ throw new FailedBefore();
+ } catch (Throwable e) {
+ addFailure(e);
+ throw new FailedBefore();
+ }
+ }
+
+ // Try to run all @Afters regardless
+ private void runAfters() {
+ List afters= testIntrospector.getTestMethods(afterAnnotation);
+ for (Method after : afters)
+ try {
+ invokeMethod(after);
+ } catch (InvocationTargetException e) {
+ addFailure(e.getTargetException());
+ } catch (Throwable e) {
+ addFailure(e); // Untested, but seems impossible
+ }
+ }
+
+ private void invokeMethod(Method method) throws Exception {
+ method.invoke(test);
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/InitializationError.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/InitializationError.java
new file mode 100644
index 0000000000..76e21d02e4
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/InitializationError.java
@@ -0,0 +1,25 @@
+package org.litejunit.v3.runners;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class InitializationError extends Exception {
+ private static final long serialVersionUID= 1L;
+ private final List fErrors;
+
+ public InitializationError(List errors) {
+ fErrors= errors;
+ }
+
+ public InitializationError(Throwable... errors) {
+ this(Arrays.asList(errors));
+ }
+
+ public InitializationError(String string) {
+ this(new Exception(string));
+ }
+
+ public List getCauses() {
+ return fErrors;
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/TestClassMethodsRunner.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/TestClassMethodsRunner.java
new file mode 100644
index 0000000000..adf3b9c40d
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/TestClassMethodsRunner.java
@@ -0,0 +1,100 @@
+package org.litejunit.v3.runners;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.litejunit.v3.Test;
+import org.litejunit.v3.notification.Failure;
+import org.litejunit.v3.notification.RunNotifier;
+import org.litejunit.v3.runner.Description;
+import org.litejunit.v3.runner.Runner;
+
+
+
+public class TestClassMethodsRunner extends Runner {
+ private final List testMethods;
+ private final Class> testClass;
+
+ public TestClassMethodsRunner(Class> klass) {
+ testClass= klass;
+ testMethods= new TestIntrospector(testClass).getTestMethods(Test.class);
+ }
+
+ @Override
+ public void run(RunNotifier notifier) {
+ /*if (testMethods.isEmpty())
+ testAborted(notifier, getDescription());*/
+ for (Method method : testMethods)
+ invokeTestMethod(method, notifier);
+ }
+
+ /*private void testAborted(RunNotifier notifier, Description description) {
+ // TODO: duped!
+ // TODO: envious
+ notifier.fireTestStarted(description);
+ notifier.fireTestFailure(new Failure(description, new Exception("No runnable methods")));
+ notifier.fireTestFinished(description);
+ }*/
+
+ @Override
+ public Description getDescription() {
+ Description spec= Description.createSuiteDescription(getName());
+ List testMethods= this.testMethods;
+ for (Method method : testMethods)
+ spec.addChild(methodDescription(method));
+ return spec;
+ }
+
+ protected String getName() {
+ return getTestClass().getName();
+ }
+
+ protected Object createTest() throws Exception {
+ return getTestClass().getConstructor().newInstance();
+ }
+
+ protected void invokeTestMethod(Method method, RunNotifier notifier) {
+ Object test;
+ try {
+ test= createTest();
+ } catch (Exception e) {
+ //testAborted(notifier, methodDescription(method));
+ return;
+ }
+ createMethodRunner(test, method, notifier).run();
+ }
+
+ protected TestMethodRunner createMethodRunner(Object test, Method method, RunNotifier notifier) {
+ return new TestMethodRunner(test, method, notifier, methodDescription(method));
+ }
+
+ protected String testName(Method method) {
+ return method.getName();
+ }
+
+ protected Description methodDescription(Method method) {
+ return Description.createTestDescription(getTestClass(), testName(method));
+ }
+
+ /*public void filter(Filter filter) throws NoTestsRemainException {
+ for (Iterator iter= fTestMethods.iterator(); iter.hasNext();) {
+ Method method= (Method) iter.next();
+ if (!filter.shouldRun(methodDescription(method)))
+ iter.remove();
+ }
+ if (fTestMethods.isEmpty())
+ throw new NoTestsRemainException();
+ }
+
+ public void sort(final Sorter sorter) {
+ Collections.sort(fTestMethods, new Comparator() {
+ public int compare(Method o1, Method o2) {
+ return sorter.compare(methodDescription(o1), methodDescription(o2));
+ }
+ });
+ }*/
+
+ protected Class> getTestClass() {
+ return testClass;
+ }
+}
\ No newline at end of file
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/TestClassRunner.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/TestClassRunner.java
new file mode 100644
index 0000000000..84c2a072ef
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/TestClassRunner.java
@@ -0,0 +1,53 @@
+package org.litejunit.v3.runners;
+
+import org.litejunit.v3.AfterClass;
+import org.litejunit.v3.BeforeClass;
+import org.litejunit.v3.notification.Failure;
+import org.litejunit.v3.notification.RunNotifier;
+import org.litejunit.v3.runner.Description;
+import org.litejunit.v3.runner.Runner;
+
+public class TestClassRunner extends Runner {
+ protected final Runner enclosedRunner;
+ private final Class> testClass;
+
+ public TestClassRunner(Class> klass) throws InitializationError {
+ this(klass, new TestClassMethodsRunner(klass));
+ }
+
+ public TestClassRunner(Class> klass, Runner runner) throws InitializationError {
+ testClass= klass;
+ enclosedRunner= runner;
+
+ }
+
+
+
+ @Override
+ public void run(final RunNotifier notifier) {
+ BeforeAndAfterRunner runner = new BeforeAndAfterRunner(getTestClass(),
+ BeforeClass.class, AfterClass.class, null) {
+ @Override
+ protected void runUnprotected() {
+ enclosedRunner.run(notifier);
+ }
+
+ // TODO: looks very similar to other method of BeforeAfter, now
+ @Override
+ protected void addFailure(Throwable targetException) {
+ notifier.fireTestFailure(new Failure(getDescription(), targetException));
+ }
+ };
+
+ runner.runProtected();
+ }
+
+ @Override
+ public Description getDescription() {
+ return enclosedRunner.getDescription();
+ }
+
+ protected Class> getTestClass() {
+ return testClass;
+ }
+}
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/TestIntrospector.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/TestIntrospector.java
new file mode 100644
index 0000000000..1dda424d7f
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/TestIntrospector.java
@@ -0,0 +1,82 @@
+package org.litejunit.v3.runners;
+
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.litejunit.v3.Before;
+import org.litejunit.v3.BeforeClass;
+import org.litejunit.v3.Ignore;
+import org.litejunit.v3.Test;
+import org.litejunit.v3.Test.None;
+
+
+
+public class TestIntrospector {
+ private final Class< ?> testClass;
+
+ public TestIntrospector(Class> testClass) {
+ this.testClass= testClass;
+ }
+
+ public List getTestMethods(Class extends Annotation> annotationClass) {
+ List results= new ArrayList();
+
+ //for (Class eachClass : getSuperClasses(testClass)) {
+ Method[] methods= testClass.getDeclaredMethods();
+ for (Method method : methods) {
+ Annotation annotation= method.getAnnotation(annotationClass);
+ if (annotation != null && ! isShadowed(method, results))
+ results.add(method);
+ }
+ //}
+ if (runsTopToBottom(annotationClass))
+ Collections.reverse(results);
+ return results;
+ }
+
+ public boolean isIgnored(Method eachMethod) {
+ return eachMethod.getAnnotation(Ignore.class) != null;
+ }
+
+ private boolean runsTopToBottom(Class< ? extends Annotation> annotation) {
+ return annotation.equals(Before.class) || annotation.equals(BeforeClass.class);
+ }
+
+ private boolean isShadowed(Method method, List results) {
+ for (Method m : results) {
+ if (m.getName().equals(method.getName()))
+ return true;
+ }
+ return false;
+ }
+
+ /*private List getSuperClasses(Class< ?> testClass) {
+ ArrayList results= new ArrayList();
+ Class> current= testClass;
+ while (current != null) {
+ results.add(current);
+ current= current.getSuperclass();
+ }
+ return results;
+ }*/
+
+ long getTimeout(Method method) {
+ Test annotation= method.getAnnotation(Test.class);
+ long timeout= annotation.timeout();
+ return timeout;
+ }
+
+ Class extends Throwable> expectedException(Method method) {
+ Test annotation= method.getAnnotation(Test.class);
+ if (annotation.expected() == None.class)
+ return null;
+ else
+ return annotation.expected();
+ }
+
+}
+
diff --git a/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/TestMethodRunner.java b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/TestMethodRunner.java
new file mode 100644
index 0000000000..7034a4c812
--- /dev/null
+++ b/liuxin/ood/ood-assignment/src/main/java/org/litejunit/v3/runners/TestMethodRunner.java
@@ -0,0 +1,122 @@
+package org.litejunit.v3.runners;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.litejunit.v3.After;
+import org.litejunit.v3.Before;
+import org.litejunit.v3.notification.Failure;
+import org.litejunit.v3.notification.RunNotifier;
+import org.litejunit.v3.runner.Description;
+
+
+
+public class TestMethodRunner extends BeforeAndAfterRunner {
+ private final Object test;
+ private final Method method;
+ private final RunNotifier notifier;
+ private final TestIntrospector testIntrospector;
+ private final Description description;
+
+ public TestMethodRunner(Object test, Method method, RunNotifier notifier, Description description) {
+ super(test.getClass(), Before.class, After.class, test);
+ this.test= test;
+ this.method= method;
+ this.notifier= notifier;
+ testIntrospector= new TestIntrospector(test.getClass());
+ this.description= description;
+ }
+
+ public void run() {
+ /*if (testIntrospector.isIgnored(method)) {
+ notifier.fireTestIgnored(description);
+ return;
+ }*/
+ notifier.fireTestStarted(description);
+ try {
+ /*long timeout= testIntrospector.getTimeout(method);
+ if (timeout > 0)
+ runWithTimeout(timeout);
+ else*/
+ runMethod();
+ } finally {
+ notifier.fireTestFinished(description);
+ }
+ }
+
+ /*private void runWithTimeout(long timeout) {
+ ExecutorService service= Executors.newSingleThreadExecutor();
+ Callable