[testng] 01/02: New upstream version 6.9.4

Eugene Zhukov eugene-guest at moszumanska.debian.org
Mon Jun 1 09:01:23 UTC 2015


This is an automated email from the git hooks/post-receive script.

eugene-guest pushed a commit to branch master
in repository testng.

commit e92b76af0c6dcd0a39fef3e503dd54151a7c4185
Author: Eugene Zhukov <jevgeni.zh at gmail.com>
Date:   Mon Jun 1 07:22:05 2015 +0000

    New upstream version 6.9.4
---
 .gitignore                                         |   2 +
 .travis.yml                                        |  10 +
 CHANGES.txt                                        |  36 +++
 README                                             |   2 +
 README.md                                          |   7 +
 README.template                                    |   2 +
 build-tests.xml                                    |   2 +-
 build.xml                                          |  14 +-
 debian/changelog                                   |   6 +
 doc/documentation-main.html                        |   8 +-
 doc/index.html                                     |   2 +-
 ivy.xml                                            |   2 +-
 pom-test.xml                                       |  30 ++-
 pom.xml                                            | 260 ++++++++++++++++-----
 src/main/java/org/testng/Assert.java               |  16 +-
 src/main/java/org/testng/DependencyMap.java        |   3 +-
 src/main/java/org/testng/ISuite.java               |   2 +
 src/main/java/org/testng/ITestContext.java         |   3 +-
 src/main/java/org/testng/ITestMethodFinder.java    |  22 +-
 src/main/java/org/testng/ITestNGMethod.java        |   8 +
 src/main/java/org/testng/SuiteRunner.java          |  11 +-
 src/main/java/org/testng/TestClass.java            |   3 +
 src/main/java/org/testng/TestNG.java               |  43 +---
 src/main/java/org/testng/TestRunner.java           |  63 ++++-
 .../java/org/testng/TimeBombSkipException.java     |   8 +-
 .../java/org/testng/annotations/BeforeMethod.java  |   4 +-
 .../java/org/testng/annotations/BeforeSuite.java   |   2 +-
 .../java/org/testng/annotations/Configuration.java |   2 +-
 .../org/testng/collections/CollectionUtils.java    |   4 +-
 .../java/org/testng/collections/ListMultiMap.java  |  77 +-----
 src/main/java/org/testng/collections/Lists.java    |  12 +-
 src/main/java/org/testng/collections/Maps.java     |  12 +-
 src/main/java/org/testng/collections/MultiMap.java | 111 +++++++++
 src/main/java/org/testng/collections/Objects.java  |   6 +-
 .../java/org/testng/collections/SetMultiMap.java   |  73 +-----
 src/main/java/org/testng/collections/Sets.java     |  13 +-
 .../java/org/testng/internal/BaseTestMethod.java   |  21 +-
 src/main/java/org/testng/internal/ClassHelper.java |  11 +-
 src/main/java/org/testng/internal/ClassImpl.java   |  59 ++---
 .../java/org/testng/internal/ClonedMethod.java     |   5 +
 .../org/testng/internal/ConfigurationMethod.java   |   2 +-
 .../org/testng/internal/DataProviderHolder.java    |   4 +-
 .../java/org/testng/internal/DynamicGraph.java     |   6 +-
 .../java/org/testng/internal/FactoryMethod.java    |   2 +-
 .../java/org/testng/internal/InvokedMethod.java    |  17 +-
 src/main/java/org/testng/internal/Invoker.java     |  50 +---
 .../org/testng/internal/MethodGroupsHelper.java    |   2 +-
 .../java/org/testng/internal/MethodHelper.java     |   2 +-
 .../java/org/testng/internal/PackageUtils.java     |  10 +-
 src/main/java/org/testng/internal/Parameters.java  |  34 ++-
 .../org/testng/internal/TestNGClassFinder.java     |  10 +-
 .../java/org/testng/internal/TestNGMethod.java     |  13 +-
 .../org/testng/internal/TestNGMethodFinder.java    |  13 +-
 src/main/java/org/testng/internal/Utils.java       |   6 +-
 .../internal/annotations/AnnotationHelper.java     |  38 +--
 .../internal/annotations/IAnnotationFinder.java    |  10 +-
 .../annotations/JDK15AnnotationFinder.java         |  84 ++++---
 .../java/org/testng/internal/annotations/Sets.java |  17 --
 .../java/org/testng/junit/JUnit4TestMethod.java    |   7 +-
 .../java/org/testng/junit/JUnit4TestRunner.java    |   2 +-
 .../java/org/testng/junit/JUnitTestMethod.java     |   6 +-
 .../java/org/testng/junit/JUnitTestRunner.java     |   2 +-
 .../java/org/testng/remote/SuiteDispatcher.java    |   1 +
 .../java/org/testng/reporters/FailedReporter.java  |   2 +-
 src/main/java/org/testng/reporters/Files.java      |  18 +-
 .../org/testng/reporters/JUnitReportReporter.java  |   8 +-
 .../org/testng/reporters/JUnitXMLReporter.java     |   2 +-
 src/main/java/org/testng/reporters/JqReporter.java |   2 +-
 .../testng/reporters/jq/IgnoredMethodsPanel.java   |   2 +-
 src/main/java/org/testng/reporters/jq/Main.java    |  17 +-
 .../org/testng/reporters/jq/ResultsByClass.java    |   1 +
 src/main/java/org/testng/xml/LaunchSuite.java      |   6 +-
 src/main/java/org/testng/xml/Parameters.java       |   5 +-
 .../java/org/testng/xml/TestNGContentHandler.java  |   4 +
 src/main/java/org/testng/xml/XmlClass.java         |  13 +-
 src/main/java/org/testng/xml/XmlSuite.java         |  14 ++
 src/main/java/org/testng/xml/XmlTest.java          |   5 +
 src/main/java/org/testng/xml/dom/XDom.java         |   3 +-
 src/main/java/testng-1.0.dtd.html                  |   2 +-
 .../org/testng/internal/Version.java               |   2 +-
 src/main/resources/testng-1.0.dtd                  |   3 +-
 src/test/java/org/testng/AssertTest.java           |  70 +++++-
 .../org/testng/internal/MethodInstanceTest.java    |   5 +
 src/test/java/test/EclipseTest.java                |   3 +-
 src/test/java/test/InvokedMethodNameListener.java  |  26 +++
 src/test/java/test/JUnit4Test.java                 |  16 ++
 .../AnnotationTransformerInvocationCountTest.java  |  32 +++
 .../AnnotationTransformerSampleTest.java           |  19 --
 .../AnnotationTransformerTest.java                 |  72 +++++-
 .../test/annotationtransformer/MyTransformer.java  |  34 +--
 src/test/java/test/asserttests/AssertTest.java     |   2 +-
 .../dataprovider/ConstructorInjectionProvider.java |  23 ++
 .../test/dataprovider/FieldInjectionProvider.java  |  19 ++
 .../java/test/dataprovider/NonStaticProvider.java  |  13 ++
 .../dataprovider/StaticDataProviderSampleTest.java |  28 +++
 src/test/java/test/enable/A.java                   |  45 ++++
 src/test/java/test/enable/B.java                   |  46 ++++
 src/test/java/test/enable/C.java                   |  46 ++++
 src/test/java/test/enable/EnableTest.java          |  43 ++++
 .../InvokedMethodListener.java                     |  10 +-
 .../expectedexceptions/ExpectedExceptionsTest.java |   2 +-
 .../test/expectedexceptions/SampleExceptions2.java |   5 +
 src/test/java/test/guice/GuiceParentModule.java    |  10 +
 .../java/test/guice/GuiceParentModuleTest.java     |   6 +
 src/test/java/test/invocationcount/Base.java       |  33 ---
 .../test/invocationcount/DataProviderBase.java     |   2 +-
 .../DataProviderFalseFalseTest.java                |   8 +-
 .../invocationcount/DataProviderFalseTrueTest.java |   8 +-
 .../invocationcount/DataProviderTrueFalseTest.java |   8 +-
 .../invocationcount/DataProviderTrueTrueTest.java  |   8 +-
 .../test/invocationcount/FirstAndLastTimeTest.java | 104 ++++++---
 .../java/test/invocationcount/InvocationBase.java  |   2 +-
 .../InvocationCountFalseFalseTest.java             |   8 +-
 .../InvocationCountFalseTrueTest.java              |   8 +-
 .../InvocationCountTrueFalseTest.java              |   8 +-
 .../InvocationCountTrueTrueTest.java               |   8 +-
 src/test/java/test/invokedmethodlistener/A.java    |   9 +
 src/test/java/test/invokedmethodlistener/B.java    |  13 ++
 src/test/java/test/invokedmethodlistener/C.java    |  13 ++
 .../InvokedMethodListener.java                     |   5 +-
 .../InvokedMethodListenerTest.java                 |  86 ++++++-
 .../InvokedMethodNameListener.java                 |  45 ++++
 .../java/test/invokedmethodlistener/Sample.java    |   4 +
 .../java/test/junit4/JUnit4ParameterizedTest.java  |  57 +++++
 .../SuiteAndConfigurationListenerTest.java         |  58 +++++
 .../java/test/methodinterceptors/Issue392.java     |  17 ++
 .../java/test/methodinterceptors/Issue392Test.java |  43 ++++
 .../java/test/preserveorder/PreserveOrderTest.java |  53 -----
 src/test/java/test/thread/BaseThreadTest.java      |   2 +-
 src/test/resources/testng.xml                      |   7 +
 130 files changed, 1828 insertions(+), 788 deletions(-)

diff --git a/.gitignore b/.gitignore
index c30969b..2c51bc2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,5 @@ src/test/java/test/ignore
 .idea
 testng.iml
 .ant-targets*
+nb-configuration.xml
+/_eclipse/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..45471e9
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,10 @@
+language: java
+
+jdk:
+  - oraclejdk8
+  - oraclejdk7
+  - openjdk7
+
+install: mvn install -Dgpg.skip=true -DskipTests=true -Dmaven.javadoc.skip=true -B -V
+before_script: export TESTNG_VERSION=$(mvn -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.4.0:exec)
+script: mvn -f pom-test.xml test -B
\ No newline at end of file
diff --git a/CHANGES.txt b/CHANGES.txt
index e1e85ec..5ff203d 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,42 @@
 Current
+Added: GITHUB-631: Avoid the static limitation of external DataProvider. (Julien Herr)
+Added: GITHUB-631: Allow to use Guice injection in DataProvider. (Julien Herr)
+Added: Drop support of Java6 and previous.
+Added: GITHUB-617: Allow injection of org.testng.ITestContext into the guice parent module. (Julien Herr)
+Fixed: GITHUB-606: RetryAnalyzer loops endlessly. (Krishnan Mahadevan)
+Fixed: GITHUB-618: Start TestNG from jar cause recursive run of tests from packages in Suite XML without ".*" on the end (Stas Gromov)
+Fixed: GITHUB-639: Typo on preserveOrder (tabei-k & Julien Herr)
+Fixed: GITHUB-632: Typo in doc (Pétur Ingi Egilsson & Julien Herr)
+Fixed: GITHUB-629: InvokedMethod doesn't recognize configuration method (Jan Mewes & Julien Herr)
+Fixed: GITHUB-615: XmlSuite, XmlTest: Time-out tag not preserved (jphollingworth & Julien Herr)
+New: GITHUB-638: Travis CI is used for continuous integration (Julien Herr)
+New: GITHUB-647: SonarQube is used to follow technical debt (Julien Herr)
+Added: GITHUB-616: org.testng.internal.Version will be always up-to-date (Julien Herr)
+Fixed: GITHUB-634: Review of the collections package (Julien Herr)
+Fixed: GITHUB-624: Fixed failure/error inversion in JUnitReportReporter (Jerome Jacob)
+Fixed: GITHUB-545: TestNG running JUnit tests but not reporting all results for parameterized tests (Jonathan Leitschuh & jdillet)
+Fixed: GITHUB-610: CustomizedSuites must be saved using utf-8 encoding (Juha Heljoranta)
+Fixed: GITHUB-602: NoClassDefFoundError in TestNGClassFinder.<init> (aanno)
+Fixed: GITHUB-529: Close InputStream and OuputStream after use (Andrew Gaul)
+Fixed: GITHUB-532: Create the parent directory if it's missing (Ion Savin)
+Fixed: GITHUB-541: Some OSGi manifest fixes (Evgeny Zhuravlev)
+Fixed: GITHUB-657: Fix OSGI Import-Package to make jUnit4 dependency optional (Xavier Fournet)
+Fixed: GITHUB-523: externally synchronize our use of the static SimpleDateFormat (mcosby)
+Fixed: GITHUB-477: Typo in DTD attribute comment (Kamil Szymański)
+Fixed: GITHUB-353: Typo in documentation (Jan Święcki)
+Fixed: GITHUB-656: Upgrade to JCommander 1.48 (Ryan Schmitt)
+Fixed: GITHUB-582: TestNG tests don't pass reliably on JDK8 (Ryan Schmitt)
+New: GITHUB-645: TestNG project on Google Code redirect to GitHub
+Fixed: GITHUB-310: Upgrade Guice (kronar & Julien Herr)
+Fixed: GITHUB-87: @BeforeSuite/@BeforeTest methods happens to be disabled by mistake (romlom & Julien Herr)
+Fixed: GITHUB-425: Wrong invocation order with lastTimeOnly (Rafael Winterhalter & Julien Herr)
+Fixed: GITHUB-417: Expected Exceptions Message fails to match multi-line messages (Michael Diamond)
+
+6.8.21:
+2015/02/02
 
 6.8.15:
+2015/01/14
 
 Fixed: OutOfMemoryException while generating reports.
 Fixed: GITHUB-566: Build does not fail when successPercentage for @Test is not met
diff --git a/README b/README
index 46784a2..ae34ca2 100644
--- a/README
+++ b/README
@@ -1,3 +1,5 @@
+[![Build Status](https://travis-ci.org/cbeust/testng.svg)](https://travis-ci.org/cbeust/testng)
+
 Welcome to TestNG 6.8beta
 
 Please note that even though the .zip distribution contains the TestNG sources,
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8237267
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+[![Build Status](http://img.shields.io/travis/cbeust/testng.svg)](https://travis-ci.org/cbeust/testng)
+[![Dependency Status](https://www.versioneye.com/user/projects/553a031c4e5d2e9408000059/badge.svg)](https://www.versioneye.com/user/projects/553a031c4e5d2e9408000059)
+[![Reference Status](https://www.versioneye.com/java/org.testng:testng/reference_badge.svg)](https://www.versioneye.com/java/org.testng:testng/references)
+[![Maven Central](https://img.shields.io/maven-central/v/org.testng/testng.svg)](https://maven-badges.herokuapp.com/maven-central/org.testng/testng)
+[![License](https://img.shields.io/github/license/cbeust/testng.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
+
+Documentation available at [TestNG's main web site](http://testng.org).
diff --git a/README.template b/README.template
index 06f6950..fe25c22 100644
--- a/README.template
+++ b/README.template
@@ -1,3 +1,5 @@
+[![Build Status](https://travis-ci.org/cbeust/testng.svg)](https://travis-ci.org/cbeust/testng)
+
 Welcome to TestNG ${version}
 
 Please note that even though the .zip distribution contains the TestNG sources,
diff --git a/build-tests.xml b/build-tests.xml
index d0ccfd7..4f51c47 100644
--- a/build-tests.xml
+++ b/build-tests.xml
@@ -34,7 +34,7 @@ TESTNG.REPORT.DIR=${testng.report.dir}
 
     <property name="build.compiler" value="modern"/>
     <javac debug="true"
-           source="1.5"
+           source="1.7"
            classpathref="compile.cp"
            srcdir="${test.dir}"
            destdir="${test.build.dir}"
diff --git a/build.xml b/build.xml
index 7f8059c..a39c816 100644
--- a/build.xml
+++ b/build.xml
@@ -30,16 +30,16 @@
   <!-- ====================================================================== -->
 
   <target name="validate" description="Validates the build environment.">
-    <!-- java greater than 1.5 required to build -->
+    <!-- java greater than 1.6 required to build -->
     <condition property="requiredJavaVersion">
       <or>
+        <equals arg1="${ant.java.version}" arg2="1.9" />
         <equals arg1="${ant.java.version}" arg2="1.8" />
         <equals arg1="${ant.java.version}" arg2="1.7" />
-        <equals arg1="${ant.java.version}" arg2="1.6" />
       </or>
     </condition>
     <fail unless="requiredJavaVersion"
-          message="Java version 1.5 required." />
+          message="Java version 1.7 required." />
     <!-- validate ant version too ... -->
   </target>
 
@@ -100,7 +100,7 @@
     <echo>Src:${src.dir}</echo>
     <javac classpathref="compile2.cp"
            verbose="false"
-           target="1.5"
+           target="1.7"
            debug="true"
            optimize="${optimize}"
            destdir="${build.dir}">
@@ -168,7 +168,7 @@
   </target>
 
   <target name="javadocs-current">
-    <javadoc additionalparam="-quiet" destdir="javadocs" source="1.5" windowtitle="TestNG"
+    <javadoc additionalparam="-quiet" destdir="javadocs" source="1.7" windowtitle="TestNG"
       classpath="${testng.jar}" classpathref="compile2.cp" verbose="false">
       <fileset dir="${src.dir}" defaultexcludes="yes">
         <include name="org/testng/*.java" />
@@ -327,8 +327,8 @@
   </target>
 
   <target name="update-readme">
-    <copy file="README.template" tofile="README" />
-    <replace file="README" token="${version}" value="${testng.version}" />
+    <copy file="README.template" tofile="README.md" />
+    <replace file="README.md" token="${version}" value="${testng.version}" />
     <touch file="TESTNG-${testng.version}" />
   </target>
       
diff --git a/debian/changelog b/debian/changelog
index a90ccae..fecfab8 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+testng (6.9.4-1) unstable; urgency=medium
+
+  * New upstream release
+
+ -- Eugene Zhukov <jevgeni.zh at gmail.com>  Mon, 01 Jun 2015 07:21:10 +0000
+
 testng (6.8.21-1) unstable; urgency=low
 
   * New upstream release
diff --git a/doc/documentation-main.html b/doc/documentation-main.html
index 36a661a..e816bb3 100644
--- a/doc/documentation-main.html
+++ b/doc/documentation-main.html
@@ -1227,7 +1227,7 @@ This name must correspond to a method on the same class annotated with <tt>@Data
 with a matching name.
 
 <p>
-By default, the data provider will be looked for in the current test class or one of its base classes.  If you want to put your data provider in a different class, it needs to be a static method and you specify the class where it can be found in the <tt>dataProviderClass</tt> attribute:
+By default, the data provider will be looked for in the current test class or one of its base classes.  If you want to put your data provider in a different class, it needs to be a static method or a class with a non-arg constructor, and you specify the class where it can be found in the <tt>dataProviderClass</tt> attribute:
 
 <h3 class="sourcetitle">StaticProvider.java</h3>
 <pre class="brush: java">
@@ -1236,7 +1236,7 @@ public class StaticProvider {
   public static Object[][] createData() {
     return new Object[][] {
       new Object[] { new Integer(42) }
-    }
+    };
   }
 }
 
@@ -1248,6 +1248,8 @@ public class MyTest {
 }
 </pre>
 
+The data provider supports injection too. TestNG will use the test context for the injection.
+
 The Data Provider method can return one of the following two types:
 
 <ul>
@@ -1379,7 +1381,7 @@ public void serverStartedOk() {}
 @Test(groups = { "init" })
 public void initEnvironment() {}
 
- at Test(dependsOnGroups = { "init.* })
+ at Test(dependsOnGroups = { "init.*" })
 public void method1() {}
 </pre>
 
diff --git a/doc/index.html b/doc/index.html
index cae6a27..e2d65dd 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -179,7 +179,7 @@ start test-output\index.html (on Windows)
 </pre>
 
 <h3><a name="requirements">Requirements</a></h3>
-<p>TestNG requires JDK 5 or higher.</p>
+<p>TestNG requires JDK 7 or higher.</p>
 
 <h3><a name="mailing-lists">Mailing-lists</a></h3>
 
diff --git a/ivy.xml b/ivy.xml
index 64c3def..cceec5d 100644
--- a/ivy.xml
+++ b/ivy.xml
@@ -7,7 +7,7 @@
     <dependency org="org.beanshell" name="bsh" rev="2.0b4" />
     <dependency org="com.google.inject" name="guice" rev="2.0" />
     <dependency org="org.yaml" name="snakeyaml" rev="1.12" />
-    <dependency org="com.beust" name="jcommander" rev="1.27" />
+    <dependency org="com.beust" name="jcommander" rev="1.48" />
   </dependencies>
 </ivy-module>
 
diff --git a/pom-test.xml b/pom-test.xml
index bf83d94..3a8f643 100644
--- a/pom-test.xml
+++ b/pom-test.xml
@@ -35,6 +35,10 @@
     <version>3</version>
   </parent>
 
+  <properties>
+    <testng.version>6.8.22-SNAPSHOT</testng.version>
+  </properties>
+
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
@@ -62,7 +66,7 @@
     <dependency>
       <groupId>com.beust</groupId>
       <artifactId>jcommander</artifactId>
-      <version>1.27</version>
+      <version>1.48</version>
     </dependency>
     <dependency>
         <groupId>org.yaml</groupId>
@@ -72,9 +76,15 @@
     <dependency>
       <groupId>org.testng</groupId>
       <artifactId>testng</artifactId>
-      <version>6.8.13</version>
+      <version>${testng.version}</version>
       <scope>test</scope>
     </dependency>
+      <dependency>
+        <groupId>org.assertj</groupId>
+        <artifactId>assertj-core</artifactId>
+        <version>2.0.0</version>
+        <scope>test</scope>
+    </dependency>
    </dependencies>
     
   <build>
@@ -86,7 +96,9 @@
         <artifactId>maven-compiler-plugin</artifactId>
         <version>3.1</version>
         <configuration>
-          <source>1.5</source>
+          <source>1.7</source>
+          <target>1.7</target>
+          <skipMain>true</skipMain> <!-- Sources are already compiled -->
         </configuration>
       </plugin>
 
@@ -110,4 +122,16 @@
 
     </plugins>
   </build>
+  <profiles>
+    <profile>
+      <activation>
+        <property>
+          <name>env.TESTNG_VERSION</name>
+        </property>
+      </activation>
+      <properties>
+        <testng.version>${env.TESTNG_VERSION}</testng.version>
+      </properties>
+    </profile>
+  </profiles>
 </project>
diff --git a/pom.xml b/pom.xml
index 9fb0ad4..a11d520 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
   <artifactId>testng</artifactId>
   <packaging>jar</packaging>
   <name>TestNG</name>
-  <version>6.8.21</version>
+  <version>6.9.4</version>
   <description>TestNG is a testing framework.</description>
   <url>http://testng.org</url>
     
@@ -38,54 +38,12 @@
     <version>3</version>
   </parent>
 
-  <profiles>
-    <profile>
-      <!-- When activated, download dependencies from the snapshot repo -->
-      <id>snapshot</id>
-
-      <repositories>
-        <repository>
-          <id>nexus-snapshot-repository</id>
-          <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
-        </repository>
-      </repositories>
-
-      <dependencies>
-        <dependency>
-            <groupId>org.apache.ant</groupId>
-            <artifactId>ant</artifactId>
-            <version>1.7.0</version>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>4.11</version>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.beanshell</groupId>
-            <artifactId>bsh</artifactId>
-            <version>2.0b4</version>
-<!--
-            <scope>provided</scope>
--->
-        </dependency>
-        <dependency>
-          <groupId>com.google.inject</groupId>
-           <artifactId>guice</artifactId>
-           <version>2.0</version>
-           <scope>provided</scope>
-        </dependency>
-        <dependency>
-          <groupId>com.beust</groupId>
-          <artifactId>jcommander</artifactId>
-          <version>1.5</version>
-        </dependency>
-      </dependencies>
-      
-    </profile>
-  </profiles>
+  <distributionManagement>
+    <repository>
+      <id>bintray</id>
+      <url>https://api.bintray.com/maven/cbeust/maven/testng</url>
+    </repository>
+  </distributionManagement>
 
   <dependencies>
     <dependency>
@@ -114,14 +72,15 @@
     <dependency>
       <groupId>com.google.inject</groupId>
       <artifactId>guice</artifactId>
-      <version>2.0</version>
+      <version>4.0</version>
+      <classifier>no_aop</classifier>
       <scope>provided</scope>
     </dependency>
 
     <dependency>
       <groupId>com.beust</groupId>
       <artifactId>jcommander</artifactId>
-      <version>1.27</version>
+      <version>1.48</version>
     </dependency>
 
 	  <dependency>
@@ -131,11 +90,64 @@
       <optional>true</optional>
 	  </dependency>
 
-  </dependencies>    
-    
+    <dependency>
+      <groupId>org.assertj</groupId>
+      <artifactId>assertj-core</artifactId>
+      <version>2.0.0</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>     
+  
+  <properties>
+  	<version.build.directory>${project.build.directory}/generated-sources/version</version.build.directory>
+  </properties>
+  
   <build>
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+        <includes>
+          <include>**/Version.java</include>
+        </includes>
+        <filtering>true</filtering>
+        <targetPath>${version.build.directory}</targetPath>
+      </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
     <plugins>
 
+      <!-- Release for bintray -->
+
+      <plugin>
+        <artifactId>maven-release-plugin</artifactId>
+        <configuration>
+          <useReleaseProfile>false</useReleaseProfile>
+          <releaseProfiles>release</releaseProfiles>
+          <autoVersionSubmodules>true</autoVersionSubmodules>
+        </configuration>
+      </plugin>
+
+      <!-- Generating Javadoc -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>2.10.3</version>
+        <configuration>
+          <failOnError>false</failOnError>
+          <excludePackageNames>*internal</excludePackageNames>
+         </configuration>
+        <executions>
+          <execution>
+            <id>attach-javadocs</id>
+              <goals>
+                <goal>jar</goal>
+              </goals>
+            </execution>
+        </executions>
+      </plugin>
+
       <!-- Bundle sources -->
 
       <plugin>
@@ -158,7 +170,8 @@
         <artifactId>maven-compiler-plugin</artifactId>
         <version>3.1</version>
         <configuration>
-          <source>1.5</source>
+          <source>1.7</source>
+          <target>1.7</target>
         </configuration>
       </plugin>
 
@@ -170,6 +183,29 @@
         <configuration>
           <encoding>UTF-8</encoding>
         </configuration>
+        <executions>
+          <execution>
+            <phase>process-sources</phase>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <version>1.9.1</version>
+        <executions>
+          <execution>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${version.build.directory}</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
       </plugin>
 
       <!-- OSGi manifest creation -->
@@ -192,8 +228,11 @@
                   com.beust.jcommander.*;version="[1.7.0,3.0.0)";resolution:=optional,
                   com.google.inject.*;version="[1.2,1.3)";resolution:=optional,
                   junit.framework;version="[3.8.1, 5.0.0)";resolution:=optional,
+                  org.junit.*;resolution:=optional,
                   org.apache.tools.ant.*;version="[1.7.0, 2.0.0)";resolution:=optional,
                   org.yaml.*;version="[1.6,2.0)";resolution:=optional,
+                  !com.beust.testng,
+                  !org.testng.*,
                   !com.sun.*,
                   *
                 </Import-Package>
@@ -215,16 +254,6 @@
         </configuration>
       </plugin>
 
-      <!-- Generating Javadoc -->
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-javadoc-plugin</artifactId>
-        <version>2.7</version>
-        <configuration>
-          <excludePackageNames>*.internal</excludePackageNames>
-        </configuration>
-      </plugin>
-
       <!-- Tests (skipping) -->
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
@@ -254,4 +283,107 @@
     </plugins>
 
   </build>
+
+
+  <profiles>
+
+    <!-- bintray profile -->
+
+    <profile>
+      <id>bintray</id>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-source-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>attach-sources</id>
+                <goals>
+                  <goal>jar</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <version>2.10.3</version>
+            <configuration>
+              <failOnError>false</failOnError>
+              <excludePackageNames>*internal</excludePackageNames>
+             </configuration>
+            <executions>
+              <execution>
+                <id>attach-javadocs</id>
+                  <goals>
+                    <goal>jar</goal>
+                  </goals>
+                </execution>
+            </executions>
+          </plugin>
+<!-- 
+          <plugin>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>attach-javadocs</id>
+                <goals>
+                  <goal>jar</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+ -->
+          </plugins>
+      </build>
+    </profile>
+
+    <profile>
+      <!-- When activated, download dependencies from the snapshot repo -->
+      <id>snapshot</id>
+
+      <repositories>
+        <repository>
+          <id>nexus-snapshot-repository</id>
+          <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
+        </repository>
+      </repositories>
+
+      <dependencies>
+        <dependency>
+            <groupId>org.apache.ant</groupId>
+            <artifactId>ant</artifactId>
+            <version>1.7.0</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.11</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.beanshell</groupId>
+            <artifactId>bsh</artifactId>
+            <version>2.0b4</version>
+<!--
+            <scope>provided</scope>
+-->
+        </dependency>
+        <dependency>
+          <groupId>com.google.inject</groupId>
+           <artifactId>guice</artifactId>
+           <version>2.0</version>
+           <scope>provided</scope>
+        </dependency>
+        <dependency>
+          <groupId>com.beust</groupId>
+          <artifactId>jcommander</artifactId>
+          <version>1.48</version>
+        </dependency>
+      </dependencies>
+      
+    </profile>
+  </profiles>
+
 </project>
diff --git a/src/main/java/org/testng/Assert.java b/src/main/java/org/testng/Assert.java
index c945696..d57dceb 100644
--- a/src/main/java/org/testng/Assert.java
+++ b/src/main/java/org/testng/Assert.java
@@ -112,13 +112,15 @@ public class Assert {
     if((expected == null) && (actual == null)) {
       return;
     }
-    if(expected != null) {
-      if (expected.getClass().isArray()) {
-        assertArrayEquals(actual, expected, message);
-        return;
-      } else if (expected.equals(actual)) {
-        return;
-      }
+    if(expected == null ^ actual == null) {
+      failNotEquals(actual, expected, message);
+    }
+    if (expected.getClass().isArray()) {
+       assertArrayEquals(actual, expected, message);
+       return;
+    }
+    if (expected.equals(actual) && actual.equals(expected)) {
+       return;
     }
     failNotEquals(actual, expected, message);
   }
diff --git a/src/main/java/org/testng/DependencyMap.java b/src/main/java/org/testng/DependencyMap.java
index 5318306..ae4f9ed 100644
--- a/src/main/java/org/testng/DependencyMap.java
+++ b/src/main/java/org/testng/DependencyMap.java
@@ -29,8 +29,7 @@ public class DependencyMap {
   }
 
   public List<ITestNGMethod> getMethodsThatBelongTo(String group, ITestNGMethod fromMethod) {
-    List<String> keys = m_groups.getKeys();
-    Set<String> uniqueKeys = Sets.newHashSet(keys);
+    Set<String> uniqueKeys = m_groups.keySet();
 
     List<ITestNGMethod> result = Lists.newArrayList();
 
diff --git a/src/main/java/org/testng/ISuite.java b/src/main/java/org/testng/ISuite.java
index 3ab5ed0..e5e3380 100755
--- a/src/main/java/org/testng/ISuite.java
+++ b/src/main/java/org/testng/ISuite.java
@@ -46,6 +46,8 @@ public interface ISuite extends IAttributes {
 
   public String getParentModule();
 
+  public String getGuiceStage();
+
   /**
    * @return The value of this parameter, or null if none was specified.
    */
diff --git a/src/main/java/org/testng/ITestContext.java b/src/main/java/org/testng/ITestContext.java
index ccb68cf..fe6f35d 100644
--- a/src/main/java/org/testng/ITestContext.java
+++ b/src/main/java/org/testng/ITestContext.java
@@ -3,6 +3,7 @@ package org.testng;
 import com.google.inject.Injector;
 import com.google.inject.Module;
 
+import org.testng.internal.ClassImpl;
 import org.testng.xml.XmlTest;
 
 import java.util.Collection;
@@ -118,8 +119,8 @@ public interface ITestContext extends IAttributes {
   public XmlTest getCurrentXmlTest();
 
   public List<Module> getGuiceModules(Class<? extends Module> cls);
-  public void addGuiceModule(Class<? extends Module> cls, Module module);
 
   public Injector getInjector(List<Module> moduleInstances);
+  Injector getInjector(IClass iClass);
   public void addInjector(List<Module> moduleInstances, Injector injector);
 }
diff --git a/src/main/java/org/testng/ITestMethodFinder.java b/src/main/java/org/testng/ITestMethodFinder.java
index e175657..9cecd35 100755
--- a/src/main/java/org/testng/ITestMethodFinder.java
+++ b/src/main/java/org/testng/ITestMethodFinder.java
@@ -20,53 +20,53 @@ public interface ITestMethodFinder {
   /**
    * @return All the applicable test methods.
    */
-  ITestNGMethod[] getTestMethods(Class cls, XmlTest xmlTest);
+  ITestNGMethod[] getTestMethods(Class<?> cls, XmlTest xmlTest);
 
   /**
    * @return All the methods that should be invoked
    * before a test method is invoked.
    */
-  ITestNGMethod[] getBeforeTestMethods(Class cls);
+  ITestNGMethod[] getBeforeTestMethods(Class<?> cls);
 
   /**
    * @return All the methods that should be invoked
    * after a test method completes.
    */
-  ITestNGMethod[] getAfterTestMethods(Class cls);
+  ITestNGMethod[] getAfterTestMethods(Class<?> cls);
 
   /**
    * @return All the methods that should be invoked
    * after the test class has been created and before
    * any of its test methods is invoked.
    */
-  ITestNGMethod[] getBeforeClassMethods(Class cls);
+  ITestNGMethod[] getBeforeClassMethods(Class<?> cls);
 
   /**
    * @return All the methods that should be invoked
    * after the test class has been created and after
    * all its test methods have completed.
    */
-  ITestNGMethod[] getAfterClassMethods(Class cls);
+  ITestNGMethod[] getAfterClassMethods(Class<?> cls);
 
   /**
    * @return All the methods that should be invoked
    * before the suite starts running.
    */
-  ITestNGMethod[] getBeforeSuiteMethods(Class cls);
+  ITestNGMethod[] getBeforeSuiteMethods(Class<?> cls);
 
   /**
    * @return All the methods that should be invoked
    * after the suite has run all its tests.
    */
-  ITestNGMethod[] getAfterSuiteMethods(Class cls);
+  ITestNGMethod[] getAfterSuiteMethods(Class<?> cls);
 
-  ITestNGMethod[] getBeforeTestConfigurationMethods(Class testClass);
+  ITestNGMethod[] getBeforeTestConfigurationMethods(Class<?> testClass);
 
-  ITestNGMethod[] getAfterTestConfigurationMethods(Class testClass);
+  ITestNGMethod[] getAfterTestConfigurationMethods(Class<?> testClass);
 
-  ITestNGMethod[] getBeforeGroupsConfigurationMethods(Class testClass);
+  ITestNGMethod[] getBeforeGroupsConfigurationMethods(Class<?> testClass);
 
-  ITestNGMethod[] getAfterGroupsConfigurationMethods(Class testClass);
+  ITestNGMethod[] getAfterGroupsConfigurationMethods(Class<?> testClass);
 
 
 }
diff --git a/src/main/java/org/testng/ITestNGMethod.java b/src/main/java/org/testng/ITestNGMethod.java
index b91426d..f0db926 100755
--- a/src/main/java/org/testng/ITestNGMethod.java
+++ b/src/main/java/org/testng/ITestNGMethod.java
@@ -165,6 +165,14 @@ public interface ITestNGMethod extends Comparable, Serializable, Cloneable {
   void setInvocationCount(int count);
 
   /**
+   * @return the total number of thimes this method needs to be invoked, including possible
+   *         clones of this method - this is relevant when threadPoolSize is bigger than 1
+   *         where each clone of this method is only invoked once individually, i.e.
+   *         {@link org.testng.ITestNGMethod#getInvocationCount()} would always return 1.
+   */
+  int getTotalInvocationCount();
+
+  /**
    * @return the success percentage for this method (between 0 and 100).
    */
   int getSuccessPercentage();
diff --git a/src/main/java/org/testng/SuiteRunner.java b/src/main/java/org/testng/SuiteRunner.java
index d1fa95c..fef2fa5 100644
--- a/src/main/java/org/testng/SuiteRunner.java
+++ b/src/main/java/org/testng/SuiteRunner.java
@@ -239,6 +239,11 @@ public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener
     return m_suite.getParentModule();
   }
 
+  @Override
+  public String getGuiceStage() {
+    return m_suite.getGuiceStage();
+  }
+
   public Injector getParentInjector() {
     return m_parentInjector;
   }
@@ -334,6 +339,10 @@ public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener
     m_reporters.add(listener);
   }
 
+  void addConfigurationListener(IConfigurationListener listener) {
+    m_configuration.addConfigurationListener(listener);
+  }
+
   public List<IReporter> getReporters() {
     return m_reporters;
   }
@@ -405,7 +414,7 @@ public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener
       addReporter((IReporter) listener);
     }
     if (listener instanceof IConfigurationListener) {
-      m_configuration.addConfigurationListener((IConfigurationListener) listener);
+      addConfigurationListener((IConfigurationListener) listener);
     }
   }
 
diff --git a/src/main/java/org/testng/TestClass.java b/src/main/java/org/testng/TestClass.java
index 3f60a30..213ce1a 100755
--- a/src/main/java/org/testng/TestClass.java
+++ b/src/main/java/org/testng/TestClass.java
@@ -244,4 +244,7 @@ class TestClass extends NoOpTestClass implements ITestClass {
         .toString();
   }
 
+  public IClass getIClass() {
+    return m_iClass;
+  }
 }
\ No newline at end of file
diff --git a/src/main/java/org/testng/TestNG.java b/src/main/java/org/testng/TestNG.java
index 35844c1..8f6ca1d 100644
--- a/src/main/java/org/testng/TestNG.java
+++ b/src/main/java/org/testng/TestNG.java
@@ -1,15 +1,9 @@
 package org.testng;
 
-import static org.testng.internal.Utils.defaultIfStringEmpty;
-import static org.testng.internal.Utils.isStringEmpty;
-import static org.testng.internal.Utils.isStringNotEmpty;
-
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -17,6 +11,7 @@ import java.util.Collection;
 import java.util.Enumeration;
 import java.util.List;
 import java.util.Map;
+import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
@@ -28,6 +23,7 @@ import javax.xml.parsers.ParserConfigurationException;
 import org.testng.annotations.ITestAnnotation;
 import org.testng.collections.Lists;
 import org.testng.collections.Maps;
+import org.testng.collections.Sets;
 import org.testng.internal.ClassHelper;
 import org.testng.internal.Configuration;
 import org.testng.internal.DynamicGraph;
@@ -40,7 +36,6 @@ import org.testng.internal.Version;
 import org.testng.internal.annotations.DefaultAnnotationTransformer;
 import org.testng.internal.annotations.IAnnotationFinder;
 import org.testng.internal.annotations.JDK15AnnotationFinder;
-import org.testng.internal.annotations.Sets;
 import org.testng.internal.thread.graph.GraphThreadPoolExecutor;
 import org.testng.internal.thread.graph.IThreadWorkerFactory;
 import org.testng.internal.thread.graph.SuiteWorkerFactory;
@@ -67,6 +62,10 @@ import org.xml.sax.SAXException;
 import com.beust.jcommander.JCommander;
 import com.beust.jcommander.ParameterException;
 
+import static org.testng.internal.Utils.defaultIfStringEmpty;
+import static org.testng.internal.Utils.isStringEmpty;
+import static org.testng.internal.Utils.isStringNotEmpty;
+
 /**
  * This class is the main entry point for running tests in the TestNG framework.
  * Users can create their own TestNG object and invoke it in many different
@@ -812,7 +811,7 @@ public class TestNG {
 
       for (XmlSuite s : m_cmdlineSuites) {
         for (XmlTest t : s.getTests()) {
-          t.setPreserveOrder(m_preserveOrder ? "true " : "false");
+          t.setPreserveOrder(String.valueOf(m_preserveOrder));
         }
         m_suites.add(s);
         if (m_groupByInstances != null) {
@@ -941,37 +940,13 @@ public class TestNG {
    * Using reflection to remain Java 5 compliant.
    */
   private void addServiceLoaderListeners() {
-    try {
-      Class c = Class.forName("java.util.ServiceLoader");
-      List<Object> parameters = Lists.newArrayList();
-      parameters.add(ITestNGListener.class);
-      Method loadMethod;
-      if (m_serviceLoaderClassLoader != null) {
-        parameters.add(m_serviceLoaderClassLoader);
-        loadMethod = c.getMethod("load", Class.class, ClassLoader.class);
-      } else {
-        loadMethod = c.getMethod("load", Class.class);
-      }
       Iterable<ITestNGListener> loader =
-          (Iterable<ITestNGListener>) loadMethod.invoke(c, parameters.toArray());
-//      Object loader = c.
-//      ServiceLoader<ITestNGListener> loader = m_serviceLoaderClassLoader != null
-//      ? ServiceLoader.load(ITestNGListener.class, m_serviceLoaderClassLoader)
-//          : ServiceLoader.load(ITestNGListener.class);
+          ServiceLoader.load(ITestNGListener.class, m_serviceLoaderClassLoader);
       for (ITestNGListener l : loader) {
         Utils.log("[TestNG]", 2, "Adding ServiceLoader listener:" + l);
         addListener(l);
         addServiceLoaderListener(l);
       }
-    } catch (ClassNotFoundException ex) {
-      // Ignore
-    } catch(NoSuchMethodException ex) {
-      // Ignore
-    } catch(IllegalAccessException ex) {
-      // Ignore
-    } catch(InvocationTargetException ex) {
-      // Ignore
-    }
   }
 
   /**
@@ -1313,7 +1288,7 @@ public class TestNG {
     }
 
     for (IConfigurationListener cl : m_configuration.getConfigurationListeners()) {
-      result.addListener(cl);
+      result.addConfigurationListener(cl);
     }
 
     return result;
diff --git a/src/main/java/org/testng/TestRunner.java b/src/main/java/org/testng/TestRunner.java
index 49daa5f..2772445 100644
--- a/src/main/java/org/testng/TestRunner.java
+++ b/src/main/java/org/testng/TestRunner.java
@@ -1,5 +1,6 @@
 package org.testng;
 
+import java.lang.annotation.Annotation;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -12,11 +13,14 @@ import java.util.Set;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 
+import org.testng.annotations.Guice;
 import org.testng.collections.ListMultiMap;
 import org.testng.collections.Lists;
 import org.testng.collections.Maps;
+import org.testng.collections.Sets;
 import org.testng.internal.Attributes;
 import org.testng.internal.ClassHelper;
+import org.testng.internal.ClassImpl;
 import org.testng.internal.ClassInfoMap;
 import org.testng.internal.ConfigurationGroupMethods;
 import org.testng.internal.Constants;
@@ -37,9 +41,9 @@ import org.testng.internal.TestNGClassFinder;
 import org.testng.internal.TestNGMethodFinder;
 import org.testng.internal.Utils;
 import org.testng.internal.XmlMethodSelector;
+import org.testng.internal.annotations.AnnotationHelper;
 import org.testng.internal.annotations.IAnnotationFinder;
 import org.testng.internal.annotations.IListeners;
-import org.testng.internal.annotations.Sets;
 import org.testng.internal.thread.ThreadUtil;
 import org.testng.internal.thread.graph.GraphThreadPoolExecutor;
 import org.testng.internal.thread.graph.IThreadWorkerFactory;
@@ -890,7 +894,7 @@ public class TestRunner
     for (ITestNGMethod m : methods) {
       lmm.put(m.getInstance(), m);
     }
-    for (Map.Entry<Object, List<ITestNGMethod>> es : lmm.getEntrySet()) {
+    for (Map.Entry<Object, List<ITestNGMethod>> es : lmm.entrySet()) {
       List<IMethodInstance> methodInstances = Lists.newArrayList();
       for (ITestNGMethod m : es.getValue()) {
         methodInstances.add(new MethodInstance(m));
@@ -1098,7 +1102,7 @@ public class TestRunner
       ListMultiMap<ITestNGMethod, ITestNGMethod> classDependencies
           = createClassDependencies(methods, getCurrentXmlTest());
 
-      for (Map.Entry<ITestNGMethod, List<ITestNGMethod>> es : classDependencies.getEntrySet()) {
+      for (Map.Entry<ITestNGMethod, List<ITestNGMethod>> es : classDependencies.entrySet()) {
         for (ITestNGMethod dm : es.getValue()) {
           result.addEdge(dm, es.getKey());
         }
@@ -1110,7 +1114,7 @@ public class TestRunner
       ListMultiMap<ITestNGMethod, ITestNGMethod> instanceDependencies
           = createInstanceDependencies(methods, getCurrentXmlTest());
 
-      for (Map.Entry<ITestNGMethod, List<ITestNGMethod>> es : instanceDependencies.getEntrySet()) {
+      for (Map.Entry<ITestNGMethod, List<ITestNGMethod>> es : instanceDependencies.entrySet()) {
         for (ITestNGMethod dm : es.getValue()) {
           result.addEdge(dm, es.getKey());
         }
@@ -1131,7 +1135,7 @@ public class TestRunner
 
     ListMultiMap<ITestNGMethod, ITestNGMethod> result = Maps.newListMultiMap();
     Object previousInstance = null;
-    for (Map.Entry<Object, List<ITestNGMethod>> es : instanceMap.getEntrySet()) {
+    for (Map.Entry<Object, List<ITestNGMethod>> es : instanceMap.entrySet()) {
       if (previousInstance == null) {
         previousInstance = es.getKey();
       } else {
@@ -1592,8 +1596,7 @@ public class TestRunner
     return result;
   }
 
-  @Override
-  public void addGuiceModule(Class<? extends Module> cls, Module module) {
+  private void addGuiceModule(Class<? extends Module> cls, Module module) {
     m_guiceModules.put(cls, module);
   }
 
@@ -1605,6 +1608,52 @@ public class TestRunner
   }
 
   @Override
+  public Injector getInjector(IClass iClass) {
+    Annotation annotation = AnnotationHelper.findAnnotationSuperClasses(Guice.class, iClass.getRealClass());
+    if (annotation == null) return null;
+    if (iClass instanceof TestClass) {
+      iClass = ((TestClass)iClass).getIClass();
+    }
+    if (!(iClass instanceof ClassImpl)) return null;
+    Injector parentInjector = ((ClassImpl)iClass).getParentInjector();
+
+    Guice guice = (Guice) annotation;
+    List<Module> moduleInstances = Lists.newArrayList(getModules(guice, parentInjector, iClass.getRealClass()));
+
+    // Reuse the previous injector, if any
+    Injector injector = getInjector(moduleInstances);
+    if (injector == null) {
+      injector = parentInjector.createChildInjector(moduleInstances);
+      addInjector(moduleInstances, injector);
+    }
+    return injector;
+  }
+
+  private Module[] getModules(Guice guice, Injector parentInjector, Class<?> testClass) {
+    List<Module> result = Lists.newArrayList();
+    for (Class<? extends Module> moduleClass : guice.modules()) {
+      List<Module> modules = getGuiceModules(moduleClass);
+      if (modules != null && modules.size() > 0) {
+        result.addAll(modules);
+      } else {
+        Module instance = parentInjector.getInstance(moduleClass);
+        result.add(instance);
+        addGuiceModule(moduleClass, instance);
+      }
+    }
+    Class<? extends IModuleFactory> factory = guice.moduleFactory();
+    if (factory != IModuleFactory.class) {
+      IModuleFactory factoryInstance = parentInjector.getInstance(factory);
+      Module moduleClass = factoryInstance.createModule(this, testClass);
+      if (moduleClass != null) {
+        result.add(moduleClass);
+      }
+    }
+
+    return result.toArray(new Module[result.size()]);
+  }
+
+  @Override
   public void addInjector(List<Module> moduleInstances, Injector injector) {
     m_injectors.put(moduleInstances, injector);
   }
diff --git a/src/main/java/org/testng/TimeBombSkipException.java b/src/main/java/org/testng/TimeBombSkipException.java
index 96dcb2d..1777233 100755
--- a/src/main/java/org/testng/TimeBombSkipException.java
+++ b/src/main/java/org/testng/TimeBombSkipException.java
@@ -181,8 +181,12 @@ public class TimeBombSkipException extends SkipException {
 
   private void initExpireDate(String date) {
     try {
-      Date d= m_inFormat.parse(date);
-      initExpireDate(d);
+      // SimpleDateFormat is not thread-safe, and m_inFormat 
+      // is, by default, connected to the static SDF variable
+      synchronized( m_inFormat ){
+        Date d = m_inFormat.parse(date);
+        initExpireDate(d);
+      }
     }
     catch(ParseException pex) {
       throw new TestNGException("Cannot parse date:" + date + " using pattern: " + m_inFormat, pex);
diff --git a/src/main/java/org/testng/annotations/BeforeMethod.java b/src/main/java/org/testng/annotations/BeforeMethod.java
index 873705f..a7356f5 100755
--- a/src/main/java/org/testng/annotations/BeforeMethod.java
+++ b/src/main/java/org/testng/annotations/BeforeMethod.java
@@ -59,12 +59,12 @@ public @interface BeforeMethod {
 
   /**
    * The description for this method.  The string used will appear in the
-   * HTML report and also on standard output if verbose >= 2.
+   * HTML report and also on standard output if verbose >= 2.
    */
   public String description() default "";
 
   /**
-   * If true and the @Test method about to be run has an invocationCount > 1, this
+   * If true and the @Test method about to be run has an invocationCount > 1, this
    * BeforeMethod will only be invoked once (before the first test invocation).
    */
   public boolean firstTimeOnly() default false;
diff --git a/src/main/java/org/testng/annotations/BeforeSuite.java b/src/main/java/org/testng/annotations/BeforeSuite.java
index 7bc118e..e811096 100755
--- a/src/main/java/org/testng/annotations/BeforeSuite.java
+++ b/src/main/java/org/testng/annotations/BeforeSuite.java
@@ -59,7 +59,7 @@ public @interface BeforeSuite {
 
   /**
    * The description for this method.  The string used will appear in the
-   * HTML report and also on standard output if verbose >= 2.
+   * HTML report and also on standard output if verbose >= 2.
    */
   public String description() default "";
 
diff --git a/src/main/java/org/testng/annotations/Configuration.java b/src/main/java/org/testng/annotations/Configuration.java
index 7c25d33..4c806d4 100755
--- a/src/main/java/org/testng/annotations/Configuration.java
+++ b/src/main/java/org/testng/annotations/Configuration.java
@@ -136,7 +136,7 @@ public @interface Configuration {
 
   /**
    * The description for this method.  The string used will appear in the
-   * HTML report and also on standard output if verbose >= 2.
+   * HTML report and also on standard output if verbose >= 2.
    */
   public String description() default "";
 }
diff --git a/src/main/java/org/testng/collections/CollectionUtils.java b/src/main/java/org/testng/collections/CollectionUtils.java
index 63f38e8..cdf2bce 100644
--- a/src/main/java/org/testng/collections/CollectionUtils.java
+++ b/src/main/java/org/testng/collections/CollectionUtils.java
@@ -3,7 +3,9 @@ package org.testng.collections;
 import java.util.Collection;
 import java.util.Map;
 
-public class CollectionUtils {
+public final class CollectionUtils {
+
+  private CollectionUtils() {}
 
   public static boolean hasElements(Collection<?> c) {
     return c != null && ! c.isEmpty();
diff --git a/src/main/java/org/testng/collections/ListMultiMap.java b/src/main/java/org/testng/collections/ListMultiMap.java
index 71b5cdc..5750c84 100644
--- a/src/main/java/org/testng/collections/ListMultiMap.java
+++ b/src/main/java/org/testng/collections/ListMultiMap.java
@@ -1,87 +1,20 @@
 package org.testng.collections;
 
 
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
 
 /**
  * A container to hold lists indexed by a key.
  */
-public class ListMultiMap<K, V> {
-  private Map<K, List<V>> m_objects = Maps.newHashMap();
-
-  public void put(K key, V method) {
-    List<V> l = m_objects.get(key);
-    if (l == null) {
-      l = Lists.newArrayList();
-      m_objects.put(key, l);
-    }
-    l.add(method);
-  }
-
-  public List<V> get(K key) {
-    return m_objects.get(key);
-  }
-
-  public List<K> getKeys() {
-    return new ArrayList(m_objects.keySet());
-//    List<K> result = new ArrayList<K>();
-//    for (K k : m_objects.keySet()) {
-//      result.add(k);
-//    }
-//    Collections.sort(result);
-//    return result;
-  }
-
-  public boolean containsKey(K k) {
-    return m_objects.containsKey(k);
-  }
+public class ListMultiMap<K, V> extends MultiMap<K, V, List<V>> {
 
   @Override
-  public String toString() {
-    StringBuilder result = new StringBuilder();
-    List<K> indices = getKeys();
-//    Collections.sort(indices);
-    for (K i : indices) {
-      result.append("\n    ").append(i).append(" <-- ");
-      for (Object o : m_objects.get(i)) {
-        result.append(o).append(" ");
-      }
-    }
-    return result.toString();
-  }
-
-  public boolean isEmpty() {
-    return m_objects.size() == 0;
-  }
-
-  public int getSize() {
-    return m_objects.size();
-  }
-
-  public List<V> remove(K key) {
-    return m_objects.remove(key);
-  }
-
-  public Set<Entry<K, List<V>>> getEntrySet() {
-    return m_objects.entrySet();
-  }
-
-  public Collection<List<V>> getValues() {
-    return m_objects.values();
-  }
-
-  public void putAll(K k, Collection<V> values) {
-    for (V v : values) {
-      put(k, v);
-    }
+  protected List<V> createValue() {
+    return Lists.newArrayList();
   }
 
+  @Deprecated
   public static <K, V> ListMultiMap<K, V> create() {
-    return new ListMultiMap<K, V>();
+    return Maps.newListMultiMap();
   }
 }
diff --git a/src/main/java/org/testng/collections/Lists.java b/src/main/java/org/testng/collections/Lists.java
index 2b5eaec..90e83df 100755
--- a/src/main/java/org/testng/collections/Lists.java
+++ b/src/main/java/org/testng/collections/Lists.java
@@ -5,23 +5,25 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
-public class Lists {
+public final class Lists {
+
+  private Lists() {}
 
   public static <K> List<K> newArrayList() {
-    return new ArrayList<K>();
+    return new ArrayList<>();
   }
 
   public static <K> List<K> newArrayList(Collection<K> c) {
-    return new ArrayList<K>(c);
+    return new ArrayList<>(c);
   }
 
   public static <K> List<K> newArrayList(K... elements) {
-    List<K> result = new ArrayList<K>();
+    List<K> result = new ArrayList<>();
     Collections.addAll(result, elements);
     return result;
   }
 
   public static <K> List<K> newArrayList(int size) {
-    return new ArrayList<K>(size);
+    return new ArrayList<>(size);
   }
 }
diff --git a/src/main/java/org/testng/collections/Maps.java b/src/main/java/org/testng/collections/Maps.java
index 2eaea02..692cfce 100755
--- a/src/main/java/org/testng/collections/Maps.java
+++ b/src/main/java/org/testng/collections/Maps.java
@@ -9,26 +9,26 @@ import java.util.Map;
 public class Maps {
 
   public static <K, V> Map<K,V> newHashMap() {
-    return new HashMap<K, V>();
+    return new HashMap<>();
   }
 
   public static <K, V> Map<K,V> newHashtable() {
-    return new Hashtable<K, V>();
+    return new Hashtable<>();
   }
 
   public static <K, V> ListMultiMap<K, V> newListMultiMap() {
-    return new ListMultiMap<K, V>();
+    return new ListMultiMap<>();
   }
 
   public static <K, V> SetMultiMap<K, V> newSetMultiMap() {
-    return new SetMultiMap<K, V>();
+    return new SetMultiMap<>();
   }
 
   public static <K, V> Map<K, V> newLinkedHashMap() {
-    return new LinkedHashMap<K, V>();
+    return new LinkedHashMap<>();
   }
 
   public static <K, V> Map<K, V> newHashMap(Map<K, V> parameters) {
-    return new HashMap<K, V>(parameters);
+    return new HashMap<>(parameters);
   }
 }
diff --git a/src/main/java/org/testng/collections/MultiMap.java b/src/main/java/org/testng/collections/MultiMap.java
new file mode 100644
index 0000000..c606645
--- /dev/null
+++ b/src/main/java/org/testng/collections/MultiMap.java
@@ -0,0 +1,111 @@
+package org.testng.collections;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public abstract class MultiMap<K, V, C extends Collection<V>> {
+  protected final Map<K, C> m_objects = Maps.newHashMap();
+
+  protected abstract C createValue();
+
+  public boolean put(K key, V method) {
+    boolean setExists = true;
+    C l = m_objects.get(key);
+    if (l == null) {
+      setExists = false;
+      l = createValue();
+      m_objects.put(key, l);
+    }
+    return l.add(method) && setExists;
+  }
+
+  public C get(K key) {
+    return m_objects.get(key);
+  }
+
+  @Deprecated
+  public List<K> getKeys() {
+    return new ArrayList<>(keySet());
+  }
+
+  public Set<K> keySet() {
+    return new HashSet(m_objects.keySet());
+  }
+
+  public boolean containsKey(K k) {
+    return m_objects.containsKey(k);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder result = new StringBuilder();
+    Set<K> indices = keySet();
+    for (K i : indices) {
+      result.append("\n    ").append(i).append(" <-- ");
+      for (Object o : m_objects.get(i)) {
+        result.append(o).append(" ");
+      }
+    }
+    return result.toString();
+  }
+
+  public boolean isEmpty() {
+    return m_objects.size() == 0;
+  }
+
+  @Deprecated
+  public int getSize() {
+    return size();
+  }
+
+  public int size() {
+    return m_objects.size();
+  }
+
+  @Deprecated
+  public C remove(K key) {
+    return removeAll(key);
+  }
+
+  public boolean remove(K key, V value) {
+    C values = get(key);
+    if (values == null) {
+      return false;
+    }
+    return values.remove(value);
+  }
+
+  public C removeAll(K key) {
+    return m_objects.remove(key);
+  }
+
+  @Deprecated
+  public Set<Map.Entry<K, C>> getEntrySet() {
+    return entrySet();
+  }
+
+  public Set<Map.Entry<K, C>> entrySet() {
+    return m_objects.entrySet();
+  }
+
+  @Deprecated
+  public Collection<C> getValues() {
+    return values();
+  }
+
+  public Collection<C> values() {
+    return m_objects.values();
+  }
+
+  public boolean putAll(K k, Collection<? extends V> values) {
+    boolean result = false;
+    for (V v : values) {
+      result = put(k, v) || result;
+    }
+    return result;
+  }
+}
diff --git a/src/main/java/org/testng/collections/Objects.java b/src/main/java/org/testng/collections/Objects.java
index 9bd6f60..547a4fa 100644
--- a/src/main/java/org/testng/collections/Objects.java
+++ b/src/main/java/org/testng/collections/Objects.java
@@ -5,7 +5,9 @@ import org.testng.util.Strings;
 import java.util.List;
 
 
-public class Objects {
+public final class Objects {
+
+  private Objects() {}
 
   private static class ValueHolder {
     private String m_name;
@@ -62,7 +64,7 @@ public class Objects {
 
     private String s(Object o) {
       return o != null
-          ? ("".equals(o.toString()) ? "\"\"" : o.toString())
+          ? (o.toString().isEmpty() ? "\"\"" : o.toString())
           : "{null}";
     }
 
diff --git a/src/main/java/org/testng/collections/SetMultiMap.java b/src/main/java/org/testng/collections/SetMultiMap.java
index ade4759..f85ba25 100644
--- a/src/main/java/org/testng/collections/SetMultiMap.java
+++ b/src/main/java/org/testng/collections/SetMultiMap.java
@@ -1,81 +1,14 @@
 package org.testng.collections;
 
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Set;
 
 /**
  * A container to hold sets indexed by a key.
  */
-public class SetMultiMap<K, V> {
-  private Map<K, Set<V>> m_objects = Maps.newHashMap();
-
-  public void put(K key, V method) {
-    Set<V> l = m_objects.get(key);
-    if (l == null) {
-      l = Sets.newHashSet();
-      m_objects.put(key, l);
-    }
-    l.add(method);
-  }
-
-  public Set<V> get(K key) {
-    return m_objects.get(key);
-  }
-
-  public Set<K> getKeys() {
-    return new HashSet(m_objects.keySet());
-//    Set<K> result = new ArraySet<K>();
-//    for (K k : m_objects.keySet()) {
-//      result.add(k);
-//    }
-//    Collections.sort(result);
-//    return result;
-  }
-
-  public boolean containsKey(K k) {
-    return m_objects.containsKey(k);
-  }
+public class SetMultiMap<K, V> extends MultiMap<K, V, Set<V>> {
 
   @Override
-  public String toString() {
-    StringBuilder result = new StringBuilder();
-    Set<K> indices = getKeys();
-//    Collections.sort(indices);
-    for (K i : indices) {
-      result.append("\n    ").append(i).append(" <-- ");
-      for (Object o : m_objects.get(i)) {
-        result.append(o).append(" ");
-      }
-    }
-    return result.toString();
-  }
-
-  public boolean isEmpty() {
-    return m_objects.size() == 0;
-  }
-
-  public int getSize() {
-    return m_objects.size();
-  }
-
-  public Set<V> remove(K key) {
-    return m_objects.remove(key);
-  }
-
-  public Set<Entry<K, Set<V>>> getEntrySet() {
-    return m_objects.entrySet();
-  }
-
-  public Collection<Set<V>> getValues() {
-    return m_objects.values();
-  }
-
-  public void putAll(K k, Collection<V> values) {
-    for (V v : values) {
-      put(k, v);
-    }
+  protected Set<V> createValue() {
+    return Sets.newHashSet();
   }
 }
diff --git a/src/main/java/org/testng/collections/Sets.java b/src/main/java/org/testng/collections/Sets.java
index 1019326..a2d3d1b 100644
--- a/src/main/java/org/testng/collections/Sets.java
+++ b/src/main/java/org/testng/collections/Sets.java
@@ -2,15 +2,22 @@ package org.testng.collections;
 
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.Set;
 
-public class Sets {
+public final class Sets {
+
+  private Sets() {}
 
   public static <V> Set<V> newHashSet() {
-    return new HashSet<V>();
+    return new HashSet<>();
   }
 
   public static <V> Set<V> newHashSet(Collection<V> c) {
-    return new HashSet<V>(c);
+    return new HashSet<>(c);
+  }
+
+  public static <V> Set<V> newLinkedHashSet() {
+    return new LinkedHashSet<>();
   }
 }
diff --git a/src/main/java/org/testng/internal/BaseTestMethod.java b/src/main/java/org/testng/internal/BaseTestMethod.java
index 5257ebd..39b635d 100755
--- a/src/main/java/org/testng/internal/BaseTestMethod.java
+++ b/src/main/java/org/testng/internal/BaseTestMethod.java
@@ -82,15 +82,15 @@ public abstract class BaseTestMethod implements ITestNGMethod {
    * @param annotationFinder
    * @param instance 
    */
-  public BaseTestMethod(Method method, IAnnotationFinder annotationFinder, Object instance) {
-    this(new ConstructorOrMethod(method), annotationFinder, instance);
+  public BaseTestMethod(String methodName, Method method, IAnnotationFinder annotationFinder, Object instance) {
+    this(methodName, new ConstructorOrMethod(method), annotationFinder, instance);
   }
 
-  public BaseTestMethod(ConstructorOrMethod com, IAnnotationFinder annotationFinder,
+  public BaseTestMethod(String methodName, ConstructorOrMethod com, IAnnotationFinder annotationFinder,
       Object instance) {
     m_methodClass = com.getDeclaringClass();
     m_method = com;
-    m_methodName = com.getName();
+    m_methodName = methodName;
     m_annotationFinder = annotationFinder;
     m_instance = instance;
     m_signature = computeSignature();
@@ -153,8 +153,8 @@ public abstract class BaseTestMethod implements ITestNGMethod {
     int result = -2;
     Class<?> thisClass = getRealClass();
     Class<?> otherClass = ((ITestNGMethod) o).getRealClass();
-    if (this == o) {
-      result = 0;
+    if (this == o) {
+      result = 0;
     } else if (thisClass.isAssignableFrom(otherClass)) {
       result = -1;
     } else if (otherClass.isAssignableFrom(thisClass)) {
@@ -347,6 +347,15 @@ public abstract class BaseTestMethod implements ITestNGMethod {
   }
 
   /**
+   * {@inheritDoc}
+   * @return the number of times this method or one of its clones must be invoked.
+   */
+  @Override
+  public int getTotalInvocationCount() {
+    return 1;
+  }
+
+  /**
    * {@inheritDoc} Default value for successPercentage.
    */
   @Override
diff --git a/src/main/java/org/testng/internal/ClassHelper.java b/src/main/java/org/testng/internal/ClassHelper.java
index 42b4eb4..405ca31 100644
--- a/src/main/java/org/testng/internal/ClassHelper.java
+++ b/src/main/java/org/testng/internal/ClassHelper.java
@@ -10,12 +10,13 @@ import org.testng.TestRunner;
 import org.testng.annotations.IAnnotation;
 import org.testng.annotations.IFactoryAnnotation;
 import org.testng.annotations.IParametersAnnotation;
+import org.testng.collections.Sets;
 import org.testng.internal.annotations.IAnnotationFinder;
-import org.testng.internal.annotations.Sets;
 import org.testng.junit.IJUnitTestRunner;
 import org.testng.xml.XmlTest;
 
 import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Arrays;
@@ -66,6 +67,14 @@ public final class ClassHelper {
     }
   }
 
+  public static <T> T newInstance(Constructor<T> constructor, Object... parameters) {
+    try {
+      return constructor.newInstance(parameters);
+    } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
+      throw new TestNGException("Cannot instantiate class " + constructor.getDeclaringClass().getName(), e);
+    }
+  }
+
   /**
    * Tries to load the specified class using the context ClassLoader or if none,
    * than from the default ClassLoader. This method differs from the standard
diff --git a/src/main/java/org/testng/internal/ClassImpl.java b/src/main/java/org/testng/internal/ClassImpl.java
index a687dce..eddbc48 100755
--- a/src/main/java/org/testng/internal/ClassImpl.java
+++ b/src/main/java/org/testng/internal/ClassImpl.java
@@ -4,6 +4,7 @@ import static org.testng.internal.Utils.isStringNotEmpty;
 
 import com.google.inject.Injector;
 import com.google.inject.Module;
+import com.google.inject.Stage;
 
 import org.testng.IClass;
 import org.testng.IModuleFactory;
@@ -21,6 +22,7 @@ import org.testng.xml.XmlClass;
 import org.testng.xml.XmlTest;
 
 import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
 import java.util.List;
 import java.util.Map;
 
@@ -127,19 +129,8 @@ public class ClassImpl implements IClass {
    */
   @SuppressWarnings("unchecked")
   private Object getInstanceFromGuice() {
-    Annotation annotation = AnnotationHelper.findAnnotationSuperClasses(Guice.class, m_class);
-    if (annotation == null) return null;
-    Injector parentInjector = getParentInjector();
-
-    Guice guice = (Guice) annotation;
-    List<Module> moduleInstances = Lists.newArrayList(getModules(guice, parentInjector, m_class));
-
-    // Reuse the previous injector, if any
-    Injector injector = m_testContext.getInjector(moduleInstances);
-    if (injector == null) {
-      injector = parentInjector.createChildInjector(moduleInstances);
-      m_testContext.addInjector(moduleInstances, injector);
-    }
+    Injector injector = m_testContext.getInjector(this);
+    if (injector == null) return null;
     return injector.getInstance(m_class);
   }
 
@@ -148,43 +139,35 @@ public class ClassImpl implements IClass {
     // Reuse the previous parent injector, if any
     Injector injector = suite.getParentInjector();
     if (injector == null) {
+      String stageString = suite.getGuiceStage();
+      Stage stage;
+      if (isStringNotEmpty(stageString)) {
+        stage = Stage.valueOf(stageString);
+      } else {
+        stage = Stage.DEVELOPMENT;
+      }
       if (m_hasParentModule) {
-        Class<?> parentModule = ClassHelper.forName(suite.getParentModule());
+        Class<Module> parentModule = (Class<Module>) ClassHelper.forName(suite.getParentModule());
         if (parentModule == null) {
           throw new TestNGException("Cannot load parent Guice module class: " + parentModule);
         }
-        Module module = (Module) ClassHelper.newInstance(parentModule);
-        injector = com.google.inject.Guice.createInjector(module);
+        Module module = newModule(parentModule);
+        injector = com.google.inject.Guice.createInjector(stage, module);
       } else {
-        injector = com.google.inject.Guice.createInjector();
+        injector = com.google.inject.Guice.createInjector(stage);
       }
       suite.setParentInjector(injector);
     }
     return injector;
   }
 
-  private Module[] getModules(Guice guice, Injector parentInejctor, Class<?> testClass) {
-    List<Module> result = Lists.newArrayList();
-    for (Class<? extends Module> moduleClass : guice.modules()) {
-      List<Module> modules = m_testContext.getGuiceModules(moduleClass);
-      if (modules != null && modules.size() > 0) {
-        result.addAll(modules);
-      } else {
-        Module instance = parentInejctor.getInstance(moduleClass);
-        result.add(instance);
-        m_testContext.addGuiceModule(moduleClass, instance);
-      }
+  private Module newModule(Class<Module> module) {
+    try {
+      Constructor<Module> moduleConstructor = module.getDeclaredConstructor(ITestContext.class);
+      return ClassHelper.newInstance(moduleConstructor, m_testContext);
+    } catch (NoSuchMethodException e) {
+      return ClassHelper.newInstance(module);
     }
-    Class<? extends IModuleFactory> factory = guice.moduleFactory();
-    if (factory != IModuleFactory.class) {
-      IModuleFactory factoryInstance = parentInejctor.getInstance(factory);
-      Module moduleClass = factoryInstance.createModule(m_testContext, testClass);
-      if (moduleClass != null) {
-        result.add(moduleClass);
-      }
-    }
-
-    return result.toArray(new Module[result.size()]);
   }
 
   @Override
diff --git a/src/main/java/org/testng/internal/ClonedMethod.java b/src/main/java/org/testng/internal/ClonedMethod.java
index ccdcc6a..29b7265 100755
--- a/src/main/java/org/testng/internal/ClonedMethod.java
+++ b/src/main/java/org/testng/internal/ClonedMethod.java
@@ -105,6 +105,11 @@ public class ClonedMethod implements ITestNGMethod {
   }
 
   @Override
+  public int getTotalInvocationCount() {
+    return 1;
+  }
+
+  @Override
   public long getInvocationTimeOut() {
     return m_method.getInvocationTimeOut();
   }
diff --git a/src/main/java/org/testng/internal/ConfigurationMethod.java b/src/main/java/org/testng/internal/ConfigurationMethod.java
index 7003939..2c84bcd 100755
--- a/src/main/java/org/testng/internal/ConfigurationMethod.java
+++ b/src/main/java/org/testng/internal/ConfigurationMethod.java
@@ -59,7 +59,7 @@ public class ConfigurationMethod extends BaseTestMethod {
                               boolean initialize,
                               Object instance)
   {
-    super(com, annotationFinder, instance);
+    super(com.getName(), com, annotationFinder, instance);
     if(initialize) {
       init();
     }
diff --git a/src/main/java/org/testng/internal/DataProviderHolder.java b/src/main/java/org/testng/internal/DataProviderHolder.java
index d6aea24..47162cc 100755
--- a/src/main/java/org/testng/internal/DataProviderHolder.java
+++ b/src/main/java/org/testng/internal/DataProviderHolder.java
@@ -8,11 +8,13 @@ import java.lang.reflect.Method;
  * A holder for a pair of Method and IDataProviderAnnotation
  */
 public class DataProviderHolder {
+  Object instance;
   Method method;
   IDataProviderAnnotation annotation;
 
-  public DataProviderHolder(IDataProviderAnnotation annotation, Method method) {
+  public DataProviderHolder(IDataProviderAnnotation annotation, Method method, Object instance) {
     this.annotation = annotation;
     this.method = method;
+    this.instance = instance;
   }
 }
diff --git a/src/main/java/org/testng/internal/DynamicGraph.java b/src/main/java/org/testng/internal/DynamicGraph.java
index 1234c3d..26ef57e 100644
--- a/src/main/java/org/testng/internal/DynamicGraph.java
+++ b/src/main/java/org/testng/internal/DynamicGraph.java
@@ -3,7 +3,7 @@ package org.testng.internal;
 import org.testng.collections.ListMultiMap;
 import org.testng.collections.Lists;
 import org.testng.collections.Maps;
-import org.testng.internal.annotations.Sets;
+import org.testng.collections.Sets;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -159,7 +159,7 @@ public class DynamicGraph<T> {
     result.append("\n  Running:" + m_nodesRunning);
     result.append("\n  Finished:" + m_nodesFinished);
     result.append("\n  Edges:\n");
-    for (Map.Entry<T, List<T>> es : m_dependingOn.getEntrySet()) {
+    for (Map.Entry<T, List<T>> es : m_dependingOn.entrySet()) {
       result.append("     " + es.getKey() + "\n");
       for (T t : es.getValue()) {
         result.append("        " + t + "\n");
@@ -199,7 +199,7 @@ public class DynamicGraph<T> {
     }
     result.append("\n");
 
-    for (T k : m_dependingOn.getKeys()) {
+    for (T k : m_dependingOn.keySet()) {
       List<T> nodes = m_dependingOn.get(k);
       for (T n : nodes) {
         String dotted = m_nodesFinished.contains(k) ? "style=dotted" : "";
diff --git a/src/main/java/org/testng/internal/FactoryMethod.java b/src/main/java/org/testng/internal/FactoryMethod.java
index c990aad..dc5e2e5 100644
--- a/src/main/java/org/testng/internal/FactoryMethod.java
+++ b/src/main/java/org/testng/internal/FactoryMethod.java
@@ -36,7 +36,7 @@ public class FactoryMethod extends BaseTestMethod {
                        IAnnotationFinder annotationFinder,
                        ITestContext testContext)
   {
-    super(com, annotationFinder, instance);
+    super(com.getName(), com, annotationFinder, instance);
 //    Utils.checkInstanceOrStatic(instance, method);
     Class<?> declaringClass = com.getDeclaringClass();
     if (instance != null && ! declaringClass.isAssignableFrom(instance.getClass())) {
diff --git a/src/main/java/org/testng/internal/InvokedMethod.java b/src/main/java/org/testng/internal/InvokedMethod.java
index 36e15f8..d97da6c 100755
--- a/src/main/java/org/testng/internal/InvokedMethod.java
+++ b/src/main/java/org/testng/internal/InvokedMethod.java
@@ -11,8 +11,6 @@ public class InvokedMethod implements Serializable, IInvokedMethod {
   transient private Object m_instance;
   private ITestNGMethod m_testMethod;
   private Object[] m_parameters;
-  private boolean m_isTest = true;
-  private boolean m_isConfigurationMethod = false;
   private long m_date = System.currentTimeMillis();
   private ITestResult m_testResult;
 
@@ -24,15 +22,11 @@ public class InvokedMethod implements Serializable, IInvokedMethod {
   public InvokedMethod(Object instance,
                        ITestNGMethod method,
                        Object[] parameters,
-                       boolean isTest,
-                       boolean isConfiguration,
                        long date,
                        ITestResult testResult) {
     m_instance = instance;
     m_testMethod = method;
     m_parameters = parameters;
-    m_isTest = isTest;
-    m_isConfigurationMethod = isConfiguration;
     m_date = date;
     m_testResult = testResult;
   }
@@ -42,7 +36,7 @@ public class InvokedMethod implements Serializable, IInvokedMethod {
    */
   @Override
   public boolean isTestMethod() {
-    return m_isTest;
+    return m_testMethod.isTest();
   }
 
   @Override
@@ -61,7 +55,14 @@ public class InvokedMethod implements Serializable, IInvokedMethod {
    */
   @Override
   public boolean isConfigurationMethod() {
-    return m_isConfigurationMethod;
+    return m_testMethod.isBeforeMethodConfiguration() ||
+           m_testMethod.isAfterMethodConfiguration() ||
+           m_testMethod.isBeforeTestConfiguration() ||
+           m_testMethod.isAfterTestConfiguration() ||
+           m_testMethod.isBeforeClassConfiguration() ||
+           m_testMethod.isAfterClassConfiguration() ||
+           m_testMethod.isBeforeSuiteConfiguration() ||
+           m_testMethod.isAfterSuiteConfiguration();
   }
 
   /* (non-Javadoc)
diff --git a/src/main/java/org/testng/internal/Invoker.java b/src/main/java/org/testng/internal/Invoker.java
index 4b46ac9..30657ba 100644
--- a/src/main/java/org/testng/internal/Invoker.java
+++ b/src/main/java/org/testng/internal/Invoker.java
@@ -25,11 +25,11 @@ import org.testng.annotations.IConfigurationAnnotation;
 import org.testng.annotations.NoInjection;
 import org.testng.collections.Lists;
 import org.testng.collections.Maps;
+import org.testng.collections.Sets;
 import org.testng.internal.InvokeMethodRunnable.TestNGRuntimeException;
 import org.testng.internal.ParameterHolder.ParameterOrigin;
 import org.testng.internal.annotations.AnnotationHelper;
 import org.testng.internal.annotations.IAnnotationFinder;
-import org.testng.internal.annotations.Sets;
 import org.testng.internal.invokers.InvokedMethodListenerInvoker;
 import org.testng.internal.invokers.InvokedMethodListenerMethod;
 import org.testng.internal.thread.ThreadExecutionException;
@@ -187,8 +187,6 @@ public class Invoker implements IInvoker {
           configurationAnnotation = AnnotationHelper.findConfiguration(m_annotationFinder, method);
 
           if (MethodHelper.isEnabled(configurationAnnotation)) {
-            boolean isClassConfiguration = isClassConfiguration(configurationAnnotation);
-            boolean isSuiteConfiguration = isSuiteConfiguration(configurationAnnotation);
             boolean alwaysRun= isAlwaysRun(configurationAnnotation);
 
             if (!confInvocationPassed(tm, currentTestMethod, testClass, instance) && !alwaysRun) {
@@ -213,7 +211,7 @@ public class Invoker implements IInvoker {
             runConfigurationListeners(testResult, true /* before */);
 
             invokeConfigurationMethod(newInstance, tm,
-              parameters, isClassConfiguration, isSuiteConfiguration, testResult);
+              parameters, testResult);
 
             // TODO: probably we should trigger the event for each instance???
             testResult.setEndMillis(System.currentTimeMillis());
@@ -264,34 +262,6 @@ public class Invoker implements IInvoker {
   }
 
   /**
-   * Is the current <code>IConfiguration</code> a class-level method.
-   */
-  private  boolean isClassConfiguration(IConfigurationAnnotation configurationAnnotation) {
-    if (null == configurationAnnotation) {
-      return false;
-    }
-
-    boolean before = configurationAnnotation.getBeforeTestClass();
-    boolean after = configurationAnnotation.getAfterTestClass();
-
-    return before || after;
-  }
-
-  /**
-   * Is the current <code>IConfiguration</code> a suite level method.
-   */
-  private  boolean isSuiteConfiguration(IConfigurationAnnotation configurationAnnotation) {
-    if (null == configurationAnnotation) {
-      return false;
-    }
-
-    boolean before = configurationAnnotation.getBeforeSuite();
-    boolean after = configurationAnnotation.getAfterSuite();
-
-    return before || after;
-  }
-
-  /**
    * Is the <code>IConfiguration</code> marked as alwaysRun.
    */
   private boolean isAlwaysRun(IConfigurationAnnotation configurationAnnotation) {
@@ -503,7 +473,6 @@ public class Invoker implements IInvoker {
    * @param targetInstance the instance to invoke the configuration method on
    * @param tm the configuration method
    * @param params the parameters needed for method invocation
-   * @param isClass flag if the configuration method is a class level method // FIXME: this looks like a missusage
    * @param testResult
    * @throws InvocationTargetException
    * @throws IllegalAccessException
@@ -511,8 +480,6 @@ public class Invoker implements IInvoker {
   private void invokeConfigurationMethod(Object targetInstance,
                                          ITestNGMethod tm,
                                          Object[] params,
-                                         boolean isClass,
-                                         boolean isSuite,
                                          ITestResult testResult)
     throws InvocationTargetException, IllegalAccessException
   {
@@ -523,8 +490,6 @@ public class Invoker implements IInvoker {
       InvokedMethod invokedMethod= new InvokedMethod(targetInstance,
                                           tm,
                                           params,
-                                          false, /* isTest */
-                                          isClass, /* ??? */
                                           System.currentTimeMillis(),
                                           testResult);
 
@@ -656,8 +621,6 @@ public class Invoker implements IInvoker {
       invokedMethod= new InvokedMethod(instance,
           tm,
           parameterValues,
-          true /* isTest */,
-          false /* isConfiguration */,
           System.currentTimeMillis(),
           testResult);
 
@@ -833,12 +796,12 @@ public class Invoker implements IInvoker {
         // If we have parameters, set the boolean if we are about to run
         // the last invocation
         if (tm.getParameterInvocationCount() > 0) {
-          isLast = current == tm.getParameterInvocationCount();
+          isLast = current == tm.getParameterInvocationCount() * tm.getTotalInvocationCount();
         }
         // If we have invocationCount > 1, set the boolean if we are about to
         // run the last invocation
-        else if (tm.getInvocationCount() > 1) {
-          isLast = current == tm.getInvocationCount();
+        else if (tm.getTotalInvocationCount() > 1) {
+          isLast = current == tm.getTotalInvocationCount();
         }
         if (! cm.isLastTimeOnly() || (cm.isLastTimeOnly() && isLast)) {
           result.add(m);
@@ -1014,6 +977,7 @@ public class Invoker implements IInvoker {
     final FailureContext failure = new FailureContext();
     failure.count = failureCount;
     do {
+      failure.instances = Lists.newArrayList ();
       Map<String, String> allParameters = Maps.newHashMap();
       /**
        * TODO: This recreates all the parameters every time when we only need
@@ -1517,7 +1481,7 @@ public class Invoker implements IInvoker {
       return true;
     } else {
       final String message = ite.getMessage();
-      return message != null && Pattern.matches(messageRegExp, message);
+      return message != null && Pattern.compile(messageRegExp, Pattern.DOTALL).matcher(ite.getMessage()).matches();
     }
   }
 
diff --git a/src/main/java/org/testng/internal/MethodGroupsHelper.java b/src/main/java/org/testng/internal/MethodGroupsHelper.java
index 622a122..1923d07 100644
--- a/src/main/java/org/testng/internal/MethodGroupsHelper.java
+++ b/src/main/java/org/testng/internal/MethodGroupsHelper.java
@@ -64,7 +64,7 @@ public class MethodGroupsHelper {
         	}
         }
         else {
-          in = MethodGroupsHelper.includeMethod(AnnotationHelper.findTest(finder, m),
+          in = MethodGroupsHelper.includeMethod(AnnotationHelper.findTest(finder, tm),
               runInfo, tm, forTests, unique, outIncludedMethods);
         }
       }
diff --git a/src/main/java/org/testng/internal/MethodHelper.java b/src/main/java/org/testng/internal/MethodHelper.java
index c53b0bc..ca5554c 100644
--- a/src/main/java/org/testng/internal/MethodHelper.java
+++ b/src/main/java/org/testng/internal/MethodHelper.java
@@ -6,9 +6,9 @@ import org.testng.annotations.IExpectedExceptionsAnnotation;
 import org.testng.annotations.ITestAnnotation;
 import org.testng.annotations.ITestOrConfiguration;
 import org.testng.collections.Lists;
+import org.testng.collections.Sets;
 import org.testng.internal.annotations.AnnotationHelper;
 import org.testng.internal.annotations.IAnnotationFinder;
-import org.testng.internal.annotations.Sets;
 import org.testng.internal.collections.Pair;
 
 import java.lang.reflect.Method;
diff --git a/src/main/java/org/testng/internal/PackageUtils.java b/src/main/java/org/testng/internal/PackageUtils.java
index a4cc7fc..2703eb7 100644
--- a/src/main/java/org/testng/internal/PackageUtils.java
+++ b/src/main/java/org/testng/internal/PackageUtils.java
@@ -30,7 +30,7 @@ public class PackageUtils {
   private static String[] s_testClassPaths;
 
   /** The additional class loaders to find classes in. */
-  private static final List<ClassLoader> m_classLoaders = new Vector<ClassLoader>();
+  private static final List<ClassLoader> m_classLoaders = new Vector<>();
 
   /** Add a class loader to the searchable loaders. */
   public static void addClassLoader(final ClassLoader loader) {
@@ -58,9 +58,9 @@ public class PackageUtils {
     String packageDirName = packageOnly.replace('.', '/') + (packageOnly.length() > 0 ? "/" : "");
 
 
-    Vector<URL> dirs = new Vector<URL>();
+    Vector<URL> dirs = new Vector<>();
     // go through additional class loaders
-    Vector<ClassLoader> allClassLoaders = new Vector<ClassLoader>();
+    Vector<ClassLoader> allClassLoaders = new Vector<>();
     ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
     if (contextClassLoader != null) {
       allClassLoaders.add(contextClassLoader);
@@ -111,9 +111,9 @@ public class PackageUtils {
               packageName = name.substring(0, idx).replace('/', '.');
             }
 
-            Utils.log("PackageUtils", 4, "Package name is " + packageName);
-            if ((idx != -1) || recursive) {
+            if (recursive || packageName.equals(packageOnly)) {
               //it's not inside a deeper dir
+              Utils.log("PackageUtils", 4, "Package name is " + packageName);
               if (name.endsWith(".class") && !entry.isDirectory()) {
                 String className = name.substring(packageName.length() + 1, name.length() - 6);
                 Utils.log("PackageUtils", 4, "Found class " + className + ", seeing it if it's included or excluded");
diff --git a/src/main/java/org/testng/internal/Parameters.java b/src/main/java/org/testng/internal/Parameters.java
index 4fa7c91..5306f76 100755
--- a/src/main/java/org/testng/internal/Parameters.java
+++ b/src/main/java/org/testng/internal/Parameters.java
@@ -1,5 +1,7 @@
 package org.testng.internal;
 
+import com.google.inject.Injector;
+
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
@@ -10,6 +12,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.testng.ITestClass;
 import org.testng.ITestContext;
 import org.testng.ITestNGMethod;
 import org.testng.ITestResult;
@@ -253,8 +256,9 @@ public class Parameters {
     return result;
   }
 
-  private static DataProviderHolder findDataProvider(Class clazz, ConstructorOrMethod m,
-      IAnnotationFinder finder) {
+  private static DataProviderHolder findDataProvider(Object instance, ITestClass clazz,
+                                                     ConstructorOrMethod m,
+                                                     IAnnotationFinder finder, ITestContext context) {
     DataProviderHolder result = null;
 
     IDataProvidable dp = findDataProviderInfo(clazz, m, finder);
@@ -263,7 +267,7 @@ public class Parameters {
       Class dataProviderClass = dp.getDataProviderClass();
 
       if (! Utils.isStringEmpty(dataProviderName)) {
-        result = findDataProvider(clazz, finder, dataProviderName, dataProviderClass);
+        result = findDataProvider(instance, clazz, finder, dataProviderName, dataProviderClass, context);
 
         if(null == result) {
           throw new TestNGException("Method " + m + " requires a @DataProvider named : "
@@ -280,7 +284,7 @@ public class Parameters {
    * Find the data provider info (data provider name and class) on either @Test(dataProvider),
    * @Factory(dataProvider) on a method or @Factory(dataProvider) on a constructor.
    */
-  private static IDataProvidable findDataProviderInfo(Class clazz, ConstructorOrMethod m,
+  private static IDataProvidable findDataProviderInfo(ITestClass clazz, ConstructorOrMethod m,
       IAnnotationFinder finder) {
     IDataProvidable result;
 
@@ -298,7 +302,7 @@ public class Parameters {
       if (result == null) {
         //
         // @Test(dataProvider) on a class
-        result = AnnotationHelper.findTest(finder, clazz);
+        result = AnnotationHelper.findTest(finder, clazz.getRealClass());
       }
     } else {
       //
@@ -313,11 +317,14 @@ public class Parameters {
   /**
    * Find a method that has a @DataProvider(name=name)
    */
-  private static DataProviderHolder findDataProvider(Class cls, IAnnotationFinder finder,
-      String name, Class dataProviderClass)
+  private static DataProviderHolder findDataProvider(Object instance, ITestClass clazz,
+                                                     IAnnotationFinder finder,
+                                                     String name, Class dataProviderClass,
+                                                     ITestContext context)
   {
     DataProviderHolder result = null;
 
+    Class cls = clazz.getRealClass();
     boolean shouldBeStatic = false;
     if (dataProviderClass != null) {
       cls = dataProviderClass;
@@ -328,13 +335,16 @@ public class Parameters {
       IDataProviderAnnotation dp = finder.findAnnotation(m, IDataProviderAnnotation.class);
       if (null != dp && name.equals(getDataProviderName(dp, m))) {
         if (shouldBeStatic && (m.getModifiers() & Modifier.STATIC) == 0) {
-          throw new TestNGException("DataProvider should be static: " + m);
+          Injector injector = context.getInjector(clazz);
+          if (injector != null) {
+            instance = injector.getInstance(dataProviderClass);
+          }
         }
 
         if (result != null) {
           throw new TestNGException("Found two providers called '" + name + "' on " + cls);
         }
-        result = new DataProviderHolder(dp, m);
+        result = new DataProviderHolder(dp, m, instance);
       }
     }
 
@@ -417,8 +427,8 @@ public class Parameters {
      * sets of parameters for this method
      */
     DataProviderHolder dataProviderHolder =
-        findDataProvider(testMethod.getTestClass().getRealClass(),
-            testMethod.getConstructorOrMethod(), annotationFinder);
+        findDataProvider(instance, testMethod.getTestClass(),
+            testMethod.getConstructorOrMethod(), annotationFinder, methodParams.context);
 
     if (null != dataProviderHolder) {
       int parameterCount = testMethod.getConstructorOrMethod().getParameterTypes().length;
@@ -429,7 +439,7 @@ public class Parameters {
       }
 
       parameters = MethodInvocationHelper.invokeDataProvider(
-          instance, /* a test instance or null if the dataprovider is static*/
+          dataProviderHolder.instance, /* a test instance or null if the dataprovider is static*/
           dataProviderHolder.method,
           testMethod,
           methodParams.context,
diff --git a/src/main/java/org/testng/internal/TestNGClassFinder.java b/src/main/java/org/testng/internal/TestNGClassFinder.java
index cca7352..8b94c25 100644
--- a/src/main/java/org/testng/internal/TestNGClassFinder.java
+++ b/src/main/java/org/testng/internal/TestNGClassFinder.java
@@ -56,7 +56,15 @@ public class TestNGClassFinder extends BaseClassFinder {
       for (Class cls : allClasses) {
         try {
           if (null != cls) {
-            for (Method m : cls.getMethods()) {
+            Method[] ms;
+            try {
+              ms = cls.getMethods();
+            } catch (NoClassDefFoundError e) {
+              // https://github.com/cbeust/testng/issues/602
+              ppp("Warning: Can't link and determine methods of " + cls);
+              ms = new Method[0];
+            }
+            for (Method m : ms) {
               IAnnotation a = annotationFinder.findAnnotation(m,
                   org.testng.annotations.IObjectFactoryAnnotation.class);
               if (null != a) {
diff --git a/src/main/java/org/testng/internal/TestNGMethod.java b/src/main/java/org/testng/internal/TestNGMethod.java
index 3cd92bc..7e86ef9 100755
--- a/src/main/java/org/testng/internal/TestNGMethod.java
+++ b/src/main/java/org/testng/internal/TestNGMethod.java
@@ -29,6 +29,7 @@ public class TestNGMethod extends BaseTestMethod implements Serializable {
   private static final long serialVersionUID = -1742868891986775307L;
   private int m_threadPoolSize = 0;
   private int m_invocationCount = 1;
+  private int m_totalInvocationCount = m_invocationCount;
   private int m_successPercentage = 100;
 
   /**
@@ -43,7 +44,7 @@ public class TestNGMethod extends BaseTestMethod implements Serializable {
 
   private TestNGMethod(Method method, IAnnotationFinder finder, boolean initialize,
       XmlTest xmlTest, Object instance) {
-    super(method, finder, instance);
+    super(method.getName(), method, finder, instance);
 
     if(initialize) {
       init(xmlTest);
@@ -62,6 +63,14 @@ public class TestNGMethod extends BaseTestMethod implements Serializable {
    * {@inheritDoc}
    */
   @Override
+  public int getTotalInvocationCount() {
+    return m_totalInvocationCount;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
   public int getSuccessPercentage() {
     return m_successPercentage;
   }
@@ -96,6 +105,7 @@ public class TestNGMethod extends BaseTestMethod implements Serializable {
         m_successPercentage = testAnnotation.getSuccessPercentage();
 
         setInvocationCount(testAnnotation.getInvocationCount());
+        m_totalInvocationCount = testAnnotation.getInvocationCount();
         setThreadPoolSize(testAnnotation.getThreadPoolSize());
         setAlwaysRun(testAnnotation.getAlwaysRun());
         setDescription(findDescription(testAnnotation, xmlTest));
@@ -185,6 +195,7 @@ public class TestNGMethod extends BaseTestMethod implements Serializable {
     clone.setEnabled(getEnabled());
     clone.setParameterInvocationCount(getParameterInvocationCount());
     clone.setInvocationCount(getInvocationCount());
+    clone.m_totalInvocationCount = getTotalInvocationCount();
     clone.m_successPercentage = getSuccessPercentage();
     clone.setTimeOut(getTimeOut());
     clone.setRetryAnalyzer(getRetryAnalyzer());
diff --git a/src/main/java/org/testng/internal/TestNGMethodFinder.java b/src/main/java/org/testng/internal/TestNGMethodFinder.java
index 86cf37e..50f3b16 100755
--- a/src/main/java/org/testng/internal/TestNGMethodFinder.java
+++ b/src/main/java/org/testng/internal/TestNGMethodFinder.java
@@ -1,6 +1,10 @@
 package org.testng.internal;
 
 
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Set;
+
 import org.testng.ITestMethodFinder;
 import org.testng.ITestNGMethod;
 import org.testng.annotations.IConfigurationAnnotation;
@@ -10,10 +14,6 @@ import org.testng.internal.annotations.AnnotationHelper;
 import org.testng.internal.annotations.IAnnotationFinder;
 import org.testng.xml.XmlTest;
 
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Set;
-
 /**
  * The default strategy for finding test methods:  look up
  * annotations @Test in front of methods.
@@ -36,15 +36,14 @@ public class TestNGMethodFinder implements ITestMethodFinder {
   private RunInfo m_runInfo = null;
   private IAnnotationFinder m_annotationFinder = null;
 
-  public TestNGMethodFinder(RunInfo runInfo,
-                            IAnnotationFinder annotationFinder)
+  public TestNGMethodFinder(RunInfo runInfo, IAnnotationFinder annotationFinder)
   {
     m_runInfo = runInfo;
     m_annotationFinder = annotationFinder;
   }
 
   @Override
-  public ITestNGMethod[] getTestMethods(Class clazz, XmlTest xmlTest) {
+  public ITestNGMethod[] getTestMethods(Class<?> clazz, XmlTest xmlTest) {
     return AnnotationHelper.findMethodsWithAnnotation(
         clazz, ITestAnnotation.class, m_annotationFinder, xmlTest);
   }
diff --git a/src/main/java/org/testng/internal/Utils.java b/src/main/java/org/testng/internal/Utils.java
index faa58e5..82d4c5d 100644
--- a/src/main/java/org/testng/internal/Utils.java
+++ b/src/main/java/org/testng/internal/Utils.java
@@ -104,7 +104,11 @@ public final class Utils {
   public static void writeUtf8File(String outputDir, String fileName, XMLStringBuffer xsb,
       String prefix) {
     try {
-      FileWriter fw = new FileWriter(new File(outputDir, fileName));
+      File parentDir = new File(outputDir);
+      if (!parentDir.exists()) {
+        parentDir.mkdirs();
+      }
+      FileWriter fw = new FileWriter(new File(parentDir, fileName));
       if (prefix != null) {
         fw.append(prefix);
       }
diff --git a/src/main/java/org/testng/internal/annotations/AnnotationHelper.java b/src/main/java/org/testng/internal/annotations/AnnotationHelper.java
index 51b931a..182e528 100755
--- a/src/main/java/org/testng/internal/annotations/AnnotationHelper.java
+++ b/src/main/java/org/testng/internal/annotations/AnnotationHelper.java
@@ -1,6 +1,13 @@
 package org.testng.internal.annotations;
 
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Map;
+
 import org.testng.ITestNGMethod;
+import org.testng.annotations.IAnnotation;
 import org.testng.annotations.IConfigurationAnnotation;
 import org.testng.annotations.IDataProviderAnnotation;
 import org.testng.annotations.IExpectedExceptionsAnnotation;
@@ -12,12 +19,6 @@ import org.testng.internal.TestNGMethod;
 import org.testng.internal.Utils;
 import org.testng.xml.XmlTest;
 
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Map;
-
 /**
  * Helper methods to find @Test and @Configuration tags.  They minimize
  * the amount of casting we need to do.
@@ -27,7 +28,7 @@ import java.util.Map;
  */
 public class AnnotationHelper {
 
-  public static ITestAnnotation findTest(IAnnotationFinder finder, Class cls) {
+  public static ITestAnnotation findTest(IAnnotationFinder finder, Class<?> cls) {
     return finder.findAnnotation(cls, ITestAnnotation.class);
   }
 
@@ -35,6 +36,10 @@ public class AnnotationHelper {
     return finder.findAnnotation(m, ITestAnnotation.class);
   }
 
+  public static ITestAnnotation findTest(IAnnotationFinder finder, ITestNGMethod m) {
+    return finder.findAnnotation(m, ITestAnnotation.class);
+  }
+
   public static IFactoryAnnotation findFactory(IAnnotationFinder finder, Method m) {
     return finder.findAnnotation(m, IFactoryAnnotation.class);
   }
@@ -72,7 +77,7 @@ public class AnnotationHelper {
   }
 
   public static IConfigurationAnnotation findConfiguration(IAnnotationFinder finder, Method m) {
-    IConfigurationAnnotation result = (IConfigurationAnnotation) finder.findAnnotation(m, IConfigurationAnnotation.class);
+    IConfigurationAnnotation result = finder.findAnnotation(m, IConfigurationAnnotation.class);
     if (result == null) {
       IConfigurationAnnotation bs = (IConfigurationAnnotation) finder.findAnnotation(m, IBeforeSuite.class);
       IConfigurationAnnotation as = (IConfigurationAnnotation) finder.findAnnotation(m, IAfterSuite.class);
@@ -187,8 +192,9 @@ public class AnnotationHelper {
    * Delegation method for creating the list of <CODE>ITestMethod</CODE>s to be
    * analysed.
    */
-  public static ITestNGMethod[] findMethodsWithAnnotation(Class rootClass, Class annotationClass,
-        IAnnotationFinder annotationFinder, XmlTest xmlTest)
+  public static ITestNGMethod[] findMethodsWithAnnotation(Class<?> rootClass,
+      Class<? extends IAnnotation> annotationClass, IAnnotationFinder annotationFinder,
+      XmlTest xmlTest)
   {
     // Keep a map of the methods we saw so that we ignore a method in a superclass if it's
     // already been seen in a child class
@@ -197,7 +203,7 @@ public class AnnotationHelper {
     try {
       vResult = Maps.newHashMap();
 //    Class[] classes = rootClass.getTestClasses();
-      Class cls = rootClass;
+      Class<?> cls = rootClass;
 
       //
       // If the annotation is on the class or superclass, it applies to all public methods
@@ -208,7 +214,7 @@ public class AnnotationHelper {
       // Otherwise walk through all the methods and keep those
       // that have the annotation
       //
-//    for (Class cls : classes) {
+//    for (Class<?> cls : classes) {
         while (null != cls) {
           boolean hasClassAnnotation = isAnnotationPresent(annotationFinder, cls, annotationClass);
           Method[] methods = cls.getDeclaredMethods();
@@ -268,7 +274,7 @@ public class AnnotationHelper {
       return result;
     }
 
-  public static Annotation findAnnotationSuperClasses(Class annotationClass, Class c) {
+  public static Annotation findAnnotationSuperClasses(Class<?> annotationClass, Class c) {
     while (c != null) {
       Annotation result = c.getAnnotation(annotationClass);
       if (result != null) return result;
@@ -289,11 +295,13 @@ public class AnnotationHelper {
     return false;
   }
 
-  private static boolean isAnnotationPresent(IAnnotationFinder annotationFinder, Method m, Class annotationClass) {
+  private static boolean isAnnotationPresent(IAnnotationFinder annotationFinder, Method m,
+      Class<? extends IAnnotation> annotationClass) {
     return annotationFinder.findAnnotation(m, annotationClass) != null;
   }
 
-  private static boolean isAnnotationPresent(IAnnotationFinder annotationFinder, Class cls, Class annotationClass) {
+  private static boolean isAnnotationPresent(IAnnotationFinder annotationFinder, Class<?> cls,
+      Class<? extends IAnnotation> annotationClass) {
     return annotationFinder.findAnnotation(cls, annotationClass) != null;
   }
 
diff --git a/src/main/java/org/testng/internal/annotations/IAnnotationFinder.java b/src/main/java/org/testng/internal/annotations/IAnnotationFinder.java
index df57c0b..c3e932f 100755
--- a/src/main/java/org/testng/internal/annotations/IAnnotationFinder.java
+++ b/src/main/java/org/testng/internal/annotations/IAnnotationFinder.java
@@ -1,10 +1,11 @@
 package org.testng.internal.annotations;
 
-import org.testng.annotations.IAnnotation;
-
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 
+import org.testng.ITestNGMethod;
+import org.testng.annotations.IAnnotation;
+
 
 /**
  * This interface defines how annotations are found on classes, methods
@@ -20,7 +21,7 @@ public interface IAnnotationFinder {
    * @param annotationClass
    * @return The annotation on the class or null if none found.
    */
-  public <A extends IAnnotation> A findAnnotation(Class cls, Class<A> annotationClass);
+  public <A extends IAnnotation> A findAnnotation(Class<?> cls, Class<A> annotationClass);
 
   /**
    * @param m
@@ -30,6 +31,7 @@ public interface IAnnotationFinder {
    * If not found, return null.
    */
   public <A extends IAnnotation> A findAnnotation(Method m, Class<A> annotationClass);
+  <A extends IAnnotation> A findAnnotation(ITestNGMethod m, Class<A> annotationClass);
 
   /**
    * @param cons
@@ -38,7 +40,7 @@ public interface IAnnotationFinder {
    * If not found, return the annotation on the declaring class.
    * If not found, return null.
    */
-  public <A extends IAnnotation> A findAnnotation(Constructor cons, Class<A> annotationClass);
+  public <A extends IAnnotation> A findAnnotation(Constructor<?> cons, Class<A> annotationClass);
 
   /**
    * @return true if the ith parameter of the given method has the annotation @TestInstance.
diff --git a/src/main/java/org/testng/internal/annotations/JDK15AnnotationFinder.java b/src/main/java/org/testng/internal/annotations/JDK15AnnotationFinder.java
index b3ef0bf..edfd80b 100755
--- a/src/main/java/org/testng/internal/annotations/JDK15AnnotationFinder.java
+++ b/src/main/java/org/testng/internal/annotations/JDK15AnnotationFinder.java
@@ -8,6 +8,7 @@ import java.util.Map;
 
 import org.testng.IAnnotationTransformer;
 import org.testng.IAnnotationTransformer2;
+import org.testng.ITestNGMethod;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.AfterGroups;
 import org.testng.annotations.AfterMethod;
@@ -47,7 +48,9 @@ import org.testng.internal.collections.Pair;
  */
 public class JDK15AnnotationFinder implements IAnnotationFinder {
   private JDK15TagFactory m_tagFactory = new JDK15TagFactory();
-  private Map<Class<? extends IAnnotation>, Class<? extends Annotation>> m_annotationMap = Collections.synchronizedMap(Maps.<Class<? extends IAnnotation>, Class<? extends Annotation>>newHashMap());
+  private Map<Class<? extends IAnnotation>, Class<? extends Annotation>> m_annotationMap =
+      Collections.synchronizedMap(Maps.<Class<? extends IAnnotation>,
+          Class<? extends Annotation>>newHashMap());
   private IAnnotationTransformer m_transformer = null;
 
   @SuppressWarnings({"deprecation"})
@@ -73,16 +76,16 @@ public class JDK15AnnotationFinder implements IAnnotationFinder {
     m_annotationMap.put(IListeners.class, Listeners.class);
   }
 
-  private <A extends Annotation> A findAnnotationInSuperClasses(Class cls, Class<A> a) {
+  private <A extends Annotation> A findAnnotationInSuperClasses(Class<?> cls, Class<A> a) {
     // Hack for @Listeners: we don't look in superclasses for this annotation
     // because inheritance of this annotation causes aggregation instead of
     // overriding
     if (a.equals(org.testng.annotations.Listeners.class)) {
-      return (A) cls.getAnnotation(a);
+      return cls.getAnnotation(a);
     }
     else {
       while (cls != null) {
-        A result = (A) cls.getAnnotation(a);
+        A result = cls.getAnnotation(a);
         if (result != null) {
           return result;
         } else {
@@ -98,14 +101,38 @@ public class JDK15AnnotationFinder implements IAnnotationFinder {
   public <A extends IAnnotation> A findAnnotation(Method m, Class<A> annotationClass) {
     final Class<? extends Annotation> a = m_annotationMap.get(annotationClass);
     if (a == null) {
-      throw new IllegalArgumentException("Java @Annotation class for '" + annotationClass + "' not found.");
+      throw new IllegalArgumentException("Java @Annotation class for '"
+          + annotationClass + "' not found.");
     }
-    return findAnnotation(m.getDeclaringClass(), m.getAnnotation(a), annotationClass, null, null, m);
+    Annotation annotation = m.getAnnotation(a);
+    return findAnnotation(annotation, annotationClass, m.getDeclaringClass(), null, m,
+        new Pair<>(annotation, m));
   }
 
-  private void transform(IAnnotation a, Class testClass,
-      Constructor testConstructor, Method testMethod)
-  {
+  @Override
+  public <A extends IAnnotation> A findAnnotation(ITestNGMethod tm, Class<A> annotationClass) {
+    final Class<? extends Annotation> a = m_annotationMap.get(annotationClass);
+    if (a == null) {
+      throw new IllegalArgumentException("Java @Annotation class for '"
+            + annotationClass + "' not found.");
+    }
+    Method m = tm.getMethod();
+    Class<?> testClass;
+    if (tm.getInstance() == null) {
+      testClass = m.getDeclaringClass();
+    } else {
+      testClass = tm.getInstance().getClass();
+    }
+    Annotation annotation = m.getAnnotation(a);
+    if (annotation == null) {
+      annotation = testClass.getAnnotation(a);
+    }
+    return findAnnotation(annotation, annotationClass, testClass, null, m,
+        new Pair<>(annotation, m));
+  }
+
+  private void transform(IAnnotation a, Class<?> testClass,
+      Constructor<?> testConstructor, Method testMethod)  {
     //
     // Transform @Test
     //
@@ -141,45 +168,42 @@ public class JDK15AnnotationFinder implements IAnnotationFinder {
   }
 
   @Override
-  public <A extends IAnnotation> A findAnnotation(Class cls, Class<A> annotationClass) {
+  public <A extends IAnnotation> A findAnnotation(Class<?> cls, Class<A> annotationClass) {
     final Class<? extends Annotation> a = m_annotationMap.get(annotationClass);
     if (a == null) {
-      throw new IllegalArgumentException("Java @Annotation class for '" + annotationClass + "' not found.");
+      throw new IllegalArgumentException("Java @Annotation class for '"
+          + annotationClass + "' not found.");
     }
-    return findAnnotation(cls, findAnnotationInSuperClasses(cls, a), annotationClass, cls, null, null);
+    Annotation annotation = findAnnotationInSuperClasses(cls, a);
+    return findAnnotation(annotation, annotationClass, cls, null, null,
+        new Pair<>(annotation, annotationClass));
   }
 
   @Override
-  public <A extends IAnnotation> A findAnnotation(Constructor cons, Class<A> annotationClass) {
+  public <A extends IAnnotation> A findAnnotation(Constructor<?> cons, Class<A> annotationClass) {
     final Class<? extends Annotation> a = m_annotationMap.get(annotationClass);
     if (a == null) {
-      throw new IllegalArgumentException("Java @Annotation class for '" + annotationClass + "' not found.");
+      throw new IllegalArgumentException("Java @Annotation class for '"
+          + annotationClass + "' not found.");
     }
-    return findAnnotation(cons.getDeclaringClass(), cons.getAnnotation(a), annotationClass, null, cons, null);
+    Annotation annotation = cons.getAnnotation(a);
+    return findAnnotation(annotation, annotationClass, cons.getDeclaringClass(), cons, null,
+        new Pair<>(annotation, cons));
   }
 
   private Map<Pair<Annotation, ?>, IAnnotation> m_annotations = Maps.newHashMap();
 
-  private <A extends IAnnotation> A findAnnotation(Class cls, Annotation a,
-                                                   Class<A> annotationClass,
-                                                   Class testClass, Constructor testConstructor, Method testMethod) {
-    final Pair<Annotation, ?> p;
-    if (testClass != null) {
-      p = new Pair<Annotation, Class>(a, testClass);
-    } else if (testConstructor != null) {
-      p = new Pair<Annotation, Constructor>(a, testConstructor);
-    } else {
-      p = new Pair<Annotation, Method>(a, testMethod);
-    }
-    //noinspection unchecked
-    A result = (A) m_annotations.get(p);
+  private <A extends IAnnotation> A findAnnotation(Annotation a,
+      Class<A> annotationClass, Class<?> testClass,
+      Constructor<?> testConstructor, Method testMethod, Pair<Annotation, ?> p) {
+    IAnnotation result = m_annotations.get(p);
     if (result == null) {
-      result = m_tagFactory.createTag(cls, a, annotationClass, m_transformer);
+      result = m_tagFactory.createTag(testClass, a, annotationClass, m_transformer);
       m_annotations.put(p, result);
       transform(result, testClass, testConstructor, testMethod);
     }
     //noinspection unchecked
-    return result;
+    return (A) result;
   }
 
   @Override
diff --git a/src/main/java/org/testng/internal/annotations/Sets.java b/src/main/java/org/testng/internal/annotations/Sets.java
deleted file mode 100755
index 2b3e4e6..0000000
--- a/src/main/java/org/testng/internal/annotations/Sets.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.testng.internal.annotations;
-
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-public class Sets {
-
-  public static <T> Set<T> newHashSet() {
-    return new HashSet<T>();
-  }
-
-  public static <T> Set<T> newLinkedHashSet() {
-    return new LinkedHashSet<T>();
-  }
-
-}
diff --git a/src/main/java/org/testng/junit/JUnit4TestMethod.java b/src/main/java/org/testng/junit/JUnit4TestMethod.java
index 77ddf6a..04a0e79 100644
--- a/src/main/java/org/testng/junit/JUnit4TestMethod.java
+++ b/src/main/java/org/testng/junit/JUnit4TestMethod.java
@@ -11,7 +11,7 @@ import org.testng.internal.Utils;
 public class JUnit4TestMethod extends JUnitTestMethod {
 
     public JUnit4TestMethod(JUnitTestClass owner, Description desc) {
-        super(owner, getMethod(desc), desc);
+        super(owner, desc.getMethodName(), getMethod(desc), desc);
     }
 
     @Override
@@ -22,6 +22,11 @@ public class JUnit4TestMethod extends JUnitTestMethod {
     private static Method getMethod(Description desc) {
         Class<?> c = desc.getTestClass();
         String method = desc.getMethodName();
+        // remove [index] from method name in case of parameterized test
+        int idx = method.indexOf('[');
+        if (idx != -1) {
+            method = method.substring(0, idx);
+        }
         try {
             return c.getMethod(method);
         } catch (Throwable t) {
diff --git a/src/main/java/org/testng/junit/JUnit4TestRunner.java b/src/main/java/org/testng/junit/JUnit4TestRunner.java
index 2b81fcc..ef627f2 100644
--- a/src/main/java/org/testng/junit/JUnit4TestRunner.java
+++ b/src/main/java/org/testng/junit/JUnit4TestRunner.java
@@ -198,7 +198,7 @@ public class JUnit4TestRunner implements IJUnitTestRunner {
                     0,
                     null);
 
-            InvokedMethod im = new InvokedMethod(tr.getTestClass(), tr.getMethod(), new Object[0], true, false, tr.getStartMillis(), tr);
+            InvokedMethod im = new InvokedMethod(tr.getTestClass(), tr.getMethod(), new Object[0], tr.getStartMillis(), tr);
             m_parentRunner.addInvokedMethod(im);
             for (IInvokedMethodListener l: m_invokeListeners) {
                 l.beforeInvocation(im, tr);
diff --git a/src/main/java/org/testng/junit/JUnitTestMethod.java b/src/main/java/org/testng/junit/JUnitTestMethod.java
index 2ee0e7a..91ee459 100644
--- a/src/main/java/org/testng/junit/JUnitTestMethod.java
+++ b/src/main/java/org/testng/junit/JUnitTestMethod.java
@@ -12,7 +12,11 @@ import org.testng.internal.BaseTestMethod;
 public abstract class JUnitTestMethod extends BaseTestMethod {
 
     protected JUnitTestMethod(JUnitTestClass owner, Method method, Object instance) {
-        super(method, null, instance);
+        this(owner, method.getName(), method, instance);
+    }
+
+    protected JUnitTestMethod(JUnitTestClass owner, String methodName, Method method, Object instance) {
+        super(methodName, method, null, instance);
         setTestClass(owner);
         owner.getTestMethodList().add(this);
     }
diff --git a/src/main/java/org/testng/junit/JUnitTestRunner.java b/src/main/java/org/testng/junit/JUnitTestRunner.java
index ac44b62..402d530 100755
--- a/src/main/java/org/testng/junit/JUnitTestRunner.java
+++ b/src/main/java/org/testng/junit/JUnitTestRunner.java
@@ -133,7 +133,7 @@ public class JUnitTestRunner implements TestListener, IJUnitTestRunner {
       m_parentRunner.addPassedTest(tm, tr);
     }
 
-    InvokedMethod im = new InvokedMethod(test, tm, new Object[0], true, false, tri.m_start, tr);
+    InvokedMethod im = new InvokedMethod(test, tm, new Object[0], tri.m_start, tr);
     m_parentRunner.addInvokedMethod(im);
     m_methods.add(tm);
     for (IInvokedMethodListener l: m_invokedMethodListeners) {
diff --git a/src/main/java/org/testng/remote/SuiteDispatcher.java b/src/main/java/org/testng/remote/SuiteDispatcher.java
index f37bafa..65a08e6 100644
--- a/src/main/java/org/testng/remote/SuiteDispatcher.java
+++ b/src/main/java/org/testng/remote/SuiteDispatcher.java
@@ -115,6 +115,7 @@ public class SuiteDispatcher
 						tmpSuite.setName("Temporary suite for " + test.getName());
 						tmpSuite.setParallel(suite.getParallel());
 						tmpSuite.setParentModule(suite.getParentModule());
+						tmpSuite.setGuiceStage(suite.getGuiceStage());
 						tmpSuite.setParameters(suite.getParameters());
 						tmpSuite.setThreadCount(suite.getThreadCount());
             tmpSuite.setDataProviderThreadCount(suite.getDataProviderThreadCount());
diff --git a/src/main/java/org/testng/reporters/FailedReporter.java b/src/main/java/org/testng/reporters/FailedReporter.java
index 5a89a10..3765290 100755
--- a/src/main/java/org/testng/reporters/FailedReporter.java
+++ b/src/main/java/org/testng/reporters/FailedReporter.java
@@ -9,9 +9,9 @@ import org.testng.ITestResult;
 import org.testng.TestListenerAdapter;
 import org.testng.collections.Lists;
 import org.testng.collections.Maps;
+import org.testng.collections.Sets;
 import org.testng.internal.MethodHelper;
 import org.testng.internal.Utils;
-import org.testng.internal.annotations.Sets;
 import org.testng.xml.XmlClass;
 import org.testng.xml.XmlInclude;
 import org.testng.xml.XmlSuite;
diff --git a/src/main/java/org/testng/reporters/Files.java b/src/main/java/org/testng/reporters/Files.java
index 1df694a..dc66104 100644
--- a/src/main/java/org/testng/reporters/Files.java
+++ b/src/main/java/org/testng/reporters/Files.java
@@ -2,6 +2,7 @@ package org.testng.reporters;
 
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
+import java.io.Closeable;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -17,7 +18,9 @@ import java.io.Writer;
 public class Files {
 
   public static String readFile(File f) throws IOException {
-    return readFile(new FileInputStream(f));
+    try (InputStream is = new FileInputStream(f)) {
+      return readFile(is);
+    }
   }
 
   public static String readFile(InputStream is) throws IOException {
@@ -45,12 +48,13 @@ public class Files {
       to.getParentFile().mkdirs();
     }
 
-    OutputStream os = new FileOutputStream(to);
-    byte[] buffer = new byte[65536];
-    int count = from.read(buffer);
-    while (count > 0) {
-      os.write(buffer, 0, count);
-      count = from.read(buffer);
+    try (OutputStream os = new FileOutputStream(to)) {
+      byte[] buffer = new byte[65536];
+      int count = from.read(buffer);
+      while (count > 0) {
+        os.write(buffer, 0, count);
+        count = from.read(buffer);
+      }
     }
   }
 
diff --git a/src/main/java/org/testng/reporters/JUnitReportReporter.java b/src/main/java/org/testng/reporters/JUnitReportReporter.java
index 237b32e..95c3b19 100644
--- a/src/main/java/org/testng/reporters/JUnitReportReporter.java
+++ b/src/main/java/org/testng/reporters/JUnitReportReporter.java
@@ -9,8 +9,8 @@ import org.testng.ITestResult;
 import org.testng.collections.ListMultiMap;
 import org.testng.collections.Lists;
 import org.testng.collections.Maps;
+import org.testng.collections.Sets;
 import org.testng.internal.Utils;
-import org.testng.internal.annotations.Sets;
 import org.testng.xml.XmlSuite;
 
 import java.io.File;
@@ -100,9 +100,9 @@ public class JUnitReportReporter implements IReporter {
         boolean isSuccess = tr.getStatus() == ITestResult.SUCCESS;
         if (! isSuccess) {
           if (tr.getThrowable() instanceof AssertionError) {
-            errors++;
-          } else {
             failures++;
+          } else {
+            errors++;
           }
         }
 
@@ -123,7 +123,7 @@ public class JUnitReportReporter implements IReporter {
           testTag.message = t.getMessage();
           testTag.type = t.getClass().getName();
           testTag.stackTrace = sw.toString();
-          testTag.errorTag = tr.getThrowable() instanceof AssertionError ? "error" : "failure";
+          testTag.errorTag = tr.getThrowable() instanceof AssertionError ? "failure" : "error";
         }
         totalTime += time;
         testCount++;
diff --git a/src/main/java/org/testng/reporters/JUnitXMLReporter.java b/src/main/java/org/testng/reporters/JUnitXMLReporter.java
index cecadd4..73648fd 100755
--- a/src/main/java/org/testng/reporters/JUnitXMLReporter.java
+++ b/src/main/java/org/testng/reporters/JUnitXMLReporter.java
@@ -6,9 +6,9 @@ import org.testng.ITestNGMethod;
 import org.testng.ITestResult;
 import org.testng.collections.Lists;
 import org.testng.collections.Maps;
+import org.testng.collections.Sets;
 import org.testng.internal.IResultListener2;
 import org.testng.internal.Utils;
-import org.testng.internal.annotations.Sets;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
diff --git a/src/main/java/org/testng/reporters/JqReporter.java b/src/main/java/org/testng/reporters/JqReporter.java
index a1de95a..6e0cb15 100644
--- a/src/main/java/org/testng/reporters/JqReporter.java
+++ b/src/main/java/org/testng/reporters/JqReporter.java
@@ -152,7 +152,7 @@ public class JqReporter implements IReporter {
     xsb.pop(D);
 
     xsb.push(D, C, "test-content");
-    for (Class<?> c : map.getKeys()) {
+    for (Class<?> c : map.keySet()) {
       xsb.push(D, C, C);
       xsb.push(D, C, "class-header");
 
diff --git a/src/main/java/org/testng/reporters/jq/IgnoredMethodsPanel.java b/src/main/java/org/testng/reporters/jq/IgnoredMethodsPanel.java
index 767099c..41f35e3 100644
--- a/src/main/java/org/testng/reporters/jq/IgnoredMethodsPanel.java
+++ b/src/main/java/org/testng/reporters/jq/IgnoredMethodsPanel.java
@@ -32,7 +32,7 @@ public class IgnoredMethodsPanel extends BaseMultiSuitePanel {
       map.put(method.getTestClass().getRealClass(), method);
     }
 
-    for (Class<?> c : map.getKeys()) {
+    for (Class<?> c : map.keySet()) {
       xsb.push(D, C, "ignored-class-div");
       xsb.addRequired(S, c.getName(), C, "ignored-class-name");
       xsb.push(D, C, "ignored-methods-div");
diff --git a/src/main/java/org/testng/reporters/jq/Main.java b/src/main/java/org/testng/reporters/jq/Main.java
index fc763ee..ad2c4e0 100644
--- a/src/main/java/org/testng/reporters/jq/Main.java
+++ b/src/main/java/org/testng/reporters/jq/Main.java
@@ -71,16 +71,17 @@ public class Main implements IReporter {
 
     String all;
     try {
-      InputStream header = getClass().getResourceAsStream("/header");
-      if (header == null) {
-        throw new RuntimeException("Couldn't find resource header");
-      } else {
+      try (InputStream header = getClass().getResourceAsStream("/header")) {
+        if (header == null) {
+          throw new RuntimeException("Couldn't find resource header");
+        }
         for (String fileName : RESOURCES) {
-          InputStream is = getClass().getResourceAsStream("/" + fileName);
-          if (is == null) {
-            throw new AssertionError("Couldn't find resource: " + fileName);
+          try (InputStream is = getClass().getResourceAsStream("/" + fileName)) {
+            if (is == null) {
+              throw new AssertionError("Couldn't find resource: " + fileName);
+            }
+            Files.copyFile(is, new File(m_outputDirectory, fileName));
           }
-          Files.copyFile(is, new File(m_outputDirectory, fileName));
         }
         all = Files.readFile(header);
         Utils.writeUtf8File(m_outputDirectory, "index.html", xsb, all); 
diff --git a/src/main/java/org/testng/reporters/jq/ResultsByClass.java b/src/main/java/org/testng/reporters/jq/ResultsByClass.java
index a1536b7..6864b05 100644
--- a/src/main/java/org/testng/reporters/jq/ResultsByClass.java
+++ b/src/main/java/org/testng/reporters/jq/ResultsByClass.java
@@ -33,6 +33,7 @@ public class ResultsByClass {
   }
 
   public List<Class<?>> getClasses() {
+    // TODO do not use deprecated method
     return m_results.getKeys();
   }
 }
diff --git a/src/main/java/org/testng/xml/LaunchSuite.java b/src/main/java/org/testng/xml/LaunchSuite.java
index dd0f8e4..9731b25 100755
--- a/src/main/java/org/testng/xml/LaunchSuite.java
+++ b/src/main/java/org/testng/xml/LaunchSuite.java
@@ -10,8 +10,10 @@ import org.testng.remote.RemoteTestNG;
 import org.testng.reporters.XMLStringBuffer;
 
 import java.io.File;
-import java.io.FileWriter;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -205,7 +207,7 @@ public abstract class LaunchSuite {
     protected void saveSuiteContent(final File file, final XMLStringBuffer content) {
 
       try {
-        FileWriter fw = new FileWriter(file);
+        OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(file), Charset.forName("UTF-8"));
         try {
           fw.write(content.getStringBuffer().toString());
         }
diff --git a/src/main/java/org/testng/xml/Parameters.java b/src/main/java/org/testng/xml/Parameters.java
index 2d87421..3c79901 100644
--- a/src/main/java/org/testng/xml/Parameters.java
+++ b/src/main/java/org/testng/xml/Parameters.java
@@ -1,6 +1,7 @@
 package org.testng.xml;
 
 import org.testng.collections.ListMultiMap;
+import org.testng.collections.Maps;
 
 import java.util.List;
 
@@ -10,8 +11,8 @@ import java.util.List;
  */
 public class Parameters {
 
-  private ListMultiMap<String, String> m_localParameters = ListMultiMap.create();
-  private ListMultiMap<String, String> m_allParameters = ListMultiMap.create();
+  private ListMultiMap<String, String> m_localParameters = Maps.newListMultiMap();
+  private ListMultiMap<String, String> m_allParameters = Maps.newListMultiMap();
 
   public List<String> getLocalParameter(String name) {
     return m_localParameters.get(name);
diff --git a/src/main/java/org/testng/xml/TestNGContentHandler.java b/src/main/java/org/testng/xml/TestNGContentHandler.java
index cfa4654..62951f3 100755
--- a/src/main/java/org/testng/xml/TestNGContentHandler.java
+++ b/src/main/java/org/testng/xml/TestNGContentHandler.java
@@ -164,6 +164,10 @@ public class TestNGContentHandler extends DefaultHandler {
       if (parentModule != null) {
         m_currentSuite.setParentModule(parentModule);
       }
+      String guiceStage = attributes.getValue("guice-stage");
+      if (guiceStage != null) {
+        m_currentSuite.setGuiceStage(guiceStage);
+      }
       String configFailurePolicy = attributes.getValue("configfailurepolicy");
       if (null != configFailurePolicy) {
         if (XmlSuite.SKIP.equals(configFailurePolicy) || XmlSuite.CONTINUE.equals(configFailurePolicy)) {
diff --git a/src/main/java/org/testng/xml/XmlClass.java b/src/main/java/org/testng/xml/XmlClass.java
index 7022b72..c588965 100755
--- a/src/main/java/org/testng/xml/XmlClass.java
+++ b/src/main/java/org/testng/xml/XmlClass.java
@@ -253,17 +253,10 @@ public class XmlClass implements Serializable, Cloneable {
     if (getClass() != obj.getClass())
       return XmlSuite.f();
     XmlClass other = (XmlClass) obj;
-    if (m_class == null) {
-
-      if (other.m_class != null) {
-        return false;
-      }
-    } else if (m_class != null && other.m_class != null && !m_class.equals(other.m_class)) {
-      return false;
-    } else if (other.m_loadClasses != m_loadClasses) {
-      return false;
+    if (other.m_loadClasses != m_loadClasses) {
+      return XmlSuite.f();
     } else if (!m_excludedMethods.equals(other.m_excludedMethods)) {
-      return false;
+      return XmlSuite.f();
     }
     if (m_includedMethods == null) {
       if (other.m_includedMethods != null)
diff --git a/src/main/java/org/testng/xml/XmlSuite.java b/src/main/java/org/testng/xml/XmlSuite.java
index bdcc3e5..4efd874 100755
--- a/src/main/java/org/testng/xml/XmlSuite.java
+++ b/src/main/java/org/testng/xml/XmlSuite.java
@@ -63,6 +63,7 @@ public class XmlSuite implements Serializable, Cloneable {
   private String m_parallel = DEFAULT_PARALLEL;
 
   private String m_parentModule = "";
+  private String m_guiceStage = "";
 
   /** Whether to SKIP or CONTINUE to re-attempt failed configuration methods. */
   public static String DEFAULT_CONFIG_FAILURE_POLICY = SKIP;
@@ -163,6 +164,10 @@ public class XmlSuite implements Serializable, Cloneable {
     return m_parentModule;
   }
 
+  public String getGuiceStage() {
+    return m_guiceStage;
+  }
+
   public ITestObjectFactory getObjectFactory() {
     return m_objectFactory;
   }
@@ -183,6 +188,10 @@ public class XmlSuite implements Serializable, Cloneable {
     m_parentModule = parentModule;
   }
 
+  public void setGuiceStage(String guiceStage) {
+    m_guiceStage = guiceStage;
+  }
+
   /**
    * Sets the configuration failure policy.
    * @param configFailurePolicy the config failure policy
@@ -458,6 +467,9 @@ public class XmlSuite implements Serializable, Cloneable {
     if (isStringNotEmpty(m_parentModule)) {
       p.setProperty("parent-module", getParentModule());
     }
+    if (isStringNotEmpty(m_guiceStage)) {
+      p.setProperty("guice-stage", getGuiceStage());
+    }
     XmlUtils.setProperty(p, "allow-return-values", String.valueOf(getAllowReturnValues()),
         DEFAULT_ALLOW_RETURN_VALUES.toString());
     xsb.push("suite", p);
@@ -587,6 +599,7 @@ public class XmlSuite implements Serializable, Cloneable {
     result.setListeners(getListeners());
     result.setParallel(getParallel());
     result.setParentModule(getParentModule());
+    result.setGuiceStage(getGuiceStage());
     result.setConfigFailurePolicy(getConfigFailurePolicy());
     result.setThreadCount(getThreadCount());
     result.setDataProviderThreadCount(getDataProviderThreadCount());
@@ -599,6 +612,7 @@ public class XmlSuite implements Serializable, Cloneable {
     result.setSkipFailedInvocationCounts(skipFailedInvocationCounts());
     result.setObjectFactory(getObjectFactory());
     result.setAllowReturnValues(getAllowReturnValues());
+    result.setTimeOut(getTimeOut());
     return result;
   }
 
diff --git a/src/main/java/org/testng/xml/XmlTest.java b/src/main/java/org/testng/xml/XmlTest.java
index cbc8c12..47a7e6f 100755
--- a/src/main/java/org/testng/xml/XmlTest.java
+++ b/src/main/java/org/testng/xml/XmlTest.java
@@ -430,6 +430,10 @@ public class XmlTest implements Serializable, Cloneable {
       m_timeOut = Long.toString(timeOut);
   }
 
+  private void setTimeOut(String timeOut) {
+      m_timeOut = timeOut;
+  }
+
   public void setExpression(String expression) {
     setBeanShellExpression(expression);
   }
@@ -651,6 +655,7 @@ public class XmlTest implements Serializable, Cloneable {
     result.setVerbose(getVerbose());
     result.setParameters(getLocalParameters());
     result.setXmlPackages(getXmlPackages());
+    result.setTimeOut(getTimeOut());
 
     Map<String, List<String>> metagroups = getMetaGroups();
     for (Map.Entry<String, List<String>> group: metagroups.entrySet()) {
diff --git a/src/main/java/org/testng/xml/dom/XDom.java b/src/main/java/org/testng/xml/dom/XDom.java
index 0bc2d76..3bffb89 100644
--- a/src/main/java/org/testng/xml/dom/XDom.java
+++ b/src/main/java/org/testng/xml/dom/XDom.java
@@ -8,6 +8,7 @@ import javax.xml.xpath.XPathExpressionException;
 import org.testng.Assert;
 import org.testng.collections.ListMultiMap;
 import org.testng.collections.Lists;
+import org.testng.collections.Maps;
 import org.testng.internal.collections.Pair;
 import org.testng.xml.XmlDefine;
 import org.testng.xml.XmlGroups;
@@ -76,7 +77,7 @@ public class XDom {
       IllegalAccessException, XPathExpressionException, SecurityException, IllegalArgumentException, NoSuchMethodException, InvocationTargetException {
     p("populateChildren: " + root.getLocalName());
     NodeList childNodes = root.getChildNodes();
-    ListMultiMap<String, Object> children = ListMultiMap.create();
+    ListMultiMap<String, Object> children = Maps.newListMultiMap();
     for (int i = 0; i < childNodes.getLength(); i++) {
       Node item = childNodes.item(i);
       if (item.getAttributes() != null) {
diff --git a/src/main/java/testng-1.0.dtd.html b/src/main/java/testng-1.0.dtd.html
index abdc835..53873aa 100644
--- a/src/main/java/testng-1.0.dtd.html
+++ b/src/main/java/testng-1.0.dtd.html
@@ -64,7 +64,7 @@ Cedric Beust & Alexandru Popescu
 @attr  time-out     The time to wait in milliseconds before aborting the
                 method (if <span class="attribute">parallel="methods"</span> ) or the test (parallel="tests")
 @attr  skipfailedinvocationCounts Whether to skip failed invocations.
- at attr  data-provider-thread-count An integer givin the size of the thread pool to use
+ at attr  data-provider-thread-count An integer giving the size of the thread pool to use
        for parallel data providers.
 @attr  object-factory A class that implements IObjectFactory that will be used to
        instantiate the test objects.
diff --git a/src/main/java/org/testng/internal/Version.java b/src/main/resources/org/testng/internal/Version.java
similarity index 76%
rename from src/main/java/org/testng/internal/Version.java
rename to src/main/resources/org/testng/internal/Version.java
index f861d9d..ab56291 100644
--- a/src/main/java/org/testng/internal/Version.java
+++ b/src/main/resources/org/testng/internal/Version.java
@@ -1,7 +1,7 @@
 package org.testng.internal;
 
 public class Version {
-  public static final String VERSION = "6.8.9beta";
+  public static final String VERSION = "${project.version}";
 
   public static void displayBanner() {
     System.out.println("...\n... TestNG " + VERSION + " by Cédric Beust (cedric at beust.com)\n...\n");
diff --git a/src/main/resources/testng-1.0.dtd b/src/main/resources/testng-1.0.dtd
index f6920a3..7993989 100755
--- a/src/main/resources/testng-1.0.dtd
+++ b/src/main/resources/testng-1.0.dtd
@@ -50,7 +50,7 @@ Cedric Beust & Alexandru Popescu
 @attr  time-out     The time to wait in milliseconds before aborting the
                 method (if parallel="methods") or the test (parallel="tests")
 @attr  skipfailedinvocationcounts Whether to skip failed invocations.
- at attr  data-provider-thread-count An integer givin the size of the thread pool to use
+ at attr  data-provider-thread-count An integer giving the size of the thread pool to use
        for parallel data providers.
 @attr  object-factory A class that implements IObjectFactory that will be used to
        instantiate the test objects.
@@ -62,6 +62,7 @@ Cedric Beust & Alexandru Popescu
     verbose CDATA #IMPLIED
     parallel (false | methods | tests | classes | instances) "false"
     parent-module CDATA #IMPLIED
+    guice-stage CDATA #IMPLIED
     configfailurepolicy (skip | continue) "skip"
     thread-count CDATA "5"
     annotations CDATA #IMPLIED
diff --git a/src/test/java/org/testng/AssertTest.java b/src/test/java/org/testng/AssertTest.java
index 10e3af8..28a97b2 100644
--- a/src/test/java/org/testng/AssertTest.java
+++ b/src/test/java/org/testng/AssertTest.java
@@ -2,7 +2,7 @@ package org.testng;
 
 import org.testng.annotations.Test;
 import org.testng.collections.Maps;
-import org.testng.internal.annotations.Sets;
+import org.testng.collections.Sets;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -115,4 +115,72 @@ public class AssertTest {
 
     Assert.assertEquals(mapActual, mapExpected);
   }
+
+  @Test(expectedExceptions = AssertionError.class)
+  public void assertEqualsSymmetricScalar() {
+    Assert.assertEquals(new Asymmetric(42, 'd'), new Contrived(42));
+  }
+
+  @Test(expectedExceptions = AssertionError.class)
+  public void assertEqualsSymmetricArrays() {
+    Object[] actual = {new Integer(1), new Asymmetric(42, 'd'), "inDay"};
+    Object[] expected = {new Integer(1), new Contrived(42), "inDay"};
+    Assert.assertEquals(actual, expected);
+  }
+
+  class Contrived {
+
+    int integer;
+
+    Contrived(int integer){
+      this.integer = integer;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (!(o instanceof Contrived)) return false;
+
+      Contrived contrived = (Contrived) o;
+
+      if (integer != contrived.integer) return false;
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return integer;
+    }
+  }
+
+  class Asymmetric extends Contrived {
+
+      char character;
+
+      Asymmetric(int integer, char character) {
+          super(integer);
+          this.character = character;
+      }
+
+      @Override
+      public boolean equals(Object o) {
+          if (this == o) return true;
+          if (!(o instanceof Asymmetric)) return false;
+          if (!super.equals(o)) return false;
+
+          Asymmetric that = (Asymmetric) o;
+
+          if (character != that.character) return false;
+
+          return true;
+      }
+
+      @Override
+      public int hashCode() {
+          int result = super.hashCode();
+          result = 31 * result + (int) character;
+          return result;
+      }
+  }
 }
diff --git a/src/test/java/org/testng/internal/MethodInstanceTest.java b/src/test/java/org/testng/internal/MethodInstanceTest.java
index 36bf2e1..f3c81dc 100644
--- a/src/test/java/org/testng/internal/MethodInstanceTest.java
+++ b/src/test/java/org/testng/internal/MethodInstanceTest.java
@@ -406,6 +406,11 @@ public class MethodInstanceTest {
     }
 
     @Override
+    public int getTotalInvocationCount() {
+      return 0;
+    }
+
+    @Override
     public void setInvocationCount(int count) {
     }
 
diff --git a/src/test/java/test/EclipseTest.java b/src/test/java/test/EclipseTest.java
index 8c46e99..6260dad 100644
--- a/src/test/java/test/EclipseTest.java
+++ b/src/test/java/test/EclipseTest.java
@@ -14,6 +14,7 @@ public class EclipseTest {
 
   @Test
   public void xmlFileShouldBeRunAtItsPlaceAndNotCopied(ITestContext ctx) {
-    Assert.assertTrue(ctx.getSuite().getXmlSuite().getFileName().contains("src/test/resources"));
+    String fileName = ctx.getSuite().getXmlSuite().getFileName().replace("\\", "/");
+    Assert.assertTrue(fileName.contains("src/test/resources"));
   }
 }
diff --git a/src/test/java/test/InvokedMethodNameListener.java b/src/test/java/test/InvokedMethodNameListener.java
new file mode 100644
index 0000000..69e70e3
--- /dev/null
+++ b/src/test/java/test/InvokedMethodNameListener.java
@@ -0,0 +1,26 @@
+package test;
+
+import org.testng.IInvokedMethod;
+import org.testng.IInvokedMethodListener;
+import org.testng.ITestResult;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class InvokedMethodNameListener implements IInvokedMethodListener {
+
+  private final List<String> invokedMethodNames = new ArrayList<>();
+
+  @Override
+  public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
+    invokedMethodNames.add(method.getTestMethod().getConstructorOrMethod().getName());
+  }
+
+  @Override
+  public void afterInvocation(IInvokedMethod method, ITestResult testResult) { }
+
+  public List<String> getInvokedMethodNames() {
+    return Collections.unmodifiableList(invokedMethodNames);
+  }
+}
diff --git a/src/test/java/test/JUnit4Test.java b/src/test/java/test/JUnit4Test.java
index 98b1f72..d9d9f27 100644
--- a/src/test/java/test/JUnit4Test.java
+++ b/src/test/java/test/JUnit4Test.java
@@ -3,6 +3,7 @@ package test;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 import test.junit4.JUnit4Child;
+import test.junit4.JUnit4ParameterizedTest;
 import test.junit4.JUnit4Sample2;
 import test.junit4.JUnit4SampleSuite;
 
@@ -77,4 +78,19 @@ public class JUnit4Test extends BaseTest {
         verifyTests("Failed", failed, getFailedTests());
         verifyTests("Skipped", skipped, getSkippedTests());
     }
+
+    @Test
+    public void testTestParameterized() {
+        addClass("test.junit4.JUnit4ParameterizedTest");
+        assert getTest().isJUnit();
+
+        run();
+        String[] passed = JUnit4ParameterizedTest.EXPECTED;
+        String[] failed = JUnit4ParameterizedTest.FAILED;
+        String[] skipped = JUnit4ParameterizedTest.SKIPPED;
+
+        verifyTests("Passed", passed, getPassedTests());
+        verifyTests("Failed", failed, getFailedTests());
+        verifyTests("Skipped", skipped, getSkippedTests());
+    }
 }
diff --git a/src/test/java/test/annotationtransformer/AnnotationTransformerInvocationCountTest.java b/src/test/java/test/annotationtransformer/AnnotationTransformerInvocationCountTest.java
new file mode 100644
index 0000000..9557408
--- /dev/null
+++ b/src/test/java/test/annotationtransformer/AnnotationTransformerInvocationCountTest.java
@@ -0,0 +1,32 @@
+package test.annotationtransformer;
+
+import org.testng.IAnnotationTransformer;
+import org.testng.annotations.ITestAnnotation;
+import org.testng.annotations.Test;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+public class AnnotationTransformerInvocationCountTest {
+
+  public static class InvocationCountTransformer implements IAnnotationTransformer {
+
+    private final int invocationCount;
+
+    public InvocationCountTransformer(int invocationCount) {
+      this.invocationCount = invocationCount;
+    }
+
+    @Override
+    public void transform(ITestAnnotation annotation, Class testClass,
+                          Constructor testConstructor, Method testMethod) {
+      if ("concurrencyTest".equals(testMethod.getName())) {
+        annotation.setInvocationCount(invocationCount);
+      }
+    }
+  }
+
+  @Test(invocationCount = 3)
+  public void concurrencyTest() {
+  }
+}
diff --git a/src/test/java/test/annotationtransformer/AnnotationTransformerSampleTest.java b/src/test/java/test/annotationtransformer/AnnotationTransformerSampleTest.java
index 6ae3efd..e930be7 100644
--- a/src/test/java/test/annotationtransformer/AnnotationTransformerSampleTest.java
+++ b/src/test/java/test/annotationtransformer/AnnotationTransformerSampleTest.java
@@ -14,25 +14,21 @@ public class AnnotationTransformerSampleTest {
   @Test(invocationCount = 2)
   public void two() {
     m_two++;
-    ppp("Should be invoked 2 times");
   }
 
   @Test(invocationCount = 5)
   public void four() {
     m_four++;
-    ppp("Should be invoked 4 times");
   }
 
   @Test(invocationCount = 5)
   public void three() {
     m_three++;
-    ppp("Should be invoked 3 times");
   }
 
   @Test
   public void five() {
     m_five++;
-    ppp("Should be invoked 5 times");
   }
 
   @Test(dependsOnMethods = {"two", "three", "four", "five"})
@@ -41,20 +37,5 @@ public class AnnotationTransformerSampleTest {
     Assert.assertEquals(m_three, 3);
     Assert.assertEquals(m_four, 4);
     Assert.assertEquals(m_five, 5);
-
-  }
-
-  public static void main(String[] argv) {
-    TestNG tng = new TestNG();
-    tng.setAnnotationTransformer(new MyTransformer());
-    tng.setTestClasses(new Class[] { AnnotationTransformerSampleTest.class});
-
-    tng.run();
-  }
-
-  private void ppp(String string) {
-    if (false) {
-      System.out.println("[AnnotationTransformerSampleTest] " + string);
-    }
   }
 }
diff --git a/src/test/java/test/annotationtransformer/AnnotationTransformerTest.java b/src/test/java/test/annotationtransformer/AnnotationTransformerTest.java
index 223dd91..548ebf2 100644
--- a/src/test/java/test/annotationtransformer/AnnotationTransformerTest.java
+++ b/src/test/java/test/annotationtransformer/AnnotationTransformerTest.java
@@ -1,5 +1,6 @@
 package test.annotationtransformer;
 
+import org.assertj.core.api.iterable.Extractor;
 import org.testng.Assert;
 import org.testng.IAnnotationTransformer;
 import org.testng.ITestResult;
@@ -16,24 +17,40 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 
+import static org.assertj.core.api.Assertions.assertThat;
+
 public class AnnotationTransformerTest extends SimpleBaseTest {
 
+  private static final Extractor NAME_EXTRACTOR = new Extractor<ITestResult, String>() {
+    @Override
+    public String extract(ITestResult input) {
+      return input.getName();
+    }
+  };
+
   /**
    * Make sure that without a transformer in place, a class-level
    * annotation invocationCount is correctly used.
    */
   @Test
   public void verifyAnnotationWithoutTransformer() {
-    TestNG tng = new TestNG();
-    tng.setVerbose(0);
-    tng.setTestClasses(new Class[] { AnnotationTransformerClassInvocationSampleTest.class});
+    TestNG tng = create(AnnotationTransformerSampleTest.class);
+    tng.setPreserveOrder(true);
+
     TestListenerAdapter tla = new TestListenerAdapter();
     tng.addListener(tla);
 
     tng.run();
 
-    List passed = tla.getPassedTests();
-    Assert.assertEquals(passed.size(), 6);
+    assertThat(tla.getPassedTests()).extracting(NAME_EXTRACTOR)
+        .containsExactly(
+            "five",
+            "four", "four", "four", "four", "four",
+            "three", "three", "three", "three", "three",
+            "two", "two"
+        );
+    assertThat(tla.getFailedTests()).extracting(NAME_EXTRACTOR)
+        .containsExactly("verify");
   }
 
   /**
@@ -41,17 +58,28 @@ public class AnnotationTransformerTest extends SimpleBaseTest {
    */
   @Test
   public void verifyAnnotationTransformerMethod() {
-    TestNG tng = new TestNG();
-    tng.setVerbose(0);
-    tng.setAnnotationTransformer(new MyTransformer());
-    tng.setTestClasses(new Class[] { AnnotationTransformerSampleTest.class});
+    TestNG tng = create(AnnotationTransformerSampleTest.class);
+    tng.setPreserveOrder(true);
+
+    MyTransformer transformer = new MyTransformer();
+    tng.setAnnotationTransformer(transformer);
+
     TestListenerAdapter tla = new TestListenerAdapter();
     tng.addListener(tla);
 
     tng.run();
 
-    List passed = tla.getPassedTests();
-    Assert.assertEquals(passed.size(), 15);
+    assertThat(transformer.getMethodNames()).contains("two", "three", "four", "five", "verify");
+
+    assertThat(tla.getPassedTests()).extracting(NAME_EXTRACTOR)
+        .containsExactly(
+            "five", "five", "five", "five", "five",
+            "four", "four", "four", "four",
+            "three", "three", "three",
+            "two", "two",
+            "verify"
+        );
+    assertThat(tla.getFailedTests()).isEmpty();
   }
 
   /**
@@ -135,6 +163,28 @@ public class AnnotationTransformerTest extends SimpleBaseTest {
     Assert.assertEquals(tla.getPassedTests().size(), 1);
   }
 
+  @Test(description = "Test for issue #605")
+  public void verifyInvocationCountTransformer() {
+    TestNG tng = create();
+    tng.setTestClasses(new Class[] { AnnotationTransformerInvocationCountTest.class });
+    TestListenerAdapter tla = new TestListenerAdapter();
+    tng.addListener(tla);
+
+    tng.run();
+
+    Assert.assertEquals(tla.getPassedTests().size(), 3);
+
+    tng = create();
+    tng.setAnnotationTransformer(new AnnotationTransformerInvocationCountTest.InvocationCountTransformer(5));
+    tng.setTestClasses(new Class[]{AnnotationTransformerInvocationCountTest.class});
+    tla = new TestListenerAdapter();
+    tng.addListener(tla);
+
+    tng.run();
+
+    Assert.assertEquals(tla.getPassedTests().size(), 5);
+  }
+
   @Test
   public void annotationTransformerInXmlShouldBeRun() throws Exception {
     String xml = "<suite name=\"SingleSuite\" >" +
diff --git a/src/test/java/test/annotationtransformer/MyTransformer.java b/src/test/java/test/annotationtransformer/MyTransformer.java
index 577003d..b3eeeb4 100644
--- a/src/test/java/test/annotationtransformer/MyTransformer.java
+++ b/src/test/java/test/annotationtransformer/MyTransformer.java
@@ -5,32 +5,34 @@ import org.testng.annotations.ITestAnnotation;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
 
 public class MyTransformer implements IAnnotationTransformer {
 
+  private final List<String> methodNames = new ArrayList<>();
+
   @Override
   public void transform(ITestAnnotation annotation, Class testClass,
-      Constructor testConstructor, Method testMethod)
-  {
+      Constructor testConstructor, Method testMethod) {
     annotation.setTimeOut(10000);
     if (testMethod != null) {
-      String name = testMethod.getName();
-      if ("three".equals(name)) {
-        annotation.setInvocationCount(3);
-      }
-      else if ("four".equals(name)) {
-        annotation.setInvocationCount(4);
-      }
-      else if ("five".equals(name)) {
-        annotation.setInvocationCount(5);
+      switch (testMethod.getName()) {
+        case "three":
+          annotation.setInvocationCount(3);
+          break;
+        case "four":
+          annotation.setInvocationCount(4);
+          break;
+        case "five":
+          annotation.setInvocationCount(5);
+          break;
       }
+      methodNames.add(testMethod.getName());
     }
   }
 
-  private void ppp(String string) {
-    System.out.println("[MyTransformer] " + string);
+  public List<String> getMethodNames() {
+    return methodNames;
   }
-
-
-
 }
diff --git a/src/test/java/test/asserttests/AssertTest.java b/src/test/java/test/asserttests/AssertTest.java
index fc5f0b6..c1ba49d 100644
--- a/src/test/java/test/asserttests/AssertTest.java
+++ b/src/test/java/test/asserttests/AssertTest.java
@@ -2,7 +2,7 @@ package test.asserttests;
 
 import org.testng.Assert;
 import org.testng.annotations.Test;
-import org.testng.internal.annotations.Sets;
+import org.testng.collections.Sets;
 
 import java.util.Set;
 
diff --git a/src/test/java/test/dataprovider/ConstructorInjectionProvider.java b/src/test/java/test/dataprovider/ConstructorInjectionProvider.java
new file mode 100644
index 0000000..e6f2cbe
--- /dev/null
+++ b/src/test/java/test/dataprovider/ConstructorInjectionProvider.java
@@ -0,0 +1,23 @@
+package test.dataprovider;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import org.testng.annotations.DataProvider;
+
+public class ConstructorInjectionProvider {
+
+  private final String value;
+
+  @Inject
+  public ConstructorInjectionProvider(@Named("test") String value) {
+    this.value = value;
+  }
+
+  @DataProvider(name = "injection")
+  public Object[][] create() {
+    return new Object[][] {
+        new Object[] { value },
+    };
+  }
+}
diff --git a/src/test/java/test/dataprovider/FieldInjectionProvider.java b/src/test/java/test/dataprovider/FieldInjectionProvider.java
new file mode 100644
index 0000000..5c0c54d
--- /dev/null
+++ b/src/test/java/test/dataprovider/FieldInjectionProvider.java
@@ -0,0 +1,19 @@
+package test.dataprovider;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import org.testng.annotations.DataProvider;
+
+public class FieldInjectionProvider {
+
+  @Inject @Named("test")
+  private String value;
+
+  @DataProvider(name = "injection")
+  public Object[][] create() {
+    return new Object[][] {
+        new Object[] { value },
+    };
+  }
+}
diff --git a/src/test/java/test/dataprovider/NonStaticProvider.java b/src/test/java/test/dataprovider/NonStaticProvider.java
new file mode 100644
index 0000000..c49b3d7
--- /dev/null
+++ b/src/test/java/test/dataprovider/NonStaticProvider.java
@@ -0,0 +1,13 @@
+package test.dataprovider;
+
+import org.testng.annotations.DataProvider;
+
+public class NonStaticProvider {
+
+  @DataProvider(name = "external")
+  public Object[][] create() {
+    return new Object[][] {
+        new Object[] { "Cedric" },
+    };
+  }
+}
diff --git a/src/test/java/test/dataprovider/StaticDataProviderSampleTest.java b/src/test/java/test/dataprovider/StaticDataProviderSampleTest.java
index 1ee1445..3f78c21 100644
--- a/src/test/java/test/dataprovider/StaticDataProviderSampleTest.java
+++ b/src/test/java/test/dataprovider/StaticDataProviderSampleTest.java
@@ -1,12 +1,40 @@
 package test.dataprovider;
 
+import com.google.inject.AbstractModule;
+import com.google.inject.name.Names;
+
 import org.testng.Assert;
+import org.testng.annotations.Guice;
 import org.testng.annotations.Test;
 
+ at Guice(modules = StaticDataProviderSampleTest.InjectionProviderModule.class)
 public class StaticDataProviderSampleTest {
 
   @Test(dataProvider = "static", dataProviderClass = StaticProvider.class)
   public void verifyStatic(String s) {
     Assert.assertEquals(s, "Cedric");
   }
+
+  @Test(dataProvider = "external", dataProviderClass = NonStaticProvider.class)
+  public void verifyExternal(String s) {
+    Assert.assertEquals(s, "Cedric");
+  }
+
+  @Test(dataProvider = "injection", dataProviderClass = FieldInjectionProvider.class)
+  public void verifyFieldInjection(String s) {
+    Assert.assertEquals(s, "Cedric");
+  }
+
+  @Test(dataProvider = "injection", dataProviderClass = ConstructorInjectionProvider.class)
+  public void verifyConstructorInjection(String s) {
+    Assert.assertEquals(s, "Cedric");
+  }
+
+  public static class InjectionProviderModule extends AbstractModule {
+
+    @Override
+    protected void configure() {
+      bind(String.class).annotatedWith(Names.named("test")).toInstance("Cedric");
+    }
+  }
 }
diff --git a/src/test/java/test/enable/A.java b/src/test/java/test/enable/A.java
new file mode 100644
index 0000000..45bd922
--- /dev/null
+++ b/src/test/java/test/enable/A.java
@@ -0,0 +1,45 @@
+package test.enable;
+
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.Test;
+
+public class A {
+
+  public void testA() {}
+
+  @Test
+  public void testA2() {}
+
+  @Test(enabled = true)
+  public void testA3() {}
+
+  @Test(enabled = false)
+  public void disabledA() {}
+
+  @BeforeSuite
+  public void beforeSuiteA() {}
+
+  @BeforeSuite(enabled = true)
+  public void beforeSuiteA2() {}
+
+  @BeforeSuite(enabled = false)
+  public void disabledBeforeSuiteA() {}
+
+  @BeforeSuite(alwaysRun = false)
+  public void beforeSuiteNoRunA() {}
+
+  @BeforeSuite(enabled = true, alwaysRun = false)
+  public void beforeSuiteNoRunA2() {}
+
+  @BeforeSuite(enabled = false, alwaysRun = false)
+  public void disabledBeforeSuiteNoRunA() {}
+
+  @BeforeSuite(alwaysRun = true)
+  public void beforeSuiteRunA() {}
+
+  @BeforeSuite(enabled = true, alwaysRun = true)
+  public void beforeSuiteRunA2() {}
+
+  @BeforeSuite(enabled = false, alwaysRun = true)
+  public void disabledBeforeSuiteRunA() {}
+}
diff --git a/src/test/java/test/enable/B.java b/src/test/java/test/enable/B.java
new file mode 100644
index 0000000..c486438
--- /dev/null
+++ b/src/test/java/test/enable/B.java
@@ -0,0 +1,46 @@
+package test.enable;
+
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.Test;
+
+ at Test(enabled = false)
+public class B {
+
+  public void testB() {}
+
+  @Test
+  public void testB2() {}
+
+  @Test(enabled = true)
+  public void testB3() {}
+
+  @Test(enabled = false)
+  public void disabledB() {}
+
+  @BeforeSuite(enabled = true)
+  public void disabledBeforeSuiteB() {}
+
+  @BeforeSuite
+  public void disabledBeforeSuiteB2() {}
+
+  @BeforeSuite(enabled = false)
+  public void disabledBeforeSuiteB3() {}
+
+  @BeforeSuite(alwaysRun = false)
+  public void beforeSuiteNoRunB() {}
+
+  @BeforeSuite(enabled = true, alwaysRun = false)
+  public void beforeSuiteNoRunB2() {}
+
+  @BeforeSuite(enabled = false, alwaysRun = false)
+  public void disabledBeforeSuiteNoRunB() {}
+
+  @BeforeSuite(alwaysRun = true)
+  public void beforeSuiteRunB() {}
+
+  @BeforeSuite(enabled = true, alwaysRun = true)
+  public void beforeSuiteRunB2() {}
+
+  @BeforeSuite(enabled = false, alwaysRun = true)
+  public void disabledBeforeSuiteRunB() {}
+}
diff --git a/src/test/java/test/enable/C.java b/src/test/java/test/enable/C.java
new file mode 100644
index 0000000..7794036
--- /dev/null
+++ b/src/test/java/test/enable/C.java
@@ -0,0 +1,46 @@
+package test.enable;
+
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.Test;
+
+ at Test
+public class C {
+
+  public void testC() {}
+
+  @Test
+  public void testC2() {}
+
+  @Test(enabled = true)
+  public void testC3() {}
+
+  @Test(enabled = false)
+  public void disabledC() {}
+
+  @BeforeSuite
+  public void beforeSuiteC() {}
+
+  @BeforeSuite(enabled = true)
+  public void beforeSuiteC2() {}
+
+  @BeforeSuite(enabled = false)
+  public void disabledBeforeSuiteC() {}
+
+  @BeforeSuite(alwaysRun = false)
+  public void beforeSuiteNoRunC() {}
+
+  @BeforeSuite(enabled = true, alwaysRun = false)
+  public void beforeSuiteNoRunC2() {}
+
+  @BeforeSuite(enabled = false, alwaysRun = false)
+  public void disabledBeforeSuiteNoRunC() {}
+
+  @BeforeSuite(alwaysRun = true)
+  public void beforeSuiteRunC() {}
+
+  @BeforeSuite(enabled = true, alwaysRun = true)
+  public void beforeSuiteRunC2() {}
+
+  @BeforeSuite(enabled = false, alwaysRun = true)
+  public void disabledBeforeSuiteRunC() {}
+}
diff --git a/src/test/java/test/enable/EnableTest.java b/src/test/java/test/enable/EnableTest.java
new file mode 100644
index 0000000..1bf7dd5
--- /dev/null
+++ b/src/test/java/test/enable/EnableTest.java
@@ -0,0 +1,43 @@
+package test.enable;
+
+import org.testng.Assert;
+import org.testng.TestNG;
+import org.testng.annotations.Test;
+
+import java.util.List;
+
+import test.SimpleBaseTest;
+
+public class EnableTest extends SimpleBaseTest {
+
+  @Test
+  public void disabled_methods_should_not_be_run() {
+    TestNG tng = create(A.class, B.class, C.class);
+    InvokedMethodListener listener = new InvokedMethodListener();
+    tng.addListener(listener);
+    tng.setPreserveOrder(true);
+    tng.run();
+
+    List<String> invokedMethods = listener.getInvokedMethods();
+    Assert.assertEquals(invokedMethods.get(0), "beforeSuiteA");
+    Assert.assertEquals(invokedMethods.get(1), "beforeSuiteA2");
+    Assert.assertEquals(invokedMethods.get(2), "beforeSuiteNoRunA");
+    Assert.assertEquals(invokedMethods.get(3), "beforeSuiteNoRunA2");
+    Assert.assertEquals(invokedMethods.get(4), "beforeSuiteRunA");
+    Assert.assertEquals(invokedMethods.get(5), "beforeSuiteRunA2");
+    Assert.assertEquals(invokedMethods.get(6), "beforeSuiteC");
+    Assert.assertEquals(invokedMethods.get(7), "beforeSuiteC2");
+    Assert.assertEquals(invokedMethods.get(8), "beforeSuiteNoRunC");
+    Assert.assertEquals(invokedMethods.get(9), "beforeSuiteNoRunC2");
+    Assert.assertEquals(invokedMethods.get(10), "beforeSuiteRunC");
+    Assert.assertEquals(invokedMethods.get(11), "beforeSuiteRunC2");
+    Assert.assertEquals(invokedMethods.get(12), "testA2");
+    Assert.assertEquals(invokedMethods.get(13), "testA3");
+    Assert.assertEquals(invokedMethods.get(14), "testB2");
+    Assert.assertEquals(invokedMethods.get(15), "testB3");
+    Assert.assertEquals(invokedMethods.get(16), "testC");
+    Assert.assertEquals(invokedMethods.get(17), "testC2");
+    Assert.assertEquals(invokedMethods.get(18), "testC3");
+    Assert.assertEquals(invokedMethods.size(), 19);
+  }
+}
diff --git a/src/test/java/test/invokedmethodlistener/InvokedMethodListener.java b/src/test/java/test/enable/InvokedMethodListener.java
similarity index 63%
copy from src/test/java/test/invokedmethodlistener/InvokedMethodListener.java
copy to src/test/java/test/enable/InvokedMethodListener.java
index c9a0f7e..35b68a2 100644
--- a/src/test/java/test/invokedmethodlistener/InvokedMethodListener.java
+++ b/src/test/java/test/enable/InvokedMethodListener.java
@@ -1,23 +1,27 @@
-package test.invokedmethodlistener;
+package test.enable;
 
 import org.testng.IInvokedMethod;
 import org.testng.IInvokedMethodListener;
 import org.testng.ITestResult;
 import org.testng.collections.Lists;
 
+import java.util.ArrayList;
 import java.util.List;
 
 public class InvokedMethodListener implements IInvokedMethodListener {
 
-  public static List<IInvokedMethod> m_methods = Lists.newArrayList();
+  private final List<String> invokedMethods = new ArrayList<>();
 
   @Override
   public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
-    m_methods.add(method);
+    invokedMethods.add(method.getTestMethod().getMethodName());
   }
 
   @Override
   public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
   }
 
+  public List<String> getInvokedMethods() {
+    return invokedMethods;
+  }
 }
diff --git a/src/test/java/test/expectedexceptions/ExpectedExceptionsTest.java b/src/test/java/test/expectedexceptions/ExpectedExceptionsTest.java
index 90e5fd2..b106364 100644
--- a/src/test/java/test/expectedexceptions/ExpectedExceptionsTest.java
+++ b/src/test/java/test/expectedexceptions/ExpectedExceptionsTest.java
@@ -17,7 +17,7 @@ public class ExpectedExceptionsTest extends BaseTest {
   @Test
   public void expectedExceptions() {
     runTest("test.expectedexceptions.SampleExceptions2",
-        new String[] { "shouldPass", "shouldPass2", "shouldPass3" },
+        new String[] { "shouldPass", "shouldPass2", "shouldPass3", "shouldPass4" },
         new String[] { "shouldFail1", "shouldFail2", "shouldFail3", "shouldFail4" },
         new String[] {});
   }
diff --git a/src/test/java/test/expectedexceptions/SampleExceptions2.java b/src/test/java/test/expectedexceptions/SampleExceptions2.java
index 302cb0d..da47a87 100644
--- a/src/test/java/test/expectedexceptions/SampleExceptions2.java
+++ b/src/test/java/test/expectedexceptions/SampleExceptions2.java
@@ -40,6 +40,11 @@ public class SampleExceptions2 {
     throw new NumberFormatException(null);
   }
 
+  @Test(expectedExceptions = NumberFormatException.class, expectedExceptionsMessageRegExp = "Multiline.*")
+  public void shouldPass4() {
+    throw new NumberFormatException("Multiline\nException");
+  }
+
   @Test(expectedExceptions = RuntimeException.class)
   public void shouldFail4() {
   }
diff --git a/src/test/java/test/guice/GuiceParentModule.java b/src/test/java/test/guice/GuiceParentModule.java
index 989438f..96da859 100644
--- a/src/test/java/test/guice/GuiceParentModule.java
+++ b/src/test/java/test/guice/GuiceParentModule.java
@@ -1,13 +1,23 @@
 package test.guice;
 
 import com.google.inject.AbstractModule;
+import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
+import org.testng.ITestContext;
+
 public class GuiceParentModule extends AbstractModule {
 
+  private final ITestContext context;
+
+  public GuiceParentModule(ITestContext context) {
+    this.context = context;
+  }
+
   @Override
   protected void configure() {
     bind(MyService.class).toProvider(MyServiceProvider.class);
     bind(MyContext.class).to(MyContextImpl.class).in(Singleton.class);
+    bind(ITestContext.class).toInstance(context);
   }
 }
diff --git a/src/test/java/test/guice/GuiceParentModuleTest.java b/src/test/java/test/guice/GuiceParentModuleTest.java
index 9279961..6b1c0d3 100644
--- a/src/test/java/test/guice/GuiceParentModuleTest.java
+++ b/src/test/java/test/guice/GuiceParentModuleTest.java
@@ -1,6 +1,7 @@
 package test.guice;
 
 import org.testng.Assert;
+import org.testng.ITestContext;
 import org.testng.annotations.Guice;
 import org.testng.annotations.Test;
 
@@ -13,10 +14,15 @@ public class GuiceParentModuleTest {
   MySession mySession;
   @Inject
   MyService myService;
+  @Inject
+  ITestContext context;
 
   public void testService() {
     Assert.assertNotNull(myService);
     Assert.assertNotNull(mySession);
     myService.serve(mySession);
+    Assert.assertNotNull(context);
+    Assert.assertEquals(context.getName(), "Guice");
+    Assert.assertEquals(context.getSuite().getName(), "parent-module-suite");
   }
 }
diff --git a/src/test/java/test/invocationcount/Base.java b/src/test/java/test/invocationcount/Base.java
deleted file mode 100644
index 5d81d47..0000000
--- a/src/test/java/test/invocationcount/Base.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package test.invocationcount;
-
-import org.testng.annotations.BeforeClass;
-
-public class Base {
-  private static int m_beforeCount;
-  private static int m_afterCount;
-
-  @BeforeClass
-  public void init() {
-//    System.out.println("RESETTING COUNTS");
-    m_beforeCount = 0;
-    m_afterCount = 0;
-  }
-
-  protected void incrementBefore() {
-    m_beforeCount++;
-//    System.out.println("INC BEFORE:" + m_beforeCount);
-  }
-
-  protected void incrementAfter() {
-    m_afterCount++;
-//    System.out.println("INC AFTER:" + m_beforeCount);
-  }
-
-  public static int getBeforeCount() {
-    return m_beforeCount;
-  }
-
-  public static int getAfterCount() {
-    return m_afterCount;
-  }
-}
diff --git a/src/test/java/test/invocationcount/DataProviderBase.java b/src/test/java/test/invocationcount/DataProviderBase.java
index e3d03b8..65dea0f 100644
--- a/src/test/java/test/invocationcount/DataProviderBase.java
+++ b/src/test/java/test/invocationcount/DataProviderBase.java
@@ -3,7 +3,7 @@ package test.invocationcount;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
-public class DataProviderBase extends Base {
+public class DataProviderBase {
   @Test(dataProvider = "dp")
   public void f(Integer n) {
   }
diff --git a/src/test/java/test/invocationcount/DataProviderFalseFalseTest.java b/src/test/java/test/invocationcount/DataProviderFalseFalseTest.java
index ba4ea74..20fbe1e 100644
--- a/src/test/java/test/invocationcount/DataProviderFalseFalseTest.java
+++ b/src/test/java/test/invocationcount/DataProviderFalseFalseTest.java
@@ -5,12 +5,8 @@ import org.testng.annotations.BeforeMethod;
 
 public class DataProviderFalseFalseTest extends DataProviderBase {
   @BeforeMethod(firstTimeOnly = false)
-  public void beforeMethod() {
-    incrementBefore();
-  }
+  public void beforeMethod() {}
 
   @AfterMethod(lastTimeOnly = false)
-  public void afterMethod() {
-    incrementAfter();
-  }
+  public void afterMethod() {}
 }
diff --git a/src/test/java/test/invocationcount/DataProviderFalseTrueTest.java b/src/test/java/test/invocationcount/DataProviderFalseTrueTest.java
index a750ed1..ff1f0a5 100644
--- a/src/test/java/test/invocationcount/DataProviderFalseTrueTest.java
+++ b/src/test/java/test/invocationcount/DataProviderFalseTrueTest.java
@@ -5,13 +5,9 @@ import org.testng.annotations.BeforeMethod;
 
 public class DataProviderFalseTrueTest extends DataProviderBase {
   @BeforeMethod(firstTimeOnly = false)
-  public void beforeMethod() {
-    incrementBefore();
-  }
+  public void beforeMethod() {}
 
   @AfterMethod(lastTimeOnly = true)
-  public void afterMethod() {
-    incrementAfter();
-  }
+  public void afterMethod() {}
 
 }
diff --git a/src/test/java/test/invocationcount/DataProviderTrueFalseTest.java b/src/test/java/test/invocationcount/DataProviderTrueFalseTest.java
index ebe1706..38c8ad7 100644
--- a/src/test/java/test/invocationcount/DataProviderTrueFalseTest.java
+++ b/src/test/java/test/invocationcount/DataProviderTrueFalseTest.java
@@ -5,12 +5,8 @@ import org.testng.annotations.BeforeMethod;
 
 public class DataProviderTrueFalseTest extends DataProviderBase {
   @BeforeMethod(firstTimeOnly = true)
-  public void beforeMethod() {
-    incrementBefore();
-  }
+  public void beforeMethod() {}
 
   @AfterMethod(lastTimeOnly = false)
-  public void afterMethod() {
-    incrementAfter();
-  }
+  public void afterMethod() {}
 }
diff --git a/src/test/java/test/invocationcount/DataProviderTrueTrueTest.java b/src/test/java/test/invocationcount/DataProviderTrueTrueTest.java
index 8414c8c..e21706f 100644
--- a/src/test/java/test/invocationcount/DataProviderTrueTrueTest.java
+++ b/src/test/java/test/invocationcount/DataProviderTrueTrueTest.java
@@ -5,13 +5,9 @@ import org.testng.annotations.BeforeMethod;
 
 public class DataProviderTrueTrueTest extends DataProviderBase {
   @BeforeMethod(firstTimeOnly = true)
-  public void beforeMethod() {
-    incrementBefore();
-  }
+  public void beforeMethod() {}
 
   @AfterMethod(lastTimeOnly = true)
-  public void afterMethod() {
-    incrementAfter();
-  }
+  public void afterMethod() {}
 
 }
diff --git a/src/test/java/test/invocationcount/FirstAndLastTimeTest.java b/src/test/java/test/invocationcount/FirstAndLastTimeTest.java
index 82c4085..8d31a06 100644
--- a/src/test/java/test/invocationcount/FirstAndLastTimeTest.java
+++ b/src/test/java/test/invocationcount/FirstAndLastTimeTest.java
@@ -1,11 +1,14 @@
 package test.invocationcount;
 
-import org.testng.Assert;
 import org.testng.TestNG;
 import org.testng.annotations.Test;
 
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
+import java.util.List;
+
+import test.InvokedMethodNameListener;
+import test.SimpleBaseTest;
+
+import static org.assertj.core.api.Assertions.assertThat;
 
 /**
  * Test various combination of @BeforeMethod(firstTimeOnly = true/false) and
@@ -14,72 +17,103 @@ import java.lang.reflect.Method;
  * @author cbeust at google.com
  *
  */
-public class FirstAndLastTimeTest {
+public class FirstAndLastTimeTest extends SimpleBaseTest {
   @Test
   public void verifyDataProviderFalseFalse() {
-    run(DataProviderFalseFalseTest.class, 3, 3);
+    List<String> invokedMethodNames = run(DataProviderFalseFalseTest.class);
+
+    assertThat(invokedMethodNames).containsExactly(
+        "beforeMethod", "f", "afterMethod",
+        "beforeMethod", "f", "afterMethod",
+        "beforeMethod", "f", "afterMethod"
+    );
   }
 
   @Test
   public void verifyDataProviderTrueFalse() {
-    run(DataProviderTrueFalseTest.class, 1, 3);
+    List<String> invokedMethodNames = run(DataProviderTrueFalseTest.class);
+
+    assertThat(invokedMethodNames).containsExactly(
+        "beforeMethod", "f", "afterMethod",
+        "f", "afterMethod",
+        "f", "afterMethod"
+    );
   }
 
   @Test
   public void verifyDataProviderFalseTrue() {
-    run(DataProviderFalseTrueTest.class, 3, 1);
+    List<String> invokedMethodNames = run(DataProviderFalseTrueTest.class);
+
+    assertThat(invokedMethodNames).containsExactly(
+        "beforeMethod", "f",
+        "beforeMethod", "f",
+        "beforeMethod", "f", "afterMethod"
+    );
   }
 
   @Test
   public void verifyDataProviderTrueTrue() {
-    run(DataProviderTrueTrueTest.class, 1, 1);
+    List<String> invokedMethodNames = run(DataProviderTrueTrueTest.class);
+
+    assertThat(invokedMethodNames).containsExactly(
+        "beforeMethod", "f",
+        "f",
+        "f", "afterMethod"
+    );
   }
 
   @Test
   public void verifyInvocationCountFalseFalse() {
-    run(InvocationCountFalseFalseTest.class, 3, 3);
+    List<String> invokedMethodNames = run(InvocationCountFalseFalseTest.class);
+
+    assertThat(invokedMethodNames).containsExactly(
+        "beforeMethod", "f", "afterMethod",
+        "beforeMethod", "f", "afterMethod",
+        "beforeMethod", "f", "afterMethod"
+    );
   }
 
   @Test
   public void verifyInvocationCountTrueFalse() {
-    run(InvocationCountTrueFalseTest.class, 1, 3);
+    List<String> invokedMethodNames = run(InvocationCountTrueFalseTest.class);
+
+    assertThat(invokedMethodNames).containsExactly(
+        "beforeMethod", "f", "afterMethod",
+        "f", "afterMethod",
+        "f", "afterMethod"
+    );
   }
 
   @Test
   public void verifyInvocationCountFalseTrue() {
-    run(InvocationCountFalseTrueTest.class, 3, 1);
+    List<String> invokedMethodNames = run(InvocationCountFalseTrueTest.class);
+
+    assertThat(invokedMethodNames).containsExactly(
+        "beforeMethod", "f",
+        "beforeMethod", "f",
+        "beforeMethod", "f", "afterMethod"
+    );
   }
 
   @Test
   public void verifyInvocationCountTrueTrue() {
-    run(InvocationCountTrueTrueTest.class, 1, 1);
+    List<String> invokedMethodNames = run(InvocationCountTrueTrueTest.class);
+
+    assertThat(invokedMethodNames).containsExactly(
+        "beforeMethod", "f",
+        "f",
+        "f", "afterMethod"
+    );
   }
 
-  private void run(Class cls, int expectedBefore, int expectedAfter) {
-    TestNG tng = new TestNG();
-    tng.setVerbose(0);
-    tng.setTestClasses(new Class[] { cls });
+  private static List<String> run(Class<?> cls) {
+    TestNG tng = create(cls);
+    InvokedMethodNameListener listener = new InvokedMethodNameListener();
+    tng.addListener(listener);
+
     tng.run();
 
-    try {
-      Method before = cls.getMethod("getBeforeCount", new Class[0]);
-      Integer beforeCount = (Integer) before.invoke(null, (Object[]) null);
-      Assert.assertEquals(beforeCount.intValue(), expectedBefore);
-
-      Method after = cls.getMethod("getAfterCount", new Class[0]);
-      Integer afterCount = (Integer) after.invoke(null, (Object[]) null);
-      Assert.assertEquals(afterCount.intValue(), expectedAfter);
-    } catch (SecurityException e) {
-      e.printStackTrace();
-    } catch (NoSuchMethodException e) {
-      e.printStackTrace();
-    } catch (IllegalArgumentException e) {
-      e.printStackTrace();
-    } catch (IllegalAccessException e) {
-      e.printStackTrace();
-    } catch (InvocationTargetException e) {
-      e.printStackTrace();
-    }
+    return listener.getInvokedMethodNames();
   }
 
 }
diff --git a/src/test/java/test/invocationcount/InvocationBase.java b/src/test/java/test/invocationcount/InvocationBase.java
index bea3807..fe80bf8 100644
--- a/src/test/java/test/invocationcount/InvocationBase.java
+++ b/src/test/java/test/invocationcount/InvocationBase.java
@@ -2,7 +2,7 @@ package test.invocationcount;
 
 import org.testng.annotations.Test;
 
-public class InvocationBase extends Base {
+public class InvocationBase {
   @Test(invocationCount = 3)
   public void f() {
   }
diff --git a/src/test/java/test/invocationcount/InvocationCountFalseFalseTest.java b/src/test/java/test/invocationcount/InvocationCountFalseFalseTest.java
index 838eb92..e325f09 100644
--- a/src/test/java/test/invocationcount/InvocationCountFalseFalseTest.java
+++ b/src/test/java/test/invocationcount/InvocationCountFalseFalseTest.java
@@ -5,12 +5,8 @@ import org.testng.annotations.BeforeMethod;
 
 public class InvocationCountFalseFalseTest extends InvocationBase {
   @BeforeMethod(firstTimeOnly = false)
-  public void beforeMethod() {
-    incrementBefore();
-  }
+  public void beforeMethod() {}
 
   @AfterMethod(lastTimeOnly = false)
-  public void afterMethod() {
-    incrementAfter();
-  }
+  public void afterMethod() {}
 }
diff --git a/src/test/java/test/invocationcount/InvocationCountFalseTrueTest.java b/src/test/java/test/invocationcount/InvocationCountFalseTrueTest.java
index 6d844df..7e5306b 100644
--- a/src/test/java/test/invocationcount/InvocationCountFalseTrueTest.java
+++ b/src/test/java/test/invocationcount/InvocationCountFalseTrueTest.java
@@ -5,12 +5,8 @@ import org.testng.annotations.BeforeMethod;
 
 public class InvocationCountFalseTrueTest extends InvocationBase {
   @BeforeMethod(firstTimeOnly = false)
-  public void beforeMethod() {
-    incrementBefore();
-  }
+  public void beforeMethod() {}
 
   @AfterMethod(lastTimeOnly = true)
-  public void afterMethod() {
-    incrementAfter();
-  }
+  public void afterMethod() {}
 }
diff --git a/src/test/java/test/invocationcount/InvocationCountTrueFalseTest.java b/src/test/java/test/invocationcount/InvocationCountTrueFalseTest.java
index a1d9af7..06a5bbb 100644
--- a/src/test/java/test/invocationcount/InvocationCountTrueFalseTest.java
+++ b/src/test/java/test/invocationcount/InvocationCountTrueFalseTest.java
@@ -5,12 +5,8 @@ import org.testng.annotations.BeforeMethod;
 
 public class InvocationCountTrueFalseTest extends InvocationBase {
   @BeforeMethod(firstTimeOnly = true)
-  public void beforeMethod() {
-    incrementBefore();
-  }
+  public void beforeMethod() {}
 
   @AfterMethod(lastTimeOnly = false)
-  public void afterMethod() {
-    incrementAfter();
-  }
+  public void afterMethod() {}
 }
diff --git a/src/test/java/test/invocationcount/InvocationCountTrueTrueTest.java b/src/test/java/test/invocationcount/InvocationCountTrueTrueTest.java
index 0a2676f..f2c1d5c 100644
--- a/src/test/java/test/invocationcount/InvocationCountTrueTrueTest.java
+++ b/src/test/java/test/invocationcount/InvocationCountTrueTrueTest.java
@@ -5,12 +5,8 @@ import org.testng.annotations.BeforeMethod;
 
 public class InvocationCountTrueTrueTest extends InvocationBase {
   @BeforeMethod(firstTimeOnly = true)
-  public void beforeMethod() {
-    incrementBefore();
-  }
+  public void beforeMethod() {}
 
   @AfterMethod(lastTimeOnly = true)
-  public void afterMethod() {
-    incrementAfter();
-  }
+  public void afterMethod() {}
 }
diff --git a/src/test/java/test/invokedmethodlistener/A.java b/src/test/java/test/invokedmethodlistener/A.java
new file mode 100644
index 0000000..24fadc3
--- /dev/null
+++ b/src/test/java/test/invokedmethodlistener/A.java
@@ -0,0 +1,9 @@
+package test.invokedmethodlistener;
+
+import org.testng.annotations.BeforeSuite;
+
+public class A {
+
+  @BeforeSuite(alwaysRun=false)
+  public static void someMethod1() {}
+}
diff --git a/src/test/java/test/invokedmethodlistener/B.java b/src/test/java/test/invokedmethodlistener/B.java
new file mode 100644
index 0000000..8f2eb36
--- /dev/null
+++ b/src/test/java/test/invokedmethodlistener/B.java
@@ -0,0 +1,13 @@
+package test.invokedmethodlistener;
+
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.Test;
+
+ at Test(enabled=false)
+public class B extends A{
+
+  @BeforeSuite
+  public static void someMethod2() {}
+
+  public void someTest() {}
+}
diff --git a/src/test/java/test/invokedmethodlistener/C.java b/src/test/java/test/invokedmethodlistener/C.java
new file mode 100644
index 0000000..335ba00
--- /dev/null
+++ b/src/test/java/test/invokedmethodlistener/C.java
@@ -0,0 +1,13 @@
+package test.invokedmethodlistener;
+
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.Test;
+
+ at Test
+public class C extends A{
+
+  @BeforeSuite
+  public static void someMethod3() {}
+
+  public void someTest() {}
+}
diff --git a/src/test/java/test/invokedmethodlistener/InvokedMethodListener.java b/src/test/java/test/invokedmethodlistener/InvokedMethodListener.java
index c9a0f7e..e25014a 100644
--- a/src/test/java/test/invokedmethodlistener/InvokedMethodListener.java
+++ b/src/test/java/test/invokedmethodlistener/InvokedMethodListener.java
@@ -9,7 +9,7 @@ import java.util.List;
 
 public class InvokedMethodListener implements IInvokedMethodListener {
 
-  public static List<IInvokedMethod> m_methods = Lists.newArrayList();
+  private final List<IInvokedMethod> m_methods = Lists.newArrayList();
 
   @Override
   public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
@@ -20,4 +20,7 @@ public class InvokedMethodListener implements IInvokedMethodListener {
   public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
   }
 
+  public List<IInvokedMethod> getInvokedMethods() {
+    return m_methods;
+  }
 }
diff --git a/src/test/java/test/invokedmethodlistener/InvokedMethodListenerTest.java b/src/test/java/test/invokedmethodlistener/InvokedMethodListenerTest.java
index 66a1ac6..1f6ff32 100644
--- a/src/test/java/test/invokedmethodlistener/InvokedMethodListenerTest.java
+++ b/src/test/java/test/invokedmethodlistener/InvokedMethodListenerTest.java
@@ -2,6 +2,7 @@ package test.invokedmethodlistener;
 
 import org.testng.Assert;
 import org.testng.IInvokedMethod;
+import org.testng.IInvokedMethodListener;
 import org.testng.ITestResult;
 import org.testng.TestNG;
 import org.testng.annotations.Test;
@@ -12,13 +13,15 @@ import java.util.List;
 
 public class InvokedMethodListenerTest extends SimpleBaseTest {
 
-  private void run(Class[] classes, MyListener l) {
+  private static void run(Class[] classes, IInvokedMethodListener l) {
     TestNG tng = create();
     tng.setTestClasses(classes);
 
     tng.addInvokedMethodListener(l);
     tng.run();
+  }
 
+  private static void assertMethodCount(MyListener l) {
     Assert.assertEquals(l.getBeforeCount(), 9);
     Assert.assertEquals(l.getAfterCount(), 9);
   }
@@ -26,13 +29,15 @@ public class InvokedMethodListenerTest extends SimpleBaseTest {
   @Test
   public void withSuccess() {
     MyListener l = new MyListener();
-    run(new Class[] { Success.class }, l);
+    run(new Class[]{Success.class}, l);
+    assertMethodCount(l);
   }
 
   @Test
   public void withFailure() {
     MyListener l = new MyListener();
     run(new Class[] { Failure.class }, l);
+    assertMethodCount(l);
     Assert.assertEquals(l.getSuiteStatus(), ITestResult.FAILURE);
     Assert.assertTrue(null != l.getSuiteThrowable());
     Assert.assertTrue(l.getSuiteThrowable().getClass() == RuntimeException.class);
@@ -44,27 +49,31 @@ public class InvokedMethodListenerTest extends SimpleBaseTest {
 
   /**
    * Fix for:
-   * http://code.google.com/p/testng/issues/detail?id=7
-   * http://code.google.com/p/testng/issues/detail?id=86
+   * https://github.com/juherr/testng-googlecode/issues/7
+   * https://github.com/juherr/testng-googlecode/issues/86
+   * https://github.com/cbeust/testng/issues/93
    */
   @Test
   public void sameMethodInvokedMultipleTimesShouldHaveDifferentTimeStamps() {
     TestNG tng = create(Sample.class);
-    tng.addListener(new InvokedMethodListener());
+    InvokedMethodListener listener = new InvokedMethodListener();
+    tng.addListener(listener);
     tng.run();
-    List<IInvokedMethod> m = InvokedMethodListener.m_methods;
-//    for (IInvokedMethod mm : m) {
-//      System.out.println(mm.getTestMethod().getMethodName() + " " + mm.getDate());
-//    }
-    IInvokedMethod after1 = m.get(1);
+    List<IInvokedMethod> m = listener.getInvokedMethods();
+    IInvokedMethod beforeSuite = m.get(0);
+    Assert.assertFalse(beforeSuite.getTestMethod().isAfterMethodConfiguration());
+    Assert.assertTrue(beforeSuite.isConfigurationMethod());
+    IInvokedMethod after1 = m.get(2);
     Assert.assertTrue(after1.getTestMethod().isAfterMethodConfiguration());
-    IInvokedMethod after2 = m.get(3);
+    Assert.assertTrue(after1.isConfigurationMethod());
+    IInvokedMethod after2 = m.get(4);
     Assert.assertTrue(after2.getTestMethod().isAfterMethodConfiguration());
+    Assert.assertTrue(after2.isConfigurationMethod());
     Assert.assertTrue(after1.getDate() != after2.getDate());
   }
 
   @Test(description = "Test methods with expected exceptions should show up as pass" +
-  		" in IInvokedMethodListener's afterInvocaiton method")
+  		" in IInvokedMethodListener's afterInvocation method")
   public void testMethodsWithExpectedExceptionsShouldShowUpAsPass() {
     TestNG tng = create(Sample2.class);
     Sample2.Sample2InvokedMethodListener l = new Sample2().new Sample2InvokedMethodListener();
@@ -73,4 +82,57 @@ public class InvokedMethodListenerTest extends SimpleBaseTest {
 
     Assert.assertTrue(l.isSuccess);
   }
+
+  @Test(description = "Invoked method does not recognize configuration method")
+  public void issue629_InvokedMethodDoesNotRecognizeConfigurationMethod() {
+    InvokedMethodNameListener l = new InvokedMethodNameListener();
+    run(new Class[]{Success.class}, l);
+
+    Assert.assertEquals(l.testMethods.size(), 1);
+    Assert.assertTrue(l.testMethods.contains("a"));
+
+    Assert.assertEquals(l.testMethodsFromTM.size(), 1);
+    Assert.assertTrue(l.testMethodsFromTM.contains("a"));
+
+    Assert.assertEquals(l.configurationMethods.size(), 8);
+    Assert.assertTrue(l.configurationMethods.contains("beforeMethod"));
+    Assert.assertTrue(l.configurationMethods.contains("afterMethod"));
+    Assert.assertTrue(l.configurationMethods.contains("beforeTest"));
+    Assert.assertTrue(l.configurationMethods.contains("afterTest"));
+    Assert.assertTrue(l.configurationMethods.contains("beforeClass"));
+    Assert.assertTrue(l.configurationMethods.contains("afterClass"));
+    Assert.assertTrue(l.configurationMethods.contains("beforeSuite"));
+    Assert.assertTrue(l.configurationMethods.contains("afterSuite"));
+
+    Assert.assertEquals(l.configurationMethodsFromTM.size(), 8);
+    Assert.assertTrue(l.configurationMethodsFromTM.contains("beforeMethod"));
+    Assert.assertTrue(l.configurationMethodsFromTM.contains("afterMethod"));
+    Assert.assertTrue(l.configurationMethodsFromTM.contains("beforeTest"));
+    Assert.assertTrue(l.configurationMethodsFromTM.contains("afterTest"));
+    Assert.assertTrue(l.configurationMethodsFromTM.contains("beforeClass"));
+    Assert.assertTrue(l.configurationMethodsFromTM.contains("afterClass"));
+    Assert.assertTrue(l.configurationMethodsFromTM.contains("beforeSuite"));
+    Assert.assertTrue(l.configurationMethodsFromTM.contains("afterSuite"));
+  }
+
+  @Test
+  public void issue87_method_orderning_with_disable_test_class() {
+    assertIssue87(A.class, B.class, C.class);
+    assertIssue87(A.class, C.class, B.class);
+    assertIssue87(B.class, A.class, C.class);
+  }
+
+  private void assertIssue87(Class<?>... tests) {
+    TestNG tng = create(tests);
+    tng.setParallel("false");
+    tng.setPreserveOrder(true);
+    InvokedMethodListener listener = new InvokedMethodListener();
+    tng.addListener(listener);
+    tng.run();
+    List<IInvokedMethod> m = listener.getInvokedMethods();
+    Assert.assertEquals(m.get(0).getTestMethod().getMethodName(), "someMethod1");
+    Assert.assertEquals(m.get(1).getTestMethod().getMethodName(), "someMethod3");
+    Assert.assertEquals(m.get(2).getTestMethod().getMethodName(), "someTest");
+    Assert.assertEquals(m.size(), 3);
+  }
 }
diff --git a/src/test/java/test/invokedmethodlistener/InvokedMethodNameListener.java b/src/test/java/test/invokedmethodlistener/InvokedMethodNameListener.java
new file mode 100644
index 0000000..be1df42
--- /dev/null
+++ b/src/test/java/test/invokedmethodlistener/InvokedMethodNameListener.java
@@ -0,0 +1,45 @@
+package test.invokedmethodlistener;
+
+import org.testng.IInvokedMethod;
+import org.testng.IInvokedMethodListener;
+import org.testng.ITestResult;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class InvokedMethodNameListener implements IInvokedMethodListener {
+
+  final Set<String> testMethods = new HashSet<>();
+  final Set<String> configurationMethods = new HashSet<>();
+  final Set<String> testMethodsFromTM = new HashSet<>();
+  final Set<String> configurationMethodsFromTM = new HashSet<>();
+
+  @Override
+  public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
+  }
+
+  @Override
+  public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
+    String methodName = method.getTestMethod().getMethodName();
+
+    if (method.isTestMethod()) {
+      testMethods.add(methodName);
+    }
+    if (method.isConfigurationMethod()) {
+      configurationMethods.add(methodName);
+    }
+    if (method.getTestMethod().isTest()) {
+      testMethodsFromTM.add(methodName);
+    }
+    if (method.getTestMethod().isBeforeMethodConfiguration() ||
+        method.getTestMethod().isAfterMethodConfiguration() ||
+        method.getTestMethod().isBeforeTestConfiguration() ||
+        method.getTestMethod().isAfterTestConfiguration() ||
+        method.getTestMethod().isBeforeClassConfiguration() ||
+        method.getTestMethod().isAfterClassConfiguration() ||
+        method.getTestMethod().isBeforeSuiteConfiguration() ||
+        method.getTestMethod().isAfterSuiteConfiguration()) {
+      configurationMethodsFromTM.add(methodName);
+    }
+  }
+}
diff --git a/src/test/java/test/invokedmethodlistener/Sample.java b/src/test/java/test/invokedmethodlistener/Sample.java
index 591865b..10a48ff 100644
--- a/src/test/java/test/invokedmethodlistener/Sample.java
+++ b/src/test/java/test/invokedmethodlistener/Sample.java
@@ -1,6 +1,7 @@
 package test.invokedmethodlistener;
 
 import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeSuite;
 import org.testng.annotations.Test;
 
 public class Sample {
@@ -25,4 +26,7 @@ public class Sample {
 
   @AfterMethod
   public void am() {}
+
+  @BeforeSuite
+  public void bs() {}
 }
diff --git a/src/test/java/test/junit4/JUnit4ParameterizedTest.java b/src/test/java/test/junit4/JUnit4ParameterizedTest.java
new file mode 100644
index 0000000..fa35a24
--- /dev/null
+++ b/src/test/java/test/junit4/JUnit4ParameterizedTest.java
@@ -0,0 +1,57 @@
+package test.junit4;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+ at RunWith(Parameterized.class)
+public class JUnit4ParameterizedTest {
+
+    public static final String[] EXPECTED = {"t2[0]", "t2[1]", "t4[0]"};
+    public static final String[] SKIPPED = {"t3[0]", "t3[1]", "ta[0]", "ta[1]"};
+    public static final String[] FAILED = {"t4[1]", "tf[0]", "tf[1]"};
+
+    private int param;
+
+    @Parameters
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] {{1}, {5}});
+    }
+
+    public JUnit4ParameterizedTest(int param) {
+        this.param = param;
+    }
+
+    @Test
+    public void t2() {
+    }
+
+    @Test
+    @Ignore
+    public void t3() {
+    }
+
+    @Test
+    public void t4() {
+        if (param == 5) {
+            Assert.fail("a test");
+        }
+    }
+
+    @Test
+    public void tf() {
+        Assert.fail("a test");
+    }
+
+    @Test
+    public void ta() {
+        Assume.assumeTrue(false);
+    }
+}
diff --git a/src/test/java/test/listeners/SuiteAndConfigurationListenerTest.java b/src/test/java/test/listeners/SuiteAndConfigurationListenerTest.java
new file mode 100644
index 0000000..f4130aa
--- /dev/null
+++ b/src/test/java/test/listeners/SuiteAndConfigurationListenerTest.java
@@ -0,0 +1,58 @@
+package test.listeners;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.testng.Assert;
+import org.testng.IConfigurationListener;
+import org.testng.ISuite;
+import org.testng.ISuiteListener;
+import org.testng.ITestResult;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+import test.listeners.SuiteAndConfigurationListenerTest.MyListener;
+
+/**
+ * Check that if a listener implements IConfigurationListener additionally to
+ * ISuiteListener, ISuiteListener gets invoked exactly once.
+ *
+ * @author Mihails Volkovs
+ */
+ at Listeners(MyListener.class)
+public class SuiteAndConfigurationListenerTest {
+  public static class MyListener implements ISuiteListener, IConfigurationListener {
+
+    private static volatile AtomicInteger started = new AtomicInteger(0);
+
+    public MyListener() {
+    }
+
+    @Override
+    public void onStart(ISuite suite) {
+      started.incrementAndGet();
+    }
+
+    @Override
+    public void onFinish(ISuite suite) {
+    }
+
+    @Override
+    public void onConfigurationSuccess(ITestResult itr) {
+    }
+
+    @Override
+    public void onConfigurationFailure(ITestResult itr) {
+    }
+
+    @Override
+    public void onConfigurationSkip(ITestResult itr) {
+    }
+
+  }
+
+  @Test
+  public void bothListenersShouldRun() {
+    Assert.assertEquals(MyListener.started.get(), 1, "ISuiteListener was not invoked exactly once:");
+  }
+
+}
diff --git a/src/test/java/test/methodinterceptors/Issue392.java b/src/test/java/test/methodinterceptors/Issue392.java
new file mode 100644
index 0000000..c843918
--- /dev/null
+++ b/src/test/java/test/methodinterceptors/Issue392.java
@@ -0,0 +1,17 @@
+package test.methodinterceptors;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+public class Issue392 {
+
+  @AfterClass
+  public void afterClass() {}
+
+  @Test
+  public void test1() {}
+
+  @Test
+  public void test2() {}
+
+}
diff --git a/src/test/java/test/methodinterceptors/Issue392Test.java b/src/test/java/test/methodinterceptors/Issue392Test.java
new file mode 100644
index 0000000..a337ed6
--- /dev/null
+++ b/src/test/java/test/methodinterceptors/Issue392Test.java
@@ -0,0 +1,43 @@
+package test.methodinterceptors;
+
+import org.testng.IMethodInstance;
+import org.testng.IMethodInterceptor;
+import org.testng.ITestContext;
+import org.testng.TestNG;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import test.InvokedMethodNameListener;
+import test.SimpleBaseTest;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class Issue392Test extends SimpleBaseTest {
+
+  @Test(description = "test for https://github.com/cbeust/testng/issues/392")
+  public void AfterClass_method_should_be_fired_when_IMethodInterceptor_removes_test_methods() {
+    TestNG tng = create(Issue392.class);
+    tng.setMethodInterceptor(new IMethodInterceptor() {
+      @Override
+      public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
+        List<IMethodInstance> instances = new ArrayList<>();
+        for (IMethodInstance instance : methods) {
+          if (!instance.getMethod().getMethodName().equals("test1")) {
+            instances.add(instance);
+          }
+        }
+        return instances;
+      }
+    });
+
+    InvokedMethodNameListener listener = new InvokedMethodNameListener();
+    tng.addListener(listener);
+
+    tng.run();
+
+    assertThat(listener.getInvokedMethodNames()).containsExactly("test2", "afterClass");
+  }
+
+}
diff --git a/src/test/java/test/preserveorder/PreserveOrderTest.java b/src/test/java/test/preserveorder/PreserveOrderTest.java
index 3ac14cc..c5a6f8e 100644
--- a/src/test/java/test/preserveorder/PreserveOrderTest.java
+++ b/src/test/java/test/preserveorder/PreserveOrderTest.java
@@ -3,9 +3,7 @@ package test.preserveorder;
 import org.testng.Assert;
 import org.testng.TestListenerAdapter;
 import org.testng.TestNG;
-import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
-import org.testng.collections.Lists;
 import org.testng.xml.XmlClass;
 import org.testng.xml.XmlSuite;
 import org.testng.xml.XmlTest;
@@ -108,57 +106,6 @@ public class PreserveOrderTest extends SimpleBaseTest {
         "c3TestOne", "c3TestTwo", "c3TestThree");
   }
 
-  @Test(dataProvider = "dp")
-  public void preserveOrderAnna(String[] classes, String[] expectedMethods) {
-    TestNG tng = create();
-    XmlSuite s = createXmlSuite("PreserveOrder");
-    XmlTest t = new XmlTest(s);
-
-    for (String c : classes) {
-      t.getXmlClasses().add(new XmlClass("test.preserveorder." + c));
-    }
-    t.setPreserveOrder("true");
-
-    tng.setXmlSuites(Arrays.asList(s));
-    TestListenerAdapter tla = new TestListenerAdapter();
-    tng.addListener(tla);
-    tng.run();
-
-    try {
-      verifyPassedTests(tla, expectedMethods);
-    } catch(Exception ex) {
-      ex.printStackTrace();
-    }
-  }
-
-  @DataProvider
-  public Object[][] dp() {
-    String[][] classes = new String[][] {
-        { "PrgTest", "SibTest", "EdnTest" },
-        { "PrgTest", "EdnTest", "SibTest" },
-        { "SibTest", "PrgTest", "EdnTest" },
-        { "SibTest", "EdnTest", "PrgTest" },
-        { "EdnTest", "PrgTest", "SibTest" },
-        { "EdnTest", "SibTest", "PrgTest" },
-    };
-    String[][] expectedMethods = new String[][] {
-        { "prg1", "prg2", "sib1", "sib2", "edn1", "edn2" },
-        { "prg1", "prg2", "edn1", "edn2", "sib1", "sib2" },
-        { "sib1", "sib2", "prg1", "prg2", "edn1", "edn2" },
-        { "sib1", "sib2", "edn1", "edn2", "prg1", "prg2" },
-        { "edn1", "edn2", "prg1", "prg2", "sib1", "sib2" },
-        { "edn1", "edn2", "sib1", "sib2", "prg1", "prg2" },
-    };
-
-    List<Object[]> result = Lists.newArrayList();
-    for (int i = 0; i < classes.length; i++) {
-      Object[] o = new Object[] { classes[i], expectedMethods[i] };
-      result.add(o);
-    }
-
-    return result.toArray(new Object[result.size()][]);
-  }
-
   @Test(description = "preserve-order on a factory doesn't cause an NPE")
   public void factoryPreserve() {
     TestNG tng = create();
diff --git a/src/test/java/test/thread/BaseThreadTest.java b/src/test/java/test/thread/BaseThreadTest.java
index 849dcb7..0924088 100644
--- a/src/test/java/test/thread/BaseThreadTest.java
+++ b/src/test/java/test/thread/BaseThreadTest.java
@@ -3,7 +3,7 @@ package test.thread;
 import org.testng.Assert;
 import org.testng.collections.Lists;
 import org.testng.collections.Maps;
-import org.testng.internal.annotations.Sets;
+import org.testng.collections.Sets;
 
 import test.SimpleBaseTest;
 
diff --git a/src/test/resources/testng.xml b/src/test/resources/testng.xml
index 34da7d0..dffeb76 100644
--- a/src/test/resources/testng.xml
+++ b/src/test/resources/testng.xml
@@ -144,6 +144,7 @@
       <class name="test.listeners.ResultEndMillisTest" />
       <class name="test.listeners.ListenerTest"/>
       <class name="test.listeners.SuiteAndInvokedMethodListenerTest" />
+      <class name="test.listeners.SuiteAndConfigurationListenerTest" />
       <class name="test.listeners.ListenerInXmlTest" />
       <class name="test.listeners.ExecutionListenerTest" />
       <class name="test.listeners.ConfigurationListenerTest" />
@@ -629,6 +630,7 @@
   <test name="MethodInterceptor">
     <classes>
       <class name="test.methodinterceptors.MethodInterceptorTest" />
+      <class name="test.methodinterceptors.Issue392Test" />
     </classes>
   </test>
 
@@ -739,5 +741,10 @@
     </classes>
   </test>
 
+  <test name="@Test(enable)">
+    <classes>
+      <class name="test.enable.EnableTest"/>
+    </classes>
+  </test>
 </suite>
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/testng.git



More information about the pkg-java-commits mailing list