testng-testng-6.9.5/0000755000175000017500000000000012564576474013667 5ustar eugeneeugenetestng-testng-6.9.5/www/0000755000175000017500000000000012551235562014475 5ustar eugeneeugenetestng-testng-6.9.5/www/index.html0000644000175000017500000000021112551235562016464 0ustar eugeneeugene Default Project Content This is the default project content. testng-testng-6.9.5/verify-release0000755000175000017500000000212412551235562016520 0ustar eugeneeugeneif [ $# -eq 0 ] then echo "Specify the release number (e.g. 5.14.2)" exit -1 fi rel=testng-$1 # # Make sure that pom.xml and pom-test.xml test the same and latest version # v1=`perl -ne 'BEGIN{undef $/}; print "$1" if m/(TestNG.*\n.*version)/mg' pom.xml | awk -F ">" '{ print $2 }' | awk -F "<" '{ print $1 }'` v2=`perl -ne 'BEGIN{undef $/}; print "$1" if m/(artifactId.testng.*\n.*version)/mg' pom-test.xml | grep version | awk -F ">" '{print $2}' | awk -F "<" '{print $1}'` if [ $v1 != $v2 ] then echo "Versions of pom.xml and pom-test.xml do not match: $v1 $v2" # exit -1 fi # # Maven # ./build-with-maven #cd $HOME/t #rm -rf surefire #svn co http://svn.apache.org/repos/asf/maven/surefire/trunk surefire #cd surefire #mvn clean install -Dtestng.version=$1 # # Distribution # cd $HOME/t rm -f *zip rm -rf $rel curl http://testng.org/$rel.zip >$rel.zip unzip $rel.zip cd $HOME/java/testng java -Dtest.resources.dir=$HOME/java/testng/src/test/resources -classpath $HOME/t/$rel/$rel.jar:target/test-classes:lib/guice-2.0.jar org.testng.TestNG $HOME/java/testng/src/test/resources/testng.xml testng-testng-6.9.5/upload-beta0000755000175000017500000000024412551235562015774 0ustar eugeneeugene#scp `ls -tr *beta.zip|tail -1` cedric@beust.com:w/testng scp `ls -tr target/*beta.zip|tail -1` beust:domains/testng.org/html ssh beust cat testng/beta/index.html testng-testng-6.9.5/update-beust.com0000755000175000017500000000131012551235562016751 0ustar eugeneeugenev=6.5.2 ev=5.13.0.3 DEST=testng TARGET=target set -x if [ -z "${U}" ] then echo Variable "$U" is not set exit -1 fi RSYNC="rsync --verbose --progress --stats" ${RSYNC} ${TARGET}/testng-${v}.zip ${U}@beust.com:${DEST} ${RSYNC} -r src/main/resources/testng-1.0.dtd testng-1.0.dtd.html ${U}@beust.com:${DEST}/doc #${RSYNC} testng-${v}.jar testng-${v}-bundle.jar testng-${v}.zip testng-eclipse-${ev}.zip ${U}@beust.com:${DEST} #scp -r javadocs doc/*.html doc/*.css src/main/resources/testng-1.0.dtd testng-1.0.dtd.html ${U}@beust.com:${DEST} #scp dtd/* ${U}@beust.com:w/dtd #(cd ~/java/beust.com; scp -r . ${U}@beust.com:w/eclipse) # scp testng-eclipse-${ev}.zip doc/download.html ${U}@beust.com:${DEST} testng-testng-6.9.5/testng-1.0.dtd.php0000644000175000017500000000306712551235562016742 0ustar eugeneeugeneTestNG DTD

DTD for TestNG

'
;

print(htmlentities(file_get_contents("testng-1.0.dtd")));

print "
"; ?> testng-testng-6.9.5/testng-1.0.dtd.html0000755000175000017500000000035012551235562017112 0ustar eugeneeugene . testng-testng-6.9.5/src/0000755000175000017500000000000012551235562014440 5ustar eugeneeugenetestng-testng-6.9.5/src/test/0000755000175000017500000000000012551235562015417 5ustar eugeneeugenetestng-testng-6.9.5/src/test/resources/0000755000175000017500000000000012564576474017447 5ustar eugeneeugenetestng-testng-6.9.5/src/test/resources/yaml/0000755000175000017500000000000012551235562020373 5ustar eugeneeugenetestng-testng-6.9.5/src/test/resources/yaml/a4.yaml0000644000175000017500000000010312551235562021555 0ustar eugeneeugenename: SingleSuite verbose: 2 suiteFiles: [ a4-a.yaml, a4-b.yaml ] testng-testng-6.9.5/src/test/resources/yaml/a4.xml0000644000175000017500000000033412551235562021421 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/yaml/a4-b.yaml0000644000175000017500000000002712551235562022001 0ustar eugeneeugenename: a4-b verbose: 2 testng-testng-6.9.5/src/test/resources/yaml/a4-a.yaml0000644000175000017500000000002712551235562022000 0ustar eugeneeugenename: a4-a verbose: 2 testng-testng-6.9.5/src/test/resources/yaml/a3.yaml0000644000175000017500000000007012551235562021557 0ustar eugeneeugenename: a3 verbose: 2 suiteFiles: [ a3-a.xml, a3-b.xml ] testng-testng-6.9.5/src/test/resources/yaml/a3.xml0000644000175000017500000000032112551235562021414 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/yaml/a3-b.yaml0000644000175000017500000000013712551235562022002 0ustar eugeneeugenename: a3-b tests: - name: Test-a3-b classes: - test.listeners.ResultEndMillisTest testng-testng-6.9.5/src/test/resources/yaml/a3-b.xml0000644000175000017500000000060512551235562021640 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/yaml/a3-a.yaml0000644000175000017500000000013712551235562022001 0ustar eugeneeugenename: a3-a tests: - name: Test-a3-a classes: - test.listeners.ResultEndMillisTest testng-testng-6.9.5/src/test/resources/yaml/a3-a.xml0000644000175000017500000000060512551235562021637 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/yaml/a2.yaml0000644000175000017500000000215412551235562021563 0ustar eugeneeugenename: SingleSuite verbose: 2 parallel: false threadCount: 4 dataProviderThreadCount: 3 packages: - name: test.testng355.org.apache.tapestry5 include: [Foo, Foo2] exclude: [Bar] - name: test.testng355.org.apache.tapestry5.dom listeners: - test.invokedmethodlistener.MyListener parameters: { n: 42, p: 10, s: "a b c", t: "a,b" } tests: - name: Test3 preserveOrder: false includedGroups: [A, B] excludedGroups: [C, D] metaGroups: { a: [ b, d] } packages: [ com.example1, com.example2 ] parameters: { n: 43, z: foo } methodSelectors: - className: org.testng.internal.XmlMethodSelector priority: 1 - expression: groups.containsKey("test1") language: beanshell - name: Test1 preserveOrder: false classes: - name: test.tmp.A includedMethods: [test1, test2] excludedMethods: [test3] - test.tmp.B - name: Test2 preserveOrder: false classes: - test.tmp.B methodSelectors: - className: org.testng.internal.XmlMethodSelector priority: 1 - expression: groups.containsKey("test1") language: beanshell testng-testng-6.9.5/src/test/resources/yaml/a2.xml0000644000175000017500000000456412551235562021430 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/yaml/a1.yaml0000644000175000017500000000102212551235562021553 0ustar eugeneeugenename: SingleSuite verbose: 2 threadCount: 4 parameters: { n: 42 } dataProviderThreadCount: 3 parallel: false listeners: - test.methodinterceptors.FastTestsFirstInterceptor - test.invokedmethodlistener.MyListener packages: - name: test.testng355.org.apache.tapestry5 include: [Foo, Foo2] exclude: [Bar] - name: test.testng355.org.apache.tapestry5.dom tests: - name: Regression2 verbose: 2 parameters: { count: 10 } excludedGroups: [ broken ] classes: - test.listeners.ResultEndMillisTest testng-testng-6.9.5/src/test/resources/yaml/a1.xml0000644000175000017500000000307112551235562021417 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/testng_convert.xml0000644000175000017500000000056312551235562023223 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/testng.yaml0000644000175000017500000002475412551235562021635 0ustar eugeneeugenename: TestNG threadCount: 2 parameters: { short: 47, parameter: out, char: c, byte: 43, first-name: Cedric, int: 42, string: Cedric, factory-param: FactoryParam, boolean: true, long: 46, double: 44.0, float: 45.0 } tests: - name: Nopackage includedGroups: [ nopackage ] classes: - NoPackageTest - name: Regression1 excludedGroups: [ excludeThisGroup ] metaGroups: { evenodd: [ even, odd ] } classes: - test.parameters.ParameterSample - test.parameters.ParameterTest - test.Test1 - test.Test2 - test.CtorCalledOnce - test.expectedexceptions.ExpectedExceptionsTest - test.access.PrivateAccessConfigurationMethods - test.expectedexceptions.WrappedExpectedException - test.parameters.OptionalParameterTest - name: Regression2 excludedGroups: [ broken ] classes: - test.Test1 - test.MethodTest - test.sample.AfterClassCalledAtEnd - test.GraphTest - test.DynamicGraphTest - test.configuration.BaseGroupsTest - test.configuration.BeforeClassThreadTest - test.configuration.BeforeTestOrderingTest - test.configuration.ConfigurationTest - test.configuration.ExternalConfigurationClass - test.configuration.GroupsTest - test.configuration.MethodCallOrderTest - test.configuration.MultipleBeforeGroupTest - test.configuration.ReflectMethodParametrizedConfigurationMethodTest - test.configuration.SuiteFactoryOnceTest - test.configuration.SuiteTest - test.configuration.VerifySuiteTest - test.privatemethod.PrivateMethodTest$PrivateMethodInnerTest - test.multiple.TestMultiple - test.ClassConfigurations - test.alwaysrun.AlwaysRunTest - test.conffailure.ConfigurationFailure - test.superclass.MainTest - test.superclass.Test3 - test.failures.FailuresTest - test.mannotation.MAnnotationSampleTest - test.mannotation.MAnnotation2SampleTest - test.thread.ThreadPoolSizeTest - test.thread.SequentialTest - test.thread.ParallelTestTest - test.thread.FactoryTest - test.thread.DataProviderThreadPoolSizeTest - test.thread.MultiThreadedDependentTest - test.simple.IncludedExcludedTest - test.reports.ReportTest - test.annotationtransformer.AnnotationTransformerTest - test.jar.JarTest - test.xml.XmlVerifyTest - test.invokedmethodlistener.InvokedMethodListenerTest - test.testng249.VerifyTest - test.testng195.AfterMethodTest - test.regression.BeforeTestFailingTest - test.testng285.TestNG285Test - test.failedreporter.FailedReporterTest - test.attributes.AttributeTest - test.verify.VerifyTest - test.abstractconfmethod.C - test.issue78.NonPublicClassTest - test.listeners.ListenerTest - test.preserveorder.PreserveOrderTest - test.listeners.ResultEndMillisTest - name: Injection classes: - test.inject.InjectTestContextTest - test.inject.InjectBeforeMethodTest - test.inject.InjectTestResultTest - test.inject.InjectDataProviderTest - test.inject.NoInjectionTest - name: BeforeMethod classes: - test.configuration.BeforeMethodTest - name: Factory tests classes: - test.factory.classconf.XClassOrderWithFactoryTest - test.factory.FactoryInterleavingTest - name: Basic classes: - test.sample.Basic2 - test.sample.Basic1 - test.Misc - name: Exclusion excludedGroups: [ excludeThisGroup ] classes: - test.Test2 - name: Dependents parameters: { foo: Cedric } classes: - test.dependent.MissingGroupTest - test.dependent.MissingMethodTest - test.dependent.OrderMethodTest - test.dependent.DependentTest - test.dependent.SampleDependentMethods - test.dependent.SampleDependentMethods2 - test.dependent.SampleDependentMethods3 - test.dependent.SampleDependentConfigurationMethods - test.dependent.ClassDependsOnGroups - test.dependent.DependentAlwaysRunTest - test.dependent.MultiGroupTest - test.dependent.ImplicitGroupInclusionTest - test.dependent.ClassWide1Test - test.dependent.ClassWide2Test - test.dependent.DepBugSampleTest - test.dependent.DepBugVerifyTest - test.dependent.DependsOnProtectedMethodTest - test.dependsongroup.DependsOnGroupsTest - name: Inheritance classes: - test.SampleInheritance - test.inheritance.ClassScopeTest - name: Test outer scope includedGroups: [ outer-group ] classes: - test.sample.Scope - name: Test inner scope parameters: { parameter: in } includedGroups: [ inner-group ] classes: - test.sample.Scope - name: AfterClassCalledAtEnd classes: - test.sample.AfterClassCalledAtEnd - name: Triangle classes: - test.triangle.Child1 - test.triangle.Child2 - name: CheckTrianglePost parameters: { expected-calls: 2 } classes: - test.triangle.CheckCount - name: Test class groups 1 classes: - test.classgroup.Second - test.classgroup.First - name: Test class groups 2 classes: - test.classgroup.First - test.classgroup.Second - name: Factory classes: - test.factory.FactoryTest - test.factory.VerifyFactoryTest - test.factory.FactoryInSeparateClass - test.factory.Factory2Test - test.factory.FactoryWithInstanceInfoTest - test.factory.VerifyFactoryWithInstanceInfoTest - test.factory.TestClassAnnotationTest - test.factory.FactoryWithDataProviderTest - test.factory.FactoryOrderMainTest - test.factory.FactoryFailureTest - test.factory.FactoryInSuperClassTest - name: TimeOut classes: - test.timeout.TimeOutTest - test.timeout.TimeOutFromXmlTest - name: InvocationCount parameters: { count: 10 } classes: - test.InvocationAndSuccessPercentageTest - test.invocationcount.FailedInvocationCountTest - test.invocationcount.FirstAndLastTimeTest - name: Method1 classes: - name: test.methods.SampleMethod1 includedMethods: - shouldRun1 - shouldRun2 - test.methods.VerifyMethod1 - name: Method2 classes: - name: test.methods.SampleMethod1 excludedMethods: - shouldNotRun1 - shouldNotRun2 - test.methods.VerifyMethod1 - name: Method3 classes: - name: test.methods.SampleMethod1 excludedMethods: - .*Not.* - test.methods.VerifyMethod1 - name: Object factory classes: - test.objectfactory.CustomFactoryTest - test.objectfactory.CombinedTestAndObjectFactoryTest - name: Parameters for constructors classes: - test.ParameterConstructorTest - name: Excluded methods includedGroups: [ group1, group2 ] classes: - name: test.Exclude excludedMethods: - excluded1 - excluded2 - name: Parameters in init 1 parameters: { param: value1 } classes: - test.configuration.ConfigurationWithParameters - name: Parameters in init 2 parameters: { param: value2 } classes: - test.configuration.ConfigurationWithParameters - name: Individual method classes: - name: test.IndividualMethodsTest includedMethods: - testMethod - name: Method inheritance classes: - test.inheritance.DChild_2 - test.inheritance.VerifyTest - name: Method selectors classes: - test.methodselectors.MethodSelectorTest - test.methodselectors.BeanShellTest - test.methodselectors.CommandLineTest - name: Test order invocation classes: - test.interleavedorder.InterleavedInvocationTest - name: DataProvider classes: - test.dataprovider.Sample1Test - test.dataprovider.IterableTest - test.dataprovider.ConfigurationAndDataProvidersTest - test.dataprovider.BooleanTest - test.dataprovider.MethodTest - test.dataprovider.StaticDataProviderSampleTest - test.dataprovider.UnnamedDataProviderTest - test.dataprovider.TestContextTest - test.dataprovider.FailingDataProviderTest - test.dataprovider.DataProviderAsTest - test.dataprovider.TestInstanceFactory - test.dataprovider.FailedDataProviderTest - test.dataprovider.InstanceDataProviderTest - test.dataprovider.FailingIterableDataProviderTest - test.dataprovider.ClassTest - test.dataprovider.InheritedDataProviderTest - name: DP classes: - test.dataprovider.ParallelDataProviderTest - name: UniqueSuite classes: - test.uniquesuite.TestBefore1 - test.uniquesuite.TestBefore2 - test.uniquesuite.TestAfter - name: InheritGroups includedGroups: [ group1 ] classes: - test.configuration.ConfigurationInheritGroupsSampleTest - name: Nested includedGroups: [ unittest ] xmlPackages: - name: test.nested.* - name: Hookable classes: - test.hook.HookSuccessTest - test.hook.HookFailureTest - name: BeforeGroups-AfterGroups-1 classes: - test.configuration.ConfigurationGroups1SampleTest - test.configuration.ConfigurationGroups2SampleTest - test.configuration.ConfigurationGroups3SampleTest - test.configuration.ConfigurationGroups4SampleTest - test.configuration.ConfigurationGroups5SampleTest - test.configuration.ConfigurationGroups6SampleTest - test.configuration.ConfigurationGroups7SampleTest - name: BeforeGroups-AfterGroups-2 includedGroups: [ A, B ] classes: - test.configuration.ConfigurationGroups8SampleTest - name: JUnit classes: - test.JUnitTest1 - test.CommandLineTest - name: Ant-ClassFileResolution classes: - test.ant.TestCommandLineArgs - name: Class Run classes: - test.regression.groupsordering.A - test.regression.groupsordering.B - name: Groups Run includedGroups: [ a ] classes: - test.regression.groupsordering.A - test.regression.groupsordering.B - name: External group invocation includedGroups: [ a ] classes: - test.groupinvocation.GroupConfiguration - test.groupinvocation.DummyTest - name: SkipExceptions classes: - test.skipex.SkippedExceptionTest - name: MethodInterceptor classes: - test.methodinterceptors.MethodInterceptorTest - name: Asserts classes: - test.asserttests.AssertTest - name: ConfigFailurePolicy classes: - test.configurationfailurepolicy.FailurePolicyTest testng-testng-6.9.5/src/test/resources/testng.xml0000644000175000017500000005441512551235562021470 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/testng-single2.yaml0000644000175000017500000000204712551235562023165 0ustar eugeneeugenename: SingleSuite verbose: 2 parallel: false threadCount: 4 dataProviderThreadCount: 3 packages: - name: test.testng355.org.apache.tapestry5 include: [Foo, Foo2] exclude: [Bar] - name: test.testng355.org.apache.tapestry5.dom listeners: - test.invokedmethodlistener.MyListener parameters: { n: 42, p: 10, s: "a b c", t: "a,b" } methodSelectors: - className: org.testng.internal.XmlMethodSelector priority: 1 - expression: groups.containsKey("test1") language: beanshell tests: - name: Test3 includedGroups: [A, B] excludedGroups: [C, D] metaGroups: { a: [ b, d] } packages: [ com.example1, com.example2 ] parameters: { n: 43, z: foo } methodSelectors: - className: org.testng.internal.XmlMethodSelector priority: 1 - expression: groups.containsKey("test1") language: beanshell - name: Test1 classes: - name: test.tmp.A includedMethods: [test1, test2] excludedMethods: [test3] - test.tmp.B - name: Test2 classes: - test.tmp.B testng-testng-6.9.5/src/test/resources/testng-single2.xml0000644000175000017500000000106512551235562023022 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/testng-single.yaml0000644000175000017500000000044312551235562023101 0ustar eugeneeugenename: SingleSuite verbose: 2 tests: - name: Test1 excludedGroups: [ excludeThisGroup ] classes: - name: test.dependent.xml.GroupDependencyTest # includedMethods: [ a ] # - test.Test2 # - name: test.CommandLineTest # includedMethods: [ junitParsing ] testng-testng-6.9.5/src/test/resources/testng-single.xml0000644000175000017500000000067712551235562022750 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/testng-remote.xml0000644000175000017500000000035112551235562022747 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/testng-package.xml0000644000175000017500000000057512551235562023057 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/testng-override.xml0000644000175000017500000000037412551235562023300 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/testng-methodselectors.xml0000644000175000017500000000034112551235562024657 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/testng-configfailure.xml0000644000175000017500000000045212551235562024273 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/testng-ant.xml0000644000175000017500000000041212551235562022234 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/testng-annconv.xml0000644000175000017500000000052712551235562023123 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/testng-all.xml0000644000175000017500000000507412551235562022233 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/suite1.xml0000644000175000017500000000053512551235562021370 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/suite1-2.xml0000644000175000017500000000023312551235562021522 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/suite1-1.xml0000644000175000017500000000031512551235562021522 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/suite-parallel-2.xml0000644000175000017500000000022112551235562023230 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/suite-parallel-1.xml0000644000175000017500000000022112551235562023227 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/suite-parallel-0.xml0000644000175000017500000000042412551235562023233 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/sanitycheck/0000755000175000017500000000000012551235562021736 5ustar eugeneeugenetestng-testng-6.9.5/src/test/resources/sanitycheck/test3.xml0000644000175000017500000000057512551235562023531 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/sanitycheck/test2.xml0000644000175000017500000000057712551235562023532 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/sanitycheck/test1.xml0000644000175000017500000000112612551235562023520 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/sanitycheck/test-s-b.xml0000644000175000017500000000031012551235562024110 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/sanitycheck/test-s-a.xml0000644000175000017500000000031012551235562024107 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/sanitycheck/test-s-3.xml0000644000175000017500000000060012551235562024033 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/sanitycheck/test-s-2.xml0000644000175000017500000000057612551235562024046 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/sanitycheck/test-s-1.xml0000644000175000017500000000057612551235562024045 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/sanitycheck/test-b.xml0000644000175000017500000000030212551235562023651 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/sanitycheck/test-a.xml0000644000175000017500000000030212551235562023650 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/parent-module-suite.xml0000644000175000017500000000041212551235562024053 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/parametertest/0000755000175000017500000000000012551235562022311 5ustar eugeneeugenetestng-testng-6.9.5/src/test/resources/parametertest/parent-suite.xml0000644000175000017500000000040512551235562025452 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/parametertest/child3-suite.xml0000644000175000017500000000046112551235562025331 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/parametertest/child2-suite.xml0000644000175000017500000000060112551235562025324 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/parametertest/child1-suite.xml0000644000175000017500000000046112551235562025327 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/param-inheritance/0000755000175000017500000000000012551235562023020 5ustar eugeneeugenetestng-testng-6.9.5/src/test/resources/param-inheritance/parent-suite.xml0000644000175000017500000000022712551235562026163 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/param-inheritance/child-suite.xml0000644000175000017500000000022112551235562025747 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/parallel-suites/0000755000175000017500000000000012551235562022537 5ustar eugeneeugenetestng-testng-6.9.5/src/test/resources/parallel-suites/suite-parallel-3.xml0000644000175000017500000000022112551235562026337 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/parallel-suites/suite-parallel-2.xml0000644000175000017500000000043112551235562026341 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/parallel-suites/suite-parallel-2-2.xml0000644000175000017500000000035412551235562026504 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/parallel-suites/suite-parallel-2-2-1.xml0000644000175000017500000000023112551235562026634 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/parallel-suites/suite-parallel-2-1.xml0000644000175000017500000000022512551235562026500 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/parallel-suites/suite-parallel-1.xml0000644000175000017500000000022112551235562026335 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/parallel-suites/suite-parallel-0.xml0000644000175000017500000000050512551235562026341 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/package.xml0000644000175000017500000000111612551235562021545 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/methodselector-in-xml.xml0000644000175000017500000000056112551235562024400 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/methodinterceptors/0000755000175000017500000000000012551235562023353 5ustar eugeneeugenetestng-testng-6.9.5/src/test/resources/methodinterceptors/multipleinterceptors/0000755000175000017500000000000012551235562027650 5ustar eugeneeugene././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootroottestng-testng-6.9.5/src/test/resources/methodinterceptors/multipleinterceptors/multiple-interceptors.xmltestng-testng-6.9.5/src/test/resources/methodinterceptors/multipleinterceptors/multiple-interceptors0000644000175000017500000000113712551235562034147 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/listener-in-xml.xml0000644000175000017500000000053112551235562023201 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/junit-suite.xml0000644000175000017500000000040512551235562022432 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/hosts.properties0000644000175000017500000000006112551235562022704 0ustar eugeneeugenetestng.hosts=localhost:5150 testng.strategy=test testng-testng-6.9.5/src/test/resources/create-serviceloader-jar.sh0000644000175000017500000000077212551235562024635 0ustar eugeneeugene# This script will update serviceloader.jar with the latest version of TmpSuiteListener.class, # which is used by test.serviceloader.ServiceLoaderTest. # Run this script after building TestNG and its tests with ant j=${PWD} rm -rf /tmp/sl mkdir /tmp/sl cd /tmp/sl jar xvf ${j}/serviceloader.jar echo "test.serviceloader.TmpSuiteListener" >META-INF/services/org.testng.ITestNGListener cp ${j}/../../../target/test-classes/test/serviceloader/TmpSuiteListener.class test/tmp jar cvf ${j}/serviceloader.jar . testng-testng-6.9.5/src/test/resources/checksuitesinitialization/0000755000175000017500000000000012551235562024713 5ustar eugeneeugenetestng-testng-6.9.5/src/test/resources/checksuitesinitialization/parent-suite.xml0000644000175000017500000000031512551235562030054 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/checksuitesinitialization/children/0000755000175000017500000000000012551235562026503 5ustar eugeneeugenetestng-testng-6.9.5/src/test/resources/checksuitesinitialization/children/morechildren/0000755000175000017500000000000012551235562031156 5ustar eugeneeugene././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootroottestng-testng-6.9.5/src/test/resources/checksuitesinitialization/children/morechildren/child-suite-5.xmltestng-testng-6.9.5/src/test/resources/checksuitesinitialization/children/morechildren/child-suite-50000644000175000017500000000022212551235562033451 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/checksuitesinitialization/children/child-suite-4.xml0000644000175000017500000000022212551235562031574 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/checksuitesinitialization/children/child-suite-3.xml0000644000175000017500000000037712551235562031606 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/checksuitesinitialization/child-suite2.xml0000644000175000017500000000022312551235562027726 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/checksuitesinitialization/child-suite1.xml0000644000175000017500000000022312551235562027725 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/b.xml0000644000175000017500000000031612551235562020374 0ustar eugeneeugene testng-testng-6.9.5/src/test/resources/a.xml0000644000175000017500000000031612551235562020373 0ustar eugeneeugene testng-testng-6.9.5/src/test/java/0000755000175000017500000000000012551235562016340 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/testhelper/0000755000175000017500000000000012551235562020517 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/testhelper/OutputDirectoryPatch.java0000644000175000017500000000301412551235562025525 0ustar eugeneeugenepackage testhelper; /** * OutputDirectoryPatch is a helper class to provide an output directory * for TestNG tests that explicitly create an instance of TestNG and do not know the * output directory specified for the test. * * @author cquezel * @since 4.8 */ public final class OutputDirectoryPatch { /** The default output directory name if none was specified. We should use something * different than "test-output" to make it clear that the output directory * has not been set. */ private static final String DEFAULT_OUTPUT_DIRECTORY = "test-output"; /** The name of the System property used to store the output directory. */ private static final String OUTPUT_DIRECTORY_PROPERTY_NAME = "testng.outputDir"; /** * Private constructor to disable instantiation. * * @since 4.8 */ private OutputDirectoryPatch() { // Hide constructor } /** * Returns the output directory as specified for the current test. * * @return the output directory as specified for the current test. * @since 4.8 */ public static String getOutputDirectory() { String tmp = System.getProperty(OUTPUT_DIRECTORY_PROPERTY_NAME); if (tmp != null) { return tmp; } // System.err.println("System property: " + OUTPUT_DIRECTORY_PROPERTY_NAME // + " has not been set. Using default path: " + DEFAULT_OUTPUT_DIRECTORY); // new Throwable("Stack is only to help locate the problem. No excpetion thrown.").printStackTrace(System.err); return DEFAULT_OUTPUT_DIRECTORY; } } testng-testng-6.9.5/src/test/java/test/0000755000175000017500000000000012551235562017317 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/yaml/0000755000175000017500000000000012551235562020261 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/yaml/YamlTest.java0000644000175000017500000000203212551235562022663 0ustar eugeneeugenepackage test.yaml; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.testng.xml.Parser; import org.testng.xml.XmlSuite; import org.xml.sax.SAXException; import test.SimpleBaseTest; import javax.xml.parsers.ParserConfigurationException; import java.io.File; import java.io.IOException; import java.util.Collection; public class YamlTest extends SimpleBaseTest { @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { "a1" }, new Object[] { "a2" }, new Object[] { "a3" }, new Object[] { "a4" }, }; } @Test(dataProvider = "dp") public void compareFiles(String name) throws ParserConfigurationException, SAXException, IOException { Collection s1 = new Parser(getPathToResource("yaml" + File.separator + name + ".yaml")).parse(); Collection s2 = new Parser(getPathToResource("yaml" + File.separator + name + ".xml")).parse(); Assert.assertEquals(s1, s2); } } testng-testng-6.9.5/src/test/java/test/xml/0000755000175000017500000000000012551235562020117 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/xml/XmlVerifyTest.java0000644000175000017500000000332312551235562023550 0ustar eugeneeugenepackage test.xml; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.TestNGException; import org.testng.annotations.Test; import org.testng.xml.XmlClass; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.Arrays; public class XmlVerifyTest extends SimpleBaseTest { // private String getFinalPath(String file) { // File currentDir = new File("."); // String path = currentDir.getAbsolutePath(); // char s = File.separatorChar; // String testDir = System.getProperty("test.dir"); // System.out.println("[XmlVerifyTest] test.dir:" + testDir); // Assert.assertNotNull(testDir); // path = path + s + testDir + s; // return path + file; // } @Test public void simple() { XmlSuite suite = new XmlSuite(); XmlTest test = new XmlTest(suite); XmlClass xClass = new XmlClass(XmlVerifyTest.class); test.getXmlClasses().add(xClass); test.getExcludedGroups().add("fast"); test.setVerbose(5); suite.toXml(); } @Test(description="Ensure that TestNG stops without running any tests if some class" + " included in suite is missing") public void handleInvalidSuites() { TestListenerAdapter tla = new TestListenerAdapter(); try { TestNG tng = create(); String testngXmlPath = getPathToResource("suite1.xml"); tng.setTestSuites(Arrays.asList(testngXmlPath)); tng.addListener(tla); tng.run(); } catch (TestNGException ex) { Assert.assertEquals(tla.getPassedTests().size(), 0); } } } testng-testng-6.9.5/src/test/java/test/verify/0000755000175000017500000000000012551235562020623 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/verify/VerifyTestListener.java0000644000175000017500000000131212551235562025275 0ustar eugeneeugenepackage test.verify; import org.testng.ITestContext; import org.testng.ITestListener; import org.testng.ITestResult; public class VerifyTestListener implements ITestListener { public static int m_count = 0; @Override public void onFinish(ITestContext context) { } @Override public void onStart(ITestContext context) { m_count++; } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult result) { } @Override public void onTestFailure(ITestResult result) { } @Override public void onTestSkipped(ITestResult result) { } @Override public void onTestStart(ITestResult result) { } @Override public void onTestSuccess(ITestResult result) { } } testng-testng-6.9.5/src/test/java/test/verify/VerifyTest.java0000644000175000017500000000211712551235562023573 0ustar eugeneeugenepackage test.verify; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class VerifyTest extends SimpleBaseTest { private void runTest(Class cls, int expected) { TestNG tng = create(cls); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), expected); } @Test public void verifyWithAnnotation() { runTest(VerifySampleTest.class, 4); } @Test public void verifyWithoutAnnotation() { runTest(VerifyNoListenersSampleTest.class, 3); } @Test public void verifyTestListener() { TestNG tng = create(Verify2SampleTest.class); VerifyTestListener.m_count = 0; tng.run(); Assert.assertEquals(VerifyTestListener.m_count, 1); } @Test public void verifyBaseClassTestListener() { TestNG tng = create(Verify3SampleTest.class); VerifyTestListener.m_count = 0; tng.run(); Assert.assertEquals(VerifyTestListener.m_count, 1); } } testng-testng-6.9.5/src/test/java/test/verify/VerifySampleTest.java0000644000175000017500000000126712551235562024742 0ustar eugeneeugenepackage test.verify; import org.testng.annotations.Listeners; import org.testng.annotations.Test; /** * Illustrate the implementation of a @Verify/@Verifier test. * * One method should be annotated with @Verifier and then each test method * annotated with @Verify will be followed with a call to the @Verifier * method. */ @Listeners(VerifyMethodInterceptor.class) public class VerifySampleTest { @Verify @Test public void f1() { log("f1"); } @Verify @Test public void f2() { log("f2"); } @Verifier @Test public void verify() { log("Verifying"); } private void log(String string) { if (false) { System.out.println(string); } } } testng-testng-6.9.5/src/test/java/test/verify/VerifyNoListenersSampleTest.java0000644000175000017500000000073112551235562027123 0ustar eugeneeugenepackage test.verify; import org.testng.annotations.Test; /** * Same class as VerifySampleTest but without the @Listeners annotation. */ public class VerifyNoListenersSampleTest { @Verify @Test public void f1() { log("f1"); } @Verify @Test public void f2() { log("f2"); } @Verifier @Test public void verify() { log("Verifying"); } private void log(String string) { if (false) { System.out.println(string); } } } testng-testng-6.9.5/src/test/java/test/verify/VerifyMethodInterceptor.java0000644000175000017500000000224612551235562026316 0ustar eugeneeugenepackage test.verify; import org.testng.IMethodInstance; import org.testng.IMethodInterceptor; import org.testng.ITestContext; import org.testng.collections.Lists; import java.util.List; public class VerifyMethodInterceptor implements IMethodInterceptor { @Override public List intercept(List methods, ITestContext context) { List result = Lists.newArrayList(); IMethodInstance verifier = null; // Doing a naive approach here: we run through the list of methods // twice, once to find the verifier and once more to actually create // the result. Obviously, this can be done with just one loop for (IMethodInstance m : methods) { if (m.getMethod().getMethod().getAnnotation(Verifier.class) != null) { verifier = m; break; } } // Create the result with each @Verify method followed by a call // to the @Verifier method for (IMethodInstance m : methods) { if (m != verifier) { result.add(m); } if (m.getMethod().getMethod().getAnnotation(Verify.class) != null) { result.add(verifier); } } return result; } }testng-testng-6.9.5/src/test/java/test/verify/Verify3SampleTest.java0000644000175000017500000000042112551235562025014 0ustar eugeneeugenepackage test.verify; import org.testng.annotations.BeforeClass; /** * Make sure that @Listeners annotations can come from superclasses */ public class Verify3SampleTest extends Verify3Base { @BeforeClass public void bc() { VerifyTestListener.m_count = 0; } } testng-testng-6.9.5/src/test/java/test/verify/Verify3Base.java0000644000175000017500000000020212551235562023602 0ustar eugeneeugenepackage test.verify; import org.testng.annotations.Listeners; @Listeners(VerifyTestListener.class) public class Verify3Base { } testng-testng-6.9.5/src/test/java/test/verify/Verify2SampleTest.java0000644000175000017500000000201312551235562025012 0ustar eugeneeugenepackage test.verify; import org.testng.ITestNGListener; import org.testng.ITestNGListenerFactory; import org.testng.annotations.Listeners; import org.testng.annotations.Test; /** * Illustrate the implementation of a @Verify/@Verifier test. * * One method should be annotated with @Verifier and then each test method * annotated with @Verify will be followed with a call to the @Verifier * method. */ @Listeners(VerifyTestListener.class) public class Verify2SampleTest implements ITestNGListenerFactory { public Verify2SampleTest() {} @Verify @Test public void f1() { log("f1"); } @Verify @Test public void f2() { log("f2"); } @Verifier @Test public void verify() { log("Verifying"); } private void log(String string) { if (false) { System.out.println(hashCode() + " " + string); } } @Override public ITestNGListener createListener(Class listenerClass) { log("Creating a listener of type " + listenerClass); return null; } } testng-testng-6.9.5/src/test/java/test/verify/Verify.java0000644000175000017500000000047512551235562022740 0ustar eugeneeugenepackage test.verify; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({METHOD, TYPE}) public @interface Verify { } testng-testng-6.9.5/src/test/java/test/verify/Verifier.java0000644000175000017500000000047712551235562023251 0ustar eugeneeugenepackage test.verify; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({METHOD, TYPE}) public @interface Verifier { } testng-testng-6.9.5/src/test/java/test/v6/0000755000175000017500000000000012551235562017652 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/v6/C.java0000644000175000017500000000070712551235562020703 0ustar eugeneeugenepackage test.v6; import org.testng.annotations.AfterSuite; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class C { @BeforeTest public void beforeTest() {} @AfterTest public void afterTest() {} @Test public void fc1() {} @BeforeSuite public void beforeSuite() {} @AfterSuite public void afterSuite() {} } testng-testng-6.9.5/src/test/java/test/v6/B.java0000644000175000017500000000124312551235562020676 0ustar eugeneeugenepackage test.v6; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; public class B { @Test(dependsOnMethods = "fb1") public void fb2() { } @Test(groups = "1") public void fb1() {} @Test public void fb3() {} @BeforeMethod public void beforeMethod() {} @AfterMethod(groups = "1") public void afterMethod() {} @BeforeSuite public void beforeSuite() {} @BeforeClass public void beforeClass() {} @AfterClass public void afterClass() {} } testng-testng-6.9.5/src/test/java/test/v6/A.java0000644000175000017500000000165512551235562020704 0ustar eugeneeugenepackage test.v6; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterGroups; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; public class A { @Test(dependsOnMethods = "fa1") public void fa2() { } @Test(groups = "1") public void fa1() {} @Test public void fa3() {} @BeforeGroups("1") public void beforeGroups() {} @AfterGroups("1") public void afterGroups() {} @BeforeMethod public void beforeMethod() {} @AfterMethod public void afterMethod() {} @BeforeSuite public void beforeSuite() {} @AfterSuite public void afterSuite() {} @BeforeClass public void beforeClass() {} @AfterClass public void afterClass() {} } testng-testng-6.9.5/src/test/java/test/uniquesuite/0000755000175000017500000000000012551235562021677 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/uniquesuite/TestBefore2.java0000644000175000017500000000033312551235562024665 0ustar eugeneeugenepackage test.uniquesuite; import org.testng.Assert; import org.testng.annotations.Test; public class TestBefore2 extends BaseBefore { @Test public void verify() { Assert.assertEquals(m_beforeCount, 1); } } testng-testng-6.9.5/src/test/java/test/uniquesuite/TestBefore1.java0000644000175000017500000000033312551235562024664 0ustar eugeneeugenepackage test.uniquesuite; import org.testng.Assert; import org.testng.annotations.Test; public class TestBefore1 extends BaseBefore { @Test public void verify() { Assert.assertEquals(m_beforeCount, 1); } } testng-testng-6.9.5/src/test/java/test/uniquesuite/TestAfter2.java0000644000175000017500000000022412551235562024523 0ustar eugeneeugenepackage test.uniquesuite; import org.testng.annotations.Test; public class TestAfter2 extends BaseAfter { @Test public void verify() { } } testng-testng-6.9.5/src/test/java/test/uniquesuite/TestAfter1.java0000644000175000017500000000022412551235562024522 0ustar eugeneeugenepackage test.uniquesuite; import org.testng.annotations.Test; public class TestAfter1 extends BaseAfter { @Test public void verify() { } } testng-testng-6.9.5/src/test/java/test/uniquesuite/TestAfter.java0000644000175000017500000000125712551235562024450 0ustar eugeneeugenepackage test.uniquesuite; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.AfterTest; import org.testng.annotations.Test; import testhelper.OutputDirectoryPatch; public class TestAfter { @Test public void testAfter() { TestNG tng = new TestNG(); tng.setOutputDirectory(OutputDirectoryPatch.getOutputDirectory()); tng.setTestClasses(new Class[] { TestAfter1.class, TestAfter2.class }); tng.setVerbose(0); tng.run(); Assert.assertEquals(BaseAfter.m_afterCount, 1); } @AfterTest public void afterTest() { BaseAfter.m_afterCount = 0; BaseBefore.m_beforeCount = 0; BaseBefore.m_afterCount = 0; } } ///// testng-testng-6.9.5/src/test/java/test/uniquesuite/BaseBefore.java0000644000175000017500000000067712551235562024551 0ustar eugeneeugenepackage test.uniquesuite; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeSuite; public class BaseBefore { public static int m_beforeCount = 0; public static int m_afterCount = 0; @BeforeSuite public void incrementBefore() { m_beforeCount++; } @AfterSuite public void incrementAfter() { m_afterCount++; } private static void ppp(String s) { System.out.println("[Base] " + s); } } testng-testng-6.9.5/src/test/java/test/uniquesuite/BaseAfter.java0000644000175000017500000000063112551235562024376 0ustar eugeneeugenepackage test.uniquesuite; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeSuite; public class BaseAfter { public static int m_afterCount = 0; @BeforeSuite public void beforeSuite() { m_afterCount = 0; } @AfterSuite public void incrementAfter() { m_afterCount++; } private static void ppp(String s) { System.out.println("[BaseAfter] " + s); } } testng-testng-6.9.5/src/test/java/test/triangle/0000755000175000017500000000000012551235562021124 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/triangle/CountCalls.java0000644000175000017500000000046512551235562024043 0ustar eugeneeugenepackage test.triangle; /** * count the number of times something is called * used to check whether certain methods have been called */ public class CountCalls { static int numCalls = 0; public static void incr () { numCalls++; } public static int getNumCalls() { return numCalls; } } testng-testng-6.9.5/src/test/java/test/triangle/Child2.java0000644000175000017500000000036012551235562023073 0ustar eugeneeugenepackage test.triangle; import org.testng.annotations.Test; /** * This class * * @author cbeust */ public class Child2 extends Base { @Test public void child2() { assert m_isInitialized : "Wasn't initialized correctly"; } } testng-testng-6.9.5/src/test/java/test/triangle/Child1.java0000644000175000017500000000062712551235562023100 0ustar eugeneeugenepackage test.triangle; import org.testng.annotations.Test; /** * This class * * @author cbeust */ public class Child1 extends Base { @Test public void child1() { assert m_isInitialized : "Wasn't initialized correctly " + hashCode() + " " + getClass(); } @Test public void child1a() { assert m_isInitialized : "Wasn't initialized correctly " + hashCode() + " " + getClass(); } } testng-testng-6.9.5/src/test/java/test/triangle/CheckCount.java0000644000175000017500000000237512551235562024024 0ustar eugeneeugenepackage test.triangle; import org.testng.annotations.Parameters; import org.testng.annotations.Test; /** * this test checks the CountCalls's static counter to see if we got the * expected number of calls */ public class CheckCount { @Test(parameters = { "expected-calls" }) public void testCheckCountDeprecated(String expectedCalls){ try { // System.out.println("\n\ntestCheckCount time = " + System.currentTimeMillis()); int i = Integer.valueOf(expectedCalls); int numCalls = CountCalls.getNumCalls(); assert (numCalls == i) : "Count calls expected " + i + " but got " + numCalls; } catch (NumberFormatException nfe) { assert false : "CountCalls needs an expected-calls numeric parameter"; } } @Parameters({ "expected-calls" }) @Test public void testCheckCount(String expectedCalls){ try { // System.out.println("\n\ntestCheckCount time = " + System.currentTimeMillis()); int i = Integer.valueOf(expectedCalls); int numCalls = CountCalls.getNumCalls(); assert (numCalls == i) : "Count calls expected " + i + " but got " + numCalls; } catch (NumberFormatException nfe) { assert false : "CountCalls needs an expected-calls numeric parameter"; } } }testng-testng-6.9.5/src/test/java/test/triangle/Base.java0000644000175000017500000000111512551235562022637 0ustar eugeneeugenepackage test.triangle; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeSuite; /** * This class * * @author cbeust */ public class Base { protected boolean m_isInitialized = false; @BeforeSuite public void beforeSuite() { CountCalls.numCalls = 0; } @BeforeClass public void initBeforeTestClass() { m_isInitialized = true; } @AfterClass public void postAfterTestClass() { CountCalls.incr(); } private static void ppp(String s) { System.out.println("[Base] " + s); } } testng-testng-6.9.5/src/test/java/test/tmp/0000755000175000017500000000000012551235562020117 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/tmp/verify/0000755000175000017500000000000012551235562021423 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/tmp/verify/VerifyTest.java0000644000175000017500000000052112551235562024370 0ustar eugeneeugenepackage test.tmp.verify; import org.testng.annotations.Test; public class VerifyTest { @Test public void f2() { System.out.println("f2()"); } @Test public void f1() { System.out.println("f1()"); } @Verify public void verify() { // throw new RuntimeException(); // System.out.println("verify()"); } } testng-testng-6.9.5/src/test/java/test/tmp/verify/VerifyInterceptor.java0000644000175000017500000000502212551235562025750 0ustar eugeneeugenepackage test.tmp.verify; import org.testng.IMethodInstance; import org.testng.IMethodInterceptor; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.TestNGUtils; import org.testng.collections.Maps; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Map; public class VerifyInterceptor implements IMethodInterceptor { /** * @return the list of methods received in parameters with all methods * annotated with @Verify inserted after each of these test methods. * * This happens in two steps: * - Find all the methods annotated with @Verify in the classes that contain test methods * - Insert these verify methods after each method passed in parameter * These @Verify methods are stored in a map keyed by the class in order to avoid looking them * up more than once on the same class. */ @Override public List intercept(List methods, ITestContext context) { List result = new ArrayList<>(); Map, List> verifyMethods = Maps.newHashMap(); for (IMethodInstance mi : methods) { ITestNGMethod tm = mi.getMethod(); List verify = verifyMethods.get(tm.getRealClass()); if (verify == null) { verify = findVerifyMethods(tm.getRealClass(), tm); } result.add(mi); result.addAll(verify); } return result; } /** * @return all the @Verify methods found on @code{realClass} */ private List findVerifyMethods(Class realClass, final ITestNGMethod tm) { List result = new ArrayList<>(); for (final Method m : realClass.getDeclaredMethods()) { Annotation a = m.getAnnotation(Verify.class); if (a != null) { final ITestNGMethod vm = TestNGUtils.createITestNGMethod(tm, m); result.add(new IMethodInstance() { @Override public Object[] getInstances() { return tm.getInstances(); } @Override public ITestNGMethod getMethod() { return vm; } public int compareTo(IMethodInstance o) { if (getInstances()[0] == o.getInstances()[0]) { return 0; } else { return -1; } } @Override public Object getInstance() { return tm.getInstance(); } }); } } return result; } } testng-testng-6.9.5/src/test/java/test/tmp/verify/Verify.java0000644000175000017500000000035512551235562023535 0ustar eugeneeugenepackage test.tmp.verify; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(java.lang.annotation.ElementType.METHOD) public @interface Verify { } testng-testng-6.9.5/src/test/java/test/tmp/p2/0000755000175000017500000000000012551235562020440 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/tmp/p2/ServiceTest.java0000644000175000017500000000035012551235562023541 0ustar eugeneeugenepackage test.tmp.p2; import static org.testng.AssertJUnit.assertNotNull; import org.testng.annotations.Test; public class ServiceTest { @Test(groups = {"group1"}) public void service() { assertNotNull(null); } }testng-testng-6.9.5/src/test/java/test/tmp/p1/0000755000175000017500000000000012551235562020437 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/tmp/p1/ContainerTest.java0000644000175000017500000000054212551235562024065 0ustar eugeneeugenepackage test.tmp.p1; import static org.testng.AssertJUnit.assertNotNull; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeSuite; public class ContainerTest { @BeforeSuite public void startup() { assertNotNull(null); } @AfterSuite public void shutdown() { assertNotNull(null); } } testng-testng-6.9.5/src/test/java/test/tmp/b/0000755000175000017500000000000012551235562020340 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/tmp/b/TmpB.java0000644000175000017500000000022412551235562022043 0ustar eugeneeugenepackage test.tmp.b; import org.testng.annotations.Test; public class TmpB { @Test public void tmpb1() { System.out.println("tmpb1"); } }testng-testng-6.9.5/src/test/java/test/tmp/Tn.java0000644000175000017500000000073312551235562021346 0ustar eugeneeugenepackage test.tmp; import org.testng.Reporter; import org.testng.annotations.Parameters; import org.testng.annotations.Test; public class Tn { @Test (groups = {"g1"}) public void m1() { System.out.println("1"); } @Test (groups = {"g1"}, dependsOnMethods="m1") public void m2() { System.out.println("2"); } @Parameters(value = "param") @Test (groups = {"g2"}) public void m3(String param) { System.out.println("3"); Reporter.log("M3 WAS CALLED"); } } testng-testng-6.9.5/src/test/java/test/tmp/Tmp.java0000644000175000017500000000111112551235562021514 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.Test; import java.util.Random; public class Tmp { @Test(invocationCount = 10, threadPoolSize = 5) public void f() { ppp("START " + Thread.currentThread().getId()); try { Random r = new Random(); Thread.sleep(Math.abs(r.nextInt() % 300)); } catch (InterruptedException handled) { Thread.currentThread().interrupt(); handled.printStackTrace(); } ppp("END " + Thread.currentThread().getId()); } private void ppp(String string) { System.out.println("[Tmp] " + string); } } testng-testng-6.9.5/src/test/java/test/tmp/TimeBombTest.java0000644000175000017500000000165412551235562023326 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.Test; import java.lang.reflect.Method; import java.util.Calendar; public class TimeBombTest { @IgnoreUntil(time = "1022") @Test public void timeBomb() throws SecurityException, NoSuchMethodException { Method m = TimeBombTest.class.getMethod("timeBomb", new Class[0]); IgnoreUntil t = m.getAnnotation(IgnoreUntil.class); long now = Calendar.getInstance().getTimeInMillis(); long l = parseTime(t.time()); ppp("IGNORE:" + (now < l)); } private long parseTime(String string) { int hour = Integer.parseInt(string.substring(0, 2)); int minute = Integer.parseInt(string.substring(2)); Calendar result = Calendar.getInstance(); result.set(Calendar.HOUR_OF_DAY, hour); result.set(Calendar.MINUTE, minute); return result.getTimeInMillis(); } private void ppp(String string) { System.out.println("[TimeBombTest] " + string); } } testng-testng-6.9.5/src/test/java/test/tmp/Test_TestListenerAppender.java0000644000175000017500000000074012551235562026066 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class Test_TestListenerAppender { @DataProvider(name = "test1") public Object[][] createData1() { // throw new RuntimeException("Intentionally thrown exception"); return new Object[][] { { "Cedric", 36}, {"Anne", 37}, }; } @Test(dataProvider = "test1") public void verifyData1(String n1, Integer n2) { System.out.println(n1 + " " + n2); } } testng-testng-6.9.5/src/test/java/test/tmp/TestNGBug.java0000644000175000017500000000103112551235562022557 0ustar eugeneeugenepackage test.tmp; import org.testng.Reporter; import org.testng.annotations.Test; public class TestNGBug { // @Configuration(beforeTestMethod = true) public void init() { ppp("Base.init()"); } @Test public void test1() { Reporter.log("Child.test1"); } @Test(enabled = false) public void test2() { Reporter.log("Child.test2"); } @Test(groups = "a") public void test3() { Reporter.log("Child.test3"); } private void ppp(String string) { System.out.println("[TestNGBug] " + string); } } testng-testng-6.9.5/src/test/java/test/tmp/TestFixture.java0000644000175000017500000000117112551235562023250 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.Configuration; public class TestFixture { public static int globalCallSequence = 0; public static int printGlobalCallSequence(String methodName) { globalCallSequence++; System.err.println("*** " + methodName + ": globalCallSequence=" + globalCallSequence); return globalCallSequence; } public int fixtureBeforeTestCallSequence; @Configuration(beforeTest=true, groups="fixture") public void beforeTest() { fixtureBeforeTestCallSequence = printGlobalCallSequence("TestFixture.beforeTest"); } public int getSomeRandomValue() { return 20; } } testng-testng-6.9.5/src/test/java/test/tmp/TestCaseFactory.java0000644000175000017500000000054712551235562024033 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.Factory; import org.testng.annotations.Test; public class TestCaseFactory { class MyTestClass { @Test public void testAll() { } } @Factory public Object[] createTestCases() { Object[] testCases = new Object[1]; testCases[0] = new MyTestClass() { }; return testCases; } }testng-testng-6.9.5/src/test/java/test/tmp/TestB.java0000644000175000017500000000172012551235562022003 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class TestB { @BeforeClass public void insertB() { // Inserts an entity 'B'. This is an expensive operation. // After this, the entity 'B' is the first row on the table. } @Test public void testGetB() { // Checks that 'B' is the first row on the table, and loads it. } @Test(dependsOnMethods = "testGetB") public void testViewB_Details1() { // Loads the first row (assumed B) and checks some details } @Test(dependsOnMethods = "testGetB") public void testViewB_Details2() { // Loads the first row (assumed B) and checks some details } @Test(dependsOnMethods = "testGetB") public void testViewB_Details3() { // Loads the first row (assumed B) and checks some details } @Test(dependsOnMethods = "testGetB") public void testViewB_Details4() { } } testng-testng-6.9.5/src/test/java/test/tmp/TestA.java0000644000175000017500000000202212551235562021776 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class TestA { @BeforeClass public void insertA() { // Inserts an entity 'A'. This is an expensive operation. // After this, the entity 'A' is the first row on the table. } @Test public void testGetA() { // Checks that 'A' is the first row on the table, and loads it. } @Test(dependsOnMethods = "testGetA") public void testViewA_Details1() { // Loads the first row (assumed A) and checks some details } @Test(dependsOnMethods = "testGetA") public void testViewA_Details2() { // Loads the first row (assumed A) and checks some details } @Test(dependsOnMethods = "testGetA") public void testViewA_Details3() { // Loads the first row (assumed A) and checks some details } @Test(dependsOnMethods = "testGetA") public void testViewA_Details4() { // Loads the first row (assumed A) and checks some details } } testng-testng-6.9.5/src/test/java/test/tmp/Test1.java0000644000175000017500000000031012551235562021754 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.Test; @Test(dependsOnGroups = { "G0" }) public class Test1 { public void test() { System.out.println("Test1.test"); } }testng-testng-6.9.5/src/test/java/test/tmp/Test0.java0000644000175000017500000000066412551235562021767 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.Configuration; import org.testng.annotations.Test; public class Test0 { @Configuration(beforeTest = true) public void setup() { System.out.println("setup"); } @Test(groups = { "G0" }) public void test() { System.out.println("Test0.test"); } @Configuration(afterTest = true) public void tearDown() { System.out.println("tearDown"); } }testng-testng-6.9.5/src/test/java/test/tmp/Sub.java0000644000175000017500000000131012551235562021506 0ustar eugeneeugenepackage test.tmp; import org.testng.Assert; import org.testng.annotations.Configuration; import org.testng.annotations.Test; @Test(groups = {"sub"}) public class Sub extends Base { boolean m_beforeTest; boolean m_afterTest; @Configuration(beforeTestClass = true) public void subSetup() { System.out.println("sub before class"); } @Configuration(afterTestClass = true) public void subTeardown() { System.out.println("sub after class"); } public void subTest() { System.out.println ("sub test"); } @Configuration(afterSuite = true) public void verify() { Assert.assertTrue(m_beforeTest); Assert.assertTrue(m_afterTest); } } testng-testng-6.9.5/src/test/java/test/tmp/StaticInitializerTest.java0000644000175000017500000000045312551235562025257 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.Test; @Test public class StaticInitializerTest { static { foo(); } public void testMe() { System.err.println("**** testMe ****"); } private static void foo() { throw new RuntimeException("FAILING"); } }testng-testng-6.9.5/src/test/java/test/tmp/RetryAnalyzer.java0000644000175000017500000000040112551235562023570 0ustar eugeneeugenepackage test.tmp; import org.testng.IRetryAnalyzer; import org.testng.ITestResult; public class RetryAnalyzer implements IRetryAnalyzer { @Override public boolean retry(ITestResult result) { System.out.println("retry()"); return true; } } testng-testng-6.9.5/src/test/java/test/tmp/RegisterCommandTest.java0000644000175000017500000000113012551235562024700 0ustar eugeneeugenepackage test.tmp; import org.testng.ITestContext; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @Test(groups = { "NewUser" }) public class RegisterCommandTest { // Logger l = LoggerFactory.getLogger(this.getClass()); @BeforeClass public void beforeClass(ITestContext itc) { System.out.println("BEFORECLASS getting injector from context"); // m_inj = (Injector) itc.getAttribute("injector"); // m_inj.injectMembers(this); } public void testExecute(ITestContext itc) throws Exception { System.out.println("TESTEXECUTE do somthing"); } } testng-testng-6.9.5/src/test/java/test/tmp/ParentTest.java0000644000175000017500000000073512551235562023060 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.Configuration; import org.testng.annotations.Test; public class ParentTest { @Configuration(beforeTestMethod = true) public void btm1() { ppp("PARENT BEFORE TEST"); } @Configuration(afterTestMethod = true) public void atm1() { ppp("PARENT AFTER TEST"); } @Test public void t1() { ppp("TEST PARENT"); } private void ppp(String string) { System.out.println("[Parent] " + string); } } testng-testng-6.9.5/src/test/java/test/tmp/ParamTest.java0000644000175000017500000000110712551235562022661 0ustar eugeneeugenepackage test.tmp; import org.testng.Reporter; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class ParamTest { @Test(dataProvider="dp") public void f(String s, int n) { // if ("Alois".equals(s)) assert false; Reporter.log("CALL " + n); ppp("TEST : " + s); } @DataProvider(name="dp") public Object[][] create() { return new Object[][] { new Object[] { "Cedric", 36}, new Object[] {"Alois", 35}, }; } private void ppp(String string) { System.err.println("[ParamTest] " + string); } } testng-testng-6.9.5/src/test/java/test/tmp/IgnoreUntil.java0000644000175000017500000000070012551235562023216 0ustar eugeneeugenepackage test.tmp; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({METHOD, TYPE, CONSTRUCTOR}) public @interface IgnoreUntil { /** * Format: hhmm */ public String time(); } testng-testng-6.9.5/src/test/java/test/tmp/Fixturable.java0000644000175000017500000000043612551235562023072 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.Configuration; public class Fixturable { @Configuration(beforeTest=true, groups="fixture") public void setupFixture() { ppp("SETUP"); } private static void ppp(String s) { System.out.println("[Fixturable] " + s); } } testng-testng-6.9.5/src/test/java/test/tmp/ExponentTest.java0000644000175000017500000000211612551235562023422 0ustar eugeneeugenepackage test.tmp; import static org.testng.Assert.assertEquals; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @Test(suiteName = "Exponent suite", testName = "Exponent test") public class ExponentTest { @DataProvider(name = "random") public Object[][] generateRandomExps() { // This array should be generated with random numbers return new Object[][] { new Object[] { 0.0, Math.exp(0) }, new Object[] { 1.0, Math.exp(1) }, new Object[] { 2.0, Math.exp(2) }, }; } @BeforeMethod public void setUp() { ppp("BEFORE METHOD"); } @Test(dataProvider = "random") public void testExponent(double exponent, double expected) { ppp("COMPARING " + myExpFunction(exponent) + " AND " + expected); assertEquals(myExpFunction(exponent), expected); } private static void ppp(String s) { System.out.println("[ExponentTest] " + s); } private double myExpFunction(double exponent) { return Math.exp(exponent); } } testng-testng-6.9.5/src/test/java/test/tmp/DataDrivenTest.java0000644000175000017500000000201312551235562023637 0ustar eugeneeugenepackage test.tmp; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Properties; public class DataDrivenTest { @DataProvider(name = "provider") public Object[][] createData() throws FileNotFoundException, IOException { Properties p = new Properties(); List vResult = new ArrayList<>(); p.load(new FileInputStream(new File("c:/t/data.properties"))); for (Enumeration e = p.keys(); e.hasMoreElements(); ) { vResult.add(e.nextElement()); } Object[][] result = new Object[vResult.size()][1]; for (int i = 0; i < result.length; i++) { result[i] = new Object[] { vResult.get(i) }; } return result; } @Test(dataProvider = "provider") public void foo(int n) { Assert.assertTrue(n > 0); } } testng-testng-6.9.5/src/test/java/test/tmp/ConcreteTest.java0000644000175000017500000000065212551235562023367 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.Configuration; import org.testng.annotations.Test; public class ConcreteTest extends Fixturable { @Configuration(beforeTest=true, afterGroups="fixture") public void beforeFixture() { ppp("BEFORE"); } @Test(groups = "fixture") public void test() { ppp("TEST"); } private static void ppp(String s) { System.out.println("[ConcreteTest] " + s); } } testng-testng-6.9.5/src/test/java/test/tmp/ChildTest.java0000644000175000017500000000077012551235562022651 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.Configuration; import org.testng.annotations.Test; public class ChildTest extends ParentTest { @Configuration(beforeTestMethod = true) public void btm2() { ppp("CHILD BEFORE TEST"); } @Configuration(afterTestMethod = true) public void atm2() { ppp("CHILD AFTER TEST"); } @Override @Test public void t1() { ppp("TEST CHILD"); } private void ppp(String string) { System.out.println("[Parent] " + string); } } testng-testng-6.9.5/src/test/java/test/tmp/C.java0000644000175000017500000000100112551235562021134 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class C { @BeforeMethod public void cm() { // System.out.println("C.cm"); } @Test(dataProvider = "data") public void c(String s) { System.out.println("c(" + s + ")"); } @DataProvider(name = "data") static public Object[][] data() { return new Object[][] { new Object[] { "Foo" }, new Object[] { "Bar" }, }; } } testng-testng-6.9.5/src/test/java/test/tmp/BeforeGroupTest.java0000644000175000017500000000103212551235562024035 0ustar eugeneeugenepackage test.tmp; import org.testng.ITestContext; import org.testng.annotations.BeforeGroups; public class BeforeGroupTest { // Logger l = LoggerFactory.getLogger(this.getClass()); @BeforeGroups(groups = { "NewUser" }, value = { "NewUser" }) public void preNewUser(ITestContext itc) { System.out.println("BEFOREGROUPS perfroming pre groups init"); // m_inj = Guice.createInjector(new JUnitModule(), new RequestModule(), // new GenericModule(), new SecurityModule()); // itc.setAttribute("injector", m_inj); } }testng-testng-6.9.5/src/test/java/test/tmp/Base.java0000644000175000017500000000030312551235562021630 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.BeforeMethod; public class Base { @BeforeMethod public void bm() { System.out.println("Thread" + Thread.currentThread().getId()); } }testng-testng-6.9.5/src/test/java/test/tmp/BListener.java0000644000175000017500000000073012551235562022651 0ustar eugeneeugenepackage test.tmp; import org.testng.ITestResult; import org.testng.TestListenerAdapter; public class BListener extends TestListenerAdapter { public BListener() { System.out.println("BListener created"); } @Override public void onTestSuccess(ITestResult tr) { System.out.println("Success"); super.onTestSuccess(tr); } @Override public void onTestFailure(ITestResult tr) { System.out.println("Failure"); super.onTestFailure(tr); } } testng-testng-6.9.5/src/test/java/test/tmp/B.java0000644000175000017500000000050112551235562021137 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class B extends C { public static final String G = "group"; @BeforeMethod public void bm() { System.out.println("B.bm"); } @Test public void btest1() { System.out.println("B.btest1"); } } testng-testng-6.9.5/src/test/java/test/tmp/AssertEqualsTest.java0000644000175000017500000000261412551235562024241 0ustar eugeneeugenepackage test.tmp; import org.testng.Assert; import org.testng.annotations.Test; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Random; import java.util.Set; public class AssertEqualsTest { private void log(String s) { System.out.println("[" + Thread.currentThread().getId() + "] " + s); } @Test(threadPoolSize = 3, invocationCount = 6) public void f1() { log("start"); try { int sleepTime = new Random().nextInt(500); Thread.sleep(sleepTime); } catch (Exception e) { log(" *** INTERRUPTED"); } log("end"); } @Test(threadPoolSize = 10, invocationCount = 10000) public void verifyMethodIsThreadSafe() { // foo(); } @Test(dependsOnMethods = "verifyMethodIsThreadSafe") public void verify() { // make sure that nothing was broken } public static void main(String[] args) { Set set1 = new LinkedHashSet(); Set set2 = new HashSet(); set1.add(5); set2.add(5); set1.add(6); set2.add(6); set1.add(1); set2.add(1); set1.add(9); set2.add(9); System.out.println("set1 is:" + set1.toString()); System.out.println("set2 is:" + set2.toString()); System.out.println("is set1 equals set2 :" + set1.equals(set2)); try { Assert.assertEquals(set1, set2, "set1 must equals with set2"); } catch (Exception ex) { ex.printStackTrace(); } } }testng-testng-6.9.5/src/test/java/test/tmp/AnnotationTransformer.java0000644000175000017500000000237512551235562025326 0ustar eugeneeugenepackage test.tmp; import org.testng.IAnnotationTransformer; import org.testng.ITestContext; import org.testng.ITestListener; import org.testng.ITestResult; import org.testng.annotations.ITestAnnotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class AnnotationTransformer implements IAnnotationTransformer, ITestListener { @Override public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { } @Override public void onFinish(ITestContext context) { // TODO Auto-generated method stub } @Override public void onStart(ITestContext context) { // TODO Auto-generated method stub } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult result) { // TODO Auto-generated method stub } @Override public void onTestFailure(ITestResult result) { // TODO Auto-generated method stub } @Override public void onTestSkipped(ITestResult result) { // TODO Auto-generated method stub } @Override public void onTestStart(ITestResult result) { // TODO Auto-generated method stub } @Override public void onTestSuccess(ITestResult result) { // TODO Auto-generated method stub } } testng-testng-6.9.5/src/test/java/test/tmp/AFactory.java0000644000175000017500000000026112551235562022471 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.Factory; public class AFactory { @Factory public Object[] create() { return new Object[] { new A(), new AA() }; } } testng-testng-6.9.5/src/test/java/test/tmp/AA.java0000644000175000017500000000217312551235562021246 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; @Test(sequential = true) public class AA { private int m_n; public AA() {} public AA(int n) { m_n = n; } private void log(String s) { System.out.println(" [AA(" + m_n + ") thread:" + Thread.currentThread().getId() + "] " + s); } @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { 42 }, }; } // @BeforeClass // public void bc() { // log("beforeClass"); // } // // @AfterClass // public void ac() { // log("afterClass"); // } @Factory public Object[] create() { return new Object[] { new A(), new AA() }; } @Test public void aatest1() { log("aatest1"); } @Test(dependsOnMethods = "aatest1") public void aatest2() { log("aatest2"); } // @Test(priority = 3) public void atest3() { } public String getTestName() { return "This is test A"; } // @Test(groups = "mytest", dependsOnMethods = "g") // public void f() { // } // // // @AfterMethod // public void after() { // } } testng-testng-6.9.5/src/test/java/test/tmp/A.java0000644000175000017500000000150112551235562021137 0ustar eugeneeugenepackage test.tmp; import org.testng.annotations.Test; import org.testng.asserts.SoftAssert; @Test public class A { // private FlexibleAssert m_assert = new FlexibleAssert(); private SoftAssert m_assert = new SoftAssert(); // private LoggingAssert m_assert = new LoggingAssert(); public void test1() { m_assert.assertTrue(true, "test1()"); } public void test2() { m_assert.assertTrue(true, "test2()"); } // @AfterClass // public void ac() { // System.out.println("Tests run in this class:" + m_assert.getMessages()); // } public void multiple() { m_assert.assertTrue(true, "Success 1"); m_assert.assertTrue(true, "Success 2"); m_assert.assertTrue(false, "Failure 1"); m_assert.assertTrue(true, "Success 3"); m_assert.assertTrue(false, "Failure 2"); m_assert.assertAll(); } }testng-testng-6.9.5/src/test/java/test/timeout/0000755000175000017500000000000012551235562021005 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/timeout/issue575.xml0000644000175000017500000000037512551235562023125 0ustar eugeneeugene testng-testng-6.9.5/src/test/java/test/timeout/TimeOutTest.java0000644000175000017500000000313512551235562024100 0ustar eugeneeugenepackage test.timeout; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import java.util.Iterator; import test.BaseTest; public class TimeOutTest extends BaseTest { private final long m_id; public TimeOutTest() { m_id = System.currentTimeMillis(); } private void privateTimeOutTest(String parallel) { addClass(TimeOutSampleTest.class); if (parallel != null) { setParallel(parallel); } run(); verifyPassedTests("timeoutShouldPass"); verifyFailedTests("timeoutShouldFailByException", "timeoutShouldFailByTimeOut"); } @DataProvider(name = "parallelModes") public Iterator createData() { final Iterator parallelModes = XmlSuite.PARALLEL_MODES.iterator(); return new Iterator() { @Override public boolean hasNext() { return parallelModes.hasNext(); } @Override public Object[] next() { return new Object[]{ parallelModes.next() }; } @Override public void remove() { throw new UnsupportedOperationException("remove"); } }; } @Test(dataProvider = "parallelModes") public void timeOutInParallel(String parallelMode) { privateTimeOutTest(parallelMode); } @Test public void timeOutInNonParallel() { privateTimeOutTest(null); } @Test public void verifyInvocationTimeOut() { addClass(InvocationTimeOutSampleTest.class); run(); verifyPassedTests("shouldPass"); verifyFailedTests("shouldFail"); } @Override public Long getId() { return m_id; } } testng-testng-6.9.5/src/test/java/test/timeout/TimeOutSampleTest.java0000644000175000017500000000106512551235562025242 0ustar eugeneeugenepackage test.timeout; import org.testng.annotations.Test; /** * This class tests timeouts * * @author cbeust */ public class TimeOutSampleTest { @Test(timeOut = 5_000 /* 5 seconds */) public void timeoutShouldPass() { } @Test(timeOut = 5_000 /* 5 seconds */) public void timeoutShouldFailByException() { throw new RuntimeException("EXCEPTION SHOULD MAKE THIS METHOD FAIL"); } @Test(timeOut = 1_000 /* 1 second */) public void timeoutShouldFailByTimeOut() throws InterruptedException { Thread.sleep(10_000 /* 10 seconds */); } } testng-testng-6.9.5/src/test/java/test/timeout/TimeOutSample2Test.java0000644000175000017500000000044312551235562025323 0ustar eugeneeugenepackage test.timeout; import org.testng.annotations.Test; /** * Tests timeouts set from testng.xml * @author cbeust */ public class TimeOutSample2Test { @Test(timeOut = 1_500) public void timeoutShouldFailByTimeOut() throws InterruptedException { Thread.sleep(10_000); } } testng-testng-6.9.5/src/test/java/test/timeout/TimeOutFromXmlTest.java0000644000175000017500000000463012551235562025406 0ustar eugeneeugenepackage test.timeout; import org.testng.annotations.Test; import org.testng.xml.SuiteXmlParser; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.BaseTest; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class TimeOutFromXmlTest extends BaseTest { private void timeOutTest(boolean onSuite) { addClass(TestTimeOutSampleTest.class); if (onSuite) { setSuiteTimeOut(1_000); } else { setTestTimeOut(1_000); } run(); verifyPassedTests(); verifyFailedTests("timeoutTest"); } @Test public void timeOutOnSuiteTag() { timeOutTest(true /* on suite */); } @Test public void timeOutOnTestTag() { timeOutTest(false /* on test */); } @Test public void noTimeOut() { addClass(TestTimeOutSampleTest.class); run(); verifyPassedTests("timeoutTest"); verifyFailedTests(); } @Test public void twoDifferentTests() { XmlSuite result = new XmlSuite(); result.setName("Suite"); createXmlTest(result, "WithoutTimeOut"); createXmlTest(result, "WithTimeOut").setTimeOut(1_000); setSuite(result); run(); verifyPassedTests("timeoutTest"); verifyFailedTests("timeoutTest"); } private XmlTest createXmlTest(XmlSuite suite, String name) { XmlTest result = new XmlTest(suite); result.setName(name); List classes = new ArrayList<>(); XmlClass cls = new XmlClass(TestTimeOutSampleTest.class); cls.setIncludedMethods( Collections.singletonList(new XmlInclude("timeoutTest"))); classes.add(cls); result.setXmlClasses(classes); return result; } @Test public void timeOutInParallelTestsFromXml() throws IOException { String file = "src/test/java/test/timeout/issue575.xml"; try (FileInputStream stream = new FileInputStream(file)) { SuiteXmlParser suiteParser = new SuiteXmlParser(); XmlSuite suite = suiteParser.parse(file, stream, true); setSuite(suite); run(); verifyPassedTests("timeoutShouldPass"); verifyFailedTests("timeoutShouldFailByException", "timeoutShouldFailByTimeOut"); } } } testng-testng-6.9.5/src/test/java/test/timeout/TestTimeOutSampleTest.java0000644000175000017500000000045612551235562026105 0ustar eugeneeugenepackage test.timeout; import org.testng.annotations.Test; public class TestTimeOutSampleTest { @Test public void timeoutTest() { try { Thread.sleep(2_000); } catch (InterruptedException handled) { Thread.currentThread().interrupt(); } } } testng-testng-6.9.5/src/test/java/test/timeout/InvocationTimeOutSampleTest.java0000644000175000017500000000103512551235562027271 0ustar eugeneeugenepackage test.timeout; import org.testng.annotations.Test; public class InvocationTimeOutSampleTest { @Test(invocationCount = 5, invocationTimeOut = 2_000) public void shouldPass() { try { Thread.sleep(250); } catch (InterruptedException handled) { Thread.currentThread().interrupt(); } } @Test(invocationCount = 5, invocationTimeOut = 1_000) public void shouldFail() { try { Thread.sleep(250); } catch (InterruptedException handled) { Thread.currentThread().interrupt(); } } } testng-testng-6.9.5/src/test/java/test/thread/0000755000175000017500000000000012551235562020566 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/thread/testng.xml0000644000175000017500000000072112551235562022614 0ustar eugeneeugene testng-testng-6.9.5/src/test/java/test/thread/TrueParallelTest.java0000644000175000017500000000320212551235562024662 0ustar eugeneeugenepackage test.thread; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import test.SimpleBaseTest; import java.util.Arrays; import java.util.List; /** * Attempt to make sure that we are truly running methods in parallel. The best I can think * of right now is to run the tests a few times in a row and verify the ordering is never * the same. */ public class TrueParallelTest extends SimpleBaseTest { @Test public void shouldRunInParallel() { boolean success = false; for (int i = 0, count = Runtime.getRuntime().availableProcessors() * 4; i < count; i++) { XmlSuite s = createXmlSuite("TrueParallel"); createXmlTest(s, "Test", TrueParallelSampleTest.class.getName()); TestNG tng = create(); s.setParallel(XmlSuite.PARALLEL_METHODS); tng.setXmlSuites(Arrays.asList(s)); BaseThreadTest.initThreadLog(); tng.run(); // A sequential result will look like "m1 m1 m3 m3 m2 m2 m4 m4 m5 m5". A properly // multithreaded result will have at least one non-consecutive different pair: // "m1 m1 m3 m2 m4 m4 m2 m3 m5 m5" List strings = TrueParallelSampleTest.getStrings(); boolean ii = isInterleaved(strings); success = success || ii; // System.out.println(strings + " -> " + ii); } Assert.assertTrue(success, "Couldn't find any interleaved test method run"); } private boolean isInterleaved(List strings) { for (int i = 0; i < strings.size(); i += 2) { if (! strings.get(i).equals(strings.get(i + 1))) { return true; } } return false; } } testng-testng-6.9.5/src/test/java/test/thread/TrueParallelSampleTest.java0000644000175000017500000000117612551235562026034 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Test; import java.util.Random; @Test public class TrueParallelSampleTest extends BaseThreadTest { static Random random = new Random(System.currentTimeMillis()); private void log(String s) { logString(s); try { Thread.sleep(random.nextInt(10)); } catch (InterruptedException ex) { Thread.yield(); } logString(s); logCurrentThread(); } public void m1() { log("m1"); } public void m2() { log("m2"); } public void m3() { log("m3"); } public void m4() { log("m4"); } public void m5() { log("m5"); } } testng-testng-6.9.5/src/test/java/test/thread/ThreadTest.java0000644000175000017500000000120012551235562023471 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Test; import test.BaseTest; public class ThreadTest extends BaseTest { @Test(groups = "broken", description = "This can be fixed by using sets instead of lists in DynamicGraph, but more failures happen then") public void timeoutAndInvocationCountShouldFail() { addClass(ThreadPoolSampleBugTest.class.getName()); run(); String[] passed = { "shouldPass1", "shouldPass2" }; String[] failed = { "shouldFail1", "shouldFail2" }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } } testng-testng-6.9.5/src/test/java/test/thread/ThreadPoolSizeWithTimeOutTest.java0000644000175000017500000000136512551235562027335 0ustar eugeneeugenepackage test.thread; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import junit.framework.Assert; public class ThreadPoolSizeWithTimeOutTest extends ThreadPoolSizeBase { @Test(invocationCount = 5, threadPoolSize = 3, timeOut = 1000) public void f1() { logThread(); } @Test(dependsOnMethods = {"f1"}) public void verify() { verifyThreads(3); } @Test public void threadPoolAndTimeOutShouldFail() { TestNG tng = create(ThreadPoolSizeSampleTest.class); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(0, tla.getPassedTests().size()); Assert.assertEquals(1, tla.getFailedTests().size()); } } testng-testng-6.9.5/src/test/java/test/thread/ThreadPoolSizeTest.java0000644000175000017500000000045512551235562025171 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Test; public class ThreadPoolSizeTest extends ThreadPoolSizeBase { @Test(invocationCount = 5, threadPoolSize = 3) public void f1() { logThread(); } @Test(dependsOnMethods = {"f1"}) public void verify() { verifyThreads(3); } } testng-testng-6.9.5/src/test/java/test/thread/ThreadPoolSizeSampleTest.java0000644000175000017500000000034312551235562026327 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Test; public class ThreadPoolSizeSampleTest { @Test(threadPoolSize=2, timeOut=100) public void willPassBug() throws InterruptedException{ Thread.sleep(500); } } testng-testng-6.9.5/src/test/java/test/thread/ThreadPoolSizeBase.java0000644000175000017500000000056312551235562025124 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.BeforeClass; public class ThreadPoolSizeBase extends BaseThreadTest { @BeforeClass public void setUp() { log(getClass().getName(), "Init log ids"); initThreadLog(); } protected void logThread() { long n = Thread.currentThread().getId(); log(getClass().getName(), ""); logThread(n); } } testng-testng-6.9.5/src/test/java/test/thread/ThreadPoolSampleBugTest.java0000644000175000017500000000132712551235562026135 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Test; public class ThreadPoolSampleBugTest { private static final long TIMEOUT = 500; @Test(invocationCount = 1, threadPoolSize = 5) public void shouldPass1() throws InterruptedException { Thread.sleep(TIMEOUT); } @Test(invocationCount = 2, threadPoolSize = 5) public void shouldPass2() throws InterruptedException { Thread.sleep(TIMEOUT); } @Test(timeOut = 10, invocationCount = 1, threadPoolSize = 5) public void shouldFail1() throws InterruptedException { Thread.sleep(TIMEOUT); } @Test(timeOut = 10, invocationCount = 2, threadPoolSize = 5) public void shouldFail2() throws InterruptedException { Thread.sleep(TIMEOUT); } } testng-testng-6.9.5/src/test/java/test/thread/TestThreadCountTest.java0000644000175000017500000000163112551235562025352 0ustar eugeneeugenepackage test.thread; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import org.testng.internal.thread.ThreadUtil; import java.util.Collections; import java.util.HashSet; import java.util.Set; /** * Test for test level thread-count. * * @author Alex Popescu */ public class TestThreadCountTest { private Set m_threads= Collections.synchronizedSet(new HashSet()); @Test public void test1() { m_threads.add(ThreadUtil.currentThreadInfo()); } @Test public void test2() { m_threads.add(ThreadUtil.currentThreadInfo()); } @Test public void test3() { m_threads.add(ThreadUtil.currentThreadInfo()); } @AfterClass public void checkThreading() { Assert.assertEquals(m_threads.size(), 3, "Test should use 3 threads"); } } testng-testng-6.9.5/src/test/java/test/thread/Test2Test.java0000644000175000017500000000052712551235562023276 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Test; public class Test2Test extends BaseSequentialSample { @Test public void f21() { ppp("f21"); addId("Test2Test.f21()", Thread.currentThread().getId()); } @Test public void f22() { ppp("f22"); addId("Test2Test.f22()", Thread.currentThread().getId()); } } testng-testng-6.9.5/src/test/java/test/thread/Test1Test.java0000644000175000017500000000052712551235562023275 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Test; public class Test1Test extends BaseSequentialSample { @Test public void f11() { ppp("f11"); addId("Test1Test.f11()", Thread.currentThread().getId()); } @Test public void f12() { ppp("f12"); addId("Test1Test.f12()", Thread.currentThread().getId()); } } testng-testng-6.9.5/src/test/java/test/thread/SuiteThreadCountTest.java0000644000175000017500000000151312551235562025523 0ustar eugeneeugenepackage test.thread; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import org.testng.internal.thread.ThreadUtil; import java.util.Collections; import java.util.HashSet; import java.util.Set; /** * Test for test level thread-count. * * @author Alex Popescu */ public class SuiteThreadCountTest { private Set m_threads= Collections.synchronizedSet(new HashSet()); @Test public void test1() { m_threads.add(ThreadUtil.currentThreadInfo()); } @Test public void test2() { m_threads.add(ThreadUtil.currentThreadInfo()); } @AfterClass public void checkThreading() { Assert.assertEquals(m_threads.size(), 2, "Test should use 2 threads (suite level)"); } } testng-testng-6.9.5/src/test/java/test/thread/SingleThreadedSampleTest.java0000644000175000017500000000100112551235562026305 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Test; @Test(singleThreaded = true) public class SingleThreadedSampleTest extends BaseSequentialSample { @Test public void f1() { addId("SingleThreadedSampleTest.f1()", Thread.currentThread().getId()); } @Test public void f2() { addId("SingleThreadedSampleTest.f2()", Thread.currentThread().getId()); } @Test public void f3() { addId("SingleThreadedSampleTest.f3()", Thread.currentThread().getId()); } } testng-testng-6.9.5/src/test/java/test/thread/SingleThreadedSample3Test.java0000644000175000017500000000107712551235562026405 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Test; @Test(singleThreaded = true) public class SingleThreadedSample3Test extends BaseSequentialSample { @Test public void f1() { addId("SingleThreadedSample3Test.f1()", Thread.currentThread().getId()); } @Test // (dependsOnMethods = "f1") public void f2() { addId("SingleThreadedSample3Test.f2()", Thread.currentThread().getId()); } @Test // (dependsOnMethods = "f2") public void f3() { addId("SingleThreadedSample3Test.f3()", Thread.currentThread().getId()); } } testng-testng-6.9.5/src/test/java/test/thread/SingleThreadedSample2Test.java0000644000175000017500000000100512551235562026373 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Test; @Test(singleThreaded = true) public class SingleThreadedSample2Test extends BaseSequentialSample { @Test public void f1() { addId("SingleThreadedSample2Test.f1()", Thread.currentThread().getId()); } @Test public void f2() { addId("SingleThreadedSample2Test.f2()", Thread.currentThread().getId()); } @Test public void f3() { addId("SingleThreadedSample2Test.f3()", Thread.currentThread().getId()); } } testng-testng-6.9.5/src/test/java/test/thread/SequentialTest.java0000644000175000017500000000435212551235562024407 0ustar eugeneeugenepackage test.thread; import org.testng.Assert; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import test.BaseTest; import java.util.HashMap; import java.util.Map; public class SequentialTest extends BaseTest { @Test public void verifySequential1() { verifySequential(1); } @Test public void verifySequential2() { verifySequential(2); } @Test public void verifySequential3() { verifySequential(3); } @Test public void verifySingleThreaded1() { verifySingleThreaded(1); } @Test public void verifySingleThreaded2() { verifySingleThreaded(2); } @Test public void verifySingleThreaded3() { verifySingleThreaded(3); } public void verifySequential(int threadCount) { runTest(threadCount, SequentialSampleTest.class.getName(), SequentialSample2Test.class.getName(), SequentialSample3Test.class.getName()); } public void verifySingleThreaded(int threadCount) { runTest(threadCount, SingleThreadedSampleTest.class.getName(), SingleThreadedSample2Test.class.getName(), SingleThreadedSample3Test.class.getName()); } private void runTest(int threadCount, String... classes) { Helper.reset(); for (String c : classes) { addClass(c); } setParallel(XmlSuite.PARALLEL_METHODS); setThreadCount(threadCount); run(); Map[] maps = new Map[] { Helper.getMap(classes[0]), Helper.getMap(classes[1]), Helper.getMap(classes[2]), }; for(Map m : maps) { Assert.assertEquals(m.size(), 1); } long[] ids = new long[] { maps[0].keySet().iterator().next(), maps[1].keySet().iterator().next(), maps[2].keySet().iterator().next(), }; Map verifyMap = new HashMap<>(); for (long id : ids) { verifyMap.put(id, id); } Assert.assertEquals(verifyMap.size(), threadCount); ppp("COUNT:" + threadCount + " THREAD ID'S:" + ids[0] + " " + ids[1] + " " + ids[2]); } private static void ppp(String s) { if (false) { System.out.println("[SequentialTest] " + s); } } } testng-testng-6.9.5/src/test/java/test/thread/SequentialSampleTest.java0000644000175000017500000000072212551235562025546 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Test; @Test(sequential = true) public class SequentialSampleTest extends BaseSequentialSample { public void f1() { addId("SequentialSampleTest.f1()", Thread.currentThread().getId()); } public void f2() { addId("SequentialSampleTest.f2()", Thread.currentThread().getId()); } public void f3() { addId("SequentialSampleTest.f3()", Thread.currentThread().getId()); } } testng-testng-6.9.5/src/test/java/test/thread/SequentialSample3Test.java0000644000175000017500000000072612551235562025635 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Test; @Test(sequential = true) public class SequentialSample3Test extends BaseSequentialSample { public void f1() { addId("SequentialSample3Test.f1()", Thread.currentThread().getId()); } public void f2() { addId("SequentialSample3Test.f2()", Thread.currentThread().getId()); } public void f3() { addId("SequentialSample3Test.f3()", Thread.currentThread().getId()); } } testng-testng-6.9.5/src/test/java/test/thread/SequentialSample2Test.java0000644000175000017500000000072612551235562025634 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Test; @Test(sequential = true) public class SequentialSample2Test extends BaseSequentialSample { public void f1() { addId("SequentialSample2Test.f1()", Thread.currentThread().getId()); } public void f2() { addId("SequentialSample2Test.f2()", Thread.currentThread().getId()); } public void f3() { addId("SequentialSample2Test.f3()", Thread.currentThread().getId()); } } testng-testng-6.9.5/src/test/java/test/thread/Sample2.java0000644000175000017500000000061212551235562022733 0ustar eugeneeugenepackage test.thread; import org.testng.ITestContext; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class Sample2 extends BaseThreadTest { @BeforeMethod public void before(ITestContext ctx) { logSuite(ctx.getSuite().getName(), System.currentTimeMillis()); } @Test public void s1() { logThread(Thread.currentThread().getId()); } } testng-testng-6.9.5/src/test/java/test/thread/Sample1.java0000644000175000017500000000027412551235562022736 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Test; public class Sample1 extends BaseThreadTest { @Test public void s1() { logThread(Thread.currentThread().getId()); } } testng-testng-6.9.5/src/test/java/test/thread/ParallelWithFactorySampleTest.java0000644000175000017500000000130212551235562027347 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; public class ParallelWithFactorySampleTest extends BaseSequentialSample { private int m_n; @DataProvider public static Object[][] dp() { return new Object[][] { new Object[] { 42 }, new Object[] { 43 } }; } @Factory(dataProvider = "dp") public ParallelWithFactorySampleTest(int n) { m_n = n; } protected int getN() { return m_n; } @Test public void f1() { addId("f1 " + getN(), Thread.currentThread().getId()); } @Test public void f2() { addId("f2", Thread.currentThread().getId()); } } testng-testng-6.9.5/src/test/java/test/thread/ParallelTestTest.java0000644000175000017500000000500112551235562024661 0ustar eugeneeugenepackage test.thread; import org.testng.Assert; import org.testng.TestNG; 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; import test.BaseTest; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; public class ParallelTestTest extends BaseTest { @Test public void verifyParallelNone() { verifyExpected(XmlSuite.PARALLEL_NONE, 1); } @Test public void verifyParallelTests() { verifyExpected(XmlSuite.PARALLEL_TESTS, 2); } @Test public void verifyParallelMethods() { verifyExpected(XmlSuite.PARALLEL_METHODS, 4); } @Test public void verifyParallelClasses() { verifyExpected(XmlSuite.PARALLEL_CLASSES, 2); } @Test public void verifyParallelClassesWithFactory() { verifyExpected(XmlSuite.PARALLEL_INSTANCES, 2, ParallelWithFactorySampleTest.class.getName()); } @Test public void verifyNonParallelClassesWithFactory() { verifyExpected(XmlSuite.PARALLEL_NONE, 1, ParallelWithFactorySampleTest.class.getName()); } public static final String CLASS1 = "test.thread.Test1Test"; public static final String CLASS2 = "test.thread.Test2Test"; private void createTest(XmlSuite xmlSuite, String className) { XmlTest result = new XmlTest(xmlSuite); List classes = result.getXmlClasses(); XmlClass xmlClass = new XmlClass(className); classes.add(xmlClass); } private void verifyExpected(String parallelMode, int expectedThreadCount) { verifyExpected(parallelMode, expectedThreadCount, CLASS1, CLASS2); } private void verifyExpected(String parallelMode, int expectedThreadCount, String... classNames) { XmlSuite xmlSuite = new XmlSuite(); xmlSuite.setName("ParallelTestTest"); xmlSuite.setParallel(parallelMode); for (String cn : classNames) { createTest(xmlSuite, cn); } TestNG tng = new TestNG(); tng.setVerbose(0); tng.setXmlSuites(Arrays.asList(new XmlSuite[] { xmlSuite })); Helper.reset(); tng.run(); List> maps = Lists.newArrayList(); for (String c : classNames) { maps.add(Helper.getMap(c)); }; Map mergedMap = new HashMap<>(); for (Mapm : maps) { mergedMap.putAll(m); } Assert.assertEquals(mergedMap.size(), expectedThreadCount); } private static void ppp(String s) { if (false) { System.out.println("[SequentialTest] " + s); } } } testng-testng-6.9.5/src/test/java/test/thread/ParallelSuiteTest.java0000644000175000017500000001024612551235562025042 0ustar eugeneeugenepackage test.thread; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; import java.util.Arrays; import java.util.List; import java.util.Map; public class ParallelSuiteTest extends SimpleBaseTest { @Test public void suitesShouldRunInParallel1() { runTest(5, 2, 2, null, Arrays.asList( getPathToResource("suite-parallel-1.xml"), getPathToResource("suite-parallel-2.xml"))); } @Test public void suitesShouldRunInParallel2() { runTest(5, 3, 3, null, Arrays.asList( getPathToResource("suite-parallel-0.xml"))); } @Test(description = "Number of threads (2) is less than number of suites (3)") public void suitesShouldRunInParallel3() { final int SUITE_THREAD_POOL_SIZE = 2; TestListenerAdapter tla = new TestListenerAdapter(); TestNG tng = create(); tng.setSuiteThreadPoolSize(SUITE_THREAD_POOL_SIZE); tng.setTestSuites(Arrays.asList(getPathToResource("suite-parallel-0.xml"))); tng.addListener(tla); BaseThreadTest.initThreadLog(); tng.run(); //Shouldn't not deadlock Assert.assertEquals(BaseThreadTest.getThreadCount(), SUITE_THREAD_POOL_SIZE); } private void runTest(int suiteThreadPoolSize, int expectedThreadCount, int expectedSuiteCount, Boolean randomizeSuites, List paths) { TestListenerAdapter tla = new TestListenerAdapter(); TestNG tng = create(); tng.setSuiteThreadPoolSize(suiteThreadPoolSize); tng.setTestSuites(paths); tng.addListener(tla); if (null != randomizeSuites) { tng.setRandomizeSuites(randomizeSuites); } BaseThreadTest.initThreadLog(); tng.run(); Assert.assertEquals(BaseThreadTest.getThreadCount(), expectedThreadCount, "Thread count expected:" + expectedThreadCount + " actual:" + BaseThreadTest.getThreadCount()); Assert.assertEquals(BaseThreadTest.getSuitesMap().keySet().size(), expectedSuiteCount); } @Test public void suitesShouldRunInParallel4() { runTest(10, 5, 5, null, Arrays.asList( getPathToResource("parallel-suites/suite-parallel-1.xml"), getPathToResource("parallel-suites/suite-parallel-2.xml"), getPathToResource("parallel-suites/suite-parallel-2-1.xml"), getPathToResource("parallel-suites/suite-parallel-2-2.xml"))); } @Test public void suitesShouldRunInParallel5() { runTest(5, 5, 7, null, Arrays.asList( getPathToResource("parallel-suites/suite-parallel-0.xml"))); } @Test(description = "Number of threads (2) is less than level of suites (3)") public void suitesShouldRunInParallel6() { runTest(2, 2, 7, null, Arrays.asList( getPathToResource("parallel-suites/suite-parallel-0.xml"))); } @Test(description = "If suiteThreadPoolSize and randomizeSuites are not specified" + " suites should run in order specified in XML") public void suitesShouldRunInOrder() { TestListenerAdapter tla = new TestListenerAdapter(); TestNG tng = create(); tng.setTestSuites(Arrays.asList(getPathToResource("suite-parallel-0.xml"))); tng.addListener(tla); BaseThreadTest.initThreadLog(); tng.run(); Map suitesMap = BaseThreadTest.getSuitesMap(); Assert.assertEquals(BaseThreadTest.getThreadCount(), 1); Assert.assertEquals(suitesMap.keySet().size(), 3); final String SUITE_NAME_PREFIX = "Suite Parallel "; if (suitesMap.get(SUITE_NAME_PREFIX + 1) > suitesMap.get(SUITE_NAME_PREFIX + 2)) { Assert.fail("Suite " + (SUITE_NAME_PREFIX + 1) + " should have run before " + (SUITE_NAME_PREFIX + 2)); } Assert.assertTrue(suitesMap.get(SUITE_NAME_PREFIX + 2) <= suitesMap.get(SUITE_NAME_PREFIX + 0)); } @Test(description = "Number of threads (1) is less than number of levels of suites (2)") public void suitesShouldRun1() { runTest(1, 1, 3, true, Arrays.asList( getPathToResource("suite-parallel-0.xml"))); // runTest(1, 1, 7, true, Arrays.asList( // getPathToResource("parallel-suites/suite-parallel-0.xml"))); // // runTest(2, 2, 7, true, Arrays.asList( // getPathToResource("parallel-suites/suite-parallel-0.xml"))); } } testng-testng-6.9.5/src/test/java/test/thread/MultiThreadedDependentTest.java0000644000175000017500000000460112551235562026654 0ustar eugeneeugenepackage test.thread; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.collections.Lists; import org.testng.collections.Maps; import test.SimpleBaseTest; import java.util.Arrays; import java.util.List; import java.util.Map; /** * Test that classes with dependent methods are still run in different threads * and in the correct order. */ public class MultiThreadedDependentTest extends SimpleBaseTest { /** * Make sure that the topological order is preserved and that if * the TestNG runner is configured to run n threads, the dependent * methods are using these n threads. */ private void assertOrder(List methods) { List expectedMethods = Arrays.asList(new String[] { "a1", "a2", "a3", "b1", "b2", "b3", "b4", "b5", "c1", "d", "x", "y", "z", "t" }); int size = expectedMethods.size(); Assert.assertEquals(methods.size(), size); for (String em : expectedMethods) { Assert.assertTrue(methods.contains(em)); } Map map = Maps.newHashMap(); for (String m : methods) { map.put(m, Boolean.TRUE); if ("b1".equals(m) || "b2".equals(m) || "b3".equals(m) || "b4".equals(m) || "b5".equals(m)) { Assert.assertTrue(map.get("a1")); Assert.assertTrue(map.get("a2")); Assert.assertTrue(map.get("a3")); } if ("d".equals(m)) { Assert.assertTrue(map.get("a1")); Assert.assertTrue(map.get("a2")); } if ("c1".equals(m)) { Assert.assertTrue(map.get("b1")); Assert.assertTrue(map.get("b2")); } } Assert.assertEquals(map.size(), size); for (Boolean val : map.values()) { Assert.assertTrue(val); } } @Test public void test2Threads() { test(2); } @Test public void test3Threads() { test(3); } private void test(int threadCount) { Helper.reset(); MultiThreadedDependentSampleTest.m_methods = Lists.newArrayList(); TestNG tng = create(MultiThreadedDependentSampleTest.class); tng.setThreadCount(threadCount); tng.setParallel("methods"); Map map = Helper.getMap(MultiThreadedDependentSampleTest.class.getName()); synchronized(map) { tng.run(); Assert.assertTrue(map.size() > 1, "Map size:" + map.size() + " expected more than 1"); assertOrder(MultiThreadedDependentSampleTest.m_methods); } } } testng-testng-6.9.5/src/test/java/test/thread/MultiThreadedDependentSampleTest.java0000644000175000017500000000417712551235562030026 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.testng.collections.Lists; import java.util.List; public class MultiThreadedDependentSampleTest { public static List m_methods = Lists.newArrayList(); @BeforeClass public void bc() { // log("beforeClass"); } @AfterClass public void ac() { // log("afterClass"); } @BeforeMethod public void bm() { // log("beforeMethod"); } @AfterMethod public void am() { // log("afterMethod"); } @Test(groups = "1") public void a1() { logThread(); log("a1"); } @Test(groups = "1") public void a2() { logThread(); log("a2"); } @Test(groups = "1") public void a3() { logThread(); log("a3"); } @Test(groups = "2", dependsOnGroups = "1") public void b1() { logThread(); log("b1"); } @Test(groups = "2", dependsOnGroups = "1") public void b2() { logThread(); log("b2"); } @Test(groups = "2", dependsOnGroups = "1") public void b3() { logThread(); log("b3"); } @Test(groups = "2", dependsOnGroups = "1") public void b4() { logThread(); log("b4"); } @Test(groups = "2", dependsOnGroups = "1") public void b5() { logThread(); log("b5"); } @Test(dependsOnGroups = "2") public void c1() { logThread(); log("c1"); } @Test(dependsOnGroups = { "1" }) public void d() { logThread(); log("d"); } @Test public void x() { log("x"); } @Test public void y() { log("y"); } @Test public void z() { log("z"); } @Test public void t() { log("t"); } // @Test(groups = "mytest", dependsOnMethods = "g") // public void f() { // } // // // @AfterMethod // public void after() { // } private void logThread() { long id = Thread.currentThread().getId(); Helper.getMap(getClass().getName()).put(id, id); } private void log(String string) { synchronized(m_methods) { m_methods.add(string); } } } testng-testng-6.9.5/src/test/java/test/thread/Helper.java0000644000175000017500000000115012551235562022645 0ustar eugeneeugenepackage test.thread; import java.util.HashMap; import java.util.Map; public class Helper { private static Map> m_maps = new HashMap<>(); public static Map getMap(String className) { synchronized(m_maps) { Map result = m_maps.get(className); if (result == null) { result = new HashMap(); m_maps.put(className, result); } return result; } // System.out.println("Putting class:" + className + " result:" + result); } public static void reset() { m_maps = new HashMap<>(); } } testng-testng-6.9.5/src/test/java/test/thread/FactoryTest.java0000644000175000017500000000275212551235562023706 0ustar eugeneeugenepackage test.thread; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; public class FactoryTest { @Test /** * In non-parallel mode, we should only have one thread id * for the two methods invoked on B. */ public void verifyFactoryNotParallel() { runTest(null, 1); } /** * In parallel mode "methods", we should have as many thread id's * as there are test methods on B (2). */ @Test public void verifyFactoryParallelMethods() { runTest("methods", 2); } @Test(groups = "broken", description = "Known bug: when parallel='tests', tests returned" + " by a @Factory are run in the same thread") public void verifyFactoryParallelTests() { runTest("tests", 2); } private void runTest(String parallelMode, int expectedThreadIdCount) { TestNG tng = new TestNG(); tng.setVerbose(0); tng.setTestClasses(new Class[] { FactorySampleTest.class}); if (parallelMode != null) { tng.setParallel(parallelMode); } TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); B.setUp(); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 2); Assert.assertEquals(B.m_threadIds.size(), expectedThreadIdCount); // ppp("# TESTS RUN " + tla.getPassedTests().size() // + " ID:" + B.m_threadIds.size()); } private void ppp(String string) { System.out.println("[FactoryTest] " + string); } } testng-testng-6.9.5/src/test/java/test/thread/FactorySampleTest.java0000644000175000017500000000037312551235562025045 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.Factory; import org.testng.annotations.Test; @Test public class FactorySampleTest { @Factory public Object[] init() { return new Object[] { new B(), new B(), }; } } testng-testng-6.9.5/src/test/java/test/thread/DataProviderThreadPoolSizeTest.java0000644000175000017500000000204412551235562027472 0ustar eugeneeugenepackage test.thread; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class DataProviderThreadPoolSizeTest extends SimpleBaseTest { @Test public void shouldUseDefaultDataProviderThreadCount() { TestNG tng = create(DataProviderThreadPoolSizeSampleTest.class); tng.setGroups("parallel"); tng.run(); Assert.assertEquals(DataProviderThreadPoolSizeSampleTest.getThreadCount(), 10); } @Test public void shouldNotUseThreadsIfNotUsingParallel() { TestNG tng = create(DataProviderThreadPoolSizeSampleTest.class); tng.setGroups("sequential"); tng.run(); Assert.assertEquals(DataProviderThreadPoolSizeSampleTest.getThreadCount(), 1); } @Test public void shouldUseSpecifiedDataProviderThreadCount() { TestNG tng = create(DataProviderThreadPoolSizeSampleTest.class); tng.setGroups("parallel"); tng.setDataProviderThreadCount(3); tng.run(); Assert.assertEquals(DataProviderThreadPoolSizeSampleTest.getThreadCount(), 3); } } testng-testng-6.9.5/src/test/java/test/thread/DataProviderThreadPoolSizeSampleTest.java0000644000175000017500000000361112551235562030635 0ustar eugeneeugenepackage test.thread; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderThreadPoolSizeSampleTest extends BaseThreadTest { @BeforeClass(alwaysRun = true) public void setUp() { log(getClass().getName(), "Init log ids"); initThreadLog(); } @DataProvider(parallel = true) public Object[][] parallelDataProvider() { return createArray(); } @DataProvider public Object[][] sequentialDataProvider() { return createArray(); } private Object[][] createArray() { int i = 0; return new Object[][] { new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, new Object[] { i++ }, }; } @Test(dataProvider = "sequentialDataProvider", groups = "sequential") public void fSequential(Integer p) { long n = Thread.currentThread().getId(); log(getClass().getName(), "Sequential"); logThread(n); } @Test(dataProvider = "parallelDataProvider", groups = "parallel") public void fParallel(Integer p) { long n = Thread.currentThread().getId(); log(getClass().getName(), "Parallel"); logThread(n); } // @Test(dependsOnMethods = {"f1"}) // public void verify() { // int expected = 3; // Assert.assertEquals(m_threadIds.size(), expected, // "Should have run on " + expected + " threads but ran on " + m_threadIds.size()); // } } testng-testng-6.9.5/src/test/java/test/thread/BaseThreadTest.java0000644000175000017500000000337112551235562024277 0ustar eugeneeugenepackage test.thread; import org.testng.Assert; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.collections.Sets; import test.SimpleBaseTest; import java.util.List; import java.util.Map; import java.util.Set; public class BaseThreadTest extends SimpleBaseTest { static private Set m_threadIds; static private Map m_suitesMap; static private List m_strings; static void initThreadLog() { m_threadIds = Sets.newHashSet(); m_suitesMap = Maps.newHashMap(); m_strings = Lists.newArrayList(); } protected void logString(String s) { synchronized(m_strings) { log("BaseThreadTest", "Logging string:" + s); m_strings.add(s); } } public static List getStrings() { return m_strings; } protected void logCurrentThread() { logThread(Thread.currentThread().getId()); } protected void logThread(long threadId) { synchronized(m_threadIds) { log("BaseThreadTest", "Logging thread:" + threadId); m_threadIds.add(threadId); } } protected void logSuite(String suiteName, long time) { synchronized(m_suitesMap) { m_suitesMap.put(suiteName, time); } } static int getThreadCount() { synchronized(m_threadIds) { return m_threadIds.size(); } } static Map getSuitesMap() { return m_suitesMap; } protected void log(String cls, String s) { if (false) { System.out.println("[" + cls + "] thread:" + Thread.currentThread().getId() + " hash:" + hashCode() + " " + s); } } protected void verifyThreads(int expected) { Assert.assertEquals(getThreadCount(), expected, "Ran on " + getThreadCount() + " threads instead of " + expected); } } testng-testng-6.9.5/src/test/java/test/thread/BaseSequentialSample.java0000644000175000017500000000106112551235562025476 0ustar eugeneeugenepackage test.thread; import java.util.Map; public class BaseSequentialSample { protected void addId(String method, long id) { ppp(method + " ID:" + id); getMap().put(id, id); } Map getMap() { Map result = Helper.getMap(getClass().getName()); ppp("RETURNING MAP " + result + " THIS:" + this); return result; } protected void ppp(String s) { if (false) { System.out.println("[" + getClass().getName() + " " + Thread.currentThread().getId() + " " + "] " + s); } } } testng-testng-6.9.5/src/test/java/test/thread/B.java0000644000175000017500000000101412551235562021606 0ustar eugeneeugenepackage test.thread; import java.util.HashMap; import java.util.Map; import org.testng.annotations.Test; import org.testng.collections.Maps; public class B { public static Map m_threadIds = Maps.newHashMap(); public static void setUp() { m_threadIds = new HashMap<>(); } @Test public void f2() { Long id = Thread.currentThread().getId(); m_threadIds.put(id, id); } private static void ppp(String s) { System.out.println("[FactoryTest] " + s); } } testng-testng-6.9.5/src/test/java/test/testng93/0000755000175000017500000000000012551235562020777 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/testng93/testng-93.xml0000644000175000017500000000076212551235562023263 0ustar eugeneeugene testng-testng-6.9.5/src/test/java/test/testng93/SingleTestTest.java0000644000175000017500000000102412551235562024560 0ustar eugeneeugenepackage test.testng93; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * This class/interface */ public class SingleTestTest { @BeforeMethod(groups={"group1"}) public void shouldRunBefore() { System.out.println("Runs before"); } @Test(groups={"group1"}) public void theFirstActualTest() { System.out.println("The first actual test"); } @Test public void theSecondActualTest() { System.out.println("The second actual test"); } } testng-testng-6.9.5/src/test/java/test/testng59/0000755000175000017500000000000012551235562021001 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/testng59/testng-59.xml0000644000175000017500000000075412551235562023270 0ustar eugeneeugene testng-testng-6.9.5/src/test/java/test/testng59/Test2.java0000644000175000017500000000066012551235562022647 0ustar eugeneeugenepackage test.testng59; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; /** * This class/interface */ public class Test2 { private boolean m_run= false; @Test public void test2() { m_run= true; } @AfterClass public void checkWasRun() { Assert.assertTrue(m_run, "test2() should have been run according to testng-59.xml"); } } testng-testng-6.9.5/src/test/java/test/testng59/Test1.java0000644000175000017500000000066012551235562022646 0ustar eugeneeugenepackage test.testng59; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; /** * This class/interface */ public class Test1 { private boolean m_run= false; @Test public void test1() { m_run= true; } @AfterClass public void checkWasRun() { Assert.assertTrue(m_run, "test1() should have been run according to testng-59.xml"); } } testng-testng-6.9.5/src/test/java/test/testng56/0000755000175000017500000000000012551235562020776 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/testng56/testng-56.xml0000644000175000017500000000040412551235562023252 0ustar eugeneeugene testng-testng-6.9.5/src/test/java/test/testng56/ParallelTest.java0000644000175000017500000000204512551235562024236 0ustar eugeneeugenepackage test.testng56; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * This class/interface */ public class ParallelTest { @BeforeClass public void setup() { System.out.println(Thread.currentThread().getId() + ":setup"); } @AfterClass public void teardown() { System.out.println(Thread.currentThread().getId() + ":teardown"); } @Test public void test1() { System.out.println(Thread.currentThread().getId() + ":test1"); } @Test(dependsOnMethods = {"test1"}) public void test2() { System.out.println(Thread.currentThread().getId() + ":test2"); } @Test public void test3() { System.out.println(Thread.currentThread().getId() + ":test3"); } @Test(dependsOnMethods = {"test3"}) public void test4() { System.out.println(Thread.currentThread().getId() + ":test4"); } @Test public void test5() { System.out.println(Thread.currentThread().getId() + ":test5"); } } testng-testng-6.9.5/src/test/java/test/testng387/0000755000175000017500000000000012551235562021065 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/testng387/TestNG387.java0000644000175000017500000000147512551235562023345 0ustar eugeneeugenepackage test.testng387; import org.testng.*; import org.testng.annotations.Test; import test.SimpleBaseTest; import java.util.List; import static org.testng.Assert.assertEqualsNoOrder; public class TestNG387 extends SimpleBaseTest { @Test(invocationCount = 500) public void testInvocationCounterIsCorrectForMethodWithDataProvider() throws Exception { final TestNG tng = create(FailedDPTest.class); tng.setThreadCount(1); tng.setParallel("false"); tng.setPreserveOrder(true); final TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); ITestNGMethod method = tla.getTestContexts().get(0).getAllTestMethods()[0]; List failed = method.getFailedInvocationNumbers(); assertEqualsNoOrder(failed.toArray(), FailedDPTest.primes.toArray()); } } testng-testng-6.9.5/src/test/java/test/testng387/FailedDPTest.java0000644000175000017500000000217712551235562024207 0ustar eugeneeugenepackage test.testng387; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * test for http://jira.opensymphony.com/browse/TESTNG-387 * The invocation-numbers logic in failed.xml is wrong for dataprovider and parallel=true * * The test will throw exception when numbers are prime, so getFailedInvocationNumbers() should be a list of prime numbers. * * @author freynaud */ public class FailedDPTest { static final List primes = Arrays.asList(2, 3, 5, 7); /** * DP generating all number from 0 to 9. * */ @DataProvider(name = "DP", parallel = true) public Iterator getData() { List list = new ArrayList<>(); for (int i = 0; i < 10; i++) { list.add(new Integer[] { i }); } return list.iterator(); } /** * Throws an exception for a prime number. * @throws Exception */ @Test(dataProvider = "DP", groups = { "DPTest" }) public void isNotPrime(Integer i) throws Exception { if (primes.contains(i)){ throw new Exception(i+" is prime"); } } } testng-testng-6.9.5/src/test/java/test/testng37/0000755000175000017500000000000012551235562020775 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/testng37/testng-37.xml0000644000175000017500000000050512551235562023252 0ustar eugeneeugene testng-testng-6.9.5/src/test/java/test/testng37/NullParameterTest.java0000644000175000017500000000071112551235562025252 0ustar eugeneeugenepackage test.testng37; import org.testng.Assert; import org.testng.annotations.Parameters; import org.testng.annotations.Test; /** * This class/interface */ public class NullParameterTest { @Test @Parameters({"notnull", "nullvalue"}) public void nullParameter(String notNull, int mustBeNull) { Assert.assertNotNull(notNull, "not null parameter expected"); Assert.assertNull(mustBeNull, "null parameter expected"); } } testng-testng-6.9.5/src/test/java/test/testng317/0000755000175000017500000000000012551235562021056 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/testng317/VerifyTest.java0000755000175000017500000000117012551235562024027 0ustar eugeneeugenepackage test.testng317; import org.testng.TestNG; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import test.SimpleBaseTest; import java.util.ArrayList; import java.util.List; public class VerifyTest extends SimpleBaseTest { static List m_methods = new ArrayList<>(); @BeforeMethod public void before() { m_methods = new ArrayList<>(); } @Test public void verify() { TestNG tng = create(); tng.setTestClasses(new Class[] { test.testng317.ClassB.class, test.testng317.ClassA.class }); tng.run(); System.out.println("Methods:" + m_methods.size()); } } testng-testng-6.9.5/src/test/java/test/testng317/ClassB.java0000755000175000017500000000162612551235562023100 0ustar eugeneeugenepackage test.testng317; import org.testng.annotations.Test; public class ClassB { @Test public void sameNameAA(){ printMethod(); } @Test (dependsOnMethods="sameNameAA") public void uniqueNameBB(){ printMethod(); } @Test (dependsOnMethods="uniqueNameBB") public void uniqueNameCC(){ printMethod(); } @Test (dependsOnMethods="uniqueNameCC") public void uniqueNameDD(){ printMethod(); } @Test (dependsOnMethods="uniqueNameDD") public void sameNameE(){ printMethod(); } public void nullTest(){ printMethod(); } protected void printMethod() { StackTraceElement[] sTrace = new Exception().getStackTrace(); String className = sTrace[0].getClassName(); String methodName = sTrace[1].getMethodName(); System.out.printf("*********** executing --- %s %s\n", className, methodName); VerifyTest.m_methods.add(className + "." + methodName); } } testng-testng-6.9.5/src/test/java/test/testng317/ClassA.java0000755000175000017500000000223212551235562023071 0ustar eugeneeugenepackage test.testng317; import org.testng.annotations.Test; public class ClassA { @Test public void sameNameA(){ printMethod(); } @Test (dependsOnMethods="sameNameA") public void uniqueNameB(){ printMethod(); } @Test (dependsOnMethods="uniqueNameB") public void uniqueNameC(){ printMethod(); } @Test (dependsOnMethods="uniqueNameC") public void uniqueNameD(){ printMethod(); } @Test (dependsOnMethods="uniqueNameD") public void sameNameE(){ printMethod(); } @Test (dependsOnMethods="sameNameE") public void sameNameF(){ printMethod(); } @Test (dependsOnMethods="sameNameF") public void sameNameG(){ printMethod(); } @Test (dependsOnMethods="sameNameG") public void sameNameH(){ printMethod(); } public void nullTest(){ printMethod(); } protected void printMethod() { StackTraceElement[] sTrace = new Exception().getStackTrace(); String className = sTrace[0].getClassName(); String methodName = sTrace[1].getMethodName(); System.out.printf("*********** executing --- %s %s\n", className, methodName); VerifyTest.m_methods.add(className + "." + methodName); } } testng-testng-6.9.5/src/test/java/test/testng285/0000755000175000017500000000000012551235562021062 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/testng285/TestNG285Test.java0000644000175000017500000000063012551235562024167 0ustar eugeneeugenepackage test.testng285; import org.testng.Assert; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import test.BaseTest; public class TestNG285Test extends BaseTest { @Test public void verifyBug() { addClass("test.testng285.Derived"); setParallel(XmlSuite.PARALLEL_METHODS); setThreadCount(5); run(); Assert.assertEquals(BugBase.m_threadIds.size(), 1); } } testng-testng-6.9.5/src/test/java/test/testng285/Derived.java0000644000175000017500000000037512551235562023314 0ustar eugeneeugenepackage test.testng285; import org.testng.annotations.Test; public class Derived extends BugBase { @Test public void f1() { log(Thread.currentThread().getId()); } @Test public void f2() { log(Thread.currentThread().getId()); } } testng-testng-6.9.5/src/test/java/test/testng285/BugBase.java0000644000175000017500000000070212551235562023234 0ustar eugeneeugenepackage test.testng285; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.util.HashSet; import java.util.Set; @Test(sequential = true) public class BugBase { static Set m_threadIds; @BeforeClass public void setup() { m_threadIds = new HashSet<>(); } void log(long threadId) { m_threadIds.add(threadId); } public void fbase() { log(Thread.currentThread().getId()); } } testng-testng-6.9.5/src/test/java/test/testng249/0000755000175000017500000000000012551235562021062 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/testng249/VerifyTest.java0000644000175000017500000000217412551235562024035 0ustar eugeneeugenepackage test.testng249; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; import java.util.Arrays; public class VerifyTest extends SimpleBaseTest { @Test public void verify() { XmlSuite suite = new XmlSuite(); suite.setName("Suite"); XmlTest test = new XmlTest(suite); test.setName("Test"); XmlClass c1 = new XmlClass(B.class); c1.setIncludedMethods(Arrays.asList(new XmlInclude[] { new XmlInclude("b")})); XmlClass c2 = new XmlClass(Base.class); c2.setIncludedMethods(Arrays.asList(new XmlInclude[] { new XmlInclude("b")})); test.setXmlClasses(Arrays.asList(new XmlClass[] { c1, c2 })); TestNG tng = new TestNG(); tng.setVerbose(0); tng.setXmlSuites(Arrays.asList(new XmlSuite[] { suite })); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 2); } } testng-testng-6.9.5/src/test/java/test/testng249/Base.java0000644000175000017500000000016312551235562022577 0ustar eugeneeugenepackage test.testng249; import org.testng.annotations.Test; public class Base { @Test public void b() { } }testng-testng-6.9.5/src/test/java/test/testng249/B.java0000644000175000017500000000021412551235562022103 0ustar eugeneeugenepackage test.testng249; import org.testng.annotations.Test; public class B extends Base { @Override @Test public void b() { } }testng-testng-6.9.5/src/test/java/test/testng195/0000755000175000017500000000000012551235562021062 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/testng195/AfterMethodTest.java0000644000175000017500000000060212551235562024765 0ustar eugeneeugenepackage test.testng195; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class AfterMethodTest extends SimpleBaseTest { @Test public void testContextShouldBeInitialized() { TestNG tng = create(AfterMethodSampleTest.class); tng.run(); Assert.assertTrue(AfterMethodSampleTest.m_success); } } testng-testng-6.9.5/src/test/java/test/testng195/AfterMethodSampleTest.java0000644000175000017500000000106512551235562026133 0ustar eugeneeugenepackage test.testng195; import org.testng.IResultMap; import org.testng.ITestContext; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.lang.reflect.Method; public class AfterMethodSampleTest { static boolean m_success; @Test public void pass() { } @BeforeClass public void init() { m_success = false; } @AfterMethod public void afterMethod(ITestContext c, Method m) { IResultMap map = c.getPassedTests(); m_success = map.size() == 1; } } testng-testng-6.9.5/src/test/java/test/testng173/0000755000175000017500000000000012551235562021056 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/testng173/anotherpackage/0000755000175000017500000000000012551235562024032 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/testng173/anotherpackage/ClassC.java0000644000175000017500000000043312551235562026045 0ustar eugeneeugenepackage test.testng173.anotherpackage; import org.testng.annotations.Test; public class ClassC { @Test public void testX() { } @Test(dependsOnMethods = "testX") public void test2() { } @Test(dependsOnMethods = "test2") public void test1() { } }testng-testng-6.9.5/src/test/java/test/testng173/TestNG173Test.java0000644000175000017500000000327712551235562024171 0ustar eugeneeugenepackage test.testng173; import java.util.Arrays; import org.testng.Assert; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlClass; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; public class TestNG173Test extends SimpleBaseTest { @Test public void orderShouldBePreservedInMethodsWithSameNameAndInDifferentClasses() { TestNG tng = create(); XmlSuite s = createXmlSuite("PreserveOrder"); XmlTest t = new XmlTest(s); t.getXmlClasses().add(new XmlClass("test.testng173.ClassA")); t.getXmlClasses().add(new XmlClass("test.testng173.ClassB")); t.setPreserveOrder("true"); tng.setXmlSuites(Arrays.asList(s)); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); // bug //verifyPassedTests(tla, "test1", "test2", "testX", "test1", "test2"); // Proposed fix verifyPassedTests(tla, "test1", "test2", "testX", "test2", "test1"); } @Test public void orderShouldBePreservedInMethodsWithSameNameAndInDifferentClassesAndDifferentPackage() { TestNG tng = create(); XmlSuite s = createXmlSuite("PreserveOrder"); XmlTest t = new XmlTest(s); t.getXmlClasses().add(new XmlClass("test.testng173.ClassA")); t.getXmlClasses().add(new XmlClass("test.testng173.anotherpackage.ClassC")); t.setPreserveOrder("true"); tng.setXmlSuites(Arrays.asList(s)); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); // bug //verifyPassedTests(tla, "test1", "test2", "testX", "test1", "test2"); verifyPassedTests(tla, "test1", "test2", "testX", "test2", "test1"); } } testng-testng-6.9.5/src/test/java/test/testng173/ClassB.java0000644000175000017500000000040112551235562023063 0ustar eugeneeugenepackage test.testng173; import org.testng.annotations.*; public class ClassB { @Test public void testX() { } @Test(dependsOnMethods = "testX") public void test2() { } @Test(dependsOnMethods = "test2") public void test1() { } }testng-testng-6.9.5/src/test/java/test/testng173/ClassA.java0000644000175000017500000000030612551235562023066 0ustar eugeneeugenepackage test.testng173; import org.testng.annotations.Test; public class ClassA { @Test public void test1() { } @Test(dependsOnMethods = "test1") public void test2() { } } testng-testng-6.9.5/src/test/java/test/testng109/0000755000175000017500000000000012551235562021055 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/testng109/SkippedTestWithExpectedExceptionTest.java0000644000175000017500000000071012551235562031212 0ustar eugeneeugenepackage test.testng109; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * This class/interface */ public class SkippedTestWithExpectedExceptionTest { @BeforeClass public void setup() { throw new RuntimeException("test-exception"); } @Test public void test1() { // empty } @Test(expectedExceptions={OutOfMemoryError.class}) public void test2() { // empty } } testng-testng-6.9.5/src/test/java/test/testng106/0000755000175000017500000000000012551235562021052 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/testng106/TestNG106.java0000644000175000017500000000152512551235562023313 0ustar eugeneeugenepackage test.testng106; import java.util.Arrays; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import test.SimpleBaseTest; public class TestNG106 extends SimpleBaseTest { @Test public void testFailingBeforeSuiteShouldSkipAllTests() throws Exception { TestNG tng = create(); XmlSuite s = createXmlSuite("TESTNG-106"); createXmlTest(s, "myTest1", FailingSuiteFixture.class.getName(), Test1.class.getName()); createXmlTest(s, "myTest2", Test1.class.getName()); createXmlTest(s, "myTest3", Test2.class.getName()); createXmlTest(s, "myTest-last", Test2.class.getName()); tng.setXmlSuites(Arrays.asList(s)); tng.run(); Assert.assertEquals(FailingSuiteFixture.s_invocations, 0, "@BeforeSuite has failed. All tests should be skipped."); } } testng-testng-6.9.5/src/test/java/test/testng106/Test2.java0000644000175000017500000000056012551235562022717 0ustar eugeneeugenepackage test.testng106; import org.testng.annotations.Test; /** * This class/interface */ public class Test2 { @Test public void method2() { System.out.println("method2"); FailingSuiteFixture.s_invocations++; } @Test public void method3() { System.out.println("method3"); FailingSuiteFixture.s_invocations++; } } testng-testng-6.9.5/src/test/java/test/testng106/Test1.java0000644000175000017500000000036712551235562022723 0ustar eugeneeugenepackage test.testng106; import org.testng.annotations.Test; /** * This class/interface */ public class Test1 { @Test public void method1() { System.out.println("method1"); FailingSuiteFixture.s_invocations++; } } testng-testng-6.9.5/src/test/java/test/testng106/FailingSuiteFixture.java0000644000175000017500000000047112551235562025651 0ustar eugeneeugenepackage test.testng106; import org.testng.annotations.BeforeSuite; /** * TESTNG-106: failing @BeforeSuite doesn't skip all tests */ public class FailingSuiteFixture { static int s_invocations = 0; @BeforeSuite public void failingBeforeSuite() { throw new RuntimeException(); } } testng-testng-6.9.5/src/test/java/test/test111/0000755000175000017500000000000012551235562020521 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/test111/Test1.java0000644000175000017500000000033512551235562022365 0ustar eugeneeugenepackage test.test111; import org.testng.annotations.Test; import junit.framework.Assert; public class Test1 extends AbstractTest { @Test public void test() { Assert.assertEquals(0, AbstractTest.R); } }testng-testng-6.9.5/src/test/java/test/test111/AbstractTest.java0000644000175000017500000000043512551235562023771 0ustar eugeneeugenepackage test.test111; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; public abstract class AbstractTest { public static int R=0; @Test public void testAbstract() { } @AfterClass public void afterClass() { R++; } } testng-testng-6.9.5/src/test/java/test/superclass/0000755000175000017500000000000012551235562021503 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/superclass/Test3.java0000644000175000017500000000106012551235562023345 0ustar eugeneeugenepackage test.superclass; import org.testng.annotations.Test; import test.BaseTest; public class Test3 extends BaseTest { @Test public void shouldExcludeBaseMethods() { addClass("test.superclass.ChildSampleTest3"); addExcludedMethod("test.superclass.ChildSampleTest3", "pass"); addExcludedMethod("test.superclass.ChildSampleTest3", "base"); run(); String[] passed = { }; String[] failed = { "fail" }; verifyTests("Failed", failed, getFailedTests()); verifyTests("Passed", passed, getPassedTests()); } } testng-testng-6.9.5/src/test/java/test/superclass/MainTest.java0000644000175000017500000000140012551235562024065 0ustar eugeneeugenepackage test.superclass; import org.testng.annotations.Test; import test.BaseTest; public class MainTest extends BaseTest { @Test public void baseMethodIsCalledWithMethodTest() { addClass("test.superclass.Child1Test"); run(); String[] passed = { "tbase", "t1", "t2", "t3" }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void baseMethodIsCalledWithClassTest() { addClass("test.superclass.Child2Test"); run(); String[] passed = { "tbase", "t1", "t2", "t3" }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } } testng-testng-6.9.5/src/test/java/test/superclass/ChildSampleTest3.java0000644000175000017500000000042512551235562025457 0ustar eugeneeugenepackage test.superclass; import org.testng.Assert; import org.testng.annotations.Test; public class ChildSampleTest3 extends BaseSampleTest3 { @Test public void pass() { Assert.assertTrue(true); } @Test public void fail() { Assert.assertTrue(false); } } testng-testng-6.9.5/src/test/java/test/superclass/Child2Test.java0000644000175000017500000000052512551235562024315 0ustar eugeneeugenepackage test.superclass; import org.testng.annotations.Test; @Test public class Child2Test extends Base2 { public void t1() { ppp("T1"); } public void t2() { ppp("T2"); } public void t3() { ppp("T3"); } private static void ppp(String s) { if (false) { System.out.println("[Child] " + s); } } } testng-testng-6.9.5/src/test/java/test/superclass/Child1Test.java0000644000175000017500000000052512551235562024314 0ustar eugeneeugenepackage test.superclass; import org.testng.annotations.Test; @Test public class Child1Test extends Base1 { public void t1() { ppp("T1"); } public void t2() { ppp("T2"); } public void t3() { ppp("T3"); } private static void ppp(String s) { if (false) { System.out.println("[Child] " + s); } } } testng-testng-6.9.5/src/test/java/test/superclass/BaseSampleTest3.java0000644000175000017500000000022712551235562025306 0ustar eugeneeugenepackage test.superclass; import org.testng.annotations.Test; public class BaseSampleTest3 { @Test public void base() { assert true; } } testng-testng-6.9.5/src/test/java/test/superclass/Base2.java0000644000175000017500000000073112551235562023303 0ustar eugeneeugenepackage test.superclass; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @Test public class Base2 { @BeforeClass public void bc() { ppp("BEFORE_CLASS"); } @BeforeMethod public void bm() { ppp("BEFORE_METHOD"); } public void tbase() { ppp("TEST IN BASE"); } private static void ppp(String s) { if (false) { System.out.println("[Base] " + s); } } } testng-testng-6.9.5/src/test/java/test/superclass/Base1.java0000644000175000017500000000073212551235562023303 0ustar eugeneeugenepackage test.superclass; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class Base1 { @BeforeClass public void bc() { ppp("BEFORE_CLASS"); } @BeforeMethod public void bm() { ppp("BEFORE_METHOD"); } @Test public void tbase() { ppp("TEST IN BASE"); } private static void ppp(String s) { if (false) { System.out.println("[Base] " + s); } } } testng-testng-6.9.5/src/test/java/test/skipex/0000755000175000017500000000000012551235562020622 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/skipex/TestSkippedExceptionTest.java0000644000175000017500000000075212551235562026447 0ustar eugeneeugenepackage test.skipex; import org.testng.SkipException; import org.testng.TimeBombSkipException; import org.testng.annotations.Test; /** * This class/interface */ public class TestSkippedExceptionTest { @Test public void genericSkipException() { throw new SkipException("genericSkipException is skipped for now"); } @Test public void timedSkipException() { throw new TimeBombSkipException("timedSkipException is time bombed", "2007/04/10"); } } testng-testng-6.9.5/src/test/java/test/skipex/SkippedExceptionTest.java0000644000175000017500000000331612551235562025606 0ustar eugeneeugenepackage test.skipex; import org.testng.Assert; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import java.util.List; /** * This class/interface */ public class SkippedExceptionTest { @Test public void skippedExceptionInConfigurationMethods() { TestListenerAdapter listener= new TestListenerAdapter(); TestNG test= new TestNG(false); test.addListener(listener); test.setVerbose(0); test.setTestClasses(new Class[] {ConfigurationSkippedExceptionTest.class}); test.run(); List confSkips= listener.getConfigurationSkips(); List testSkips= listener.getSkippedTests(); Assert.assertEquals(testSkips.size(), 1); Assert.assertEquals(testSkips.get(0).getMethod().getMethodName(), "dummyTest"); Assert.assertEquals(confSkips.size(), 1); Assert.assertEquals(confSkips.get(0).getMethod().getMethodName(), "configurationLevelSkipException"); } @Test public void skippedExceptionInTestMethods() { TestListenerAdapter listener= new TestListenerAdapter(); TestNG test= new TestNG(false); test.addListener(listener); test.setVerbose(0); test.setTestClasses(new Class[] {TestSkippedExceptionTest.class}); test.run(); List skips= listener.getSkippedTests(); List failures= listener.getFailedTests(); Assert.assertEquals(skips.size(), 1); Assert.assertEquals(failures.size(), 1); Assert.assertEquals(skips.get(0).getMethod().getMethodName(), "genericSkipException"); Assert.assertEquals(failures.get(0).getMethod().getMethodName(), "timedSkipException"); } } testng-testng-6.9.5/src/test/java/test/skipex/SkipAndExpectedTest.java0000644000175000017500000000114212551235562025336 0ustar eugeneeugenepackage test.skipex; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class SkipAndExpectedTest extends SimpleBaseTest { @Test public void shouldSkip() { TestNG tng = create(SkipAndExpectedSampleTest.class); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 0); Assert.assertEquals(tla.getSkippedTests().size(), 1); Assert.assertEquals(tla.getFailedTests().size(), 0); } } testng-testng-6.9.5/src/test/java/test/skipex/SkipAndExpectedSampleTest.java0000644000175000017500000000037712551235562026511 0ustar eugeneeugenepackage test.skipex; import org.testng.SkipException; import org.testng.annotations.Test; public class SkipAndExpectedSampleTest { @Test(expectedExceptions = NullPointerException.class) public void a2() { throw new SkipException("test"); } } testng-testng-6.9.5/src/test/java/test/skipex/ConfigurationSkippedExceptionTest.java0000644000175000017500000000062112551235562030332 0ustar eugeneeugenepackage test.skipex; import org.testng.SkipException; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * This class/interface */ public class ConfigurationSkippedExceptionTest { @BeforeMethod public void configurationLevelSkipException() { throw new SkipException("some skip message"); } @Test public void dummyTest() { } } testng-testng-6.9.5/src/test/java/test/simple/0000755000175000017500000000000012551235562020610 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/simple/SimpleTest.java0000644000175000017500000000032412551235562023543 0ustar eugeneeugenepackage test.simple; import org.testng.annotations.Test; public class SimpleTest { @Test public void f() { } private void ppp(String string) { System.out.println("[SimpleTest] " + string); } } testng-testng-6.9.5/src/test/java/test/simple/IncludedExcludedTest.java0000644000175000017500000000477412551235562025534 0ustar eugeneeugenepackage test.simple; import org.testng.Assert; import org.testng.IReporter; import org.testng.ISuite; import org.testng.ITestNGMethod; import org.testng.TestNG; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import testhelper.OutputDirectoryPatch; import java.util.Collection; import java.util.List; public class IncludedExcludedTest { private TestNG m_tng; @BeforeMethod public void init() { m_tng = new TestNG(); m_tng.setOutputDirectory(OutputDirectoryPatch.getOutputDirectory()); m_tng.setVerbose(0); m_tng.setUseDefaultListeners(false); } @Test(description = "First test method") public void verifyIncludedExcludedCount1() { m_tng.setTestClasses(new Class[] {IncludedExcludedSampleTest.class}); m_tng.setGroups("a"); m_tng.addListener( new MyReporter(new String[] { "test3" }, new String[] { "test1", "test2"})); m_tng.run(); } @Test(description = "Second test method") public void verifyIncludedExcludedCount2() { m_tng.setTestClasses(new Class[] {IncludedExcludedSampleTest.class}); m_tng.addListener( new MyReporter( new String[] { "beforeSuite", "beforeTest", "beforeTestClass", "beforeTestMethod", "test1", "beforeTestMethod", "test3" }, new String[] { "test2"})); m_tng.run(); } } class MyReporter implements IReporter { private String[] m_included; private String[] m_excluded; public MyReporter(String[] included, String[] excluded) { m_included = included; m_excluded = excluded; } @Override public void generateReport(List xmlSuites, List suites, String outputDirectory) { Assert.assertEquals(suites.size(), 1); ISuite suite = suites.get(0); { Collection invoked = suite.getInvokedMethods(); Assert.assertEquals(invoked.size(), m_included.length); for (String s : m_included) { Assert.assertTrue(containsMethod(invoked, s)); } } { Collection excluded = suite.getExcludedMethods(); Assert.assertEquals(excluded.size(), m_excluded.length); for (String s : m_excluded) { Assert.assertTrue(containsMethod(excluded, s)); } } } private boolean containsMethod(Collection invoked, String string) { for (ITestNGMethod m : invoked) { if (m.getMethodName().equals(string)) { return true; } } return false; } } testng-testng-6.9.5/src/test/java/test/simple/IncludedExcludedSampleTest.java0000644000175000017500000000172612551235562026670 0ustar eugeneeugenepackage test.simple; import org.testng.Reporter; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class IncludedExcludedSampleTest { @BeforeSuite public void beforeSuite() { Reporter.log("beforeSuite"); } @BeforeTest public void beforeTest() { Reporter.log("beforeTest"); } @BeforeClass public void beforeTestClass() { Reporter.log("beforeTestClass"); } @BeforeMethod public void beforeTestMethod() { Reporter.log("beforeTestMethod"); } @Test public void test1() { Reporter.log("Child.test1"); } @Test(enabled = false) public void test2() { Reporter.log("Child.test2"); } @Test(groups = "a") public void test3() { Reporter.log("Child.test3"); } private void ppp(String string) { System.out.println("[TestNGBug] " + string); } } testng-testng-6.9.5/src/test/java/test/serviceloader/0000755000175000017500000000000012551235562022146 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/serviceloader/TmpSuiteListener.java0000644000175000017500000000037612551235562026277 0ustar eugeneeugenepackage test.serviceloader; import org.testng.ISuite; import org.testng.ISuiteListener; public class TmpSuiteListener implements ISuiteListener { @Override public void onFinish(ISuite suite) {} @Override public void onStart(ISuite suite) {} } testng-testng-6.9.5/src/test/java/test/serviceloader/ServiceLoaderTest.java0000644000175000017500000000263312551235562026404 0ustar eugeneeugenepackage test.serviceloader; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import org.testng.TestNG; import org.testng.annotations.Test; import junit.framework.Assert; import test.SimpleBaseTest; public class ServiceLoaderTest extends SimpleBaseTest { @Test public void serviceLoaderShouldWork() throws MalformedURLException { TestNG tng = create(ServiceLoaderSampleTest.class); URL url = getClass().getClassLoader().getResource("serviceloader.jar"); URLClassLoader ucl = URLClassLoader.newInstance(new URL[] { url }); tng.setServiceLoaderClassLoader(ucl); tng.run(); Assert.assertEquals(1, tng.getServiceLoaderListeners().size()); } @Test public void serviceLoaderWithNoClassLoader() { //Here ServiceLoader is expected to rely on the current context class loader to load the service loader file //Since serviceloader.jar doesn't seem to be visible to the current thread's contextual class loader //resorting to pushing in a class loader into the current thread that can load the resource URL url = getClass().getClassLoader().getResource("serviceloader.jar"); URLClassLoader ucl = URLClassLoader.newInstance(new URL[] { url }); Thread.currentThread().setContextClassLoader(ucl); TestNG tng = create(ServiceLoaderSampleTest.class); tng.run(); Assert.assertEquals(1, tng.getServiceLoaderListeners().size()); } } testng-testng-6.9.5/src/test/java/test/serviceloader/ServiceLoaderSampleTest.java0000644000175000017500000000034412551235562027543 0ustar eugeneeugenepackage test.serviceloader; import org.testng.annotations.Test; /** * Dummy class to test ServiceLoader * * @author Cedric Beust */ public class ServiceLoaderSampleTest { @Test public void f() {} } testng-testng-6.9.5/src/test/java/test/sanitycheck/0000755000175000017500000000000012551235562021624 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/sanitycheck/SampleTest3.java0000644000175000017500000000020212551235562024625 0ustar eugeneeugenepackage test.sanitycheck; import org.testng.annotations.Test; public class SampleTest3 { @Test() public void test3() {} } testng-testng-6.9.5/src/test/java/test/sanitycheck/SampleTest2.java0000644000175000017500000000020212551235562024624 0ustar eugeneeugenepackage test.sanitycheck; import org.testng.annotations.Test; public class SampleTest2 { @Test() public void test2() {} } testng-testng-6.9.5/src/test/java/test/sanitycheck/SampleTest1.java0000644000175000017500000000020212551235562024623 0ustar eugeneeugenepackage test.sanitycheck; import org.testng.annotations.Test; public class SampleTest1 { @Test() public void test1() {} } testng-testng-6.9.5/src/test/java/test/sanitycheck/CheckTestNamesTest.java0000644000175000017500000000533612551235562026177 0ustar eugeneeugenepackage test.sanitycheck; import java.util.Arrays; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.TestNGException; import org.testng.annotations.Test; import org.testng.xml.XmlClass; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; public class CheckTestNamesTest extends SimpleBaseTest { /** * Child suites and same suite has two tests with same name */ @Test public void checkWithChildSuites() { runSuite("sanitycheck/test-a.xml"); } /** * Simple suite with two tests with same name */ @Test public void checkWithoutChildSuites() { runSuite("sanitycheck/test1.xml"); } private void runSuite(String suitePath) { TestListenerAdapter tla = new TestListenerAdapter(); boolean exceptionRaised = false; try { TestNG tng = create(); String testngXmlPath = getPathToResource(suitePath); tng.setTestSuites(Arrays.asList(testngXmlPath)); tng.addListener(tla); tng.run(); } catch (TestNGException ex) { exceptionRaised = true; Assert.assertEquals(tla.getPassedTests().size(), 0); Assert.assertEquals(tla.getFailedTests().size(), 0); } Assert.assertTrue(exceptionRaised); } /** * Simple suite with no two tests with same name */ @Test public void checkNoError() { TestListenerAdapter tla = new TestListenerAdapter(); TestNG tng = create(); String testngXmlPath = getPathToResource("sanitycheck/test2.xml"); tng.setTestSuites(Arrays.asList(testngXmlPath)); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 2); } /** * Child suites and tests within different suites have same names */ @Test(enabled = false) public void checkNoErrorWtihChildSuites() { TestListenerAdapter tla = new TestListenerAdapter(); TestNG tng = create(); String testngXmlPath = getPathToResource("sanitycheck/test-b.xml"); tng.setTestSuites(Arrays.asList(testngXmlPath)); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 4); } /** * Checks that suites created programmatically also run as expected */ @Test public void checkTestNamesForProgrammaticSuites() { XmlSuite xmlSuite = new XmlSuite(); xmlSuite.setName("SanityCheckSuite"); XmlTest result = new XmlTest(xmlSuite); result.getXmlClasses().add(new XmlClass(SampleTest1.class.getCanonicalName())); result = new XmlTest(xmlSuite); result.getXmlClasses().add(new XmlClass(SampleTest2.class.getCanonicalName())); TestNG tng = new TestNG(); tng.setVerbose(0); tng.setXmlSuites(Arrays.asList(new XmlSuite[] { xmlSuite })); tng.run(); } } testng-testng-6.9.5/src/test/java/test/sanitycheck/CheckSuiteNamesTest.java0000644000175000017500000000375412551235562026353 0ustar eugeneeugenepackage test.sanitycheck; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.TestNGException; import org.testng.annotations.Test; import org.testng.xml.XmlClass; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; import java.util.Arrays; public class CheckSuiteNamesTest extends SimpleBaseTest { /** * Child suites have different names */ @Test public void checkChildSuites() { TestListenerAdapter tla = new TestListenerAdapter(); TestNG tng = create(); String testngXmlPath = getPathToResource("sanitycheck/test-s-b.xml"); tng.setTestSuites(Arrays.asList(testngXmlPath)); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 4); } /** * Child suites have same names */ @Test(expectedExceptions = TestNGException.class, expectedExceptionsMessageRegExp = "\\s*Two suites cannot have the same name.*") public void checkChildSuitesFails() { TestNG tng = create(); String testngXmlPath = getPathToResource("sanitycheck/test-s-a.xml"); tng.setTestSuites(Arrays.asList(testngXmlPath)); tng.run(); } /** * Checks that suites created programmatically also fails as expected */ @Test(expectedExceptions = TestNGException.class, expectedExceptionsMessageRegExp = "\\s*Two suites cannot have the same name.*") public void checkProgrammaticSuitesFails() { XmlSuite xmlSuite1 = new XmlSuite(); xmlSuite1.setName("SanityCheckSuite"); { XmlTest result = new XmlTest(xmlSuite1); result.getXmlClasses().add(new XmlClass(SampleTest1.class.getCanonicalName())); } XmlSuite xmlSuite2 = new XmlSuite(); xmlSuite2.setName("SanityCheckSuite"); { XmlTest result = new XmlTest(xmlSuite2); result.getXmlClasses().add(new XmlClass(SampleTest2.class.getCanonicalName())); } TestNG tng = create(); tng.setXmlSuites(Arrays.asList(xmlSuite1, xmlSuite2)); tng.run(); } } testng-testng-6.9.5/src/test/java/test/sample/0000755000175000017500000000000012551235562020600 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/sample/SetUpWithParameterTest.java0000644000175000017500000000052512551235562026042 0ustar eugeneeugenepackage test.sample; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * This class fails in setUp and should result in 1 failure, 1 skip * * @author cbeust */ public class SetUpWithParameterTest { @BeforeClass public void setUp(String bogusParameter) { } @Test public void test() { } } testng-testng-6.9.5/src/test/java/test/sample/Scope.java0000644000175000017500000000075412551235562022522 0ustar eugeneeugenepackage test.sample; import org.testng.annotations.Test; /** * This class tests paramete scopes. * * @author cbeust */ public class Scope { @Test(groups = { "outer-group" }, parameters = { "parameter" }) public void outerDeprecated(String s) { assert "out".equals(s) : "Expected out got " + s; } @Test(groups = { "inner-group" }, parameters = { "parameter" }) public void innerDeprecated(String s) { assert "in".equals(s) : "Expected in got " + s; } } testng-testng-6.9.5/src/test/java/test/sample/Sample2.java0000644000175000017500000000071012551235562022744 0ustar eugeneeugenepackage test.sample; import org.testng.annotations.Test; /** * This class * * @author Cedric Beust, Apr 26, 2004 * */ public class Sample2 { @Test(groups = "g1") public void method1() { // System.out.println("@@@@@@@@@@@@@@@@@@@ METHOD1"); } @Test public void method2() { // System.out.println("@@@@@@@@@@@@@@@@@@@ METHOD2"); } @Test public void method3() { // System.out.println("@@@@@@@@@@@@@@@@@@@ METHOD3"); } } testng-testng-6.9.5/src/test/java/test/sample/Sample1.java0000644000175000017500000000302112551235562022741 0ustar eugeneeugenepackage test.sample; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.ExpectedExceptions; import org.testng.annotations.Test; /** * This class * * @author Cedric Beust, Apr 26, 2004 * */ public class Sample1 extends BaseSample1 { @AfterClass public static void tearDownClass1() { } @AfterClass public void tearDownClass2() { } @BeforeMethod public void beforeTest() { } @AfterMethod public void afterTest() { } @Test(groups = {"even"}) public void method2() { } @Test(groups = {"odd"}) public void method3() { } @Test(groups = {"odd"}, enabled = false) public void oddDisableMethod() { } @Test(groups = {"broken"}) public void broken() { } @Test(groups = {"fail"}) @ExpectedExceptions( {NumberFormatException.class, ArithmeticException.class}) public void throwExpectedException1ShouldPass() { throw new NumberFormatException(); } @Test(groups = {"fail"}) @ExpectedExceptions( {NumberFormatException.class, ArithmeticException.class}) public void throwExpectedException2ShouldPass() { throw new ArithmeticException(); } @Test(groups = {"fail", "bug"}) public void throwExceptionShouldFail() { throw new NumberFormatException(); } @Test(groups = {"assert"}) public void verifyLastNameShouldFail() { Assert.assertEquals("Beust", "", "Expected name Beust, found blah"); } private static void ppp(String s) { System.out.println("[Test1] " + s); } } testng-testng-6.9.5/src/test/java/test/sample/README.txt0000644000175000017500000000023312551235562022274 0ustar eugeneeugeneThis directory contains "samples": TestNG tests that are not invoked directly but invoked programmatically by the real test classes in the main directory. testng-testng-6.9.5/src/test/java/test/sample/PartialGroupVerification.java0000644000175000017500000000053412551235562026421 0ustar eugeneeugene package test.sample; import org.testng.annotations.Test; /** * This class verifies the PartialGroupTest * * @author cbeust */ public class PartialGroupVerification { @Test public void verify() { assert PartialGroupTest.m_successMethod && PartialGroupTest.m_successClass : "test1 and test2 should have been invoked both"; } }testng-testng-6.9.5/src/test/java/test/sample/PartialGroupTest.java0000644000175000017500000000162412551235562024717 0ustar eugeneeugenepackage test.sample; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * This class tests groups that are partially defined at the class level * and then augmented at the method level. * * @author cbeust */ @Test(groups = { "classGroup" }) public class PartialGroupTest { public static boolean m_successMethod = false; public static boolean m_successClass = false; @BeforeClass public void init() { m_successMethod = false; m_successClass = false; } @Test(groups = { "methodGroup" }) public void testMethodGroup() { m_successMethod = true; } @Test public void testClassGroupShouldFail() { Assert.assertTrue(false); } @Test(groups = { "methodGroup" }) public void testMethodGroupShouldFail() { Assert.assertTrue(false); } @Test public void testClassGroup() { m_successClass = true; } } testng-testng-6.9.5/src/test/java/test/sample/JUnitSample4.java0000644000175000017500000000131612551235562023723 0ustar eugeneeugenepackage test.sample; import junit.framework.Assert; import junit.framework.TestCase; import junit.framework.TestSuite; /** * * @author lukas */ public abstract class JUnitSample4 extends TestCase { private int i = 0; public JUnitSample4(String name, int i) { super(name); this.i = i; } public void testXY() { Assert.assertEquals(1, 1); } public static TestSuite suite() { TestSuite ts = new TestSuite("Sample Suite"); for (int i = 0; i < 3; i++) { ts.addTest(new T(i)); } return ts; } private static class T extends JUnitSample4 { public T(int i) { super("testXY", i); } } } testng-testng-6.9.5/src/test/java/test/sample/JUnitSample3.java0000644000175000017500000000076612551235562023732 0ustar eugeneeugenepackage test.sample; import org.testng.Assert; import junit.framework.TestCase; /** * This class verifies that a new instance is used every time * * @author cbeust */ public class JUnitSample3 extends TestCase { private int m_count = 0; public void test1() { Assert.assertEquals( m_count, 0); m_count++; } public void test2() { Assert.assertEquals( m_count, 0); m_count++; } private static void ppp(String s) { System.out.println("[JUnitSample3] " + s); } } testng-testng-6.9.5/src/test/java/test/sample/JUnitSample2.java0000644000175000017500000000102412551235562023715 0ustar eugeneeugenepackage test.sample; import junit.framework.TestCase; /** * This class * * @author Cedric Beust, May 5, 2004 * */ public class JUnitSample2 extends TestCase { public static final String EXPECTED = "testSample2ThatSetUpWasRun"; private String m_field = null; public JUnitSample2() { super(); } public JUnitSample2(String n) { super(n); } @Override public void setUp() { m_field = "foo"; } public void testSample2ThatSetUpWasRun() { assert null != m_field : "setUp() wasn't run"; } } testng-testng-6.9.5/src/test/java/test/sample/JUnitSample1.java0000644000175000017500000000141012551235562023713 0ustar eugeneeugenepackage test.sample; import junit.framework.TestCase; /** * This class * * @author Cedric Beust, May 5, 2004 * */ public class JUnitSample1 extends TestCase { private String m_field = null; public static final String EXPECTED2 = "testSample1_2"; public static final String EXPECTED1 = "testSample1_1"; public JUnitSample1() { super(); } public JUnitSample1(String n) { super(n); } @Override public void setUp() { m_field = "foo"; } @Override public void tearDown() { m_field = null; } /** * * */ public void testSample1_1() { // ppp("Sample 1_1"); } public void testSample1_2() { // ppp("Sample 1_2"); } private static void ppp(String s) { System.out.println("[JUnitSample1] " + s); } } testng-testng-6.9.5/src/test/java/test/sample/InvocationCountTest.java0000644000175000017500000000357012551235562025432 0ustar eugeneeugenepackage test.sample; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterSuite; import org.testng.annotations.Test; /** * This class is used to test invocationCountTest * * @author cbeust */ public class InvocationCountTest { // // Invocation test // private static int m_count = 0; @AfterSuite(groups = {"invocationOnly"}) public void afterSuite() { m_count = 0; m_count2 = 0; m_count3 = 0; } @Test(groups = { "invocationOnly"}, invocationCount = 10 ) public void tenTimesShouldSucceed() { m_count++; } // // Invocation + Success percentage test // This method will work the first 8 times and fail after that, but overall // the test should still pass because successPercentage = 80 // private static int m_count2 = 0; @Test(groups = { "successPercentageThatSucceedsOnly" }, invocationCount = 10, successPercentage = 80) public void successPercentageShouldSucceed() { if (m_count2 >= 8) { throw new RuntimeException("Called more than eight times : " + m_count2); } m_count2++; } // // Invocation + Success percentage test // This method will work the first 8 times and fail after that. One of // the failures will fall under the percentage tolerance but the next one // will not. // private static int m_count3 = 0; @Test(groups = { "successPercentageThatFailsOnly" }, invocationCount = 10, successPercentage = 90) public void successPercentageShouldFail() { if (m_count3>= 8) { throw new RuntimeException("Called more than eight times : " + m_count3); } m_count3++; } @AfterClass(groups = { "invocationOnly"}) public void verify() { assert 10 == m_count : "Method should have been invoked 10 times but was invoked " + m_count + " times"; } public static void ppp(String s) { System.out.println("[InvocationCount] " + s); } } testng-testng-6.9.5/src/test/java/test/sample/ConverterSample3.java0000644000175000017500000000362412551235562024644 0ustar eugeneeugenepackage test.sample; /* * Created on 12-Sep-2006 by micheb10 */ /** * Sample file for the Javadoc annotations to Java 5 annotations converter for a non-default package * @author micheb10 12-Sep-2006 * @testng.test */ public class ConverterSample3 { /** * This comment line should be preserved * @testng.before-suite alwaysRun = "true" */ public void beforeSuiteAlwaysRun() { // We are just checking appropriate annotations are added so we don't care about body } /** * @testng.test */ public void plainTest() { // Empty body } /** * @testng.test * @testng.expected-exceptions * value = "java.lang.NullPointerException java.lang.NumberFormatException" */ public void expectedExceptions() { // Empty body } /** * @testng.test groups = "groupA groupB" */ public void testGroups() { // Empty body } /** * @testng.after-method */ public void afterMethod() { // Empty body } /** * This key should be preserved * @author The author is a standard tag and should not be touched * @testng.test groups = "groupA" alwaysRun=true * dependsOnMethods = "expectedExceptions" timeOut="3000" * @version another standard tag should not be changed * @testng.expected-exceptions * value = "java.lang.NullPointerException java.lang.NumberFormatException" * @testng.parameters value="firstParameter secondParameter thirdParameter" */ public void testEverything() { // Lots and lots of stuff } /** * @testng.data-provider name="test1" */ public Object[][] dataProvider() { return null; } /** * @testng.factory */ public Object[] factory() { return null; } /** * @testng.test */ public class TestInnerClass { public void bareInnerMethod() { // Empty body } /** * @testng.test */ public void testInnerMethod() { // empty body } } } testng-testng-6.9.5/src/test/java/test/sample/Basic2.java0000644000175000017500000000163112551235562022547 0ustar eugeneeugenepackage test.sample; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterTest; import org.testng.annotations.Test; public class Basic2 { private boolean m_basic2WasRun = false; private static int m_afterClass = 0; @Test(dependsOnGroups = { "basic1" }) public void basic2() { m_basic2WasRun = true; assert Basic1.getCount() > 0 : "COUNT WAS NOT INCREMENTED"; } @AfterTest public void cleanUp() { m_basic2WasRun = false; m_afterClass = 0; } private void ppp(String s) { System.out.println("[Basic2 " + Thread.currentThread().getId() + " ] " + hashCode() + " " + s); } @AfterClass public void checkTestAtClassLevelWasRun() { m_afterClass++; assert m_basic2WasRun : "Class annotated with @Test didn't have its methods run."; assert 1 == m_afterClass : "After class should have been called exactly once, not " + m_afterClass; } }testng-testng-6.9.5/src/test/java/test/sample/Basic1.java0000644000175000017500000000105712551235562022550 0ustar eugeneeugenepackage test.sample; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class Basic1 { static private int m_count = 0; public static void incrementCount() { m_count++; } public static int getCount() { return m_count; } @BeforeMethod public void beforeTestMethod() { incrementCount(); } @Test(groups = { "basic1" } ) public void basic1() { assert getCount() > 0 : "COUNT WAS NOT INCREMENTED"; } static private void ppp(String s) { System.out.println("[Basic1] " + s); } }testng-testng-6.9.5/src/test/java/test/sample/BaseSampleInheritance.java0000644000175000017500000000224212551235562025631 0ustar eugeneeugenepackage test.sample; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.List; /** * @author Cedric Beust, Apr 30, 2004 * */ public class BaseSampleInheritance { protected List m_configurations = new ArrayList<>(); protected void addConfiguration(String c) { m_configurations.add(c); } protected boolean m_invokedBaseMethod = false; @Test(groups = { "inheritedTestMethod" }) public void baseMethod() { m_invokedBaseMethod = true; } protected boolean m_invokedBaseConfiguration = false; @BeforeClass public void baseConfiguration() { m_invokedBaseConfiguration = true; } @BeforeClass(groups = { "configuration1" }, dependsOnGroups = { "configuration0" }) public void configuration1() { // System.out.println("CONFIGURATION 1"); addConfiguration("configuration1"); } @Test(dependsOnGroups = { "inheritedTestMethod" }) public void testBooleans() { assert m_invokedBaseMethod : "Didn't invoke test method in base class"; assert m_invokedBaseConfiguration : "Didn't invoke configuration method in base class"; } } testng-testng-6.9.5/src/test/java/test/sample/BaseSample1.java0000644000175000017500000000030612551235562023537 0ustar eugeneeugenepackage test.sample; import org.testng.annotations.Test; /** * @author Cedric Beust, Apr 30, 2004 * */ public class BaseSample1 { @Test(groups = { "odd" }) public void method1() { } } testng-testng-6.9.5/src/test/java/test/sample/BaseAfterClassCalledAtEnd.java0000644000175000017500000000046712551235562026315 0ustar eugeneeugenepackage test.sample; import org.testng.annotations.AfterClass; public class BaseAfterClassCalledAtEnd { protected boolean m_afterClass = false; @AfterClass(dependsOnGroups = { ".*" }) public void baseAfterClass() { assert m_afterClass : "This afterClass method should have been called last"; } } testng-testng-6.9.5/src/test/java/test/sample/AllJUnitTests.java0000644000175000017500000000065112551235562024152 0ustar eugeneeugenepackage test.sample; import junit.framework.Test; import junit.framework.TestSuite; /** * Tests the suite() functionality of TestNG * * @author Cedric Beust, May 5, 2004 * */ public class AllJUnitTests { public static Test suite() { TestSuite suite= new TestSuite(); suite.addTest(new JUnitSample1(JUnitSample1.EXPECTED1)); suite.addTest(new JUnitSample2(JUnitSample2.EXPECTED)); return suite; } } testng-testng-6.9.5/src/test/java/test/sample/AfterClassCalledAtEnd.java0000644000175000017500000000310612551235562025513 0ustar eugeneeugenepackage test.sample; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * Check to see that AfterClass is called only at the end and that after methods * are called in reverse order of the before methods. */ public class AfterClassCalledAtEnd extends BaseAfterClassCalledAtEnd { boolean m_before1Class = false; boolean m_test1 = false; boolean m_test2 = false; boolean m_test3 = false; @BeforeClass(groups = { "before1Class" } ) public void before1Class() { m_before1Class = true; } @AfterClass(groups = { "someGroup" }) public void afterClass() { m_afterClass = true; assert m_test1 && m_test2 && m_test3 : "One of the test methods was not invoked: " + m_test1 + " " + m_test2 + " " + m_test3; } @Test(description = "Verify that beforeClass and afterClass are called correctly") public void test1() { m_test1 = true; assert m_before1Class : "beforeClass configuration must be called before method"; assert ! m_afterClass : "afterClass configuration must not be called before test method"; } @Test public void test2() { m_test2 = true; assert m_before1Class : "beforeClass configuration must be called before method"; assert ! m_afterClass : "afterClass configuration must not be called before test method"; } @Test public void test3() { m_test3 = true; assert m_before1Class : "beforeClass configuration must be called before method"; assert ! m_afterClass : "afterClass configuration must not be called before test method"; } }testng-testng-6.9.5/src/test/java/test/retryAnalyzer/0000755000175000017500000000000012551235562022172 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/retryAnalyzer/RetryAnalyzerTest.java0000644000175000017500000000454012551235562026513 0ustar eugeneeugenepackage test.retryAnalyzer; import org.testng.Assert; import org.testng.ITestResult; import org.testng.TestNG; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.testng.util.RetryAnalyzerCount; /** * retryAnalyzer parameter unit tests. * @author tocman@gmail.com (Jeremie Lenfant-Engelmann) * */ public final class RetryAnalyzerTest extends RetryAnalyzerCount { private static int r = 1; private static int r2 = 1; private static int r3 = 1; private static int value = 42; public RetryAnalyzerTest() { setCount(2); } @Test(retryAnalyzer=RetryAnalyzerTest.class) public void testAnnotation() { Assert.assertTrue(true); } @Test(retryAnalyzer=RetryAnalyzerTest.class) public void testAnnotationWithOneRetry() { if (r == 1) { r--; Assert.assertTrue(false); } if (r == 0) { Assert.assertTrue(true); } } @DataProvider(name="dataProvider") private Object[][] dataProvider() { return new Object[][] { { 1, false }, { 0, true }, { 0, true }, { 1, false } }; } @DataProvider(name="dataProvider2") private Object[][] dataProvider2() { value = 42; return new Object[][] { { true }, { true } }; } @Test(retryAnalyzer=RetryAnalyzerTest.class, dataProvider="dataProvider") public void testAnnotationWithDataProvider(int paf, boolean test) { if (paf == 1 && test == false) { if (r2 >= 1) { r2--; Assert.assertTrue(false); } else if (r2 == 0) { Assert.assertTrue(true); } } else if (paf == 0 || test == true) { Assert.assertTrue(true); } } @Test(retryAnalyzer=RetryAnalyzerTest.class, dataProvider="dataProvider2") public void testAnnotationWithDataProviderAndRecreateParameters(boolean dummy) { if (r3 == 1) { this.value = 0; r3--; Assert.assertTrue(false); } else if (r3 == 0) { Assert.assertEquals(this.value, 42); } } @Test public void withFactory() { TestNG tng = new TestNG(); tng.setVerbose(0); tng.setTestClasses(new Class[] { MyFactory.class}); FactoryTest.m_count = 0; tng.run(); Assert.assertEquals(FactoryTest.m_count, 4); } @Override public boolean retryMethod(ITestResult result) { return true; } } testng-testng-6.9.5/src/test/java/test/retryAnalyzer/PersistentFailure.java0000644000175000017500000000032412551235562026504 0ustar eugeneeugenepackage test.retryAnalyzer; import org.testng.Assert; import org.testng.annotations.Test; public class PersistentFailure { @Test(retryAnalyzer = MyRetry.class) public void test() { Assert.fail(); } } testng-testng-6.9.5/src/test/java/test/retryAnalyzer/MyRetry.java0000755000175000017500000000046712551235562024462 0ustar eugeneeugenepackage test.retryAnalyzer; import org.testng.ITestResult; import org.testng.util.RetryAnalyzerCount; public class MyRetry extends RetryAnalyzerCount { public MyRetry(){ setCount(3); } @Override public boolean retryMethod(ITestResult arg0) { // TODO Auto-generated method stub return true; } } testng-testng-6.9.5/src/test/java/test/retryAnalyzer/MyFactory.java0000755000175000017500000000047412551235562024762 0ustar eugeneeugenepackage test.retryAnalyzer; import org.testng.annotations.Factory; public class MyFactory { @Factory public Object[] createTests(){ int num = 10; Object[] result = new Object[num]; for(int i=0;iCedric Beust */ public class ReporterSampleTest { @DataProvider(name = "dp") public Object[][] createParameters() { return new Object[][] { new Object[] { "param1"}, new Object[] {"param2"} }; } @Test(dataProvider = "dp", timeOut = 10000) public void report(String p) { Reporter.log("IN THE REPORTER: " + p); } } testng-testng-6.9.5/src/test/java/test/reports/ReporterLogTest.java0000644000175000017500000000131412551235562024763 0ustar eugeneeugenepackage test.reports; import org.testng.Assert; import org.testng.Reporter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; import java.util.List; /** * Make sure that Reporter.log() in listeners don't get discarded. */ public class ReporterLogTest extends SimpleBaseTest { @Test public void shouldLogFromListener() { TestNG tng = create(ReporterLogSampleTest.class); tng.run(); List output = Reporter.getOutput(); boolean success = false; for(String s : output) { if (s.contains("Log from listener")) { success = true; break; } } Assert.assertTrue(success); // System.out.println(output); } } testng-testng-6.9.5/src/test/java/test/reports/ReporterLogSampleTest.java0000644000175000017500000000116312551235562026127 0ustar eugeneeugenepackage test.reports; import org.testng.ITestResult; import org.testng.Reporter; import org.testng.TestListenerAdapter; import org.testng.annotations.Listeners; import org.testng.annotations.Test; import test.reports.ReporterLogSampleTest.MyTestListener; @Listeners(MyTestListener.class) public class ReporterLogSampleTest { public static class MyTestListener extends TestListenerAdapter { @Override public void onTestSuccess(ITestResult result) { Reporter.log("Log from listener"); super.onTestSuccess(result); } } @Test public void test1() { Reporter.log("Log from test method"); } }testng-testng-6.9.5/src/test/java/test/reports/ReportTest.java0000644000175000017500000000767312551235562024010 0ustar eugeneeugenepackage test.reports; import org.testng.Assert; import org.testng.ITestListener; import org.testng.ITestResult; import org.testng.Reporter; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.TestHelper; import java.io.File; import java.util.Arrays; import java.util.List; public class ReportTest { @Test public void verifyIndex() { String suiteName = "VerifyIndexSuite"; File outputDir = TestHelper.createRandomDirectory(); XmlSuite suite = TestHelper.createSuite("test.simple.SimpleTest", suiteName); File f = new File(outputDir.getAbsolutePath() + File.separatorChar + suiteName + File.separatorChar + "index.html"); f.delete(); Assert.assertFalse(f.exists()); TestNG tng = TestHelper.createTestNG(suite, outputDir.getAbsolutePath()); tng.run(); Assert.assertTrue(f.exists()); f.deleteOnExit(); } @Test public void directoryShouldBeSuiteName() { String outputDirectory = TestHelper.createRandomDirectory().getAbsolutePath(); TestNG testng = new TestNG(); testng.setVerbose(0); testng.setOutputDirectory(outputDirectory); XmlSuite xmlSuite = new XmlSuite(); String suiteName = "ReportTestSuite1"; xmlSuite.setName(suiteName); XmlTest xmlTest = new XmlTest(xmlSuite); xmlTest.setName("Test1"); testng.setXmlSuites(Arrays.asList(new XmlSuite[] { xmlSuite })); File indexFile = new File(outputDirectory + File.separatorChar + suiteName + File.separatorChar + "index.html"); indexFile.delete(); Assert.assertFalse(indexFile.exists()); testng.run(); Assert.assertTrue(indexFile.exists(), "Expected to find file:" + indexFile); } @Test public void oneDirectoryPerSuite() { XmlSuite xmlSuiteA = TestHelper.createSuite("test.reports.A", "ReportSuiteA"); XmlSuite xmlSuiteB = TestHelper.createSuite("test.reports.B", "ReportSuiteB"); TestNG testng = TestHelper.createTestNG(); testng.setXmlSuites(Arrays.asList(new XmlSuite[] { xmlSuiteA, xmlSuiteB })); String outputDir = testng.getOutputDirectory(); File f1 = new File(outputDir + File.separatorChar + xmlSuiteA.getName() + File.separatorChar + "index.html"); File f2 = new File(outputDir + File.separatorChar + xmlSuiteB.getName() + File.separatorChar + "index.html"); Assert.assertFalse(f1.exists()); Assert.assertFalse(f2.exists()); testng.run(); Assert.assertTrue(f1.exists()); Assert.assertTrue(f2.exists()); } @Test public void shouldHonorSuiteName() { TestNG testng = TestHelper.createTestNG(); testng.setTestClasses(new Class[] { A.class, B.class }); String outputDir = testng.getOutputDirectory(); String dirA = outputDir + File.separatorChar + "SuiteA-JDK5"; File fileA = new File(dirA); String dirB = outputDir + File.separatorChar + "SuiteB-JDK5"; File fileB = new File(dirB); Assert.assertFalse(fileA.exists()); Assert.assertFalse(fileB.exists()); testng.run(); Assert.assertTrue(fileA.exists(), fileA + " wasn't created"); Assert.assertTrue(fileB.exists(), fileB + " wasn't created"); } static boolean m_success = false; @Test public void reportLogShouldBeAvailableEvenWithTimeOut() { m_success = false; TestNG tng = new TestNG(); tng.setVerbose(0); tng.setTestClasses(new Class[] { ReporterSampleTest.class }); ITestListener listener = new TestListenerAdapter() { @Override public void onTestSuccess(ITestResult tr) { super.onTestSuccess(tr); List output = Reporter.getOutput(tr); m_success = output != null && output.size() > 0; // ppp("ON SUCCESS, OUTPUT:" + output + " SUCCESS:" + m_success); } }; tng.addListener(listener); tng.run(); Assert.assertTrue(m_success); } private static void ppp(String s) { System.out.println("[ReporterTest] " + s); } } testng-testng-6.9.5/src/test/java/test/reports/FailedSampleTest.java0000644000175000017500000000027512551235562025052 0ustar eugeneeugenepackage test.reports; import org.testng.annotations.Test; public class FailedSampleTest { @Test public void failed() { throw new RuntimeException("Failing intentionally"); } } testng-testng-6.9.5/src/test/java/test/reports/FailedReporterTest.java0000644000175000017500000000372112551235562025432 0ustar eugeneeugenepackage test.reports; import javax.xml.parsers.ParserConfigurationException; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.collections.Lists; import org.testng.reporters.FailedReporter; import org.testng.xml.Parser; import org.testng.xml.XmlClass; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import org.xml.sax.SAXException; import test.SimpleBaseTest; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.util.Collection; public class FailedReporterTest extends SimpleBaseTest { private static final String XML = "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" + "" + ""; @Test public void failedFile() throws ParserConfigurationException, SAXException, IOException { TestNG tng = new TestNG(); tng.setVerbose(0); Collection suites = new Parser(new ByteArrayInputStream(XML.getBytes())).parse(); tng.setXmlSuites(Lists.newArrayList(suites)); TestListenerAdapter tla = new TestListenerAdapter(); File f = new File("/tmp"); tng.setOutputDirectory(f.getAbsolutePath()); tng.addListener(tla); tng.run(); Collection failedSuites = new Parser(new File(f, FailedReporter.TESTNG_FAILED_XML).getAbsolutePath()).parse(); XmlSuite failedSuite = failedSuites.iterator().next(); Assert.assertEquals("42", failedSuite.getParameter("n")); XmlTest test = failedSuite.getTests().get(0); Assert.assertEquals("43", test.getParameter("o")); XmlClass c = test.getClasses().get(0); Assert.assertEquals("44", c.getAllParameters().get("p")); } } testng-testng-6.9.5/src/test/java/test/reports/EmailableReportDriver.java0000644000175000017500000000172612551235562026111 0ustar eugeneeugenepackage test.reports; import org.testng.Assert; import org.testng.Reporter; import org.testng.annotations.Test; /** * Generates multiple permutations of TestNG output to see how things look in EmailableReporter. * * @author Paul Mendelson * @since 5.3 * @version $Revision$ */ @Test public class EmailableReportDriver { public void doFailureSansLog() { Assert.fail("show failure in report"); } public void doFailureNested() { Assert.fail("show failure in report",new Exception("Real cuase")); } public void doFailureWithLog() { Reporter.log("Preparing to fail"); Assert.fail("show failure in report"); } @Test(expectedExceptions={NumberFormatException.class}) public void doExpectedExceptionSansLog() { Reporter.log("step 1"); Reporter.log("step 2"); Integer.parseInt("BAD TEXT"); } @Test(expectedExceptions={NumberFormatException.class}) public void doExpectedExceptionWithLog() { Integer.parseInt("BAD TEXT"); } } testng-testng-6.9.5/src/test/java/test/reports/B.java0000644000175000017500000000020712551235562022040 0ustar eugeneeugenepackage test.reports; import org.testng.annotations.Test; @Test(suiteName = "SuiteB-JDK5") public class B { public void f() {} } testng-testng-6.9.5/src/test/java/test/reports/A.java0000644000175000017500000000024012551235562022034 0ustar eugeneeugenepackage test.reports; import org.testng.annotations.Test; @Test(suiteName = "SuiteA-JDK5", testName = "TestA-JDK5") public class A { public void f() {} } testng-testng-6.9.5/src/test/java/test/remote/0000755000175000017500000000000012551235562020612 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/remote/RemoteTest.java0000644000175000017500000000542712551235562023560 0ustar eugeneeugenepackage test.remote; import org.testng.Assert; import org.testng.annotations.Test; import org.testng.collections.Lists; import org.testng.remote.RemoteTestNG; import org.testng.remote.strprotocol.IMessage; import org.testng.remote.strprotocol.IMessageSender; import org.testng.remote.strprotocol.MessageHub; import org.testng.remote.strprotocol.SerializedMessageSender; import org.testng.remote.strprotocol.StringMessageSender; import test.SimpleBaseTest; import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.List; /** * A simple client that launches RemoteTestNG and then talks to it via the * two supported protocols, String and Serialized. * * @author Cedric Beust */ public class RemoteTest extends SimpleBaseTest { // Note: don't use the ports used by the plug-in or the RemoteTestNG processes // launched in this test will interfere with the plug-in. private static final int PORT1 = 1243; private static final int PORT2 = 1242; private static final List EXPECTED_MESSAGES = new ArrayList() {{ add("GenericMessage"); // method and test counts add("SuiteMessage"); // suite started add("TestMessage"); // test started add("TestResultMessage"); // status: started add("TestResultMessage"); // status: success add("TestResultMessage"); // status: started add("TestResultMessage"); // status: success add("TestMessage"); // test finished add("SuiteMessage"); // suite finished }}; @Test public void testSerialized() { runTest("-serport", PORT1, new SerializedMessageSender("localhost", PORT1)); } @Test public void testString() { runTest("-port", PORT2, new StringMessageSender("localhost", PORT2)); } private void launchRemoteTestNG(final String portArg, final int portValue) { new Thread(new Runnable() { @Override public void run() { RemoteTestNG.main(new String[] { portArg, Integer.toString(portValue), "-dontexit", getPathToResource("testng-remote.xml") }); } }).start(); } private void runTest(String arg, int portValue, IMessageSender sms) { p("Launching RemoteTestNG on port " + portValue); launchRemoteTestNG(arg, portValue); MessageHub mh = new MessageHub(sms); List received = Lists.newArrayList(); try { mh.initReceiver(); IMessage message = mh.receiveMessage(); while (message != null) { received.add(message.getClass().getSimpleName()); message = mh.receiveMessage(); } Assert.assertEquals(received, EXPECTED_MESSAGES); } catch(SocketTimeoutException ex) { Assert.fail("Time out"); } } private static void p(String s) { if (false) { System.out.println("[RemoteTest] " + s); } } } testng-testng-6.9.5/src/test/java/test/remote/RemoteSampleTest.java0000644000175000017500000000040012551235562024704 0ustar eugeneeugenepackage test.remote; import org.testng.annotations.Test; /** * Used by RemoteTest to test RemoteTestNG. * * @author Cedric Beust * */ public class RemoteSampleTest { @Test public void f1() {} @Test public void f2() {} } testng-testng-6.9.5/src/test/java/test/regression/0000755000175000017500000000000012551235562021477 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/regression/groupsordering/0000755000175000017500000000000012551235562024550 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/regression/groupsordering/testng.xml0000644000175000017500000000103712551235562026577 0ustar eugeneeugene testng-testng-6.9.5/src/test/java/test/regression/groupsordering/Base.java0000644000175000017500000000163312551235562026270 0ustar eugeneeugenepackage test.regression.groupsordering; import org.testng.Assert; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; public abstract class Base { protected static boolean s_childAWasRun; protected static boolean s_childBWasRun; @BeforeGroups(value= "a", groups= "a") public void setUp() throws Exception { // System.out.println("class is " + getClass().getName() + " Before group "); Assert.assertFalse(s_childAWasRun || s_childBWasRun, "Static field was not reset: @AfterGroup method not invoked"); } @AfterGroups(value= "a", groups= "a") public void tearDown() { // System.out.println("class is " + getClass().getName() + " After group "); Assert.assertTrue(s_childAWasRun, "Child A was not run"); Assert.assertTrue(s_childBWasRun, "Child B was not run"); s_childAWasRun = false; s_childBWasRun = false; } } testng-testng-6.9.5/src/test/java/test/regression/groupsordering/B.java0000644000175000017500000000033512551235562025575 0ustar eugeneeugenepackage test.regression.groupsordering; import org.testng.annotations.Test; public class B extends Base { @Test(groups= "a") public void testB() throws Exception { Base.s_childBWasRun= true; } } testng-testng-6.9.5/src/test/java/test/regression/groupsordering/A.java0000644000175000017500000000033012551235562025567 0ustar eugeneeugenepackage test.regression.groupsordering; import org.testng.annotations.Test; public class A extends Base { @Test(groups= "a") public void testA() throws Exception { s_childAWasRun= true; } } testng-testng-6.9.5/src/test/java/test/regression/MyTestngTest2.java0000644000175000017500000000076012551235562025041 0ustar eugeneeugenepackage test.regression; import org.testng.ITestContext; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class MyTestngTest2 extends MyTestngTest { @BeforeClass() public void beforeClass(ITestContext tc) throws Exception { } @BeforeMethod() public void beforeMethod(ITestContext tc) throws Exception { //throw new Exception("fail me"); } @Test() public void test(ITestContext tc) { } } testng-testng-6.9.5/src/test/java/test/regression/MyTestngTest.java0000644000175000017500000000060512551235562024755 0ustar eugeneeugenepackage test.regression; import org.testng.ITestContext; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; public class MyTestngTest { @BeforeSuite() public void beforeSuite(ITestContext tc) throws Exception { } @BeforeTest() public void beforeTest(ITestContext tc) throws Exception { throw new RuntimeException("barfing now"); } } testng-testng-6.9.5/src/test/java/test/regression/BeforeTestFailingTest.java0000644000175000017500000000107212551235562026536 0ustar eugeneeugenepackage test.regression; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class BeforeTestFailingTest extends SimpleBaseTest { @Test public void beforeTestFailingShouldCauseSkips() { TestNG tng = create(MyTestngTest2.class); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getSkippedTests().size(), 1); Assert.assertEquals(tla.getPassedTests().size(), 0); } } testng-testng-6.9.5/src/test/java/test/privatemethod/0000755000175000017500000000000012551235562022172 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/privatemethod/PrivateMethodTest.java0000644000175000017500000000076012551235562026453 0ustar eugeneeugenepackage test.privatemethod; import org.testng.Assert; import org.testng.annotations.Test; public class PrivateMethodTest { public PrivateMethodTest(String name, int value) { } private int privateMethod() { return 1; } public static class PrivateMethodInnerTest { @Test public void testPrivateMethod() { PrivateMethodTest pmt = new PrivateMethodTest("aname", 1); int returnValue = pmt.privateMethod(); Assert.assertEquals(returnValue, 1); } } } testng-testng-6.9.5/src/test/java/test/priority/0000755000175000017500000000000012551235562021200 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/priority/WithoutPrioritySampleTest.java0000644000175000017500000000035312551235562027253 0ustar eugeneeugenepackage test.priority; import org.testng.annotations.Test; public class WithoutPrioritySampleTest extends BaseSample { @Test public void first() { add("first"); } @Test public void second() { add("second"); } } testng-testng-6.9.5/src/test/java/test/priority/WithPrioritySampleTest.java0000644000175000017500000000040712551235562026523 0ustar eugeneeugenepackage test.priority; import org.testng.annotations.Test; public class WithPrioritySampleTest extends BaseSample { @Test(priority = -2) public void first() { add("first"); } @Test(priority = -1) public void second() { add("second"); } } testng-testng-6.9.5/src/test/java/test/priority/WithPrioritySample2Test.java0000644000175000017500000000041012551235562026577 0ustar eugeneeugenepackage test.priority; import org.testng.annotations.Test; public class WithPrioritySample2Test extends BaseSample { @Test(priority = -2) public void first() { add("first"); } @Test(priority = -3) public void second() { add("second"); } } testng-testng-6.9.5/src/test/java/test/priority/PriorityTest.java0000644000175000017500000000245612551235562024533 0ustar eugeneeugenepackage test.priority; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class PriorityTest extends SimpleBaseTest { private void runTest(Class cls, String first, String second, boolean parallel) { TestNG tng = create(cls); if (parallel) tng.setParallel("methods"); tng.run(); Assert.assertEquals(BaseSample.m_methods.get(0), first); Assert.assertEquals(BaseSample.m_methods.get(1), second); } @Test(enabled = false, description = "Make sure priorities work in parallel mode") public void priorityInParallel1() { runTest(WithPrioritySampleTest.class, "first", "second", true /* parallel */); } @Test(enabled = false, description = "Make sure priorities work in parallel mode") public void priorityInParallel2() { runTest(WithPrioritySample2Test.class, "second", "first", true /* parallel */); } @Test(description = "Make sure priorities work in sequential mode") public void priorityInSequential1() { runTest(WithPrioritySampleTest.class, "first", "second", false /* sequential */); } @Test(description = "Make sure priorities work in sequential mode") public void priorityInSequential2() { runTest(WithPrioritySample2Test.class, "second", "first", false /* sequential */); } } testng-testng-6.9.5/src/test/java/test/priority/Priority2SampleTest.java0000644000175000017500000000037112551235562025751 0ustar eugeneeugenepackage test.priority; import org.testng.annotations.Test; public class Priority2SampleTest { @Test(priority = 1) public void cOne() { } @Test(priority = 2) public void bTwo() { } @Test(priority = 3) public void aThree() { } } testng-testng-6.9.5/src/test/java/test/priority/BaseSample.java0000644000175000017500000000160412551235562024060 0ustar eugeneeugenepackage test.priority; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.testng.collections.Lists; import org.testng.collections.Maps; import java.util.List; public class BaseSample { public static List m_methods = Lists.newArrayList(); protected void add(String m) { String s = m; // System.out.println("BaseSample recording " + this + " " + s); synchronized(m_methods) { m_methods.add(s); } } @BeforeClass public void bc() { m_methods = Lists.newArrayList(); } @Test public void f1() { add("f1"); } @Test public void f2() { add("f2"); } @Test public void f3() { add("f3"); } @Test public void f4() { add("f4"); } @Test public void f5() { add("f5"); } @Test public void f6() { add("f6"); } @Test public void f7() { add("f7"); } @Test public void f8() { add("f8"); } } testng-testng-6.9.5/src/test/java/test/preserveorder/0000755000175000017500000000000012551235562022206 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/preserveorder/TestClassFactory.java0000644000175000017500000000045612551235562026313 0ustar eugeneeugenepackage test.preserveorder; import org.testng.annotations.Factory; public class TestClassFactory { @Factory public Object[] f() { final Object[] res = new Object[4]; for (int i = 1; i < 5; i++) { res[i-1] = new TestClass(i); } return res; } } testng-testng-6.9.5/src/test/java/test/preserveorder/TestClass.java0000644000175000017500000000112012551235562024750 0ustar eugeneeugene/* * @(#) TestClass.java * Created: Aug 10, 2011 * By: Wolfgang & Monika Baltes * Copyright 2011 Wolfgang Baltes * WOLFGANG & MONIKA BALTES PROPRIETARY/CONFIDENTIAL. * Use is subject to license terms. */ package test.preserveorder; import org.testng.Assert; import org.testng.annotations.Test; /** * @author Wolfgang Baltes * */ public class TestClass { private final int val; public TestClass(final int val) { this.val = val; } @Test public void checkVal() { Assert.assertTrue(this.val != 0); } } testng-testng-6.9.5/src/test/java/test/preserveorder/SibTest.java0000755000175000017500000000037612551235562024437 0ustar eugeneeugenepackage test.preserveorder; import org.testng.annotations.Test; @Test(singleThreaded = true) public class SibTest { @Test public void sib1() { } @Test(dependsOnMethods = "sib1") public void sib2() { // System.out.println("sib2"); } } testng-testng-6.9.5/src/test/java/test/preserveorder/PrgTest.java0000755000175000017500000000030512551235562024442 0ustar eugeneeugenepackage test.preserveorder; import org.testng.annotations.Test; @Test(singleThreaded=true) public class PrgTest { @Test public void prg1() { } @Test public void prg2() { } } testng-testng-6.9.5/src/test/java/test/preserveorder/PreserveOrderTest.java0000644000175000017500000000750512551235562026507 0ustar eugeneeugenepackage test.preserveorder; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlClass; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.BaseLogTest; import test.SimpleBaseTest; import java.util.Arrays; import java.util.List; public class PreserveOrderTest extends SimpleBaseTest { @Test public void preserveClassOrder() { String[][] tests = new String[][] { new String[] { "AAA", "B", "C" }, new String[] { "AAA", "C", "B" }, new String[] { "B", "AAA", "C" }, new String[] { "B", "C", "AAA" }, new String[] { "C", "B", "AAA" }, new String[] { "C", "AAA", "B" }, }; for (String[] t : tests) { TestNG tng = create(); // tng.setVerbose(2); XmlSuite s = createXmlSuite("Suite"); String[] fullTestNames = new String[t.length]; for (int i = 0; i < t.length; i++) { fullTestNames[i] = "test.preserveorder." + t[i]; } XmlTest xt = createXmlTest(s, "Test", fullTestNames); xt.setPreserveOrder("true"); // System.out.println(s.toXml()); tng.setXmlSuites(Arrays.asList(s)); tng.run(); // 3 methods per class, 3 classes, so the log should contain 9 calls List log = BaseLogTest.getLog(); Assert.assertEquals(log.size(), 9); // Every slice of 3 logs should belong to the same class in the same // order as in the specified string: AAA.a1, AAA.a2, AAA.a3, B.a1, etc... // Since we're only testing class ordering in this test, we only match // against the class name for (int i = 0; i < t.length; i++) { for (int j = 0; j < 3; j++) { Assert.assertTrue(log.get(j + (3 * i)).startsWith(t[i] + ".")); } } } } @Test public void preserveMethodOrder() { String[][] methods = new String[][] { new String[] { "a1", "a2", "a3" }, new String[] { "a1", "a3", "a2" }, new String[] { "a2", "a1", "a3" }, new String[] { "a2", "a3", "a1" }, new String[] { "a3", "a2", "a1" }, new String[] { "a3", "a1", "a2" }, }; for (String[] m : methods) { TestNG tng = create(); // tng.setVerbose(2); XmlSuite s = createXmlSuite("Suite"); String testName = "test.preserveorder.AAA"; XmlTest xt = createXmlTest(s, "Test", testName); addMethods(xt.getXmlClasses().get(0), m); xt.setPreserveOrder("true"); // System.out.println(s.toXml()); tng.setXmlSuites(Arrays.asList(s)); tng.run(); List log = BaseLogTest.getLog(); // System.out.println(log); for (int i = 0; i < log.size(); i++) { if (!log.get(i).endsWith(m[i])) { throw new AssertionError("Expected " + Arrays.asList(m) + " but got " + log); } } } } @Test public void orderShouldBePreservedWithDependencies() { TestNG tng = create(); XmlSuite s = createXmlSuite("PreserveOrder"); XmlTest t = new XmlTest(s); t.getXmlClasses().add(new XmlClass("test.preserveorder.ChuckTest4")); t.getXmlClasses().add(new XmlClass("test.preserveorder.ChuckTest3")); t.setPreserveOrder("true"); tng.setXmlSuites(Arrays.asList(s)); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); verifyPassedTests(tla, "c4TestOne", "c4TestTwo", "c4TestThree", "c3TestOne", "c3TestTwo", "c3TestThree"); } @Test(description = "preserve-order on a factory doesn't cause an NPE") public void factoryPreserve() { TestNG tng = create(); XmlSuite s = createXmlSuite("FactoryPreserve"); XmlTest t = new XmlTest(s); t.getXmlClasses().add(new XmlClass(TestClassFactory.class.getName())); t.setPreserveOrder("true"); tng.setXmlSuites(Arrays.asList(s)); tng.run(); } } testng-testng-6.9.5/src/test/java/test/preserveorder/EdnTest.java0000755000175000017500000000030112551235562024414 0ustar eugeneeugenepackage test.preserveorder; import org.testng.annotations.Test; @Test(singleThreaded = true) public class EdnTest { @Test public void edn1() { } @Test public void edn2() { } } testng-testng-6.9.5/src/test/java/test/preserveorder/ChuckTest4.java0000755000175000017500000000105712551235562025040 0ustar eugeneeugenepackage test.preserveorder; import org.testng.annotations.Test; public class ChuckTest4 { @Test(groups = {"functional"}, dependsOnMethods = {"c4TestTwo"}) public void c4TestThree() { // System.out.println("chucktest4: test three"); } @Test(groups = {"functional"}) public static void c4TestOne() { // System.out.println("chucktest4: test one"); } @Test(groups = {"functional"}, dependsOnMethods = {"c4TestOne"}) public static void c4TestTwo() { // System.out.println("chucktest4: test two"); } } testng-testng-6.9.5/src/test/java/test/preserveorder/ChuckTest3.java0000755000175000017500000000105712551235562025037 0ustar eugeneeugenepackage test.preserveorder; import org.testng.annotations.Test; public class ChuckTest3 { @Test(groups = {"functional"}, dependsOnMethods = {"c3TestTwo"}) public void c3TestThree() { // System.out.println("chucktest3: test three"); } @Test(groups = {"functional"}) public static void c3TestOne() { // System.out.println("chucktest3: test one"); } @Test(groups = {"functional"}, dependsOnMethods = {"c3TestOne"}) public static void c3TestTwo() { // System.out.println("chucktest3: test two"); } } testng-testng-6.9.5/src/test/java/test/preserveorder/C.java0000644000175000017500000000043412551235562023234 0ustar eugeneeugenepackage test.preserveorder; import org.testng.annotations.Test; import test.BaseLogTest; public class C extends BaseLogTest { @Test public void c1() { log("C.c1"); } @Test public void c2() { log("C.c2"); } @Test public void c3() { log("C.c3"); } } testng-testng-6.9.5/src/test/java/test/preserveorder/B.java0000644000175000017500000000043412551235562023233 0ustar eugeneeugenepackage test.preserveorder; import org.testng.annotations.Test; import test.BaseLogTest; public class B extends BaseLogTest { @Test public void b1() { log("B.b1"); } @Test public void b2() { log("B.b2"); } @Test public void b3() { log("B.b3"); } } testng-testng-6.9.5/src/test/java/test/preserveorder/AAA.java0000644000175000017500000000044412551235562023435 0ustar eugeneeugenepackage test.preserveorder; import org.testng.annotations.Test; import test.BaseLogTest; public class AAA extends BaseLogTest { @Test public void a1() { log("AAA.a1"); } @Test public void a2() { log("AAA.a2"); } @Test public void a3() { log("AAA.a3"); } } testng-testng-6.9.5/src/test/java/test/pkg2/0000755000175000017500000000000012551235562020162 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/pkg2/Test3.java0000644000175000017500000000017312551235562022030 0ustar eugeneeugenepackage test.pkg2; import org.testng.annotations.Test; public class Test3 { @Test public void method31() { } } testng-testng-6.9.5/src/test/java/test/pkg2/Test2.java0000644000175000017500000000027712551235562022034 0ustar eugeneeugenepackage test.pkg2; import test.pkg.PackageTest; public class Test2 { private Test2(float afloat) { PackageTest.NON_TEST_CONSTRUCTOR= true; } public void nonTestMethod() { } } testng-testng-6.9.5/src/test/java/test/pkg2/Test1.java0000644000175000017500000000024312551235562022024 0ustar eugeneeugenepackage test.pkg2; import org.testng.annotations.Test; public class Test1 { @Test public void method11() { } @Test public void method12() { } } testng-testng-6.9.5/src/test/java/test/pkg/0000755000175000017500000000000012551235562020100 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/pkg/PackageTest.java0000644000175000017500000000471012551235562023140 0ustar eugeneeugenepackage test.pkg; import static org.testng.Assert.assertTrue; import org.testng.annotations.Test; import test.BaseTest; import test.pkg2.Test2; /** * Tests that in testng.xml works. * * Created on Aug 2, 2005 * @author cbeust */ public class PackageTest extends BaseTest { public static boolean NON_TEST_CONSTRUCTOR= false; @Test public void stringSingle() { addPackage("test.pkg2", new String[0], new String[0]); run(); String[] passed = { "method11", "method12", "method31", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void packageWithNonTestClasses() { addPackage("test.pkg2", new String[0], new String[0]); run(); assertTrue(!NON_TEST_CONSTRUCTOR, Test2.class.getName() + " should not be considered"); } @Test public void packageWithRegExp1() { addPackage("test.pkg2", new String[] { ".*1.*"}, new String[0]); run(); String[] passed = { "method11", "method12", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void packageWithRegExp2() { addPackage("test.pkg2", new String[0], new String[] { ".*1.*"}); run(); String[] passed = { "method31", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void packageWithRegExp3() { addPackage("test.pkg2", new String[] { ".*3.*"}, new String[] { ".*1.*"}); run(); String[] passed = { "method31", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void packageWithRegExp4() { addPackage("test.pkg2", new String[] { ".*1.*"}, new String[] { ".*3.*"}); run(); String[] passed = { "method11", "method12" }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void packageWithRegExp5() { addPackage("test.pkg2", new String[0], new String[] { "Test.*"}); run(); String[] passed = { }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } } testng-testng-6.9.5/src/test/java/test/pholser/0000755000175000017500000000000012551235562020773 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/pholser/Saboteur.java0000644000175000017500000000155612551235562023431 0ustar eugeneeugenepackage test.pholser; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * @author Paul Holser * @version $Id: Saboteur.java,v 1.4 2006/06/22 13:45:01 cedric Exp $ */ public class Saboteur { @BeforeClass public void setUpFixture() { Captor.reset(); Captor.instance().capture( "Saboteur.setUpFixture" ); } @BeforeMethod public void setUp() { Captor.instance().capture( "Saboteur.setUp" ); } @AfterMethod public void tearDown() { Captor.instance().capture( "Saboteur.tearDown" ); } @AfterClass public void tearDownFixture() { Captor.instance().capture( "Saboteur.tearDownFixture" ); } @Test public void go() { } } testng-testng-6.9.5/src/test/java/test/pholser/Demo.java0000644000175000017500000000317512551235562022530 0ustar eugeneeugenepackage test.pholser; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.Arrays; import java.util.List; /** * @author Paul Holser * @version $Id: Demo.java,v 1.5 2006/06/22 13:45:01 cedric Exp $ */ public class Demo { @BeforeClass public void setUpFixture() { Captor.reset(); Captor.instance().capture( "Demo.setUpFixture" ); } @BeforeMethod public void setUp() { Captor.instance().capture( "Demo.setUp" ); } @AfterMethod public void tearDown() { Captor.instance().capture( "Demo.tearDown" ); } @AfterClass public void tearDownFixture() { final List expected = Arrays.asList(new String[] { "Demo.setUpFixture", "Demo.setUp", "Demo.tearDown" }); final List actual = Captor.instance().captives(); verify(expected, actual); } @Test public void go() { final List expected = Arrays.asList(new String[] { "Demo.setUpFixture", "Demo.setUp" } ); final List actual = Captor.instance().captives(); verify(expected, actual); } private void verify(List expected, List actual) { if (! expected.equals(actual)) { throw new AssertionError("\nExpected:" + dumpList(expected) + "\n Got:" + dumpList(actual)); } } private String dumpList(List list) { StringBuffer result = new StringBuffer(); for (String l : list) { result.append(" " + l); } return result.toString(); } }testng-testng-6.9.5/src/test/java/test/pholser/Captor.java0000644000175000017500000000151112551235562023064 0ustar eugeneeugenepackage test.pholser; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * @author Paul Holser * @version $Id: Captor.java,v 1.3 2004/08/26 22:25:22 cedric Exp $ */ public class Captor { private static Captor instance = null; private List captives; public static Captor instance() { if (null == instance) { instance = new Captor(); } return instance; } public static void reset() { // System.out.println("@@PHOLSER RESETTING CAPTOR"); instance().captives = new ArrayList<>(); } public void capture( String aString ) { // System.out.println("@@PHOLSER CAPTURING " + aString); captives.add( aString ); } public List captives() { return Collections.unmodifiableList( captives ); } } testng-testng-6.9.5/src/test/java/test/parameters/0000755000175000017500000000000012551235562021462 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/parameters/SuiteSampleTest.java0000644000175000017500000000052412551235562025421 0ustar eugeneeugenepackage test.parameters; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Parameters; public class SuiteSampleTest { @Parameters({"param"}) @BeforeSuite public void suiteParameter(String s) { ppp("PARAM:" + s); } private void ppp(String s) { System.out.println("[SuiteSampleTest] " + s); } } testng-testng-6.9.5/src/test/java/test/parameters/ShadowTest.java0000644000175000017500000000254112551235562024414 0ustar eugeneeugenepackage test.parameters; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; import java.util.Arrays; public class ShadowTest extends SimpleBaseTest { @Test public void parametersShouldNotBeShadowed() { XmlSuite s = createXmlSuite("s"); XmlTest t = createXmlTest(s, "t"); { XmlClass c1 = new XmlClass(Shadow1SampleTest.class.getName()); XmlInclude include1 = new XmlInclude("test1"); include1.setXmlClass(c1); c1.getLocalParameters().put("a", "First"); c1.getIncludedMethods().add(include1); t.getXmlClasses().add(c1); } { XmlClass c2 = new XmlClass(Shadow2SampleTest.class.getName()); XmlInclude include2 = new XmlInclude("test2"); include2.setXmlClass(c2); c2.getLocalParameters().put("a", "Second"); c2.getIncludedMethods().add(include2); t.getXmlClasses().add(c2); } TestNG tng = create(); tng.setXmlSuites(Arrays.asList(s)); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); // System.out.println(s.toXml()); assertTestResultsEqual(tla.getPassedTests(), Arrays.asList("test1", "test2")); } } testng-testng-6.9.5/src/test/java/test/parameters/Shadow2SampleTest.java0000644000175000017500000000041412551235562025635 0ustar eugeneeugenepackage test.parameters; import org.testng.Assert; import org.testng.annotations.Parameters; import org.testng.annotations.Test; public class Shadow2SampleTest { @Parameters("a") @Test public void test2(String a) { Assert.assertEquals("Second", a); } } testng-testng-6.9.5/src/test/java/test/parameters/Shadow1SampleTest.java0000644000175000017500000000041312551235562025633 0ustar eugeneeugenepackage test.parameters; import org.testng.Assert; import org.testng.annotations.Parameters; import org.testng.annotations.Test; public class Shadow1SampleTest { @Parameters("a") @Test public void test1(String a) { Assert.assertEquals("First", a); } } testng-testng-6.9.5/src/test/java/test/parameters/SampleTest.java0000644000175000017500000000023512551235562024406 0ustar eugeneeugenepackage test.parameters; import org.testng.annotations.Test; public class SampleTest { @Test public void foo() { //purposefully does nothing } } testng-testng-6.9.5/src/test/java/test/parameters/ParameterTest.java0000644000175000017500000000177712551235562025121 0ustar eugeneeugenepackage test.parameters; import org.testng.annotations.Test; import test.BaseTest; /** * This class * * @author Cedric Beust, Jul 22, 2004 * */ public class ParameterTest extends BaseTest { public static void ppp(String s) { System.out.println("[ParameterTest] " + s); } @Test public void stringSingle() { addClass("test.parameters.ParameterSample"); setParameter("first-name", "Cedric"); run(); String[] passed = { "testSingleString", "testNonExistentParameter", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void beforeMethodWithParameters() { addClass("test.parameters.BeforeSampleTest"); setParameter("parameter", "parameter value"); run(); String[] passed = { "testExample", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } } testng-testng-6.9.5/src/test/java/test/parameters/ParameterSample.java0000644000175000017500000000273612551235562025417 0ustar eugeneeugenepackage test.parameters; import org.testng.TestNG; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.testng.annotations.Test; import org.testng.xml.Parser; import java.io.ByteArrayInputStream; /** * This class * * @author Cedric Beust, Jul 22, 2004 * */ public class ParameterSample { @Parameters({ "first-name" }) @BeforeMethod public void beforeTest(String firstName) { // System.out.println("[ParameterSample] Invoked beforeTestMethod with: " + firstName); assert "Cedric".equals(firstName) : "Expected Cedric, got " + firstName; } @Parameters({ "first-name" }) @Test(groups = { "singleString"}) public void testSingleString(String firstName) { // System.out.println("[ParameterSample] Invoked testString " + firstName); assert "Cedric".equals(firstName); } @Parameters({"this parameter doesn't exist"}) @Test public void testNonExistentParameter(@Optional String foo) { } public static void main(String[] args) throws Exception { TestNG tng = new TestNG(); String xml = ""; System.out.println(xml); ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes()); tng.setXmlSuites(new Parser(is).parseToList()); tng.run(); } } testng-testng-6.9.5/src/test/java/test/parameters/ParameterOverrideTest.java0000644000175000017500000000464512551235562026616 0ustar eugeneeugenepackage test.parameters; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; import java.util.Arrays; public class ParameterOverrideTest extends SimpleBaseTest { enum S { FAIL, PASS_TEST, PASS_CLASS, PASS_INCLUDE, }; @Test public void testOverrideSuite() { privateTestOverrideSuite(S.PASS_TEST); } @Test(expectedExceptions = AssertionError.class) public void testOverrideSuiteNegative() { privateTestOverrideSuite(S.FAIL); } @Test public void classOverrideSuite() { privateTestOverrideSuite(S.PASS_CLASS); } @Test(expectedExceptions = AssertionError.class) public void classOverrideSuiteNegative() { privateTestOverrideSuite(S.FAIL); } @Test public void includeOverrideClass() { privateTestOverrideSuite(S.PASS_INCLUDE); } @Test(expectedExceptions = AssertionError.class) public void includeOverrideClassNegative() { privateTestOverrideSuite(S.FAIL); } public void privateTestOverrideSuite(S status) { XmlSuite s = createXmlSuite("s"); s.getParameters().put("a", "Incorrect"); s.getParameters().put("InheritedFromSuite", "InheritedFromSuite"); XmlTest t = createXmlTest(s, "t"); t.getLocalParameters().put("InheritedFromTest", "InheritedFromTest"); if (status == S.PASS_TEST) { t.getLocalParameters().put("a", "Correct"); } { XmlClass c1 = new XmlClass(Override1Sample.class.getName()); c1.getLocalParameters().put("InheritedFromClass", "InheritedFromClass"); if (status == S.PASS_CLASS) { c1.getLocalParameters().put("a", "Correct"); } t.getXmlClasses().add(c1); for (String method : new String[] { "f", "g" }) { XmlInclude include1 = new XmlInclude(method); if (status == S.PASS_INCLUDE) { include1.getLocalParameters().put("a", "Correct"); } include1.setXmlClass(c1); c1.getIncludedMethods().add(include1); } } TestNG tng = create(); tng.setXmlSuites(Arrays.asList(s)); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); // System.out.println(s.toXml()); // tng.setVerbose(10); tng.run(); assertTestResultsEqual(tla.getPassedTests(), Arrays.asList("f", "g")); } } testng-testng-6.9.5/src/test/java/test/parameters/ParamInheritanceTest.java0000644000175000017500000000417612551235562026407 0ustar eugeneeugenepackage test.parameters; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.Arrays; public class ParamInheritanceTest extends SimpleBaseTest { @Test(description = "When verbose is set to >1, TNG prints test results on CLI which are printed " + "using SuiteResultCounts.calculateResultCounts(). This method has been throwing NPE " + "because it's unable to find SuiteRunner in HashMap, because the list of parameters in " + "SuiteRunner changed" + " during execution. This test makes sure we dont run into any NPEs") public void noNPEInCountingResults() { TestListenerAdapter tla = new TestListenerAdapter(); TestNG tng = create(); tng.setTestSuites(Arrays.asList(getPathToResource("param-inheritance/parent-suite.xml"))); tng.setVerbose(2); tng.addListener(tla); OutputStream os = new ByteArrayOutputStream(); PrintStream out = System.out; PrintStream err = System.err; try { /* * Changing system print streams so that exception or results stmt is not logged * while running test (avoid confusing person running tests) */ System.setOut(new PrintStream(os)); System.setErr(new PrintStream(os)); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 1); } finally { try { os.close(); } catch (IOException e) { //no need to handle this } System.setOut(out); System.setErr(err); } } @Test(description = "Checks to make sure parameters are inherited and overridden properly") public void parameterInheritanceAndOverriding() { TestListenerAdapter tla = new TestListenerAdapter(); TestNG tng = create(); tng.setUseDefaultListeners(false); tng.setTestSuites(Arrays.asList(getPathToResource("parametertest/parent-suite.xml"))); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 3); } } testng-testng-6.9.5/src/test/java/test/parameters/Override1Sample.java0000644000175000017500000000115212551235562025326 0ustar eugeneeugenepackage test.parameters; import org.testng.Assert; import org.testng.annotations.Parameters; import org.testng.annotations.Test; @Test public class Override1Sample { @Parameters({"InheritedFromSuite", "InheritedFromTest", "InheritedFromClass"}) public void g(String suite, String test, String cls) { Assert.assertEquals(suite, "InheritedFromSuite"); Assert.assertEquals(test, "InheritedFromTest"); Assert.assertEquals(cls, "InheritedFromClass"); } public void h() { System.out.println("h()"); } @Parameters("a") public void f(String p) { Assert.assertEquals(p, "Correct"); } } testng-testng-6.9.5/src/test/java/test/parameters/OptionalParameterTest.java0000644000175000017500000000035512551235562026616 0ustar eugeneeugenepackage test.parameters; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; public class OptionalParameterTest { @Parameters("optional") public OptionalParameterTest(@Optional String optional) {} } testng-testng-6.9.5/src/test/java/test/parameters/InheritFromSuiteChild3.java0000644000175000017500000000117412551235562026617 0ustar eugeneeugenepackage test.parameters; import org.testng.Assert; import org.testng.annotations.Parameters; import org.testng.annotations.Test; /** * Checks to see if the parameters from parent suite are passed onto the * child suite (referred by ) * @author nullin * */ public class InheritFromSuiteChild3 { @Test @Parameters({"parameter1", "parameter2", "parameter3", "parameter4"}) public void inheritedparameter(String p1, String p2, String p3, String p4) { Assert.assertEquals(p1, "p1"); Assert.assertEquals(p2, "c3p2"); Assert.assertEquals(p3, "c2p3"); Assert.assertEquals(p4, "c3p4"); } } testng-testng-6.9.5/src/test/java/test/parameters/InheritFromSuiteChild2.java0000644000175000017500000000126312551235562026615 0ustar eugeneeugenepackage test.parameters; import org.testng.Assert; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.testng.annotations.Test; /** * Checks to see if the parameters from parent suite are passed onto the * child suite (referred by ) * @author nullin * */ public class InheritFromSuiteChild2 { @Test @Parameters({"parameter1", "parameter2", "parameter3", "parameter4"}) public void inheritedparameter(String p1, String p2, String p3, @Optional("abc")String p4) { Assert.assertEquals(p1, "p1"); Assert.assertEquals(p2, "c2p2"); Assert.assertEquals(p3, "c2p3"); Assert.assertEquals(p4, "abc"); } } testng-testng-6.9.5/src/test/java/test/parameters/InheritFromSuiteChild1.java0000644000175000017500000000127112551235562026613 0ustar eugeneeugenepackage test.parameters; import org.testng.Assert; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.testng.annotations.Test; /** * Checks to see if the parameters from parent suite are passed onto the * child suite (referred by ) * @author nullin * */ public class InheritFromSuiteChild1 { @Test @Parameters({"parameter1", "parameter2", "parameter3", "parameter4"}) public void inheritedparameter(String p1, String p2, @Optional("foobar")String p3, String p4) { Assert.assertEquals(p1, "p1"); Assert.assertEquals(p2, "c1p2"); Assert.assertEquals(p3, "foobar"); Assert.assertEquals(p4, "c1p4"); } } testng-testng-6.9.5/src/test/java/test/parameters/BeforeSampleTest.java0000644000175000017500000000133012551235562025526 0ustar eugeneeugenepackage test.parameters; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Parameters; import org.testng.annotations.Test; import junit.framework.Assert; public class BeforeSampleTest { @BeforeMethod @Parameters("parameter") public static void beforeMethod(String parameter) { Assert.assertEquals("parameter value", parameter); } @DataProvider(name = "dataProvider") public static Object[][] dataProvider() { return new Object[][]{{"abc", "def"}}; } @Test(dataProvider = "dataProvider") public static void testExample(String a, String b) { Assert.assertEquals("abc", a); Assert.assertEquals("def", b); } }testng-testng-6.9.5/src/test/java/test/override/0000755000175000017500000000000012551235562021136 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/override/OverrideTest.java0000644000175000017500000000350212551235562024420 0ustar eugeneeugenepackage test.override; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.internal.Utils; import org.xml.sax.SAXException; import test.SimpleBaseTest; import javax.xml.parsers.ParserConfigurationException; import java.io.File; import java.io.IOException; import java.util.Arrays; /** * Verify that command line switches override parameters in testng.xml. * * @author Cedric Beust */ public class OverrideTest extends SimpleBaseTest { private void runTest(String include, String exclude) { File f = Utils.createTempFile( "" + " " + " " + " " + " " + " " + "" ); TestNG tng = create(); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); if (include != null) tng.setGroups(include); if (exclude != null) tng.setExcludedGroups(exclude); tng.setTestSuites(Arrays.asList(f.getAbsolutePath())); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 1); } @Test(description = "Override -groups") public void overrideIncludeShouldWork() throws ParserConfigurationException, SAXException, IOException { runTest("goodGroup", null); } @Test(description = "Override -excludegroups") public void overrideExcludeShouldWork() throws ParserConfigurationException, SAXException, IOException { runTest(null, "badGroup"); } @Test(description = "Override -groups and -excludegroups") public void overrideIncludeAndExcludeShouldWork() throws ParserConfigurationException, SAXException, IOException { runTest("goodGroup", "badGroup"); } } testng-testng-6.9.5/src/test/java/test/override/OverrideSampleTest.java0000644000175000017500000000041012551235562025555 0ustar eugeneeugenepackage test.override; import org.testng.annotations.Test; public class OverrideSampleTest { @Test(groups = "goodGroup") public void good() { } @Test(groups = "badGroup") public void bad() { throw new RuntimeException("Should not happen"); } } testng-testng-6.9.5/src/test/java/test/objectfactory/0000755000175000017500000000000012551235562022155 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/objectfactory/Simple.java0000644000175000017500000000033112551235562024246 0ustar eugeneeugenepackage test.objectfactory; import org.testng.annotations.Test; /** * @author Hani Suleiman * Date: Mar 6, 2007 * Time: 3:56:57 PM */ public class Simple { @Test public void dummy() { } } testng-testng-6.9.5/src/test/java/test/objectfactory/ObjectFactory2Test.java0000644000175000017500000000201212551235562026473 0ustar eugeneeugenepackage test.objectfactory; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import test.TestHelper; /** * Test IObjectFactory2, which is an object factory that receives just the Class in parameter. * * @author Cedric Beust */ public class ObjectFactory2Test { private void testFactory(boolean onSuite) { XmlSuite suite = TestHelper.createSuite(ClassObjectFactorySampleTest.class.getName(), "Test IObjectFactory2"); TestNG tng = TestHelper.createTestNG(suite); if (onSuite) suite.setObjectFactory(new ClassObjectFactory()); else tng.setObjectFactory(ClassObjectFactory.class); ClassObjectFactorySampleTest.m_n = 0; tng.run(); Assert.assertEquals(ClassObjectFactorySampleTest.m_n, 42); } @Test public void factoryOnSuiteShouldWork() { testFactory(true /* on suite object */); } @Test public void factoryOnTestNGShouldWork() { testFactory(false /* on TestNG object */); } } testng-testng-6.9.5/src/test/java/test/objectfactory/MyFactoryFactory.java0000644000175000017500000000051012551235562026261 0ustar eugeneeugenepackage test.objectfactory; import org.testng.IObjectFactory; import org.testng.annotations.ObjectFactory; /** * @author Hani Suleiman * Date: Mar 6, 2007 * Time: 5:03:19 PM */ public class MyFactoryFactory { @ObjectFactory public IObjectFactory create() { return new LoggingObjectFactory(); } } testng-testng-6.9.5/src/test/java/test/objectfactory/LoggingObjectFactory.java0000644000175000017500000000103612551235562027065 0ustar eugeneeugenepackage test.objectfactory; import org.testng.internal.ObjectFactoryImpl; import java.lang.reflect.Constructor; /** * @author Hani Suleiman * Date: Mar 6, 2007 * Time: 3:53:28 PM */ public class LoggingObjectFactory extends ObjectFactoryImpl { /** * */ private static final long serialVersionUID = -395096650866727480L; public static int invoked; @Override public Object newInstance(Constructor constructor, Object... params) { invoked++; return super.newInstance(constructor, params); } } testng-testng-6.9.5/src/test/java/test/objectfactory/CustomFactoryTest.java0000644000175000017500000000473612551235562026474 0ustar eugeneeugenepackage test.objectfactory; import org.testng.TestNG; import org.testng.TestNGException; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import org.testng.xml.XmlClass; import org.testng.xml.XmlSuite; import test.TestHelper; /** * @author Hani Suleiman Date: Mar 6, 2007 Time: 3:52:19 PM */ public class CustomFactoryTest { @Test public void setFactoryOnTestNG() { XmlSuite suite = TestHelper.createSuite("test.objectfactory.Simple", "objectfactory"); // suite.setObjectFactory(new LoggingObjectFactory()); TestNG tng = TestHelper.createTestNG(suite); tng.setObjectFactory(LoggingObjectFactory.class); tng.run(); assert LoggingObjectFactory.invoked == 1 : "Logging factory invoked " + LoggingObjectFactory.invoked + " times"; } @AfterMethod public void resetCount() { LoggingObjectFactory.invoked = 0; } @Test public void setFactoryOnSuite() { XmlSuite suite = TestHelper.createSuite("test.objectfactory.Simple", "objectfactory"); suite.setObjectFactory(new LoggingObjectFactory()); TestNG tng = TestHelper.createTestNG(suite); tng.run(); assert LoggingObjectFactory.invoked == 1 : "Logging factory invoked " + LoggingObjectFactory.invoked + " times"; } @Test(enabled = false, description = "This broke after I made the change to enable AbstractTest") public void setFactoryByAnnotation() { XmlSuite suite = TestHelper.createSuite("test.objectfactory.Simple", "objectfactory"); suite.getTests().get(0).getXmlClasses() .add(new XmlClass("test.objectfactory.MyFactoryFactory")); TestNG tng = TestHelper.createTestNG(suite); tng.run(); assert LoggingObjectFactory.invoked == 1 : "Logging factory invoked " + LoggingObjectFactory.invoked + " times"; } @Test public void factoryReceivesContext() { XmlSuite suite = TestHelper.createSuite("test.objectfactory.Simple", "objectfactory"); suite.getTests().get(0).getXmlClasses() .add(new XmlClass("test.objectfactory.ContextAwareFactoryFactory")); TestNG tng = TestHelper.createTestNG(suite); tng.run(); } @Test(expectedExceptions = TestNGException.class) public void setInvalidMethodFactoryByAnnotation() { XmlSuite suite = TestHelper.createSuite("test.objectfactory.Simple", "objectfactory"); suite.getTests().get(0).getXmlClasses() .add(new XmlClass("test.objectfactory.BadMethodFactoryFactory")); TestNG tng = TestHelper.createTestNG(suite); tng.run(); } } testng-testng-6.9.5/src/test/java/test/objectfactory/ContextAwareFactoryFactory.java0000644000175000017500000000071612551235562030310 0ustar eugeneeugenepackage test.objectfactory; import org.testng.IObjectFactory; import org.testng.ITestContext; import org.testng.annotations.ObjectFactory; import org.testng.internal.ObjectFactoryImpl; /** * @author Hani Suleiman * Date: Mar 8, 2007 * Time: 10:05:55 PM */ public class ContextAwareFactoryFactory { @ObjectFactory public IObjectFactory create(ITestContext context) { assert context != null; return new ObjectFactoryImpl(); } } testng-testng-6.9.5/src/test/java/test/objectfactory/CombinedTestAndObjectFactoryTest.java0000644000175000017500000000135012551235562031341 0ustar eugeneeugenepackage test.objectfactory; import org.testng.TestNG; import org.testng.annotations.Test; import test.BaseTest; public class CombinedTestAndObjectFactoryTest extends BaseTest { @Test void combinedTestAndObjectFactory() { addClass(CombinedTestAndObjectFactorySample.class.getName()); run(); verifyTests("Should have passed", new String[]{"isConfigured"}, getPassedTests()); verifyTests("Failures", new String[0], getFailedTests()); verifyTests("Skipped", new String[0], getSkippedTests()); } public static void main(String[] args) { TestNG tng = new TestNG(); tng.setTestClasses(new Class[] {CombinedTestAndObjectFactorySample.class}); tng.setVerbose(10); tng.run(); } } testng-testng-6.9.5/src/test/java/test/objectfactory/CombinedTestAndObjectFactorySample.java0000644000175000017500000000210312551235562031640 0ustar eugeneeugenepackage test.objectfactory; import org.testng.Assert; import org.testng.IObjectFactory; import org.testng.annotations.ObjectFactory; import org.testng.annotations.Test; import java.lang.reflect.Constructor; @SuppressWarnings("serial") public class CombinedTestAndObjectFactorySample implements IObjectFactory{ private boolean configured = false; @ObjectFactory public IObjectFactory create() { return new CombinedTestAndObjectFactorySample(); } @Test public void isConfigured() { Assert.assertTrue(configured, "Should have been configured by object factory"); } @Override @SuppressWarnings("unchecked") public Object newInstance(Constructor constructor, Object... params) { Object o; try { o = constructor.newInstance(params); } catch (Exception e) { throw new RuntimeException(e); } if (CombinedTestAndObjectFactorySample.class.equals(o.getClass())) { CombinedTestAndObjectFactorySample s = (CombinedTestAndObjectFactorySample) o; s.configured = true; } return o; } } testng-testng-6.9.5/src/test/java/test/objectfactory/ClassObjectFactorySampleTest.java0000644000175000017500000000054412551235562030551 0ustar eugeneeugenepackage test.objectfactory; import org.testng.Assert; import org.testng.annotations.Test; public class ClassObjectFactorySampleTest { public static int m_n = 0; /** * Will be invoked with 42 by the factory. */ public ClassObjectFactorySampleTest(int n) { m_n = n; } @Test public void f() { Assert.assertEquals(42, m_n); } } testng-testng-6.9.5/src/test/java/test/objectfactory/ClassObjectFactory.java0000644000175000017500000000065312551235562026550 0ustar eugeneeugenepackage test.objectfactory; import org.testng.IObjectFactory2; import java.lang.reflect.Constructor; public class ClassObjectFactory implements IObjectFactory2 { @Override public Object newInstance(Class cls) { try { Constructor ctor = cls.getConstructors()[0]; return ctor.newInstance(new Object[] { 42 }); } catch(Exception ex) { ex.printStackTrace(); return null; } } } testng-testng-6.9.5/src/test/java/test/objectfactory/BadMethodFactoryFactory.java0000644000175000017500000000044512551235562027532 0ustar eugeneeugenepackage test.objectfactory; import org.testng.annotations.ObjectFactory; /** * @author Hani Suleiman * Date: Mar 6, 2007 * Time: 5:03:19 PM */ public class BadMethodFactoryFactory { @ObjectFactory public Object create() { return new LoggingObjectFactory(); } } testng-testng-6.9.5/src/test/java/test/nested2/0000755000175000017500000000000012551235562020663 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/nested2/TmpA.java0000644000175000017500000000100212551235562022360 0ustar eugeneeugenepackage test.nested2; import org.testng.annotations.Test; public class TmpA { public static class NestedAWithTest { @Test public void nestedA() {} } public static class NestedAWithoutTest { public NestedAWithoutTest() { throw new RuntimeException("TestNG should not instantiate me"); } public void nestedA() {} } @Test public static class DummyBase {} public static class NestedAWithInheritedTest extends DummyBase { public void nestedWithInheritedTest() {} } }testng-testng-6.9.5/src/test/java/test/nested/0000755000175000017500000000000012551235562020601 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/nested/foo/0000755000175000017500000000000012551235562021364 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/nested/foo/AccountTypeEnum.java0000644000175000017500000000017212551235562025312 0ustar eugeneeugenepackage test.nested.foo; public class AccountTypeEnum { public static final AccountTypeEnum ClearingMember = null; } testng-testng-6.9.5/src/test/java/test/nested/GarfTest.java0000644000175000017500000000055212551235562023165 0ustar eugeneeugenepackage test.nested; import org.testng.Assert; import org.testng.annotations.Test; import test.nested.foo.AccountTypeEnum; @Test(groups = { "unittest" }, enabled = true ) public class GarfTest { @Test() public void testGarf() { AccountTypeEnum foo = AccountTypeEnum.ClearingMember; Assert.assertEquals(foo,AccountTypeEnum.ClearingMember); } } testng-testng-6.9.5/src/test/java/test/mustache/0000755000175000017500000000000012551235562021130 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/mustache/MustacheTest.java0000644000175000017500000000537712551235562024420 0ustar eugeneeugenepackage test.mustache; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.testng.collections.Maps; import org.testng.mustache.Mustache; @Test public class MustacheTest { public static class Person { public String name; public Person(String n) { name = n; } } public static class Age { public int age; public Age(int a) { this.age = a; } } private static final List PEOPLE = new ArrayList<>( Arrays.asList(new Person("Carl"), new Person("Christopher"))); private static final List AGES = new ArrayList<>( Arrays.asList(new Age(42), new Age(43))); @DataProvider public Object[][] dp() { return new Object[][] { // Simple new Object[] { create("one", "ello", "two", "orld"), "H{{one}} W{{two}}", "Hello World" }, // Null condition new Object[] { Collections.emptyMap(), "E{{#foo}}xxx{{/foo}}lephant", "Elephant" }, // Null condition with new line new Object[] { Collections.emptyMap(), "Hello\n{{#foo}}@\n{{/foo}}World", "Hello\nWorld" }, // Simple scope new Object[] { create("person", new Person("John"), "day", "Monday"), "Hello {{#person}}{{name}}{{/person}}, {{day}}", "Hello John, Monday" }, // Scope with shadowing new Object[] { create("person", new Person("John"), "name", "Carl"), "Hello {{#person}}{{name}}{{/person}}, {{name}}", "Hello John, Carl" }, // Test iteration new Object[] { create("people", PEOPLE), "People:@{{#people}}-{{/people}}!", "People:@--!", }, // Nested scopes new Object[] { create("people", PEOPLE, "ages", AGES), ":@{{#people}}{{name}}{{#ages}}{{age}}{{/ages}}@{{/people}}!_", ":@Carl4243@Christopher4243@!_", }, }; } private Map create(Object... objects) { Map result = Maps.newHashMap(); for (int i = 0; i < objects.length; i += 2) { result.put((String) objects[i], objects[i + 1]); } return result; } @Test(dataProvider = "dp") public void runTest(Map model, String template, String expected) throws IOException { // InputStream is = new StringInputStream(template); Assert.assertEquals(new Mustache().run(template, model), expected); } } testng-testng-6.9.5/src/test/java/test/multiplelisteners/0000755000175000017500000000000012551235562023103 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/multiplelisteners/TestMaker.java0000755000175000017500000000270012551235562025647 0ustar eugeneeugenepackage test.multiplelisteners; import org.testng.TestListenerAdapter; import org.testng.TestNG; 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; import java.util.Arrays; import java.util.Collections; import java.util.List; public class TestMaker { @Test(description = "Make sure only one listener is created and not 2^3") public void run() { final TestNG tng = new TestNG(); tng.setUseDefaultListeners(false); tng.setListenerClasses(Arrays. asList(TestListenerAdapter.class, SimpleReporter.class)); final List suites = createSuites(); tng.setXmlSuites(suites); tng.setVerbose(0); tng.run(); // Reporter.log(tng.getSuiteListeners().size() + "", true); // for (final XmlSuite xmlSuite : suites) // { // Reporter.log(xmlSuite.getName() + ": " + xmlSuite.getListeners().size(), true); // } } private List createSuites() { final List ret = Lists.newArrayList(); for (int i = 0; i < 3; i++) { ret.add(createSuite(i)); } return ret; } private XmlSuite createSuite(final int nr) { final XmlSuite suite = new XmlSuite(); suite.setName("Suite_" + nr); new XmlTest(suite).setXmlClasses(Collections.singletonList(new XmlClass(Test1.class))); return suite; } } testng-testng-6.9.5/src/test/java/test/multiplelisteners/Test1.java0000755000175000017500000000025712551235562024755 0ustar eugeneeugenepackage test.multiplelisteners; import org.testng.annotations.Test; @Test public class Test1 { public void test() { // Reporter.log("test1", true); } } testng-testng-6.9.5/src/test/java/test/multiplelisteners/SimpleReporter.java0000755000175000017500000000201112551235562026717 0ustar eugeneeugenepackage test.multiplelisteners; import org.testng.Assert; import org.testng.IReporter; import org.testng.ISuite; import org.testng.SuiteRunner; import org.testng.internal.IConfiguration; import org.testng.xml.XmlSuite; import java.lang.reflect.Field; import java.util.List; public class SimpleReporter implements IReporter { @Override public void generateReport(final List xmlSuites, final List suites, final String outputDirectory) { for (final ISuite iSuite : suites) { try { final Field field = SuiteRunner.class.getDeclaredField("m_configuration"); field.setAccessible(true); final IConfiguration conf = (IConfiguration) field.get(iSuite); // Reporter.log(iSuite.getName() + ": " + conf.getConfigurationListeners().size(), true); Assert.assertEquals(conf.getConfigurationListeners().size(), 1); } catch (final Exception e) { throw new RuntimeException(e); } } } } testng-testng-6.9.5/src/test/java/test/multiple/0000755000175000017500000000000012551235562021152 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/multiple/ThisFactory.java0000644000175000017500000000056312551235562024260 0ustar eugeneeugenepackage test.multiple; import org.testng.annotations.Factory; import java.util.ArrayList; import java.util.List; /** * This class * * @author cbeust */ public class ThisFactory { @Factory public Object[] create() { List result = new ArrayList(); for (int i = 0; i < 10; i++) { result.add(new Test1()); } return result.toArray(); } } testng-testng-6.9.5/src/test/java/test/multiple/TestMultiple.java0000644000175000017500000000103312551235562024445 0ustar eugeneeugenepackage test.multiple; import org.testng.annotations.Test; import test.BaseTest; public class TestMultiple extends BaseTest { private static final String CLASS_NAME = "test.multiple.ThisFactory"; @Test(groups = { "current" }) public void multiple() { addClass(CLASS_NAME); run(); String[] passed = { "f1", }; String[] failed = { "f1","f1","f1","f1","f1", "f1","f1","f1","f1", }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } } testng-testng-6.9.5/src/test/java/test/multiple/Test1.java0000644000175000017500000000073412551235562023021 0ustar eugeneeugenepackage test.multiple; import static org.testng.Assert.assertTrue; import org.testng.annotations.AfterTest; import org.testng.annotations.Test; public class Test1 { private static int m_count = 0; @Test public void f1() { // ppp("INVOKING f1 " + m_count); assertTrue(m_count < 1, "FAILING"); m_count++; } @AfterTest public void cleanUp() { m_count = 0; } private static void ppp(String s) { System.out.println("[Test1] " + s); } } testng-testng-6.9.5/src/test/java/test/morten/0000755000175000017500000000000012551235562020623 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/morten/SampleTestFactory.java0000644000175000017500000000044412551235562025101 0ustar eugeneeugenepackage test.morten; import org.testng.annotations.Factory; public class SampleTestFactory { public SampleTestFactory() {} // CTR necessary ? @Factory public Object[] createInstances() { return new SampleTest[] { new SampleTest(1, 0.1f), new SampleTest(10, 0.5f), }; } }; testng-testng-6.9.5/src/test/java/test/morten/SampleTest.java0000644000175000017500000000152312551235562023550 0ustar eugeneeugenepackage test.morten; import org.testng.annotations.Factory; import org.testng.annotations.Test; public class SampleTest { private int capacity = 10; private float loadFactor = 0.3f; public class SampleTestTestFactory { public SampleTestTestFactory() {} // CTR necessary ? @Factory public Object[] createInstances() { return new SampleTest[] { new SampleTest(1, 0.1f), new SampleTest(10, 0.5f), }; } }; public SampleTest() { } public SampleTest(int capacity, float loadFactor) { System.out.println("CREATING TEST WITH " + capacity); this.capacity=capacity; this.loadFactor=loadFactor; } @Test public void testPut() { //FIXME: This test does nothing //HashMap hashTable = new HashMap(capacity, loadFactor); // ... } } testng-testng-6.9.5/src/test/java/test/mixed/0000755000175000017500000000000012551235562020425 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/mixed/TestNGTest1.java0000644000175000017500000000033012551235562023351 0ustar eugeneeugenepackage test.mixed; import org.testng.annotations.Test; /** * * @author lukas */ public class TestNGTest1 { @Test public void tngTest1() { } @Test public void tngCustomTest1() { } } testng-testng-6.9.5/src/test/java/test/mixed/TestNGGroups.java0000644000175000017500000000035612551235562023640 0ustar eugeneeugenepackage test.mixed; import org.testng.annotations.Test; @Test(groups = {"unit"}) public class TestNGGroups { @Test public void tngTest1() { } @Test(groups = {"ignore"}) public void tngShouldBeIgnored() { } } testng-testng-6.9.5/src/test/java/test/mixed/MixedTest.java0000644000175000017500000000407412551235562023203 0ustar eugeneeugenepackage test.mixed; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.BaseTest; import testhelper.OutputDirectoryPatch; /** * * @author lukas */ public class MixedTest extends BaseTest { @Test public void mixedWithExcludedGroups() { String[] argv = { "-d", OutputDirectoryPatch.getOutputDirectory(), "-log", "0", "-mixed", "-groups", "unit", "-excludegroups", "ignore", "-testclass", "test.mixed.JUnit3Test1,test.mixed.JUnit4Test1,test.mixed.TestNGTest1,test.mixed.TestNGGroups" }; TestListenerAdapter tla = new TestListenerAdapter(); TestNG.privateMain(argv, tla); Assert.assertEquals(tla.getPassedTests().size(), 5); //2 from junit3test1, 2 from junit4test1, 0 from testngtest1 (no groups), 1 from testnggroups (1 is included, 1 is excluded) Assert.assertEquals(tla.getFailedTests().size(), 0); } @Test public void mixedClasses() { String[] argv = { "-d", OutputDirectoryPatch.getOutputDirectory(), "-log", "0", "-mixed", "-testclass", "test.mixed.JUnit3Test1,test.mixed.JUnit4Test1,test.mixed.TestNGTest1" }; TestListenerAdapter tla = new TestListenerAdapter(); TestNG.privateMain(argv, tla); Assert.assertEquals(tla.getPassedTests().size(), 6); Assert.assertEquals(tla.getFailedTests().size(), 0); } @Test public void mixedMethods() { String[] argv = { "-d", OutputDirectoryPatch.getOutputDirectory(), "-mixed", "-log", "0", "-methods", "test.mixed.JUnit3Test1.testB,test.mixed.JUnit4Test1.atest,test.mixed.TestNGTest1.tngCustomTest1" }; TestListenerAdapter tla = new TestListenerAdapter(); TestNG.privateMain(argv, tla); Assert.assertEquals(tla.getPassedTests().size(), 3); Assert.assertEquals(tla.getFailedTests().size(), 0); } } testng-testng-6.9.5/src/test/java/test/mixed/JUnit4Test1.java0000644000175000017500000000027612551235562023333 0ustar eugeneeugenepackage test.mixed; import org.junit.Test; /** * * @author lukas */ public class JUnit4Test1 { @Test public void atest() { } @Test public void bTest() { } } testng-testng-6.9.5/src/test/java/test/mixed/JUnit3Test1.java0000644000175000017500000000041712551235562023327 0ustar eugeneeugenepackage test.mixed; import junit.framework.TestCase; /** * * @author lukas */ public class JUnit3Test1 extends TestCase { public JUnit3Test1(String name) { super(name); } public void testA() { } public void testB() { } } testng-testng-6.9.5/src/test/java/test/methodselectors/0000755000175000017500000000000012551235562022523 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/methodselectors/Test2MethodSelector.java0000644000175000017500000000134612551235562027235 0ustar eugeneeugenepackage test.methodselectors; import org.testng.IMethodSelector; import org.testng.IMethodSelectorContext; import org.testng.ITestNGMethod; import java.util.List; public class Test2MethodSelector implements IMethodSelector { /** * */ private static final long serialVersionUID = 4166247968392649912L; @Override public boolean includeMethod(IMethodSelectorContext context, ITestNGMethod method, boolean isTestMethod) { for (String group : method.getGroups()) { if (group.equals("test2")) { context.setStopped(true); return true; } } return false; } @Override public void setTestMethods(List testMethods) { // TODO Auto-generated method stub } } testng-testng-6.9.5/src/test/java/test/methodselectors/SampleTest.java0000644000175000017500000000067112551235562025453 0ustar eugeneeugenepackage test.methodselectors; import org.testng.annotations.Test; public class SampleTest { @Test(groups = { "test1" }) public void test1() { ppp("TEST1"); } @Test(groups = { "test2" }) public void test2() { ppp("TEST2"); } @Test(groups = { "test3" }) public void test3() { ppp("TEST3"); } private static void ppp(String s) { if (false) { System.out.println("[SampleTest] " + s); } } } testng-testng-6.9.5/src/test/java/test/methodselectors/PriorityTest.java0000644000175000017500000000301612551235562026047 0ustar eugeneeugenepackage test.methodselectors; import org.testng.Assert; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import java.util.List; public class PriorityTest { private void runTest(int priority, String[] passedTests) { TestNG tng = new TestNG(); tng.setVerbose(0); tng.setTestClasses(new Class[] { PrioritySampleTest.class }); tng.addMethodSelector("test.methodselectors.NoTestSelector", priority); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); List passed = tla.getPassedTests(); Assert.assertEquals(passedTests.length, passed.size()); if (passedTests.length == 1) { String passed0 = passed.get(0).getName(); Assert.assertEquals(passed0, passedTests[0]); } if (passedTests.length == 2) { String passed0 = passed.get(0).getName(); String passed1 = passed.get(1).getName(); Assert.assertTrue(passed0.equals(passedTests[0]) || passed0.equals(passedTests[1])); Assert.assertTrue(passed1.equals(passedTests[0]) || passed1.equals(passedTests[1])); } } // @Test public void negativePriority() { runTest(-5, new String[] {}); } @Test public void lessThanTenPriority() { runTest(5, new String[] { "alwaysRun" }); } // @Test public void greaterThanTenPriority() { runTest(15, new String[] { "alwaysRun", "neverRun" }); } } testng-testng-6.9.5/src/test/java/test/methodselectors/PrioritySampleTest.java0000644000175000017500000000053512551235562027214 0ustar eugeneeugenepackage test.methodselectors; import org.testng.annotations.Test; public class PrioritySampleTest { @Test public void alwaysRun() { ppp("ALWAYS"); } @Test @NoTest public void neverRun() { ppp("NEVER"); } private static void ppp(String s) { System.out.println("[PrioritySampleTest] " + s); } } testng-testng-6.9.5/src/test/java/test/methodselectors/NoTestSelector.java0000644000175000017500000000132012551235562026277 0ustar eugeneeugenepackage test.methodselectors; import org.testng.IMethodSelector; import org.testng.IMethodSelectorContext; import org.testng.ITestNGMethod; import java.util.List; public class NoTestSelector implements IMethodSelector { /** * */ private static final long serialVersionUID = -7751190578710846487L; @Override public boolean includeMethod(IMethodSelectorContext context, ITestNGMethod method, boolean isTestMethod) { ppp("NOTEST RETURNING FALSE FOR " + method); return false; } @Override public void setTestMethods(List testMethods) { } private static void ppp(String s) { // System.out.println("[NoTestSelector] " + s); } } testng-testng-6.9.5/src/test/java/test/methodselectors/NoTest1MethodSelector.java0000644000175000017500000000165412551235562027533 0ustar eugeneeugenepackage test.methodselectors; import org.testng.IMethodSelector; import org.testng.IMethodSelectorContext; import org.testng.ITestNGMethod; import java.util.List; public class NoTest1MethodSelector implements IMethodSelector { /** * */ private static final long serialVersionUID = 6706869410370733524L; @Override public boolean includeMethod(IMethodSelectorContext context, ITestNGMethod method, boolean isTestMethod) { for (String group : method.getGroups()) { if (group.equals("test1")) { ppp( method.getMethodName() + " is group test1, don't include" ); context.setStopped(true); return false; } } ppp( method.getMethodName() + " is not in group test1" ); return true; } @Override public void setTestMethods(List testMethods) { } public static void ppp(String s) { //System.out.println("[NoTest1MethodSelector] " + s); } } testng-testng-6.9.5/src/test/java/test/methodselectors/NoTest.java0000644000175000017500000000010012551235562024571 0ustar eugeneeugenepackage test.methodselectors; public @interface NoTest { } testng-testng-6.9.5/src/test/java/test/methodselectors/MethodSelectorTest.java0000644000175000017500000000430512551235562027151 0ustar eugeneeugenepackage test.methodselectors; import org.testng.annotations.Test; import test.BaseTest; public class MethodSelectorTest extends BaseTest { @Test public void negativePriorityAllGroups() { addClass("test.methodselectors.SampleTest"); addMethodSelector("test.methodselectors.AllTestsMethodSelector", -1); run(); String[] passed = { "test1", "test2", "test3", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void negativePriorityGroup2() { addClass("test.methodselectors.SampleTest"); addMethodSelector("test.methodselectors.Test2MethodSelector", -1); run(); String[] passed = { "test2", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void lessThanPriorityTest1Test() { addClass("test.methodselectors.SampleTest"); addIncludedGroup("test1"); addMethodSelector("test.methodselectors.Test2MethodSelector", 5); run(); String[] passed = { "test1", "test2", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void greaterThanPriorityTest1Test2() { addClass("test.methodselectors.SampleTest"); addIncludedGroup("test1"); addMethodSelector("test.methodselectors.Test2MethodSelector", 15); run(); String[] passed = { "test2", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void lessThanPriorityAllTests() { addClass("test.methodselectors.SampleTest"); addIncludedGroup("test1"); addMethodSelector("test.methodselectors.AllTestsMethodSelector", 5); run(); String[] passed = { "test1", "test2", "test3" }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } public static void ppp(String s) { System.out.println("[MethodSelectorTest] " + s); } } testng-testng-6.9.5/src/test/java/test/methodselectors/MethodSelectorInSuiteTest.java0000644000175000017500000000442112551235562030451 0ustar eugeneeugenepackage test.methodselectors; import org.testng.Assert; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.testng.collections.Lists; import org.testng.xml.XmlClass; import org.testng.xml.XmlMethodSelector; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; import testhelper.OutputDirectoryPatch; import java.util.Arrays; import java.util.List; public class MethodSelectorInSuiteTest extends SimpleBaseTest{ private TestListenerAdapter m_tla; @BeforeMethod public void setup() { m_tla = new TestListenerAdapter(); } @Test public void programmaticXmlSuite() { TestNG tng = create(); XmlSuite suite = new XmlSuite(); XmlMethodSelector methodSelector = new XmlMethodSelector(); methodSelector.setName("test.methodselectors.Test2MethodSelector"); methodSelector.setPriority(-1); List methodSelectors = Lists.newArrayList(); methodSelectors.add(methodSelector); suite.setMethodSelectors(methodSelectors); XmlTest test = new XmlTest(suite); XmlClass testClass = new XmlClass(test.methodselectors.SampleTest.class); test.setXmlClasses(Arrays.asList(testClass)); tng.setXmlSuites(Arrays.asList(suite)); tng.addListener(m_tla); tng.run(); validate(new String[] { "test2" }); } @Test public void xmlXmlSuite() { TestNG tng = create(); tng.setTestSuites(Arrays.asList(getPathToResource("methodselector-in-xml.xml"))); tng.addListener(m_tla); tng.run(); validate(new String[] { "test2" }); } @Test public void fileOnCommandLine() { String[] args = new String[] { "-d", OutputDirectoryPatch.getOutputDirectory(), getPathToResource("methodselector-in-xml.xml") }; TestNG.privateMain(args, m_tla); validate(new String[] { "test2" }); } private void validate(String[] expectPassed) { List passed = m_tla.getPassedTests(); Assert.assertEquals(passed.size(), expectPassed.length); // doing this index based is probably not the best for (int i = 0; i < expectPassed.length; i++) { Assert.assertEquals(passed.get(i).getName(), expectPassed[i]); } } } testng-testng-6.9.5/src/test/java/test/methodselectors/CommandLineTest.java0000644000175000017500000001262712551235562026424 0ustar eugeneeugenepackage test.methodselectors; import org.testng.Assert; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import test.SimpleBaseTest; import testhelper.OutputDirectoryPatch; import java.util.ArrayList; import java.util.List; public class CommandLineTest extends SimpleBaseTest { private String[] ARG_WITHOUT_CLASSES = new String[]{ "-log", "0", "-d", OutputDirectoryPatch.getOutputDirectory(), "-methodselectors", "", "" }; private String[] ARG_WITH_GROUPS = new String[]{ "-log", "0", "-d", OutputDirectoryPatch.getOutputDirectory(), "-testclass", "test.methodselectors.SampleTest", "-methodselectors", "", "-groups", "" }; private String[] ARG_WITHOUT_GROUPS = new String[]{ "-log", "0", "-d", OutputDirectoryPatch.getOutputDirectory(), "-testclass", "test.methodselectors.SampleTest", "-methodselectors", "", }; private TestListenerAdapter tla; @BeforeMethod public void setup() { ppp("setup()"); tla = new TestListenerAdapter(); } @Test public void commandLineNegativePriorityAllGroups() { ppp("commandLineNegativePriorityAllGroups()"); ARG_WITHOUT_GROUPS[7] = "test.methodselectors.AllTestsMethodSelector:-1"; TestNG.privateMain(ARG_WITHOUT_GROUPS, tla); String[] passed = { "test1", "test2", "test3" }; String[] failed = { }; verifyTests("Passed", passed, tla.getPassedTests()); verifyTests("Failed", failed, tla.getFailedTests()); } @Test public void commandLineNegativePriorityGroup2() { ppp("commandLineNegativePriorityGroup2()"); ARG_WITHOUT_GROUPS[7] = "test.methodselectors.Test2MethodSelector:-1"; TestNG.privateMain(ARG_WITHOUT_GROUPS, tla); String[] passed = { "test2" }; String[] failed = { }; verifyTests("Passed", passed, tla.getPassedTests()); verifyTests("Failed", failed, tla.getFailedTests()); } @Test public void commandLineLessThanPriorityTest1Test() { ppp("commandLineLessThanPriorityTest1Test()"); ARG_WITH_GROUPS[7] = "test.methodselectors.Test2MethodSelector:5"; ARG_WITH_GROUPS[9] = "test1"; TestNG.privateMain(ARG_WITH_GROUPS, tla); String[] passed = { "test1", "test2" }; String[] failed = { }; verifyTests("Passed", passed, tla.getPassedTests()); verifyTests("Failed", failed, tla.getFailedTests()); } @Test public void commandLineGreaterThanPriorityTest1Test2() { ppp("commandLineGreaterThanPriorityTest1Test2()"); ARG_WITH_GROUPS[7] = "test.methodselectors.Test2MethodSelector:15"; ARG_WITH_GROUPS[9] = "test1"; TestNG.privateMain(ARG_WITH_GROUPS, tla); String[] passed = { "test2" }; String[] failed = { }; verifyTests("Passed", passed, tla.getPassedTests()); verifyTests("Failed", failed, tla.getFailedTests()); } @Test public void commandLineLessThanPriorityAllTests() { ppp("commandLineLessThanPriorityAllTests()"); ARG_WITH_GROUPS[7] = "test.methodselectors.AllTestsMethodSelector:5"; ARG_WITH_GROUPS[9] = "test1"; TestNG.privateMain(ARG_WITH_GROUPS, tla); String[] passed = { "test1", "test2", "test3" }; String[] failed = { }; verifyTests("Passed", passed, tla.getPassedTests()); verifyTests("Failed", failed, tla.getFailedTests()); } @Test public void commandLineMultipleSelectors() { ppp("commandLineMultipleSelectors()"); ARG_WITH_GROUPS[7] = "test.methodselectors.NoTestSelector:7,test.methodselectors.Test2MethodSelector:5"; ARG_WITH_GROUPS[9] = "test1"; TestNG.privateMain(ARG_WITH_GROUPS, tla); String[] passed = { "test1", "test2" }; String[] failed = { }; verifyTests("Passed", passed, tla.getPassedTests()); verifyTests("Failed", failed, tla.getFailedTests()); } @Test public void commandLineNoTest1Selector() { ppp("commandLineNoTest1Selector()"); ARG_WITHOUT_GROUPS[7] = "test.methodselectors.NoTest1MethodSelector:5"; TestNG.privateMain(ARG_WITHOUT_GROUPS, tla); String[] passed = { "test2", "test3" }; String[] failed = { }; verifyTests("Passed", passed, tla.getPassedTests()); verifyTests("Failed", failed, tla.getFailedTests()); } @Test public void commandLineTestWithXmlFile() { ppp("commandLineTestWithXmlFile()"); ARG_WITHOUT_CLASSES[5] = "test.methodselectors.NoTest1MethodSelector:5"; ARG_WITHOUT_CLASSES[6] = getPathToResource("testng-methodselectors.xml"); TestNG.privateMain(ARG_WITHOUT_CLASSES, tla); String[] passed = { "test2", "test3" }; String[] failed = { }; verifyTests("Passed", passed, tla.getPassedTests()); verifyTests("Failed", failed, tla.getFailedTests()); } private void verifyTests(String title, String[] expected, List found) { List resultMethods = new ArrayList<>(); for( ITestResult result : found ) { resultMethods.add( result.getName() ); } Assert.assertEquals(resultMethods.size(), expected.length, "wrong number of " + title + " tests"); for(String e : expected) { Assert.assertTrue(resultMethods.contains(e), "Expected to find method " + e + " in " + title + " but didn't find it."); } } public static void ppp(String s) { //System.out.println("[CommandLineTest] " + s); } } testng-testng-6.9.5/src/test/java/test/methodselectors/BeanShellTest.java0000644000175000017500000000112612551235562026063 0ustar eugeneeugenepackage test.methodselectors; import org.testng.annotations.Test; import test.BaseTest; public class BeanShellTest extends BaseTest { @Test public void onlyGroup1() { addClass("test.methodselectors.SampleTest"); setBeanShellExpression("groups.\n containsKey \t (\"test1\")"); run(); String[] passed = { "test1", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } public static void ppp(String s) { System.out.println("[MethodSelectorTest] " + s); } } testng-testng-6.9.5/src/test/java/test/methodselectors/AllTestsMethodSelector.java0000644000175000017500000000131512551235562027763 0ustar eugeneeugenepackage test.methodselectors; import org.testng.IMethodSelector; import org.testng.IMethodSelectorContext; import org.testng.ITestNGMethod; import java.util.List; public class AllTestsMethodSelector implements IMethodSelector { /** * */ private static final long serialVersionUID = 8059117082807260868L; @Override public boolean includeMethod(IMethodSelectorContext context, ITestNGMethod method, boolean isTestMethod) { context.setStopped(true); return true; } private static void ppp(String s) { System.out.println("[MyMethodSelector] " + s); } @Override public void setTestMethods(List testMethods) { // TODO Auto-generated method stub } } testng-testng-6.9.5/src/test/java/test/methods/0000755000175000017500000000000012551235562020762 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/methods/VerifyMethod1.java0000644000175000017500000000061412551235562024314 0ustar eugeneeugenepackage test.methods; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; /** * This class verifies that the correct methods were run * * @author cbeust */ @Test(dependsOnGroups = { "sample1" }) public class VerifyMethod1 { @BeforeSuite public void init() { SampleMethod1.reset(); } @Test public void verify() { SampleMethod1.verify(); } } testng-testng-6.9.5/src/test/java/test/methods/SampleMethod1.java0000644000175000017500000000175512551235562024300 0ustar eugeneeugenepackage test.methods; import org.testng.annotations.Test; /** * This class is used to test invocation of methods * * @author cbeust */ public class SampleMethod1 { private static boolean m_ok1 = false; private static boolean m_ok2 = false; private static boolean m_ok3 = true; private static boolean m_ok4 = true; public static void reset() { m_ok1 = false; m_ok2 = false; m_ok3 = true; m_ok4 = true; } @Test(groups = { "sample1" }) public void shouldRun1() { m_ok1 = true; } @Test(groups = { "sample1" }) public void shouldRun2() { m_ok2 = true; } @Test public void shouldNotRun1() { m_ok3 = false; } @Test public void shouldNotRun2() { m_ok4 = false; } public static void verify() { assert m_ok1 && m_ok2 && m_ok3 && m_ok4 : "All booleans should be true: " + m_ok1 + " " + m_ok2 + " " + m_ok3 + " " + m_ok4; } static private void ppp(String s) { System.out.println("[SampleMethod1] " + s); } } testng-testng-6.9.5/src/test/java/test/methodinterceptors/0000755000175000017500000000000012551235562023241 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/methodinterceptors/multipleinterceptors/0000755000175000017500000000000012551235562027536 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/methodinterceptors/multipleinterceptors/ThirdInterceptor.java0000644000175000017500000000027012551235562033671 0ustar eugeneeugenepackage test.methodinterceptors.multipleinterceptors; public class ThirdInterceptor extends MethodNameFilterInterceptor { public ThirdInterceptor() { super("c"); } } ././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootroottestng-testng-6.9.5/src/test/java/test/methodinterceptors/multipleinterceptors/SecondInterceptor.javatestng-testng-6.9.5/src/test/java/test/methodinterceptors/multipleinterceptors/SecondInterceptor.jav0000644000175000017500000000027212551235562033673 0ustar eugeneeugenepackage test.methodinterceptors.multipleinterceptors; public class SecondInterceptor extends MethodNameFilterInterceptor { public SecondInterceptor() { super("b"); } } ././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootroottestng-testng-6.9.5/src/test/java/test/methodinterceptors/multipleinterceptors/MultipleInterceptorsTest.javatestng-testng-6.9.5/src/test/java/test/methodinterceptors/multipleinterceptors/MultipleInterceptorsT0000644000175000017500000000246212551235562034006 0ustar eugeneeugenepackage test.methodinterceptors.multipleinterceptors; import java.util.Collections; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class MultipleInterceptorsTest extends SimpleBaseTest { @Test public void testMultipleInterceptors(){ TestNG tng = create(FooTest.class); tng.setMethodInterceptor(new FirstInterceptor()); tng.setMethodInterceptor(new SecondInterceptor()); tng.setMethodInterceptor(new ThirdInterceptor()); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 1); Assert.assertEquals(tla.getPassedTests().get(0).getName(), "d"); } @Test public void testMultipleInterceptorsWithPreserveOrder() { TestNG tng = create(); tng.setTestSuites(Collections.singletonList( getPathToResource("/methodinterceptors/multipleinterceptors/multiple-interceptors.xml"))); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); // Interceptor are called twice => GITHUB #154 Assert.assertEquals(tla.getPassedTests().get(0).getMethod().getDescription(), "abcabc"); } } ././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootroottestng-testng-6.9.5/src/test/java/test/methodinterceptors/multipleinterceptors/MethodNameFilterInterceptor.javatestng-testng-6.9.5/src/test/java/test/methodinterceptors/multipleinterceptors/MethodNameFilterInter0000644000175000017500000000215712551235562033657 0ustar eugeneeugenepackage test.methodinterceptors.multipleinterceptors; import org.testng.IMethodInstance; import org.testng.IMethodInterceptor; import org.testng.ITestContext; import org.testng.ITestNGMethod; import java.util.ArrayList; import java.util.List; public abstract class MethodNameFilterInterceptor implements IMethodInterceptor { private final String methodName; protected MethodNameFilterInterceptor(String methodName) { this.methodName = methodName; } @Override public List intercept(List methods, ITestContext context) { List result = new ArrayList<>(); for (IMethodInstance methodInstance : methods) { ITestNGMethod method = methodInstance.getMethod(); String name = method.getMethodName(); if (!name.equals(methodName)) { result.add(methodInstance); String currentDescription = method.getDescription(); if (currentDescription == null) { method.setDescription(methodName); } else { method.setDescription(currentDescription + methodName); } } } return result; } } testng-testng-6.9.5/src/test/java/test/methodinterceptors/multipleinterceptors/FooTest.java0000644000175000017500000000037112551235562031765 0ustar eugeneeugenepackage test.methodinterceptors.multipleinterceptors; import org.testng.annotations.Test; public class FooTest { @Test public void a() { } @Test public void b() { } @Test public void c() { } @Test public void d() { } } testng-testng-6.9.5/src/test/java/test/methodinterceptors/multipleinterceptors/FirstInterceptor.java0000644000175000017500000000027012551235562033706 0ustar eugeneeugenepackage test.methodinterceptors.multipleinterceptors; public class FirstInterceptor extends MethodNameFilterInterceptor { public FirstInterceptor() { super("a"); } } testng-testng-6.9.5/src/test/java/test/methodinterceptors/RemoveAMethodInterceptor.java0000644000175000017500000000275012551235562031026 0ustar eugeneeugenepackage test.methodinterceptors; import org.testng.IMethodInstance; import org.testng.IMethodInterceptor; import org.testng.ITestContext; import java.util.ArrayList; import java.util.List; /** * An interceptor that removes the method called "two". */ public class RemoveAMethodInterceptor implements IMethodInterceptor { @Override public List intercept(List methods, ITestContext context) { List result = new ArrayList<>(); for (IMethodInstance method : methods) { String name = method.getMethod().getMethodName(); if (!name.equals("two")) { result.add(method); } } log(this, methods, result); return result; } public static void log(IMethodInterceptor listener, List input, List output) { StringBuilder msg = new StringBuilder().append(listener.getClass().getName()) .append(" - Input:").append(getMethodNames(input)).append(" ").append(input.size()) .append(" methods.").append(" Output:").append(getMethodNames(output)).append(" ") .append(output.size()).append(" methods"); log(msg.toString()); } public static List getMethodNames(List methods) { List names = new ArrayList<>(); for (IMethodInstance m : methods) { names.add(m.getMethod().getMethodName()); } return names; } private static void log(String s) { // System.out.println("[MI2] " + s); } }testng-testng-6.9.5/src/test/java/test/methodinterceptors/NullMethodInterceptor.java0000644000175000017500000000062312551235562030377 0ustar eugeneeugenepackage test.methodinterceptors; import org.testng.IMethodInstance; import org.testng.IMethodInterceptor; import org.testng.ITestContext; import java.util.ArrayList; import java.util.List; public class NullMethodInterceptor implements IMethodInterceptor { @Override public List intercept(List methods, ITestContext context) { return new ArrayList<>(); } } testng-testng-6.9.5/src/test/java/test/methodinterceptors/MethodInterceptorTest.java0000644000175000017500000000627212551235562030412 0ustar eugeneeugenepackage test.methodinterceptors; import org.testng.Assert; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.Parser; import org.testng.xml.XmlSuite; import org.xml.sax.SAXException; import test.SimpleBaseTest; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.List; import javax.xml.parsers.ParserConfigurationException; public class MethodInterceptorTest extends SimpleBaseTest { private String XML = "" + "" + "" + "" + "" + " " + "" + "" + " " + " " + " " + " " + " " + "" + ""; @Test public void noMethodsShouldRun() { TestNG tng = create(); tng.setTestClasses(new Class[] { FooTest.class }); testNullInterceptor(tng); } private void testNullInterceptor(TestNG tng) { tng.setMethodInterceptor(new NullMethodInterceptor()); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 0); Assert.assertEquals(tla.getFailedTests().size(), 0); Assert.assertEquals(tla.getSkippedTests().size(), 0); } private void testFast(boolean useInterceptor) { TestNG tng = create(); tng.setTestClasses(new Class[] { FooTest.class }); if (useInterceptor) { tng.setMethodInterceptor(new FastTestsFirstInterceptor()); } TestListenerAdapter tla = new TestListenerAdapter(); // tng.setParallel("methods"); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 3); ITestResult first = tla.getPassedTests().get(0); String method = "zzzfast"; if (useInterceptor) { Assert.assertEquals(first.getMethod().getMethodName(), method); } else { Assert.assertNotSame(first.getMethod().getMethodName(), method); } } @Test public void fastShouldRunFirst() { testFast(true /* use interceptor */); } @Test public void fastShouldNotRunFirst() { testFast(false /* don't use interceptor */); } @Test public void nullMethodInterceptorWorksInTestngXml() throws IOException, ParserConfigurationException, SAXException { File f = File.createTempFile("testng-tests-", ""); f.deleteOnExit(); BufferedWriter bw = new BufferedWriter(new FileWriter(f)); bw.write(XML); bw.close(); try { List xmlSuites = new Parser(f.getAbsolutePath()).parseToList(); TestNG tng = create(); tng.setXmlSuites(xmlSuites); testNullInterceptor(tng); } catch(Exception ex) { ex.printStackTrace(); } } @Test(timeOut = 1000) public void shouldNotLockUpWithInterceptorThatRemovesMethods() { TestNG tng = create(LockUpInterceptorSampleTest.class); tng.setParallel("methods"); tng.run(); } } testng-testng-6.9.5/src/test/java/test/methodinterceptors/LockUpInterceptorSampleTest.java0000644000175000017500000000075112551235562031525 0ustar eugeneeugenepackage test.methodinterceptors; import org.testng.annotations.Listeners; import org.testng.annotations.Test; @Listeners({RemoveAMethodInterceptor.class}) public class LockUpInterceptorSampleTest { @Test public void one() { log("one"); } @Test public void two() { log("two"); } @Test public void three() { log("three"); } private static void log(String s) { // System.out.println("[MITest] " + s); } }testng-testng-6.9.5/src/test/java/test/methodinterceptors/Issue521Test.java0000644000175000017500000000245612551235562026273 0ustar eugeneeugenepackage 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 Issue521Test extends SimpleBaseTest { @Test(description = "test for https://github.com/cbeust/testng/issues/521") public void BeforeClass_method_should_be_fired_when_IMethodInterceptor_removes_test_methods() { TestNG tng = create(Issue521.class); tng.setMethodInterceptor(new IMethodInterceptor() { @Override public List intercept(List methods, ITestContext context) { List 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("beforeClass", "test2"); } } testng-testng-6.9.5/src/test/java/test/methodinterceptors/Issue521.java0000644000175000017500000000040012551235562025416 0ustar eugeneeugenepackage test.methodinterceptors; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class Issue521 { @BeforeClass public void beforeClass() {} @Test public void test1() {} @Test public void test2() {} } testng-testng-6.9.5/src/test/java/test/methodinterceptors/Issue392Test.java0000644000175000017500000000245412551235562026277 0ustar eugeneeugenepackage 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 intercept(List methods, ITestContext context) { List 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"); } } testng-testng-6.9.5/src/test/java/test/methodinterceptors/Issue392.java0000644000175000017500000000037512551235562025437 0ustar eugeneeugenepackage 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() {} } testng-testng-6.9.5/src/test/java/test/methodinterceptors/FooTest.java0000644000175000017500000000032412551235562025466 0ustar eugeneeugenepackage test.methodinterceptors; import org.testng.annotations.Test; public class FooTest { @Test(groups = "fast") public void zzzfast() {} @Test public void slow() {} @Test public void a() {} } testng-testng-6.9.5/src/test/java/test/methodinterceptors/FastTestsFirstInterceptor.java0000644000175000017500000000160112551235562031251 0ustar eugeneeugenepackage test.methodinterceptors; import org.testng.IMethodInstance; import org.testng.IMethodInterceptor; import org.testng.ITestContext; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class FastTestsFirstInterceptor implements IMethodInterceptor { @Override public List intercept(List methods, ITestContext context) { List result = new ArrayList<>(); for (IMethodInstance m : methods) { Test test = m.getMethod().getMethod().getAnnotation(Test.class); Set groups = new HashSet<>(); for (String group : test.groups()) { groups.add(group); } if (groups.contains("fast")) { result.add(0, m); } else { result.add(m); } } return result; } } testng-testng-6.9.5/src/test/java/test/mannotation/0000755000175000017500000000000012551235562021646 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/mannotation/MTest3.java0000644000175000017500000000136512551235562023635 0ustar eugeneeugenepackage test.mannotation; import org.testng.annotations.Configuration; import org.testng.annotations.Test; @Test(groups = "child-class-test3", dependsOnGroups = "dog1", dependsOnMethods = "dom1") public class MTest3 extends MBase { @Test(groups = "method-test3") public void groups1() {} @Test public void groups2() {} @Test(dependsOnGroups = "dog2") public void dependsOnGroups1() {} @Test public void dependsOnGroups2() {} @Test(dependsOnMethods = "dom2") public void dependsOnMethods1() {} @Test public void dependsOnMethods2() {} @Test(enabled = false) public void enabled1() {} @Test public void enabled2() {} @Configuration(beforeSuite = true, groups = "method-test3") public void beforeSuite() { } } testng-testng-6.9.5/src/test/java/test/mannotation/MTest2.java0000644000175000017500000000016212551235562023626 0ustar eugeneeugenepackage test.mannotation; import org.testng.annotations.Test; @Test(alwaysRun = false) public class MTest2 { } testng-testng-6.9.5/src/test/java/test/mannotation/MTest1.java0000644000175000017500000000563312551235562023635 0ustar eugeneeugenepackage test.mannotation; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterGroups; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterSuite; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; import org.testng.annotations.Configuration; import org.testng.annotations.DataProvider; import org.testng.annotations.ExpectedExceptions; import org.testng.annotations.Factory; import org.testng.annotations.Parameters; import org.testng.annotations.Test; @Test(enabled = true, groups = {"group1", "group2"}, alwaysRun = true, parameters = {"param1", "param2"}, dependsOnGroups = {"dg1", "dg2"}, dependsOnMethods = {"dm1", "dm2"}, timeOut = 42, invocationCount = 43, successPercentage = 44, threadPoolSize = 3, dataProvider = "dp", description = "Class level description") public class MTest1 { @Test(enabled = true, groups = {"group5", "group6"}, alwaysRun = true, parameters = {"param5", "param6"}, dependsOnGroups = {"dg5", "dg6"}, dependsOnMethods = {"dm5", "dm6"}, timeOut = 242, invocationCount = 243, successPercentage = 62, dataProvider = "dp3", description = "Constructor description", expectedExceptions = NumberFormatException.class) public MTest1() {} @Test(enabled = true, groups = {"group3", "group4"}, alwaysRun = true, parameters = {"param3", "param4"}, dependsOnGroups = {"dg3", "dg4"}, dependsOnMethods = {"dm3", "dm4"}, timeOut = 142, invocationCount = 143, successPercentage = 61, dataProvider = "dp2", description = "Method description", expectedExceptions = NullPointerException.class) public void f() {} @Configuration(beforeSuite = true, beforeTestMethod = true, beforeTest = true, beforeTestClass = true, beforeGroups = { "b1", "b2"}) public void before() {} @Configuration(afterSuite = true, afterTestMethod = true, afterTest = true, afterTestClass = true, afterGroups = {"a1", "a2"}) public void after() {} @Configuration(parameters = {"oparam1", "oparam2"}, enabled = false, groups = {"ogroup1", "ogroup2"}, dependsOnGroups = {"odg1","odg2"}, dependsOnMethods = {"odm1", "odm2"}, alwaysRun = true, inheritGroups = false, description = "beforeSuite description") @DataProvider(name = "dp4") @ExpectedExceptions({MTest1.class, MTest2.class }) public void otherConfigurations() {} @Factory(parameters = {"pf1", "pf2"}) public void factory() {} @Parameters({"pp1", "pp2", "pp3"}) public void parameters() {} @BeforeSuite @BeforeTest @BeforeGroups @BeforeClass @BeforeMethod public void newBefore() {} @AfterSuite @AfterTest @AfterGroups @AfterClass @AfterMethod public void newAfter() {} } testng-testng-6.9.5/src/test/java/test/mannotation/MChildCaptureTest.java0000644000175000017500000000025212551235562026034 0ustar eugeneeugenepackage test.mannotation; import org.testng.annotations.Test; @Test(groups = "child") public class MChildCaptureTest extends MBaseCapture { public void f() { } } testng-testng-6.9.5/src/test/java/test/mannotation/MBaseCapture.java0000644000175000017500000000053512551235562025027 0ustar eugeneeugenepackage test.mannotation; import org.testng.annotations.Test; /** * Make sure that if a method is declared in the base class and a child class * adds a class-scoped group to it, that method receives it as well. * * @author cbeust * @date Mar 22, 2006 */ public class MBaseCapture { @Test public void shouldBelongToGroupChild() { } } testng-testng-6.9.5/src/test/java/test/mannotation/MBase.java0000644000175000017500000000032512551235562023500 0ustar eugeneeugenepackage test.mannotation; import org.testng.annotations.Test; @Test(groups = "base-class", dependsOnGroups="dog3", dependsOnMethods="dom3", enabled=true) public class MBase { public void baseTest() {} } testng-testng-6.9.5/src/test/java/test/mannotation/MAnnotationSampleTest.java0000644000175000017500000002745512551235562026757 0ustar eugeneeugenepackage test.mannotation; import org.testng.Assert; import org.testng.annotations.Configuration; import org.testng.annotations.IConfigurationAnnotation; import org.testng.annotations.IDataProviderAnnotation; import org.testng.annotations.IExpectedExceptionsAnnotation; import org.testng.annotations.IFactoryAnnotation; import org.testng.annotations.IParametersAnnotation; import org.testng.annotations.ITestAnnotation; import org.testng.annotations.Test; import org.testng.internal.IConfiguration; import org.testng.internal.annotations.IAfterSuite; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.internal.annotations.IBeforeSuite; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @Test(enabled = true) public class MAnnotationSampleTest { private IConfiguration m_configuration = new org.testng.internal.Configuration(); private IAnnotationFinder m_finder; @Configuration(beforeTestClass = true, enabled = true) public void init() { m_finder = m_configuration.getAnnotationFinder(); } public void verifyTestClassLevel() { // // Tests on MTest1SampleTest // ITestAnnotation test1 = (ITestAnnotation) m_finder.findAnnotation(MTest1.class, ITestAnnotation.class); Assert.assertTrue(test1.getEnabled()); Assert.assertEquals(test1.getGroups(), new String[] { "group1", "group2" }); Assert.assertTrue(test1.getAlwaysRun()); Assert.assertEquals(test1.getParameters(), new String[] { "param1", "param2" }); Assert.assertEqualsNoOrder(test1.getDependsOnGroups(), new String[] { "dg1", "dg2" }, "depends on groups"); Assert.assertEqualsNoOrder( test1.getDependsOnMethods(), new String[] { "dm1", "dm2" }); Assert.assertEquals(test1.getTimeOut(), 42); Assert.assertEquals(test1.getInvocationCount(), 43); Assert.assertEquals(test1.getSuccessPercentage(), 44); Assert.assertEquals(test1.getThreadPoolSize(), 3); Assert.assertEquals(test1.getDataProvider(), "dp"); Assert.assertEquals(test1.getDescription(), "Class level description"); // // Tests on MTest1SampleTest (test defaults) // ITestAnnotation test2 = (ITestAnnotation) m_finder.findAnnotation(MTest2.class, ITestAnnotation.class); // test default for enabled Assert.assertTrue(test2.getEnabled()); Assert.assertFalse(test2.getAlwaysRun()); Assert.assertEquals(test2.getTimeOut(), 0); Assert.assertEquals(test2.getInvocationCount(), 1); Assert.assertEquals(test2.getSuccessPercentage(), 100); Assert.assertEquals(test2.getDataProvider(), ""); } public void verifyTestMethodLevel() throws SecurityException, NoSuchMethodException { // // Tests on MTest1SampleTest // Method method = MTest1.class.getMethod("f", new Class[0]); ITestAnnotation test1 = (ITestAnnotation) m_finder.findAnnotation(method, ITestAnnotation.class); Assert.assertTrue(test1.getEnabled()); Assert.assertEqualsNoOrder(test1.getGroups(), new String[] { "group1", "group3", "group4", "group2" }); Assert.assertTrue(test1.getAlwaysRun()); Assert.assertEquals(test1.getParameters(), new String[] { "param3", "param4" }); Assert.assertEqualsNoOrder(test1.getDependsOnGroups(), new String[] { "dg1", "dg2", "dg3", "dg4" }); Assert.assertEqualsNoOrder(test1.getDependsOnMethods(), new String[] { "dm1", "dm2", "dm3", "dm4" }); Assert.assertEquals(test1.getTimeOut(), 142); Assert.assertEquals(test1.getInvocationCount(), 143); Assert.assertEquals(test1.getSuccessPercentage(), 61); Assert.assertEquals(test1.getDataProvider(), "dp2"); Assert.assertEquals(test1.getDescription(), "Method description"); Class[] exceptions = test1.getExpectedExceptions(); Assert.assertEquals(exceptions.length, 1); Assert.assertEquals(exceptions[0], NullPointerException.class); } public void verifyTestConstructorLevel() throws SecurityException, NoSuchMethodException { // // Tests on MTest1SampleTest // Constructor constructor = MTest1.class.getConstructor(new Class[0]); ITestAnnotation test1 = (ITestAnnotation) m_finder.findAnnotation(constructor, ITestAnnotation.class); Assert.assertNotNull(test1); Assert.assertTrue(test1.getEnabled()); Assert.assertEqualsNoOrder(test1.getGroups(), new String[] { "group5", "group1", "group6", "group2" }); Assert.assertTrue(test1.getAlwaysRun()); Assert.assertEquals(test1.getParameters(), new String[] { "param5", "param6" }); Assert.assertEqualsNoOrder(test1.getDependsOnGroups(), new String[] { "dg1", "dg2", "dg5", "dg6" }); Assert.assertEqualsNoOrder(test1.getDependsOnMethods(), new String[] { "dm1", "dm2", "dm5", "dm6" }); Assert.assertEquals(test1.getTimeOut(), 242); Assert.assertEquals(test1.getInvocationCount(), 243); Assert.assertEquals(test1.getSuccessPercentage(), 62); Assert.assertEquals(test1.getDataProvider(), "dp3"); Assert.assertEquals(test1.getDescription(), "Constructor description"); Class[] exceptions = test1.getExpectedExceptions(); Assert.assertEquals(exceptions.length, 1); Assert.assertEquals(exceptions[0], NumberFormatException.class); } public void verifyConfigurationBefore() throws SecurityException, NoSuchMethodException { Method method = MTest1.class.getMethod("before", new Class[0]); IConfigurationAnnotation configuration = (IConfigurationAnnotation) m_finder.findAnnotation(method, IConfigurationAnnotation.class); Assert.assertNotNull(configuration); Assert.assertTrue(configuration.getBeforeSuite()); Assert.assertTrue(configuration.getBeforeTestMethod()); Assert.assertTrue(configuration.getBeforeTest()); Assert.assertTrue(configuration.getBeforeTestClass()); Assert.assertFalse(configuration.getAfterSuite()); Assert.assertFalse(configuration.getAfterTestMethod()); Assert.assertFalse(configuration.getAfterTest()); Assert.assertFalse(configuration.getAfterTestClass()); Assert.assertEquals(0, configuration.getAfterGroups().length); String[] bg = configuration.getBeforeGroups(); Assert.assertEquals(bg.length, 2); Assert.assertEqualsNoOrder(bg, new String[] {"b1", "b2"}); // Default values Assert.assertTrue(configuration.getEnabled()); Assert.assertTrue(configuration.getInheritGroups()); Assert.assertFalse(configuration.getAlwaysRun()); } public void verifyConfigurationAfter() throws SecurityException, NoSuchMethodException { Method method = MTest1.class.getMethod("after", new Class[0]); IConfigurationAnnotation configuration = (IConfigurationAnnotation) m_finder.findAnnotation(method, IConfigurationAnnotation.class); Assert.assertNotNull(configuration); Assert.assertFalse(configuration.getBeforeSuite()); Assert.assertFalse(configuration.getBeforeTestMethod()); Assert.assertFalse(configuration.getBeforeTest()); Assert.assertFalse(configuration.getBeforeTestClass()); Assert.assertTrue(configuration.getAfterSuite()); Assert.assertTrue(configuration.getAfterTestMethod()); Assert.assertTrue(configuration.getAfterTest()); Assert.assertTrue(configuration.getAfterTestClass()); Assert.assertEquals(0, configuration.getBeforeGroups().length); String[] ag = configuration.getAfterGroups(); Assert.assertEquals(ag.length, 2); Assert.assertEqualsNoOrder(ag, new String[] {"a1", "a2"}); // Default values Assert.assertTrue(configuration.getEnabled()); Assert.assertTrue(configuration.getInheritGroups()); Assert.assertFalse(configuration.getAlwaysRun()); } public void verifyConfigurationOthers() throws SecurityException, NoSuchMethodException { Method method = MTest1.class.getMethod("otherConfigurations", new Class[0]); IConfigurationAnnotation configuration = (IConfigurationAnnotation) m_finder.findAnnotation(method, IConfigurationAnnotation.class); Assert.assertNotNull(configuration); Assert.assertFalse(configuration.getBeforeSuite()); Assert.assertFalse(configuration.getBeforeTestMethod()); Assert.assertFalse(configuration.getBeforeTest()); Assert.assertFalse(configuration.getBeforeTestClass()); Assert.assertFalse(configuration.getAfterSuite()); Assert.assertFalse(configuration.getAfterTestMethod()); Assert.assertFalse(configuration.getAfterTest()); Assert.assertFalse(configuration.getAfterTestClass()); Assert.assertFalse(configuration.getEnabled()); Assert.assertEquals(configuration.getParameters(), new String[] { "oparam1", "oparam2" }); Assert.assertEqualsNoOrder(configuration.getGroups(), new String[] { "group1", "ogroup1", "ogroup2", "group2" }, "groups"); Assert.assertEqualsNoOrder(configuration.getDependsOnGroups(), new String[] { "odg1", "odg2" }, "depends on groups"); Assert.assertEqualsNoOrder(configuration.getDependsOnMethods(), new String[] { "odm1", "odm2" }, "depends on methods"); Assert.assertFalse(configuration.getInheritGroups()); Assert.assertTrue(configuration.getAlwaysRun()); Assert.assertEquals(configuration.getDescription(), "beforeSuite description"); } public void verifyDataProvider() throws SecurityException, NoSuchMethodException { Method method = MTest1.class.getMethod("otherConfigurations", new Class[0]); IDataProviderAnnotation dataProvider = (IDataProviderAnnotation) m_finder.findAnnotation(method, IDataProviderAnnotation.class); Assert.assertNotNull(dataProvider); Assert.assertEquals(dataProvider.getName(), "dp4"); } public void verifyExpectedExceptions() throws SecurityException, NoSuchMethodException { Method method = MTest1.class.getMethod("otherConfigurations", new Class[0]); IExpectedExceptionsAnnotation exceptions= (IExpectedExceptionsAnnotation) m_finder.findAnnotation(method, IExpectedExceptionsAnnotation.class); Assert.assertNotNull(exceptions); Assert.assertEquals(exceptions.getValue(), new Class[] { MTest1.class, MTest2.class }); } public void verifyFactory() throws SecurityException, NoSuchMethodException { Method method = MTest1.class.getMethod("factory", new Class[0]); IFactoryAnnotation factory= (IFactoryAnnotation) m_finder.findAnnotation(method, IFactoryAnnotation.class); Assert.assertNotNull(factory); Assert.assertEquals(factory.getParameters(), new String[] { "pf1", "pf2" }); } public void verifyParameters() throws SecurityException, NoSuchMethodException { Method method = MTest1.class.getMethod("parameters", new Class[0]); IParametersAnnotation parameters = (IParametersAnnotation) m_finder.findAnnotation(method, IParametersAnnotation.class); Assert.assertNotNull(parameters); Assert.assertEquals(parameters.getValue(), new String[] { "pp1", "pp2", "pp3" }); } public void verifyNewConfigurationBefore() throws SecurityException, NoSuchMethodException { Method method = MTest1.class.getMethod("newBefore", new Class[0]); IConfigurationAnnotation configuration = (IConfigurationAnnotation) m_finder.findAnnotation(method, IBeforeSuite.class); Assert.assertNotNull(configuration); Assert.assertTrue(configuration.getBeforeSuite()); // Default values Assert.assertTrue(configuration.getEnabled()); Assert.assertTrue(configuration.getInheritGroups()); Assert.assertFalse(configuration.getAlwaysRun()); } public void verifyNewConfigurationAfter() throws SecurityException, NoSuchMethodException { Method method = MTest1.class.getMethod("newAfter", new Class[0]); IConfigurationAnnotation configuration = (IConfigurationAnnotation) m_finder.findAnnotation(method, IAfterSuite.class); Assert.assertNotNull(configuration); Assert.assertTrue(configuration.getAfterSuite()); // Default values Assert.assertTrue(configuration.getEnabled()); Assert.assertTrue(configuration.getInheritGroups()); Assert.assertFalse(configuration.getAlwaysRun()); } private static void ppp(String s) { System.out.println("[MAnnotationSampleTest] " + s); } } testng-testng-6.9.5/src/test/java/test/mannotation/MAnnotation2SampleTest.java0000644000175000017500000001042112551235562027022 0ustar eugeneeugenepackage test.mannotation; import org.testng.Assert; import org.testng.annotations.Configuration; import org.testng.annotations.IConfigurationAnnotation; import org.testng.annotations.ITestAnnotation; import org.testng.annotations.Test; import org.testng.internal.IConfiguration; import org.testng.internal.annotations.IAnnotationFinder; import java.lang.reflect.Method; public class MAnnotation2SampleTest { private IConfiguration m_configuration = new org.testng.internal.Configuration(); private IAnnotationFinder m_finder; @Configuration(beforeTestClass = true, enabled = true, groups="current") public void init() { m_finder = m_configuration.getAnnotationFinder(); } @Test public void verifyTestGroupsInheritance() throws SecurityException, NoSuchMethodException { { Method method = MTest3.class.getMethod("groups1", new Class[0]); ITestAnnotation test1 = (ITestAnnotation) m_finder.findAnnotation(method, ITestAnnotation.class); Assert.assertEqualsNoOrder(new String[] { "method-test3", "child-class-test3", "base-class" }, test1.getGroups()); } { Method method = MTest3.class.getMethod("groups2", new Class[0]); ITestAnnotation test1 = (ITestAnnotation) m_finder.findAnnotation(method, ITestAnnotation.class); Assert.assertEqualsNoOrder(new String[] { "child-class-test3", "base-class" }, test1.getGroups()); } } @Test public void verifyTestDependsOnGroupsInheritance() throws SecurityException, NoSuchMethodException { { Method method = MTest3.class.getMethod("dependsOnGroups1", new Class[0]); ITestAnnotation test1 = (ITestAnnotation) m_finder.findAnnotation(method, ITestAnnotation.class); Assert.assertEqualsNoOrder(new String[] { "dog2", "dog1", "dog3" }, test1.getDependsOnGroups()); } { Method method = MTest3.class.getMethod("dependsOnGroups2", new Class[0]); ITestAnnotation test1 = (ITestAnnotation) m_finder.findAnnotation(method, ITestAnnotation.class); Assert.assertEqualsNoOrder(new String[] { "dog1", "dog3" }, test1.getDependsOnGroups()); } } @Test public void verifyTestDependsOnMethodsInheritance() throws SecurityException, NoSuchMethodException { { Method method = MTest3.class.getMethod("dependsOnMethods1", new Class[0]); ITestAnnotation test1 = (ITestAnnotation) m_finder.findAnnotation(method, ITestAnnotation.class); Assert.assertEqualsNoOrder(new String[] { "dom2", "dom3", "dom1" }, test1.getDependsOnMethods()); } { Method method = MTest3.class.getMethod("dependsOnMethods2", new Class[0]); ITestAnnotation test1 = (ITestAnnotation) m_finder.findAnnotation(method, ITestAnnotation.class); Assert.assertEqualsNoOrder(new String[] { "dom1", "dom3" }, test1.getDependsOnMethods()); } } @Test public void verifyConfigurationGroupsInheritance() throws SecurityException, NoSuchMethodException { Method method = MTest3.class.getMethod("beforeSuite", new Class[0]); IConfigurationAnnotation test1 = (IConfigurationAnnotation) m_finder.findAnnotation(method, IConfigurationAnnotation.class); Assert.assertEqualsNoOrder(new String[] { "method-test3", "child-class-test3", "base-class" }, test1.getGroups()); } @Test(groups="current") public void verifyTestEnabledInheritance() throws SecurityException, NoSuchMethodException { { Method method = MTest3.class.getMethod("enabled1", new Class[0]); ITestAnnotation test1 = (ITestAnnotation) m_finder.findAnnotation(method, ITestAnnotation.class); Assert.assertFalse(test1.getEnabled()); } { Method method = MTest3.class.getMethod("enabled2", new Class[0]); ITestAnnotation test1 = (ITestAnnotation) m_finder.findAnnotation(method, ITestAnnotation.class); Assert.assertTrue(test1.getEnabled()); } } // @Test(groups = "current") // public void verifyCapture() // throws SecurityException, NoSuchMethodException // { // { // Method method = MChildCaptureTest.class.getMethod("shouldBelongToGroupChild", new Class[0]); // ITest test1 = (ITest) m_finder.findAnnotation(method, ITest.class); // Assert.assertEqualsNoOrder(new String[] { "child" }, // test1.getGroups()); // } // } } testng-testng-6.9.5/src/test/java/test/listeners/0000755000175000017500000000000012551235562021327 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/listeners/SuiteListenerSample.java0000644000175000017500000000031712551235562026134 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.Listeners; import org.testng.annotations.Test; @Listeners(SuiteListener.class) public class SuiteListenerSample { @Test public void foo(){} } testng-testng-6.9.5/src/test/java/test/listeners/SuiteListener.java0000644000175000017500000000056312551235562024775 0ustar eugeneeugenepackage test.listeners; import org.testng.ISuite; import org.testng.ISuiteListener; public class SuiteListener implements ISuiteListener { public static boolean start = false; public static boolean finish = false; @Override public void onFinish(ISuite suite) { finish = true; } @Override public void onStart(ISuite suite) { start = true; } } testng-testng-6.9.5/src/test/java/test/listeners/SuiteAndInvokedMethodListenerTest.java0000644000175000017500000000261112551235562030735 0ustar eugeneeugenepackage test.listeners; import org.testng.Assert; import org.testng.IInvokedMethod; import org.testng.IInvokedMethodListener; 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.SuiteAndInvokedMethodListenerTest.MyListener; /** * Make sure that if a listener implements both IInvokedMethodListener * and ISuiteListener, both listeners get invoked. * * @author Cedric Beust */ @Listeners(MyListener.class) public class SuiteAndInvokedMethodListenerTest { public static class MyListener implements IInvokedMethodListener, ISuiteListener { private static boolean m_before = false; private static boolean m_start = false; public MyListener() { } @Override public void beforeInvocation(IInvokedMethod method, ITestResult result) { m_before = true; } @Override public void afterInvocation(IInvokedMethod method, ITestResult result) { } @Override public void onStart(ISuite suite) { m_start = true; } @Override public void onFinish(ISuite suite) { } } @Test public void bothListenersShouldRun() { Assert.assertTrue(MyListener.m_before, "IInvokedMethodListener was not invoked"); Assert.assertTrue(MyListener.m_start, "ISuiteListener was not invoked"); } } testng-testng-6.9.5/src/test/java/test/listeners/SuiteAndConfigurationListenerTest.java0000644000175000017500000000255012551235562031006 0ustar eugeneeugenepackage 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 */ @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:"); } } testng-testng-6.9.5/src/test/java/test/listeners/SimpleListener.java0000644000175000017500000000067012551235562025134 0ustar eugeneeugenepackage test.listeners; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import java.util.List; public class SimpleListener extends TestListenerAdapter { public static List m_list; @Override public void onTestSuccess(ITestResult tr) { m_list.add(3); super.onTestSuccess(tr); } @Override public void onTestFailure(ITestResult tr) { m_list.add(5); super.onTestSuccess(tr); } } testng-testng-6.9.5/src/test/java/test/listeners/ResultListener.java0000644000175000017500000000256012551235562025161 0ustar eugeneeugenepackage test.listeners; import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.internal.IResultListener2; public class ResultListener implements IResultListener2 { public static long m_end = 0; @Override public void onTestStart(ITestResult result) { // TODO Auto-generated method stub } @Override public void beforeConfiguration(ITestResult tr) { } @Override public void onTestSuccess(ITestResult result) { m_end = result.getEndMillis(); } @Override public void onTestFailure(ITestResult result) { // TODO Auto-generated method stub } @Override public void onTestSkipped(ITestResult result) { // TODO Auto-generated method stub } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult result) { // TODO Auto-generated method stub } @Override public void onStart(ITestContext context) { // TODO Auto-generated method stub } @Override public void onFinish(ITestContext context) { // TODO Auto-generated method stub } @Override public void onConfigurationSuccess(ITestResult itr) { // TODO Auto-generated method stub } @Override public void onConfigurationFailure(ITestResult itr) { // TODO Auto-generated method stub } @Override public void onConfigurationSkip(ITestResult itr) { // TODO Auto-generated method stub } } testng-testng-6.9.5/src/test/java/test/listeners/ResultEndMillisTest.java0000644000175000017500000000067012551235562026114 0ustar eugeneeugenepackage test.listeners; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; import test.sample.Sample1; import junit.framework.Assert; public class ResultEndMillisTest extends SimpleBaseTest { @Test public void endMillisShouldBeNonNull() { TestNG tng = create(Sample1.class); tng.addListener(new ResultListener()); tng.run(); Assert.assertTrue(ResultListener.m_end > 0); } } testng-testng-6.9.5/src/test/java/test/listeners/ResultContextTest.java0000644000175000017500000000067412551235562025664 0ustar eugeneeugenepackage test.listeners; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class ResultContextTest extends SimpleBaseTest { @Test public void testResultContext() { TestNG tng = create(ResultContextListenerSample.class); tng.run(); Assert.assertTrue(ResultContextListener.contextProvided, "Test context was not provided to the listener"); } } testng-testng-6.9.5/src/test/java/test/listeners/ResultContextListenerSample.java0000644000175000017500000000033512551235562027666 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.Listeners; import org.testng.annotations.Test; @Listeners(ResultContextListener.class) public class ResultContextListenerSample { @Test public void f() { } } testng-testng-6.9.5/src/test/java/test/listeners/ResultContextListener.java0000644000175000017500000000133312551235562026523 0ustar eugeneeugenepackage test.listeners; import org.testng.ITestContext; import org.testng.ITestListener; import org.testng.ITestResult; public class ResultContextListener implements ITestListener { public static boolean contextProvided = false; public void onTestStart(ITestResult result) { ITestContext context = result.getTestContext(); if (context != null) { contextProvided = true; } } public void onTestSuccess(ITestResult result) { } public void onTestFailure(ITestResult result) { } public void onTestSkipped(ITestResult result) { } public void onTestFailedButWithinSuccessPercentage(ITestResult result) { } public void onStart(ITestContext context) { } public void onFinish(ITestContext context) { } } testng-testng-6.9.5/src/test/java/test/listeners/OrderedListenerSampleTest.java0000644000175000017500000000103112551235562027261 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Listeners; import org.testng.annotations.Test; import test.SimpleBaseTest; @Listeners(SimpleListener.class) public class OrderedListenerSampleTest extends SimpleBaseTest { @BeforeMethod public void bm() { SimpleListener.m_list.add(1); } @Test public void f() { SimpleListener.m_list.add(2); } @AfterMethod public void am() { SimpleListener.m_list.add(4); } } testng-testng-6.9.5/src/test/java/test/listeners/ListenerTest.java0000644000175000017500000000364112551235562024623 0ustar eugeneeugenepackage test.listeners; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.testng.collections.Lists; import test.SimpleBaseTest; import java.util.Arrays; public class ListenerTest extends SimpleBaseTest { @BeforeMethod public void bm() { SimpleListener.m_list = Lists.newArrayList(); } @Test(description = "Ensure that if a listener is present, we get test(), onSuccess()," + " afterMethod()") public void listenerShouldBeCalledBeforeConfiguration() { TestNG tng = create(OrderedListenerSampleTest.class); tng.run(); Assert.assertEquals(SimpleListener.m_list, Arrays.asList(1, 2, 3, 4)); } @Test(description = "TESTNG-400: onTestFailure should be called before @AfterMethod") public void failureBeforeAfterMethod() { TestNG tng = create(FailingSampleTest.class); tng.run(); Assert.assertEquals( SimpleListener.m_list, Arrays.asList(4, 5, 6)); } @Test(description = "Inherited @Listeners annotations should aggregate") public void aggregateListeners() { TestNG tng = create(AggregateSampleTest.class); AggregateSampleTest.m_count = 0; tng.run(); Assert.assertEquals(AggregateSampleTest.m_count, 2); } @Test(description = "Should attach only one instance of the same @Listener class per test") public void shouldAttachOnlyOneInstanceOfTheSameListenerClassPerTest() { TestNG tng = create(new Class [] {Derived1.class, Derived2.class}); BaseWithListener.m_count = 0; tng.run(); Assert.assertEquals(BaseWithListener.m_count, 2); } @Test(description = "@Listeners with an ISuiteListener") public void suiteListenersShouldWork() { TestNG tng = create(SuiteListenerSample.class); SuiteListener.start = false; SuiteListener.finish = false; tng.run(); Assert.assertTrue(SuiteListener.start); Assert.assertTrue(SuiteListener.finish); } } testng-testng-6.9.5/src/test/java/test/listeners/ListenerInXmlTest.java0000644000175000017500000000105612551235562025571 0ustar eugeneeugenepackage test.listeners; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; import java.util.Arrays; public class ListenerInXmlTest extends SimpleBaseTest { @Test(description = "Make sure that listeners defined in testng.xml are invoked") public void listenerInXmlShouldBeInvoked() { TestNG tng = create(); tng.setTestSuites(Arrays.asList(getPathToResource("listener-in-xml.xml"))); LListener.invoked = false; tng.run(); Assert.assertTrue(LListener.invoked); } } testng-testng-6.9.5/src/test/java/test/listeners/LSampleTest.java0000644000175000017500000000017512551235562024372 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.Test; public class LSampleTest { @Test public void dummy() {} } testng-testng-6.9.5/src/test/java/test/listeners/LListener.java0000644000175000017500000000070112551235562024071 0ustar eugeneeugenepackage test.listeners; import org.testng.IInvokedMethod; import org.testng.IInvokedMethodListener; import org.testng.ITestResult; public class LListener implements IInvokedMethodListener { public static boolean invoked = false; @Override public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { invoked = true; } @Override public void afterInvocation(IInvokedMethod method, ITestResult testResult) { } } testng-testng-6.9.5/src/test/java/test/listeners/L3.java0000644000175000017500000000036712551235562022456 0ustar eugeneeugenepackage test.listeners; import org.testng.ITestResult; import org.testng.TestListenerAdapter; public class L3 extends TestListenerAdapter { @Override public void onTestStart(ITestResult result) { BaseWithListener.incrementCount(); } } testng-testng-6.9.5/src/test/java/test/listeners/L2.java0000644000175000017500000000010212551235562022440 0ustar eugeneeugenepackage test.listeners; public class L2 extends BaseListener { } testng-testng-6.9.5/src/test/java/test/listeners/L1.java0000644000175000017500000000010212551235562022437 0ustar eugeneeugenepackage test.listeners; public class L1 extends BaseListener { } testng-testng-6.9.5/src/test/java/test/listeners/FailingSampleTest.java0000644000175000017500000000060712551235562025550 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.AfterMethod; import org.testng.annotations.Listeners; import org.testng.annotations.Test; @Listeners(SimpleListener.class) public class FailingSampleTest { @AfterMethod public void am() { SimpleListener.m_list.add(6); } @Test public void a1() { SimpleListener.m_list.add(4); throw new RuntimeException(); } } testng-testng-6.9.5/src/test/java/test/listeners/ExecutionListenerTest.java0000644000175000017500000000332612551235562026507 0ustar eugeneeugenepackage test.listeners; import org.testng.Assert; import org.testng.IExecutionListener; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; import java.util.Arrays; public class ExecutionListenerTest extends SimpleBaseTest { public static class ExecutionListener implements IExecutionListener { public static boolean m_start = false; public static boolean m_finish = false; @Override public void onExecutionStart() { m_start = true; } @Override public void onExecutionFinish() { m_finish = true; } } @Test public void executionListenerWithXml() { runTest(ExecutionListener1SampleTest.class, true /* add listener */, true /* should run */); } @Test public void executionListenerWithoutListener() { runTest(ExecutionListener1SampleTest.class, false /* don't add listener */, false /* should not run */); } @Test public void executionListenerAnnotation() { runTest(ExecutionListener2SampleTest.class, false /* don't add listener */, true /* should run */); } private void runTest(Class listenerClass, boolean addListener, boolean expected) { XmlSuite s = createXmlSuite("ExecutionListener"); XmlTest t = createXmlTest(s, "Test", listenerClass.getName()); if (addListener) { s.addListener(ExecutionListener.class.getName()); } TestNG tng = create(); tng.setXmlSuites(Arrays.asList(s)); ExecutionListener.m_start = false; ExecutionListener.m_finish = false; tng.run(); Assert.assertEquals(ExecutionListener.m_start, expected); Assert.assertEquals(ExecutionListener.m_finish, expected); } } testng-testng-6.9.5/src/test/java/test/listeners/ExecutionListener2SampleTest.java0000644000175000017500000000035512551235562027732 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.Listeners; import org.testng.annotations.Test; @Listeners(ExecutionListenerTest.ExecutionListener.class) public class ExecutionListener2SampleTest { @Test public void f() {} } testng-testng-6.9.5/src/test/java/test/listeners/ExecutionListener1SampleTest.java0000644000175000017500000000021312551235562027722 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.Test; public class ExecutionListener1SampleTest { @Test public void f() {} } testng-testng-6.9.5/src/test/java/test/listeners/EndMillisShouldNotBeZeroTest.java0000644000175000017500000000226612551235562027667 0ustar eugeneeugenepackage test.listeners; import org.testng.IInvokedMethod; import org.testng.IInvokedMethodListener; import org.testng.ITestResult; import org.testng.annotations.BeforeClass; import org.testng.annotations.Listeners; import org.testng.annotations.Test; import test.listeners.EndMillisShouldNotBeZeroTest.MyInvokedMethodListener; import junit.framework.Assert; @Listeners(MyInvokedMethodListener.class) public class EndMillisShouldNotBeZeroTest { private static long m_end; public static class MyInvokedMethodListener implements IInvokedMethodListener { @Override public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { } @Override public void afterInvocation(IInvokedMethod method, ITestResult testResult) { m_end = testResult.getEndMillis(); } } @BeforeClass public void bm() { m_end = 0; } @Test public void f1() { try { Thread.sleep(1); } catch (InterruptedException handled) { Thread.currentThread().interrupt(); } } @Test(description = "Make sure that ITestResult#getEndMillis is properly set", dependsOnMethods = "f1") public void f2() { Assert.assertTrue(m_end > 0); } } testng-testng-6.9.5/src/test/java/test/listeners/Derived2.java0000644000175000017500000000021212551235562023631 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.Test; class Derived2 extends BaseWithListener { @Test public void s() { } } testng-testng-6.9.5/src/test/java/test/listeners/Derived1.java0000644000175000017500000000021212551235562023630 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.Test; class Derived1 extends BaseWithListener { @Test public void t() { } } testng-testng-6.9.5/src/test/java/test/listeners/ConfigurationListenerTest.java0000644000175000017500000000251212551235562027347 0ustar eugeneeugenepackage test.listeners; import org.testng.Assert; import org.testng.IConfigurationListener2; import org.testng.ITestResult; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class ConfigurationListenerTest extends SimpleBaseTest { static public class CL implements IConfigurationListener2 { private static int m_status = 0; @Override public void beforeConfiguration(ITestResult tr) { m_status += 1; } @Override public void onConfigurationSuccess(ITestResult itr) { m_status += 3; } @Override public void onConfigurationFailure(ITestResult itr) { m_status += 5; } @Override public void onConfigurationSkip(ITestResult itr) { m_status += 7; } } private void runTest(Class cls, int expected) { TestNG tng = create(cls); CL listener = new CL(); CL.m_status = 0; tng.addListener(listener); tng.run(); Assert.assertEquals(CL.m_status, expected); } @Test public void shouldSucceed() { runTest(ConfigurationListenerSucceedSampleTest.class, 1 + 3); } @Test public void shouldFail() { runTest(ConfigurationListenerFailSampleTest.class, 1 + 5); } @Test public void shouldSkip() { runTest(ConfigurationListenerSkipSampleTest.class, 1 + 5 + 7); // fail + skip } } testng-testng-6.9.5/src/test/java/test/listeners/ConfigurationListenerSucceedSampleTest.java0000644000175000017500000000036712551235562032013 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class ConfigurationListenerSucceedSampleTest { @BeforeMethod public void bmShouldSucceed() {} @Test public void f() { } } testng-testng-6.9.5/src/test/java/test/listeners/ConfigurationListenerSkipSampleTest.java0000644000175000017500000000054312551235562031342 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class ConfigurationListenerSkipSampleTest { @BeforeMethod public void bmShouldFail() { throw new RuntimeException(); } @BeforeMethod(dependsOnMethods = "bmShouldFail") public void bm() { } @Test public void f() { } } testng-testng-6.9.5/src/test/java/test/listeners/ConfigurationListenerFailSampleTest.java0000644000175000017500000000042612551235562031307 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class ConfigurationListenerFailSampleTest { @BeforeMethod public void bmShouldFail() { throw new RuntimeException(); } @Test public void f() { } } testng-testng-6.9.5/src/test/java/test/listeners/BaseWithListener.java0000644000175000017500000000032112551235562025402 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.Listeners; @Listeners(value = L3.class) class BaseWithListener { static int m_count = 0; public static void incrementCount() { m_count++; } } testng-testng-6.9.5/src/test/java/test/listeners/BaseListener.java0000644000175000017500000000130112551235562024545 0ustar eugeneeugenepackage test.listeners; import org.testng.ITestContext; import org.testng.ITestListener; import org.testng.ITestResult; public class BaseListener implements ITestListener { @Override public void onTestStart(ITestResult result) { AggregateSampleTest.incrementCount(); } @Override public void onTestSuccess(ITestResult result) { } @Override public void onTestFailure(ITestResult result) { } @Override public void onTestSkipped(ITestResult result) { } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult result) { } @Override public void onStart(ITestContext context) { } @Override public void onFinish(ITestContext context) { } } testng-testng-6.9.5/src/test/java/test/listeners/BaseAggregate.java0000644000175000017500000000017012551235562024651 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.Listeners; @Listeners(L1.class) public class BaseAggregate { } testng-testng-6.9.5/src/test/java/test/listeners/AggregateSampleTest.java0000644000175000017500000000045512551235562026066 0ustar eugeneeugenepackage test.listeners; import org.testng.annotations.Listeners; import org.testng.annotations.Test; @Listeners(L2.class) public class AggregateSampleTest extends BaseAggregate { static int m_count = 0; static public void incrementCount() { m_count++; } @Test public void f() { } } testng-testng-6.9.5/src/test/java/test/justin/0000755000175000017500000000000012551235562020633 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/justin/MonthTest.java0000644000175000017500000000075612551235562023433 0ustar eugeneeugenepackage test.justin; import org.testng.annotations.Test; import java.text.ParseException; /** * Created Jul 10, 2005 * * @author Justin Lee */ public class MonthTest extends BaseTestCase { public MonthTest() { } public MonthTest(String name) { super(name); } @Test(groups = {"bean-tests"}) public void july2005() throws ParseException { } @Test public void weekendDay() throws ParseException { } }testng-testng-6.9.5/src/test/java/test/justin/BaseTestCase.java0000644000175000017500000000200212551235562023776 0ustar eugeneeugenepackage test.justin; import org.testng.annotations.Test; /** * @author Justin Lee Date: Aug 15, 2004 */ @Test public abstract class BaseTestCase { protected static final String TEST_PASSWORD = "testPassword"; public BaseTestCase() { init(); } public BaseTestCase(String name) { this(); } private void init() { setSessionUser(null); } protected void commit() { } protected void tearDown() throws Exception { commit(); } protected Object createCustomer() throws Exception { return null; } protected Object createProject() throws Exception { return null; } protected Object createTimeEntry() throws Exception { return null; } protected Object createUser(String name) throws Exception { return null; } protected Object createUserGroup() throws Exception { return null; } protected void setSessionUser(Object user) { } } testng-testng-6.9.5/src/test/java/test/junit4/0000755000175000017500000000000012551235562020534 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/junit4/JUnit4SampleSuite.java0000644000175000017500000000064312551235562024673 0ustar eugeneeugenepackage test.junit4; import org.junit.runner.RunWith; import org.junit.runners.Suite; /** * * @author lukas */ @RunWith(Suite.class) @Suite.SuiteClasses({ JUnit4Sample1.class, JUnit4Sample2.class }) public class JUnit4SampleSuite { public static final String[] EXPECTED = {"t1", "t2", "t4"}; public static final String[] SKIPPED = {"t3", "ta"}; public static final String[] FAILED = {"tf"}; } testng-testng-6.9.5/src/test/java/test/junit4/JUnit4Sample2.java0000644000175000017500000000115712551235562023744 0ustar eugeneeugenepackage test.junit4; import org.junit.Assert; import org.junit.Assume; import org.junit.Ignore; import org.junit.Test; /** * * @author lukas */ public class JUnit4Sample2 { public static final String[] EXPECTED = {"t2", "t4"}; public static final String[] SKIPPED = {"t3", "ta"}; public static final String[] FAILED = {"tf"}; @Test public void t2() { } @Test @Ignore public void t3() { } @Test public void t4() { } @Test public void tf() { Assert.fail("a test"); } @Test public void ta() { Assume.assumeTrue(false); } } testng-testng-6.9.5/src/test/java/test/junit4/JUnit4Sample1.java0000644000175000017500000000022212551235562023733 0ustar eugeneeugenepackage test.junit4; import org.junit.Test; /** * * @author lukas */ public class JUnit4Sample1 { @Test public void t1() { } } testng-testng-6.9.5/src/test/java/test/junit4/JUnit4ParameterizedTest.java0000644000175000017500000000223412551235562026072 0ustar eugeneeugenepackage 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; @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 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); } } testng-testng-6.9.5/src/test/java/test/junit4/JUnit4Child.java0000644000175000017500000000035112551235562023457 0ustar eugeneeugenepackage test.junit4; import org.junit.runners.Suite; /** * * @author lukas */ @Suite.SuiteClasses({JUnit4Sample1.class}) public class JUnit4Child extends JUnit4SampleSuite { public static final String[] EXPECTED = {"t1"}; } testng-testng-6.9.5/src/test/java/test/junit4/InheritedTest.java0000644000175000017500000000015012551235562024146 0ustar eugeneeugenepackage test.junit4; /** * * @author lukas */ public class InheritedTest extends JUnit4Sample1 { } testng-testng-6.9.5/src/test/java/test/junit/0000755000175000017500000000000012551235562020450 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/junit/testsetup/0000755000175000017500000000000012551235562022510 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/junit/testsetup/TestSuiteContainerWrapper.java0000644000175000017500000000161112551235562030507 0ustar eugeneeugenepackage test.junit.testsetup; import junit.extensions.TestSetup; import junit.framework.TestSuite; public class TestSuiteContainerWrapper extends TestSetup { private static Data INSTANCE = null; private static TestSuite _test = null; private static Class dataImpl = null; public TestSuiteContainerWrapper(TestSuite testSuite, Class dataImpl) { super(testSuite); _test = testSuite; TestSuiteContainerWrapper.dataImpl = dataImpl; } public static Data getData() { return INSTANCE; } @Override protected void setUp() throws Exception { System.out.println("setup"); INSTANCE = (Data) dataImpl.newInstance(); } @Override protected void tearDown() throws Exception { System.out.println("teardown"); INSTANCE = null; System.out.println(_test.countTestCases() + " test cases defined by \"" + _test.getName() + "\" were executed."); } } testng-testng-6.9.5/src/test/java/test/junit/testsetup/SmokeSuite.java0000644000175000017500000000077212551235562025451 0ustar eugeneeugenepackage test.junit.testsetup; import junit.framework.Test; import junit.framework.TestSuite; public class SmokeSuite extends LoggingTestSuite { public static void main( String[] args ) { junit.textui.TestRunner.run( suite() ); } public static Test suite() { TestSuite suite = new TestSuite( "Smoke Test Suite" ); suite.addTest(LayerATestSuite.suite()); return suite; } // public SmokeSuite() // { // this("SmokeSuite"); // } public SmokeSuite( String name ) { super( name ); } } testng-testng-6.9.5/src/test/java/test/junit/testsetup/LoggingTestSuite.java0000644000175000017500000000066312551235562026620 0ustar eugeneeugenepackage test.junit.testsetup; import junit.framework.Test; import junit.framework.TestResult; import junit.framework.TestSuite; public class LoggingTestSuite extends TestSuite { public LoggingTestSuite( String string ) { super( string ); } @Override public void run( TestResult result ) { super.run( result ); } @Override public void runTest( Test test, TestResult result ) { super.runTest( test, result ); } } testng-testng-6.9.5/src/test/java/test/junit/testsetup/LayerATestSuite.java0000644000175000017500000000055612551235562026410 0ustar eugeneeugenepackage test.junit.testsetup; import junit.framework.Test; import junit.framework.TestSuite; public class LayerATestSuite { public static Test suite() { TestSuite suite = new TestSuite( "Layer A Test Suite" ); suite.addTestSuite( ATest.class ); TestSuiteContainerWrapper wrapper = new TestSuiteContainerWrapper(suite, Data.class); return wrapper; } } testng-testng-6.9.5/src/test/java/test/junit/testsetup/Data.java0000644000175000017500000000011012551235562024214 0ustar eugeneeugenepackage test.junit.testsetup; public class Data { public int i = 3; } testng-testng-6.9.5/src/test/java/test/junit/testsetup/ATest.java0000644000175000017500000000036212551235562024374 0ustar eugeneeugenepackage test.junit.testsetup; import junit.framework.TestCase; public class ATest extends TestCase { public void testIt() { System.out.println("A.testIt()"); Data d = TestSuiteContainerWrapper.getData(); assertEquals(3,d.i); } } testng-testng-6.9.5/src/test/java/test/junit/TestAf.java0000644000175000017500000000020012551235562022471 0ustar eugeneeugenepackage test.junit; import junit.framework.TestCase; public class TestAf extends TestCase { public void testAf1() { } } testng-testng-6.9.5/src/test/java/test/junit/TestAe.java0000644000175000017500000000020012551235562022470 0ustar eugeneeugenepackage test.junit; import junit.framework.TestCase; public class TestAe extends TestCase { public void testAe1() { } } testng-testng-6.9.5/src/test/java/test/junit/TestAd.java0000644000175000017500000000020012551235562022467 0ustar eugeneeugenepackage test.junit; import junit.framework.TestCase; public class TestAd extends TestCase { public void testAd1() { } } testng-testng-6.9.5/src/test/java/test/junit/TestAc.java0000644000175000017500000000020012551235562022466 0ustar eugeneeugenepackage test.junit; import junit.framework.TestCase; public class TestAc extends TestCase { public void testAc1() { } } testng-testng-6.9.5/src/test/java/test/junit/TestAb.java0000644000175000017500000000020012551235562022465 0ustar eugeneeugenepackage test.junit; import junit.framework.TestCase; public class TestAb extends TestCase { public void testAb1() { } } testng-testng-6.9.5/src/test/java/test/junit/TestAa.java0000644000175000017500000000020012551235562022464 0ustar eugeneeugenepackage test.junit; import junit.framework.TestCase; public class TestAa extends TestCase { public void testAa1() { } } testng-testng-6.9.5/src/test/java/test/junit/Suite4.java0000644000175000017500000000043512551235562022472 0ustar eugeneeugenepackage test.junit; import junit.framework.Test; import junit.framework.TestSuite; public class Suite4 { public static Test suite() { TestSuite suite = new TestSuite("Suite4"); suite.addTestSuite(TestAe.class); suite.addTestSuite(TestAf.class); return suite; } } testng-testng-6.9.5/src/test/java/test/junit/Suite3.java0000644000175000017500000000036412551235562022472 0ustar eugeneeugenepackage test.junit; import junit.framework.Test; import junit.framework.TestSuite; public class Suite3 { public static Test suite() { TestSuite suite = new TestSuite("Suite3"); suite.addTest(Suite4.suite()); return suite; } } testng-testng-6.9.5/src/test/java/test/junit/Suite2.java0000644000175000017500000000050012551235562022461 0ustar eugeneeugenepackage test.junit; import junit.framework.Test; import junit.framework.TestSuite; public class Suite2 { public static Test suite() { TestSuite suite = new TestSuite("Suite2"); suite.addTestSuite(TestAc.class); suite.addTestSuite(TestAd.class); suite.addTest(Suite3.suite()); return suite; } } testng-testng-6.9.5/src/test/java/test/junit/Suite1.java0000644000175000017500000000052012551235562022462 0ustar eugeneeugenepackage test.junit; import junit.framework.Test; import junit.framework.TestSuite; public class Suite1 { public Suite1(String s) { // dummy } public static Test suite() { TestSuite suite = new TestSuite("JUnitSuite1"); suite.addTestSuite(TestAa.class); suite.addTestSuite(TestAb.class); return suite; } } testng-testng-6.9.5/src/test/java/test/junit/SetUpExceptionTest.java0000644000175000017500000000107212551235562025072 0ustar eugeneeugenepackage test.junit; import org.testng.annotations.Test; public class SetUpExceptionTest extends test.BaseTest { @Test public void setUpFailingShouldCauseMethodsToBeSkipped() { addClass("test.junit.SetUpExceptionSampleTest"); setJUnit(true); run(); String[] passed = { }; String[] failed = { "setUp" }; String[] skipped = { "testM1", "tearDown" }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Skipped", skipped, getSkippedTests()); verifyTests("Failed", failed, getFailedTests()); } } testng-testng-6.9.5/src/test/java/test/junit/SetUpExceptionSampleTest.java0000644000175000017500000000045712551235562026242 0ustar eugeneeugenepackage test.junit; import junit.framework.TestCase; public class SetUpExceptionSampleTest extends TestCase { @Override protected void setUp() throws Exception { throw new RuntimeException(); } public void testM1() { } @Override protected void tearDown() throws Exception { } }testng-testng-6.9.5/src/test/java/test/junit/SetNameTest.java0000644000175000017500000000131212551235562023504 0ustar eugeneeugenepackage test.junit; import org.testng.Assert; import java.io.Serializable; import junit.framework.TestCase; public class SetNameTest extends TestCase implements Serializable { public static int m_ctorCount = 0; public SetNameTest() { ppp("CTOR"); m_ctorCount++; } @Override public void setName(String name) { ppp("SETNAME " + name); super.setName(name); } public void testFoo() { Assert.assertEquals("testFoo", getName()); ppp("FOO"); } public void testBar() { Assert.assertEquals("testBar", getName()); ppp("BAR"); } private void ppp(String string) { if (false) { System.out.println("[FooBarTest#" + hashCode() + "] " + string); } } }testng-testng-6.9.5/src/test/java/test/junit/MainSuite.java0000644000175000017500000000050312551235562023207 0ustar eugeneeugenepackage test.junit; import junit.framework.Test; import junit.framework.TestSuite; public class MainSuite { public static Test suite() { TestSuite suite = new TestSuite("MainSuite"); suite.addTest(Suite1.suite()); suite.addTest(Suite2.suite()); suite.addTest(Suite3.suite()); return suite; } } testng-testng-6.9.5/src/test/java/test/junit/JUnitEmptyTest.java0000644000175000017500000000051412551235562024223 0ustar eugeneeugenepackage test.junit; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; public class JUnitEmptyTest extends TestCase { public JUnitEmptyTest(String name) { super(name); } public static Test suite() { TestSuite s = new TestSuite(JUnitEmptyTest.class); return s; } }testng-testng-6.9.5/src/test/java/test/junit/JUnitConstructorTest.java0000644000175000017500000000203712551235562025454 0ustar eugeneeugenepackage test.junit; import junit.framework.TestCase; /** * Test that the correct number of constructors is called * * Created on Aug 9, 2005 * @author cbeust */ public class JUnitConstructorTest extends TestCase { private static int m_constructorCount = 0; private static int m_createCount = 0; private static int m_queryCount = 0; public JUnitConstructorTest(/*String string */) { // super(string); // setName(string); ppp("CONSTRUCTING"); m_constructorCount++; } // public void test1() { // ppp("TEST1"); // } // // public void test2() { // ppp("TEST2"); // } public void testCreate() { ppp("TEST_CREATE"); m_createCount++; } public void testQuery() { ppp("TEST_QUERY"); m_queryCount++; } @Override public void tearDown() { assertEquals(3, m_constructorCount); assertTrue((1 == m_createCount && 0 == m_queryCount) || (0 == m_createCount && 1 == m_queryCount)); } private static void ppp(String s) { System.out.println("[JUnitHierarchyTest] " + s); } }testng-testng-6.9.5/src/test/java/test/junit/BaseTest.java0000644000175000017500000000140112551235562023021 0ustar eugeneeugenepackage test.junit; import junit.framework.TestCase; /** * Base JUnit test case to verify TestNG handles * TestCase hierarchies properly. * * @author mperham */ public abstract class BaseTest extends TestCase { private static int setUpInvokeCount = 0; private static int tearDownInvokeCount = 0; public BaseTest(String name) { super(name); } @Override protected void setUp() throws Exception { setUpInvokeCount++; } @Override protected void tearDown() throws Exception { tearDownInvokeCount++; } public abstract void testA(); public abstract void testB(); public static int getSetUpInvokeCount() { return setUpInvokeCount; } public static int getTearDownInvokeCount() { return tearDownInvokeCount; } } testng-testng-6.9.5/src/test/java/test/jason/0000755000175000017500000000000012551235562020431 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/jason/MainTest.java0000644000175000017500000000142612551235562023023 0ustar eugeneeugenepackage test.jason; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; import java.util.Arrays; public class MainTest extends SimpleBaseTest { @Test public void afterClassShouldRun() { XmlSuite s = createXmlSuite("S"); XmlTest t = createXmlTest(s, "T", Main.class.getName()); XmlClass c = t.getXmlClasses().get(0); c.getIncludedMethods().add(new XmlInclude("test1")); t.setPreserveOrder("true"); TestNG tng = create(); tng.setXmlSuites(Arrays.asList(new XmlSuite[] { s })); Main.m_passed = false; tng.run(); Assert.assertTrue(Main.m_passed); } }testng-testng-6.9.5/src/test/java/test/jason/MainBase.java0000644000175000017500000000031712551235562022754 0ustar eugeneeugenepackage test.jason; import org.testng.annotations.Test; public class MainBase { @Test(description = "This test is never run but prevents AfterClass") public void checkReportsExist() { } } testng-testng-6.9.5/src/test/java/test/jason/Main.java0000644000175000017500000000055612551235562022166 0ustar eugeneeugenepackage test.jason; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; public class Main extends MainBase { public static boolean m_passed = false; @AfterClass public void afterClass() { m_passed = true; } @Test(description = "This test is run") public void test1() throws InterruptedException { } } testng-testng-6.9.5/src/test/java/test/jarpackages/0000755000175000017500000000000012551235562021572 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/jarpackages/tests/0000755000175000017500000000000012551235562022734 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/jarpackages/tests/B.java0000644000175000017500000000016712551235562023764 0ustar eugeneeugenepackage test.jarpackages.tests; import org.testng.annotations.Test; public class B { @Test public void g() {} } testng-testng-6.9.5/src/test/java/test/jarpackages/tests/A.java0000644000175000017500000000016712551235562023763 0ustar eugeneeugenepackage test.jarpackages.tests; import org.testng.annotations.Test; public class A { @Test public void f() {} } testng-testng-6.9.5/src/test/java/test/jarpackages/testng.xml0000644000175000017500000000037012551235562023620 0ustar eugeneeugene testng-testng-6.9.5/src/test/java/test/jarpackages/JarPackagesTest.java0000644000175000017500000000313712551235562025454 0ustar eugeneeugenepackage test.jarpackages; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; import java.io.File; public class JarPackagesTest extends SimpleBaseTest { private TestListenerAdapter init(String jarFile) { TestNG tng = create(); File currentDir = new File("."); String path = currentDir.getAbsolutePath(); char s = File.separatorChar; path = path + s + "test" + s + "src" + s + "test" + s + "jarpackages" + s; String finalPath = path + jarFile; tng.setTestJar(finalPath); TestListenerAdapter result = new TestListenerAdapter(); tng.addListener(result); tng.run(); return result; } @Test public void jarWithTestngXml() { TestListenerAdapter tla = init("withtestngxml.jar"); Assert.assertEquals(tla.getPassedTests().size(), 2); String first = tla.getPassedTests().get(0).getName(); String second = tla.getPassedTests().get(1).getName(); boolean fThenG = "f".equals(first) && "g".equals(second); boolean gThenF = "g".equals(first) && "f".equals(second); Assert.assertTrue(fThenG || gThenF); } @Test public void jarWithoutTestngXml() { TestListenerAdapter tla = init("withouttestngxml.jar"); Assert.assertEquals(tla.getPassedTests().size(), 2); String first = tla.getPassedTests().get(0).getName(); String second = tla.getPassedTests().get(1).getName(); boolean fThenG = "f".equals(first) && "g".equals(second); boolean gThenF = "g".equals(first) && "f".equals(second); Assert.assertTrue(fThenG || gThenF); } } testng-testng-6.9.5/src/test/java/test/issue107/0000755000175000017500000000000012551235562020677 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/issue107/TestTestngCounter.java0000644000175000017500000000125412551235562025210 0ustar eugeneeugenepackage test.issue107; import org.testng.Assert; import org.testng.annotations.Listeners; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.testng.annotations.Test; @Listeners(MySuiteListener.class) public class TestTestngCounter { public static final String PARAMETER_NAME = "key1"; public static final String EXPECTED_VALUE = "zzz"; @Parameters({PARAMETER_NAME}) @Test public void testParameter(String key) { Assert.assertEquals(key, EXPECTED_VALUE); } @Parameters({PARAMETER_NAME}) @Test public void testParameterAsOptional(@Optional("Unknown") String key) { Assert.assertEquals(key, EXPECTED_VALUE); } } testng-testng-6.9.5/src/test/java/test/issue107/MySuiteListener.java0000644000175000017500000000102512551235562024645 0ustar eugeneeugenepackage test.issue107; import org.testng.ISuite; import org.testng.ISuiteListener; import org.testng.xml.XmlSuite; import java.util.Map; public class MySuiteListener implements ISuiteListener { public void onFinish(ISuite suite) { } public void onStart(ISuite suite) { final XmlSuite xmlSuite = suite.getXmlSuite(); final Map parameters = xmlSuite.getParameters(); parameters.put(TestTestngCounter.PARAMETER_NAME, TestTestngCounter.EXPECTED_VALUE); xmlSuite.setParameters(parameters); } } testng-testng-6.9.5/src/test/java/test/issue107/Issue107Test.java0000644000175000017500000000312512551235562023723 0ustar eugeneeugenepackage test.issue107; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; import java.util.Arrays; import java.util.Map; /** * @author Vladislav.Rassokhin */ public class Issue107Test extends SimpleBaseTest { @Test(description = "GITHUB-107, Check that suite parameters set from listener does not affects tests count") public void testSuiteParameterModificationFromListener() throws Exception { final XmlSuite suite = createXmlSuite("Simple suite"); final Map parameters = suite.getParameters(); parameters.put(TestTestngCounter.PARAMETER_NAME, "some value that must be overriden in listener"); suite.setParameters(parameters); runTest(suite); } @Test(description = "GITHUB-107, Check that suite parameters modification from listener does not affects tests count") public void testSuiteParameterSetFromListener() throws Exception { final XmlSuite suite = createXmlSuite("Simple suite"); runTest(suite); } private void runTest(XmlSuite suite) { final XmlTest test = createXmlTest(suite, "Simple Test", TestTestngCounter.class.getName()); suite.setTests(Arrays.asList(test)); final TestListenerAdapter tla = new TestListenerAdapter(); final TestNG tng = create(); tng.setXmlSuites(Arrays.asList(suite)); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getFailedTests().size(), 0); Assert.assertEquals(tla.getPassedTests().size(), 2); } } testng-testng-6.9.5/src/test/java/test/invokedmethodlistener/0000755000175000017500000000000012551235562023725 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/invokedmethodlistener/Success.java0000644000175000017500000000016712551235562026204 0ustar eugeneeugenepackage test.invokedmethodlistener; public class Success extends Base { public Success() { super(false); } } testng-testng-6.9.5/src/test/java/test/invokedmethodlistener/Sample2.java0000644000175000017500000000163512551235562026100 0ustar eugeneeugenepackage test.invokedmethodlistener; import org.testng.IInvokedMethod; import org.testng.IInvokedMethodListener; import org.testng.ITestResult; import org.testng.annotations.Test; public class Sample2 { @Test(expectedExceptions = IllegalArgumentException.class) public void t1() { throw new IllegalArgumentException("Throw this exception on purpose in test"); } public class Sample2InvokedMethodListener implements IInvokedMethodListener { boolean isSuccess = false; /** * {@inheritDoc} */ @Override public void afterInvocation(IInvokedMethod m, ITestResult tr) { isSuccess = tr.isSuccess(); } /** * {@inheritDoc} */ @Override public void beforeInvocation(IInvokedMethod arg0, ITestResult arg1) { // no need to implement this right now } public boolean isSuccess() { return isSuccess; } } } testng-testng-6.9.5/src/test/java/test/invokedmethodlistener/Sample.java0000644000175000017500000000111012551235562026002 0ustar eugeneeugenepackage test.invokedmethodlistener; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; public class Sample { @Test public void t1() { try { Thread.sleep(100); } catch (InterruptedException handled) { Thread.currentThread().interrupt(); } } @Test public void t2() { try { Thread.sleep(100); } catch (InterruptedException handled) { Thread.currentThread().interrupt(); } } @AfterMethod public void am() {} @BeforeSuite public void bs() {} } testng-testng-6.9.5/src/test/java/test/invokedmethodlistener/MyListener.java0000644000175000017500000000250312551235562026663 0ustar eugeneeugenepackage test.invokedmethodlistener; import org.testng.IInvokedMethod; import org.testng.IInvokedMethodListener; import org.testng.ITestResult; public class MyListener implements IInvokedMethodListener { private int m_beforeCount = 0; private int m_afterCount = 0; private Throwable suiteThrowable; private int suiteStatus = 0; private Throwable methodThrowable; private int methodStatus = 0; @Override public void afterInvocation(IInvokedMethod method, ITestResult testResult) { m_afterCount++; if (method.getTestMethod().isAfterSuiteConfiguration()) { suiteStatus = testResult.getStatus(); suiteThrowable = testResult.getThrowable(); } if (method.getTestMethod().isTest()) { methodStatus = testResult.getStatus(); methodThrowable = testResult.getThrowable(); } } @Override public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { m_beforeCount++; } public int getBeforeCount() { return m_beforeCount; } public int getAfterCount() { return m_afterCount; } public Throwable getSuiteThrowable() { return suiteThrowable; } public int getSuiteStatus() { return suiteStatus; } public Throwable getMethodThrowable() { return methodThrowable; } public int getMethodStatus() { return methodStatus; } } testng-testng-6.9.5/src/test/java/test/invokedmethodlistener/InvokedMethodNameListener.java0000644000175000017500000000305012551235562031635 0ustar eugeneeugenepackage 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 testMethods = new HashSet<>(); final Set configurationMethods = new HashSet<>(); final Set testMethodsFromTM = new HashSet<>(); final Set 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); } } } testng-testng-6.9.5/src/test/java/test/invokedmethodlistener/InvokedMethodListenerTest.java0000644000175000017500000001262512551235562031704 0ustar eugeneeugenepackage 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; import test.SimpleBaseTest; import java.util.List; public class InvokedMethodListenerTest extends SimpleBaseTest { 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); } @Test public void withSuccess() { MyListener l = new MyListener(); 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); Assert.assertEquals(l.getMethodStatus(), ITestResult.FAILURE); Assert.assertTrue(null != l.getMethodThrowable()); Assert.assertTrue(l.getMethodThrowable().getClass() == IllegalArgumentException.class); } /** * Fix for: * 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); InvokedMethodListener listener = new InvokedMethodListener(); tng.addListener(listener); tng.run(); List 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()); 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 afterInvocation method") public void testMethodsWithExpectedExceptionsShouldShowUpAsPass() { TestNG tng = create(Sample2.class); Sample2.Sample2InvokedMethodListener l = new Sample2().new Sample2InvokedMethodListener(); tng.addListener(l); tng.run(); 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 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); } } testng-testng-6.9.5/src/test/java/test/invokedmethodlistener/InvokedMethodListener.java0000644000175000017500000000121212551235562031032 0ustar eugeneeugenepackage test.invokedmethodlistener; import org.testng.IInvokedMethod; import org.testng.IInvokedMethodListener; import org.testng.ITestResult; import org.testng.collections.Lists; import java.util.List; public class InvokedMethodListener implements IInvokedMethodListener { private final List m_methods = Lists.newArrayList(); @Override public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { m_methods.add(method); } @Override public void afterInvocation(IInvokedMethod method, ITestResult testResult) { } public List getInvokedMethods() { return m_methods; } } testng-testng-6.9.5/src/test/java/test/invokedmethodlistener/Failure.java0000644000175000017500000000016612551235562026162 0ustar eugeneeugenepackage test.invokedmethodlistener; public class Failure extends Base { public Failure() { super(true); } } testng-testng-6.9.5/src/test/java/test/invokedmethodlistener/C.java0000644000175000017500000000035212551235562024752 0ustar eugeneeugenepackage test.invokedmethodlistener; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; @Test public class C extends A{ @BeforeSuite public static void someMethod3() {} public void someTest() {} } testng-testng-6.9.5/src/test/java/test/invokedmethodlistener/Base.java0000644000175000017500000000210712551235562025442 0ustar eugeneeugenepackage test.invokedmethodlistener; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterSuite; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class Base { private boolean m_fail; public Base(boolean fail) { m_fail = fail; } @BeforeMethod public void beforeMethod() { } @AfterMethod public void afterMethod() {} @BeforeTest public void beforeTest() {} @AfterTest public void afterTest() {} @BeforeClass public void beforeClass() {} @AfterClass public void afterClass() {} @BeforeSuite public void beforeSuite() {} @AfterSuite public void afterSuite() { if (m_fail) { throw new RuntimeException("After Suite FAILING"); } } @Test public void a() { if (m_fail) { throw new IllegalArgumentException("Test Method FAILING"); } } } testng-testng-6.9.5/src/test/java/test/invokedmethodlistener/B.java0000644000175000017500000000037112551235562024752 0ustar eugeneeugenepackage test.invokedmethodlistener; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; @Test(enabled=false) public class B extends A{ @BeforeSuite public static void someMethod2() {} public void someTest() {} } testng-testng-6.9.5/src/test/java/test/invokedmethodlistener/A.java0000644000175000017500000000025312551235562024750 0ustar eugeneeugenepackage test.invokedmethodlistener; import org.testng.annotations.BeforeSuite; public class A { @BeforeSuite(alwaysRun=false) public static void someMethod1() {} } testng-testng-6.9.5/src/test/java/test/invocationcount/0000755000175000017500000000000012551235562022541 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/invocationcount/InvocationCountTrueTrueTest.java0000644000175000017500000000050512551235562031066 0ustar eugeneeugenepackage test.invocationcount; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; public class InvocationCountTrueTrueTest extends InvocationBase { @BeforeMethod(firstTimeOnly = true) public void beforeMethod() {} @AfterMethod(lastTimeOnly = true) public void afterMethod() {} } testng-testng-6.9.5/src/test/java/test/invocationcount/InvocationCountTrueFalseTest.java0000644000175000017500000000050712551235562031203 0ustar eugeneeugenepackage test.invocationcount; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; public class InvocationCountTrueFalseTest extends InvocationBase { @BeforeMethod(firstTimeOnly = true) public void beforeMethod() {} @AfterMethod(lastTimeOnly = false) public void afterMethod() {} } testng-testng-6.9.5/src/test/java/test/invocationcount/InvocationCountFalseTrueTest.java0000644000175000017500000000050712551235562031203 0ustar eugeneeugenepackage test.invocationcount; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; public class InvocationCountFalseTrueTest extends InvocationBase { @BeforeMethod(firstTimeOnly = false) public void beforeMethod() {} @AfterMethod(lastTimeOnly = true) public void afterMethod() {} } testng-testng-6.9.5/src/test/java/test/invocationcount/InvocationCountFalseFalseTest.java0000644000175000017500000000051112551235562031311 0ustar eugeneeugenepackage test.invocationcount; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; public class InvocationCountFalseFalseTest extends InvocationBase { @BeforeMethod(firstTimeOnly = false) public void beforeMethod() {} @AfterMethod(lastTimeOnly = false) public void afterMethod() {} } testng-testng-6.9.5/src/test/java/test/invocationcount/InvocationBase.java0000644000175000017500000000023112551235562026304 0ustar eugeneeugenepackage test.invocationcount; import org.testng.annotations.Test; public class InvocationBase { @Test(invocationCount = 3) public void f() { } } testng-testng-6.9.5/src/test/java/test/invocationcount/FirstAndLastTimeTest.java0000644000175000017500000000611412551235562027423 0ustar eugeneeugenepackage test.invocationcount; import org.testng.TestNG; import org.testng.annotations.Test; 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 * @AfterMethod(lastTimeOnly = true/false) with invocation counts and data * providers. * @author cbeust@google.com * */ public class FirstAndLastTimeTest extends SimpleBaseTest { @Test public void verifyDataProviderFalseFalse() { List invokedMethodNames = run(DataProviderFalseFalseTest.class); assertThat(invokedMethodNames).containsExactly( "beforeMethod", "f", "afterMethod", "beforeMethod", "f", "afterMethod", "beforeMethod", "f", "afterMethod" ); } @Test public void verifyDataProviderTrueFalse() { List invokedMethodNames = run(DataProviderTrueFalseTest.class); assertThat(invokedMethodNames).containsExactly( "beforeMethod", "f", "afterMethod", "f", "afterMethod", "f", "afterMethod" ); } @Test public void verifyDataProviderFalseTrue() { List invokedMethodNames = run(DataProviderFalseTrueTest.class); assertThat(invokedMethodNames).containsExactly( "beforeMethod", "f", "beforeMethod", "f", "beforeMethod", "f", "afterMethod" ); } @Test public void verifyDataProviderTrueTrue() { List invokedMethodNames = run(DataProviderTrueTrueTest.class); assertThat(invokedMethodNames).containsExactly( "beforeMethod", "f", "f", "f", "afterMethod" ); } @Test public void verifyInvocationCountFalseFalse() { List invokedMethodNames = run(InvocationCountFalseFalseTest.class); assertThat(invokedMethodNames).containsExactly( "beforeMethod", "f", "afterMethod", "beforeMethod", "f", "afterMethod", "beforeMethod", "f", "afterMethod" ); } @Test public void verifyInvocationCountTrueFalse() { List invokedMethodNames = run(InvocationCountTrueFalseTest.class); assertThat(invokedMethodNames).containsExactly( "beforeMethod", "f", "afterMethod", "f", "afterMethod", "f", "afterMethod" ); } @Test public void verifyInvocationCountFalseTrue() { List invokedMethodNames = run(InvocationCountFalseTrueTest.class); assertThat(invokedMethodNames).containsExactly( "beforeMethod", "f", "beforeMethod", "f", "beforeMethod", "f", "afterMethod" ); } @Test public void verifyInvocationCountTrueTrue() { List invokedMethodNames = run(InvocationCountTrueTrueTest.class); assertThat(invokedMethodNames).containsExactly( "beforeMethod", "f", "f", "f", "afterMethod" ); } private static List run(Class cls) { TestNG tng = create(cls); InvokedMethodNameListener listener = new InvokedMethodNameListener(); tng.addListener(listener); tng.run(); return listener.getInvokedMethodNames(); } } testng-testng-6.9.5/src/test/java/test/invocationcount/FailedInvocationCountTest.java0000644000175000017500000000257212551235562030501 0ustar eugeneeugenepackage test.invocationcount; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; public class FailedInvocationCountTest { private void runTest(boolean skip, int passed, int failed, int skipped) { TestNG testng = new TestNG(); testng.setVerbose(0); testng.setSkipFailedInvocationCounts(skip); testng.setTestClasses(new Class[] { FailedInvocationCount.class }); TestListenerAdapter tla = new TestListenerAdapter(); testng.addListener(tla); testng.run(); Assert.assertEquals(tla.getPassedTests().size(), passed); Assert.assertEquals(tla.getFailedTests().size(), failed); Assert.assertEquals(tla.getSkippedTests().size(), skipped); } @Test public void verifyGloballyShouldStop() { runTest(true, 4, 1, 5); } @Test public void verifyGloballyShouldNotStop() { runTest(false, 4, 6, 0); } @Test public void verifyAttributeShouldStop() { TestNG testng = new TestNG(); testng.setVerbose(0); testng.setTestClasses(new Class[] { FailedInvocationCount2.class }); TestListenerAdapter tla = new TestListenerAdapter(); testng.addListener(tla); testng.run(); Assert.assertEquals(tla.getPassedTests().size(), 8); Assert.assertEquals(tla.getFailedTests().size(), 7); Assert.assertEquals(tla.getSkippedTests().size(), 5); } } testng-testng-6.9.5/src/test/java/test/invocationcount/FailedInvocationCount2.java0000644000175000017500000000115112551235562027713 0ustar eugeneeugenepackage test.invocationcount; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class FailedInvocationCount2 { int m_count; int m_count2; @BeforeClass public void setUp() { m_count = 0; m_count2 = 0; } @Test(invocationCount = 10, skipFailedInvocations = true) public void shouldSkipFromAnnotation() { if (m_count++ > 3) { throw new RuntimeException(); } } @Test(invocationCount = 10, skipFailedInvocations = false) public void shouldNotSkipFromAnnotation() { if (m_count2++ > 3) { throw new RuntimeException(); } } } testng-testng-6.9.5/src/test/java/test/invocationcount/FailedInvocationCount.java0000644000175000017500000000053512551235562027636 0ustar eugeneeugenepackage test.invocationcount; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class FailedInvocationCount { int m_count; @BeforeClass public void setUp() { m_count = 0; } @Test(invocationCount = 10) public void f() { if (m_count++ > 3) { throw new RuntimeException(); } } } testng-testng-6.9.5/src/test/java/test/invocationcount/DataProviderTrueTrueTest.java0000644000175000017500000000050512551235562030330 0ustar eugeneeugenepackage test.invocationcount; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; public class DataProviderTrueTrueTest extends DataProviderBase { @BeforeMethod(firstTimeOnly = true) public void beforeMethod() {} @AfterMethod(lastTimeOnly = true) public void afterMethod() {} } testng-testng-6.9.5/src/test/java/test/invocationcount/DataProviderTrueFalseTest.java0000644000175000017500000000050612551235562030444 0ustar eugeneeugenepackage test.invocationcount; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; public class DataProviderTrueFalseTest extends DataProviderBase { @BeforeMethod(firstTimeOnly = true) public void beforeMethod() {} @AfterMethod(lastTimeOnly = false) public void afterMethod() {} } testng-testng-6.9.5/src/test/java/test/invocationcount/DataProviderFalseTrueTest.java0000644000175000017500000000050712551235562030445 0ustar eugeneeugenepackage test.invocationcount; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; public class DataProviderFalseTrueTest extends DataProviderBase { @BeforeMethod(firstTimeOnly = false) public void beforeMethod() {} @AfterMethod(lastTimeOnly = true) public void afterMethod() {} } testng-testng-6.9.5/src/test/java/test/invocationcount/DataProviderFalseFalseTest.java0000644000175000017500000000051012551235562030552 0ustar eugeneeugenepackage test.invocationcount; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; public class DataProviderFalseFalseTest extends DataProviderBase { @BeforeMethod(firstTimeOnly = false) public void beforeMethod() {} @AfterMethod(lastTimeOnly = false) public void afterMethod() {} } testng-testng-6.9.5/src/test/java/test/invocationcount/DataProviderBase.java0000644000175000017500000000057412551235562026571 0ustar eugeneeugenepackage test.invocationcount; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderBase { @Test(dataProvider = "dp") public void f(Integer n) { } @DataProvider public Object[][] dp() { return new Integer[][] { new Integer[] { 0 }, new Integer[] { 1 }, new Integer[] { 2 }, }; } } testng-testng-6.9.5/src/test/java/test/interleavedorder/0000755000175000017500000000000012551235562022655 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/interleavedorder/testng-order.xml0000644000175000017500000000044712551235562026021 0ustar eugeneeugene testng-testng-6.9.5/src/test/java/test/interleavedorder/TestChild2.java0000644000175000017500000000111712551235562025465 0ustar eugeneeugenepackage test.interleavedorder; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; public class TestChild2 extends BaseTestClass { @BeforeClass public void beforeTestChildTwoClass() { ppp("beforeTestChild2Class"); InterleavedInvocationTest.LOG.add("beforeTestChild2Class"); } @AfterClass public void afterTestChildTwoClass() { ppp("afterTestChild2Class"); InterleavedInvocationTest.LOG.add("afterTestChild2Class"); } private void ppp(String s) { if (false) { System.out.println("[TestChild2] " + s); } } } testng-testng-6.9.5/src/test/java/test/interleavedorder/TestChild1.java0000644000175000017500000000111612551235562025463 0ustar eugeneeugenepackage test.interleavedorder; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; public class TestChild1 extends BaseTestClass { @BeforeClass public void beforeTestChildOneClass() { ppp("beforeTestChild1Class"); InterleavedInvocationTest.LOG.add("beforeTestChild1Class"); } @AfterClass public void afterTestChildOneClass() { ppp("afterTestChild1Class"); InterleavedInvocationTest.LOG.add("afterTestChild1Class"); } private void ppp(String s) { if (false) { System.out.println("[TestChild1] " + s); } } } testng-testng-6.9.5/src/test/java/test/interleavedorder/InterleavedInvocationTest.java0000644000175000017500000000322712551235562030660 0ustar eugeneeugenepackage test.interleavedorder; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import test.BaseTest; import testhelper.OutputDirectoryPatch; import java.util.ArrayList; import java.util.List; public class InterleavedInvocationTest extends BaseTest { public static List LOG = new ArrayList<>(); @BeforeTest public void beforeTest() { LOG = new ArrayList<>(); } private void verifyInvocation(int number, List log, int index) { Assert.assertEquals(log.get(index), "beforeTestChild" + number + "Class"); Assert.assertTrue(("test1".equals(log.get(index + 1)) && "test2".equals(LOG.get(index + 2))) || ("test2".equals(LOG.get(index + 1)) && "test1".equals(LOG.get(index + 2))), "test methods were not invoked correctly"); Assert.assertEquals(log.get(index + 3), "afterTestChild" + number + "Class"); } @Test public void invocationOrder() { TestListenerAdapter tla = new TestListenerAdapter(); TestNG testng = new TestNG(); testng.setOutputDirectory(OutputDirectoryPatch.getOutputDirectory()); testng.setTestClasses(new Class[] { TestChild1.class, TestChild2.class }); testng.addListener(tla); testng.setVerbose(0); testng.run(); Assert.assertEquals(LOG.size(), 8, LOG.toString()); int number1 = "beforeTestChild1Class".equals(LOG.get(0)) ? 1 : 2; int number2 = number1 == 1 ? 2 : 1; verifyInvocation(number1, LOG, 0); verifyInvocation(number2, LOG, 4); } public static void ppp(String s) { System.out.println("[InterleavedTest] " + s); } } testng-testng-6.9.5/src/test/java/test/interleavedorder/BaseTestClass.java0000644000175000017500000000065512551235562026226 0ustar eugeneeugenepackage test.interleavedorder; import org.testng.annotations.Test; public class BaseTestClass { @Test public void testOne() { ppp("test1"); InterleavedInvocationTest.LOG.add("test1"); } @Test public void testTwo() { ppp("test2"); InterleavedInvocationTest.LOG.add("test2"); } private void ppp(String s) { if (false) { System.out.println(getClass().toString() + " " + s); } } } testng-testng-6.9.5/src/test/java/test/inject/0000755000175000017500000000000012551235562020573 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/inject/Sample.java0000644000175000017500000000064712551235562022666 0ustar eugeneeugenepackage test.inject; import org.testng.Assert; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.annotations.Test; public class Sample { @Test public void f(ITestContext tc) { Assert.assertNotNull(tc); ITestNGMethod[] allMethods = tc.getAllTestMethods(); Assert.assertEquals(allMethods.length, 1); Assert.assertEquals(allMethods[0].getMethod().getName(),"f"); } } testng-testng-6.9.5/src/test/java/test/inject/NoInjectionTest.java0000644000175000017500000000140412551235562024514 0ustar eugeneeugenepackage test.inject; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.NoInjection; import org.testng.annotations.Test; import java.lang.reflect.Method; /** * Test the @NoInjection annotation. * * @author cbeust */ public class NoInjectionTest { @DataProvider(name = "provider") public Object[][] provide() throws Exception { return new Object[][] { { CC.class.getMethod("f") } }; } @Test(dataProvider = "provider") public void withoutInjection(@NoInjection Method m) { Assert.assertEquals(m.getName(), "f"); } @Test(dataProvider = "provider") public void withInjection(Method m) { Assert.assertEquals(m.getName(), "withInjection"); } } class CC { public void f() { } } testng-testng-6.9.5/src/test/java/test/inject/InjectTestResultTest.java0000644000175000017500000000070112551235562025547 0ustar eugeneeugenepackage test.inject; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class InjectTestResultTest extends SimpleBaseTest { @Test public void verifyTestResultInjection() { TestNG tng = create(InjectBeforeAndAfterMethodsWithTestResultSampleTest.class); tng.run(); Assert.assertEquals(0, InjectBeforeAndAfterMethodsWithTestResultSampleTest.m_success); } } testng-testng-6.9.5/src/test/java/test/inject/InjectTestContextTest.java0000644000175000017500000000167212551235562025725 0ustar eugeneeugenepackage test.inject; import org.testng.Assert; import org.testng.ITestContext; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Parameters; import org.testng.annotations.Test; import org.testng.xml.XmlTest; import test.SimpleBaseTest; public class InjectTestContextTest extends SimpleBaseTest { @Test(enabled = false) public void verifyTestContextInjection(ITestContext tc, XmlTest xmlTest) { TestNG tng = create(); tng.setTestClasses(new Class[] { Sample.class }); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(xmlTest.getName(), "Injection"); Assert.assertEquals(tla.getPassedTests().size(), 1); Assert.assertEquals(tla.getPassedTests().get(0).getMethod().getMethodName(), "f"); } @Parameters("string") @Test(enabled = true) public void injectionAndParameters(String s, ITestContext ctx) { } } testng-testng-6.9.5/src/test/java/test/inject/InjectDataProviderTest.java0000644000175000017500000000252712551235562026025 0ustar eugeneeugenepackage test.inject; import org.testng.ITestContext; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import test.dataprovider.MyIterator; import java.util.Iterator; /** * Test that injection works for data providers. * * @author Cedric Beust, Mar 3, 2010 * */ public class InjectDataProviderTest { @DataProvider public Object[][] dp1() { return new Object[][] { new Object[] { 1, "a" }, new Object[] { 2, "b" }, }; } @Test(dataProvider = "dp1", enabled = true) public void dpObject1(Integer n, ITestContext ctx, String a) { } @Test(dataProvider = "dp1", enabled = true) public void dpObject2(ITestContext ctx, Integer n, String a) { } @Test(dataProvider = "dp1", enabled = true) public void dpObject3(Integer n, String a, ITestContext ctx) { } @DataProvider public Iterator dp2() { return new MyIterator( new Object[][] { new Object[] { 1, "a" }, new Object[] { 2, "b" }, }); } @Test(dataProvider = "dp2", enabled = false) public void dpIterator1(Integer n, ITestContext ctx, String a) { } @Test(dataProvider = "dp2", enabled = false) public void dpIterator2(ITestContext ctx, Integer n, String a) { } @Test(dataProvider = "dp2", enabled = false) public void dpIterator3(Integer n, String a, ITestContext ctx) { } } testng-testng-6.9.5/src/test/java/test/inject/InjectBeforeMethodTest.java0000644000175000017500000000177712551235562026012 0ustar eugeneeugenepackage test.inject; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.lang.reflect.Method; public class InjectBeforeMethodTest { private int m_beforeIndex = 0; private int m_afterIndex = 0; private static final Object[][] DATA = { new Object[] { "a" }, new Object[] { "b" }, }; @BeforeMethod public void before(Object[] parameters) { Assert.assertEquals(DATA[m_beforeIndex], parameters); m_beforeIndex++; } @BeforeMethod public void before2(Object[] parameters, Method m) { } @BeforeMethod public void before3(Method m, Object[] parameters) { } @DataProvider public Object[][] dp() { return DATA; } @AfterMethod public void after(Object[] parameters) { Assert.assertEquals(DATA[m_afterIndex], parameters); m_afterIndex++; } @Test(dataProvider = "dp") public void f(String a) { } } ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootroottestng-testng-6.9.5/src/test/java/test/inject/InjectBeforeAndAfterMethodsWithTestResultSampleTest.javatestng-testng-6.9.5/src/test/java/test/inject/InjectBeforeAndAfterMethodsWithTestResultSampleTest.ja0000644000175000017500000000236212551235562033277 0ustar eugeneeugenepackage test.inject; import org.testng.Assert; import org.testng.ITestResult; import org.testng.SkipException; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.lang.reflect.Method; public class InjectBeforeAndAfterMethodsWithTestResultSampleTest { static int m_success; private ITestResult m_testResult; @Test public void pass() { Assert.assertEquals(m_testResult.getAttribute("before"), 10); } @Test public void fail() { throw new RuntimeException(); } @Test public void skip() { throw new SkipException("Skipped"); } @BeforeClass public void init() { m_success = 3; } @BeforeMethod public void before(Method m, ITestResult r) { m_testResult = r; r.setAttribute("before", 10); } @AfterMethod public void after(Method m, ITestResult r) { String name = m.getName(); Assert.assertEquals(r, m_testResult); if (("pass".equals(name) && r.getStatus() == ITestResult.SUCCESS) || ("fail".equals(name) && r.getStatus() == ITestResult.FAILURE) || ("skip".equals(name) && r.getStatus() == ITestResult.SKIP)) { m_success--; } } } testng-testng-6.9.5/src/test/java/test/inject/InjectAfterMethodWithTestResultTest.java0000644000175000017500000000067412551235562030537 0ustar eugeneeugenepackage test.inject; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class InjectAfterMethodWithTestResultTest extends SimpleBaseTest { @Test public void verifyTestResultInjection() { TestNG tng = create(InjectAfterMethodWithTestResultSampleTest.class); tng.run(); Assert.assertEquals(0, InjectAfterMethodWithTestResultSampleTest.m_success); } } testng-testng-6.9.5/src/test/java/test/inject/InjectAfterMethodWithTestResultSampleTest.java0000644000175000017500000000206212551235562031672 0ustar eugeneeugenepackage test.inject; import org.testng.ITestResult; import org.testng.SkipException; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.lang.reflect.Method; public class InjectAfterMethodWithTestResultSampleTest { static int m_success; @Test public void pass() {} @Test public void fail() { throw new RuntimeException(); } @Test public void skip() { throw new SkipException("Skipped"); } @BeforeClass public void init() { m_success = 3; } @BeforeMethod public void before(Method m, ITestResult r) { System.out.println("Before result: " + r); } @AfterMethod public void after(Method m, ITestResult r) { String name = m.getName(); if (("pass".equals(name) && r.getStatus() == ITestResult.SUCCESS) || ("fail".equals(name) && r.getStatus() == ITestResult.FAILURE) || ("skip".equals(name) && r.getStatus() == ITestResult.SKIP)) { m_success--; } } } testng-testng-6.9.5/src/test/java/test/inheritance/0000755000175000017500000000000012551235562021610 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/inheritance/testng739/0000755000175000017500000000000012551235562023357 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/inheritance/testng739/TestNG739.java0000644000175000017500000000153612551235562025636 0ustar eugeneeugenepackage test.inheritance.testng739; import org.testng.TestNG; import org.testng.annotations.Test; import test.InvokedMethodNameListener; import test.SimpleBaseTest; import static org.assertj.core.api.Assertions.assertThat; public class TestNG739 extends SimpleBaseTest { @Test public void test_classes_should_be_skipped_when_a_before_class_fails() { TestNG tng = create(A.class, B.class); tng.setPreserveOrder(true); InvokedMethodNameListener listener = new InvokedMethodNameListener(); tng.setPreserveOrder(true); tng.addListener(listener); tng.run(); assertThat(listener.getSucceedMethodNames()).containsExactly("beforeBaseClass", "beforeBaseClass", "testB"); assertThat(listener.getFailedMethodNames()).containsExactly("beforeClassA"); assertThat(listener.getSkippedMethodNames()).containsExactly("testA"); } } testng-testng-6.9.5/src/test/java/test/inheritance/testng739/BaseClass.java0000644000175000017500000000023712551235562026064 0ustar eugeneeugenepackage test.inheritance.testng739; import org.testng.annotations.BeforeClass; public class BaseClass { @BeforeClass public void beforeBaseClass() {} } testng-testng-6.9.5/src/test/java/test/inheritance/testng739/B.java0000644000175000017500000000022412551235562024401 0ustar eugeneeugenepackage test.inheritance.testng739; import org.testng.annotations.Test; public class B extends BaseClass { @Test public void testB() { } } testng-testng-6.9.5/src/test/java/test/inheritance/testng739/A.java0000644000175000017500000000043712551235562024406 0ustar eugeneeugenepackage test.inheritance.testng739; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class A extends BaseClass { @BeforeClass public void beforeClassA() { Assert.fail(); } @Test public void testA() { } } testng-testng-6.9.5/src/test/java/test/inheritance/testng471/0000755000175000017500000000000012551235562023350 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/inheritance/testng471/TestNG471.java0000644000175000017500000000301112551235562025606 0ustar eugeneeugenepackage test.inheritance.testng471; import org.testng.TestNG; import org.testng.annotations.Test; import test.InvokedMethodNameListener; import test.SimpleBaseTest; import static org.assertj.core.api.Assertions.assertThat; public class TestNG471 extends SimpleBaseTest { @Test public void test_classes_should_not_be_skipped_when_a_after_method_fails() { TestNG tng = create(Class1.class, Class2.class, Class3.class); tng.setPreserveOrder(true); tng.setVerbose(10); InvokedMethodNameListener listener = new InvokedMethodNameListener(); tng.setPreserveOrder(true); tng.addListener(listener); tng.run(); assertThat(listener.getFailedMethodNames()).containsExactly("afterMethodClass1"); assertThat(listener.getSkippedMethodNames()).containsExactly("test1_2"); assertThat(listener.getSucceedMethodNames()).containsExactly( "beforeSuperClass1", "beforeClass1", "beforeMethodClass1", "test1_1", // "afterMethodClass1" failed // "beforeMethodClass1", "test1_2" and "afterMethodClass1" skipped // "afterClass1" skipped "beforeSuperClass1", "beforeClass2", "beforeMethodClass2", "test2_1", "afterMethodClass2", "beforeMethodClass2", "test2_2", "afterMethodClass2", "afterClass2", "beforeSuperClass2", "beforeClass3", "beforeMethodClass3", "test3_1", "afterMethodClass3", "beforeMethodClass3", "test3_2", "afterMethodClass3", "afterClass3"); } } testng-testng-6.9.5/src/test/java/test/inheritance/testng471/SuperClass2.java0000644000175000017500000000024612551235562026363 0ustar eugeneeugenepackage test.inheritance.testng471; import org.testng.annotations.BeforeClass; public class SuperClass2 { @BeforeClass public void beforeSuperClass2() { } } testng-testng-6.9.5/src/test/java/test/inheritance/testng471/SuperClass1.java0000644000175000017500000000024612551235562026362 0ustar eugeneeugenepackage test.inheritance.testng471; import org.testng.annotations.BeforeClass; public class SuperClass1 { @BeforeClass public void beforeSuperClass1() { } } testng-testng-6.9.5/src/test/java/test/inheritance/testng471/Class3.java0000644000175000017500000000110612551235562025341 0ustar eugeneeugenepackage test.inheritance.testng471; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class Class3 extends SuperClass2 { @BeforeClass public void beforeClass3() { } @AfterClass public void afterClass3() { } @BeforeMethod public void beforeMethodClass3() { } @AfterMethod public void afterMethodClass3() { } @Test public void test3_1() { } @Test public void test3_2() { } } testng-testng-6.9.5/src/test/java/test/inheritance/testng471/Class2.java0000644000175000017500000000062712551235562025347 0ustar eugeneeugenepackage test.inheritance.testng471; import org.testng.annotations.*; public class Class2 extends SuperClass1 { @BeforeClass public void beforeClass2() { } @AfterClass public void afterClass2() { } @BeforeMethod public void beforeMethodClass2() { } @AfterMethod public void afterMethodClass2() { } @Test public void test2_1() { } @Test public void test2_2() { } } testng-testng-6.9.5/src/test/java/test/inheritance/testng471/Class1.java0000644000175000017500000000070312551235562025341 0ustar eugeneeugenepackage test.inheritance.testng471; import org.junit.Assert; import org.testng.annotations.*; public class Class1 extends SuperClass1 { @BeforeClass public void beforeClass1() { } @AfterClass public void afterClass1() { } @BeforeMethod public void beforeMethodClass1() { } @AfterMethod public void afterMethodClass1() { Assert.fail(); } @Test public void test1_1() { } @Test public void test1_2() { } } testng-testng-6.9.5/src/test/java/test/inheritance/testng234/0000755000175000017500000000000012551235562023345 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/inheritance/testng234/PolymorphicFailureTest.java0000644000175000017500000000135212551235562030666 0ustar eugeneeugenepackage test.inheritance.testng234; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; import java.util.Arrays; public class PolymorphicFailureTest extends SimpleBaseTest { @Test public void superclassFailureShouldCauseFailure() { TestNG tng = create(ChildTest.class); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); assertTestResultsEqual(tla.getSkippedTests(), Arrays.asList( "polymorphicMethod", "executePolymorphicMethod") ); Assert.assertEquals(0, tla.getPassedTests().size()); Assert.assertEquals(0, tla.getFailedTests().size()); } } testng-testng-6.9.5/src/test/java/test/inheritance/testng234/ParentTest.java0000644000175000017500000000033012551235562026275 0ustar eugeneeugenepackage test.inheritance.testng234; import org.testng.annotations.Test; public abstract class ParentTest { @Test public void executePolymorphicMethod() { } protected abstract void polymorphicMethod(); } testng-testng-6.9.5/src/test/java/test/inheritance/testng234/ChildTest.java0000644000175000017500000000060412551235562026073 0ustar eugeneeugenepackage test.inheritance.testng234; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class ChildTest extends ParentTest { @BeforeClass public void beforeClassMethod() { Assert.assertTrue(false, "This is so sad... I must skip all my tests ..."); } @Override @Test public void polymorphicMethod() { } } testng-testng-6.9.5/src/test/java/test/inheritance/ZBase_0.java0000644000175000017500000000153412551235562023701 0ustar eugeneeugenepackage test.inheritance; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import java.util.ArrayList; import java.util.List; public class ZBase_0 { protected static boolean m_verbose = false; protected static List m_methodList = new ArrayList<>(); @BeforeTest public void beforeTest() { m_methodList = new ArrayList<>(); } @BeforeMethod public void initApplication() { m_methodList.add("initApplication"); ppp("INIT 0"); } @AfterMethod public void tearDownApplication() { m_methodList.add("tearDownApplication"); ppp("TEAR DOWN 0"); } private static void ppp(String s) { if (m_verbose) { System.out.println("[Z0] " + s); } } public static List getMethodList() { return m_methodList; } } testng-testng-6.9.5/src/test/java/test/inheritance/VerifyTest.java0000644000175000017500000000126512551235562024563 0ustar eugeneeugenepackage test.inheritance; import org.testng.AssertJUnit; import org.testng.annotations.Test; import java.util.List; public class VerifyTest { @Test(dependsOnGroups = {"before"}) public void verify() { String[] expected = { "initApplication", "initDialog", "initDialog2", "test", "tearDownDialog2", "tearDownDialog", "tearDownApplication" }; int i = 0; List l = ZBase_0.getMethodList(); AssertJUnit.assertEquals(expected.length, l.size()); for (String s : l) { AssertJUnit.assertEquals(expected[i++], s); } } private static void ppp(String s) { System.out.println("[VerifyTest] " + s); } } testng-testng-6.9.5/src/test/java/test/inheritance/DChild_2.java0000644000175000017500000000157612551235562024034 0ustar eugeneeugenepackage test.inheritance; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * Make sure that configuration inherited methods are invoked in the right * order. The funny naming is to make sure that the class names do not * play any role in the ordering of methods. * * Created on Sep 8, 2005 * @author cbeust */ public class DChild_2 extends Child_1 { @BeforeMethod public void initDialog2() { m_methodList.add("initDialog2"); ppp(" INIT 2"); } @AfterMethod public void tearDownDialog2() { m_methodList.add("tearDownDialog2"); ppp(" TEAR_DOWN 2"); } @Test(groups = {"before" }) public void test() { m_methodList.add("test"); ppp(" TEST"); } private static void ppp(String s) { if (m_verbose) { System.out.println("[D2] " + s); } } } testng-testng-6.9.5/src/test/java/test/inheritance/ClassScopeTest.java0000644000175000017500000000052312551235562025352 0ustar eugeneeugenepackage test.inheritance; import org.testng.Assert; import org.testng.annotations.Test; public class ClassScopeTest extends BaseClassScope { private boolean m_verify = false; public void setVerify() { m_verify = true; } @Test(dependsOnMethods = "setVerify") public void verify() { Assert.assertTrue(m_verify); } } testng-testng-6.9.5/src/test/java/test/inheritance/Child_1.java0000644000175000017500000000075412551235562023724 0ustar eugeneeugenepackage test.inheritance; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; public class Child_1 extends ZBase_0 { @BeforeMethod public void initDialog() { m_methodList.add("initDialog"); ppp(" INIT 1"); } @AfterMethod public void tearDownDialog() { m_methodList.add("tearDownDialog"); ppp(" TEAR_DOWN 1"); } private static void ppp(String s) { if (m_verbose) { System.out.println("[C1] " + s); } } } testng-testng-6.9.5/src/test/java/test/inheritance/BaseClassScope.java0000644000175000017500000000014612551235562025306 0ustar eugeneeugenepackage test.inheritance; import org.testng.annotations.Test; @Test public class BaseClassScope { } testng-testng-6.9.5/src/test/java/test/hook/0000755000175000017500000000000012551235562020257 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/hook/HookableTest.java0000644000175000017500000000741112551235562023511 0ustar eugeneeugenepackage test.hook; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import test.BaseTest; /** * Because IHookable and IConfigurable are global, it's safer to run them in a * sub-TestNG object, otherwise they will be run for your entire test suite... * * @author cbeust */ public class HookableTest extends BaseTest { @BeforeMethod public void bm() { HookSuccessTest.m_hook = false; HookSuccessTest.m_testWasRun = false; HookSuccessTest.m_parameter = null; HookSuccess599Test.m_hook = false; HookSuccess599Test.m_testWasRun = false; HookSuccess599Test.m_parameter = null; HookFailureTest.m_hook = false; HookFailureTest.m_testWasRun = false; HookListener.m_hook = false; BaseConfigurable.m_hookCount = 0; BaseConfigurable.m_bc = false; BaseConfigurable.m_bm = false; BaseConfigurable.m_bs = false; BaseConfigurable.m_bt = false; BaseConfigurable.m_methodName = null; ConfigurableListener.m_hookCount = 0; ConfigurableListener.m_methodName = null; ConfigurableSuccessWithListenerTest.m_bc = false; ConfigurableSuccessWithListenerTest.m_bm = false; } @Test public void hookSuccess() { addClass(HookSuccessTest.class); run(); verifyTests("Passed", new String[] { "verify" }, getPassedTests()); Assert.assertTrue(HookSuccessTest.m_hook); Assert.assertTrue(HookSuccessTest.m_testWasRun); Assert.assertEquals(HookSuccessTest.m_parameter, "foo"); } @Test(description = "https://github.com/cbeust/testng/issues/599") public void issue599() { addClass(HookSuccess599Test.class); run(); verifyTests("Passed", new String[] { "verify" }, getPassedTests()); Assert.assertTrue(HookSuccess599Test.m_hook); Assert.assertTrue(HookSuccess599Test.m_testWasRun); Assert.assertEquals(HookSuccess599Test.m_parameter, "foo"); } @Test public void hookSuccessWithListener() { addClass(HookSuccessWithListenerTest.class); run(); verifyTests("Passed", new String[] { "verify" }, getPassedTests()); Assert.assertTrue(HookListener.m_hook); } @Test public void hookFailure() { addClass(HookFailureTest.class); run(); // To investigate: TestNG still thinks the test passed since it can't know whether // the hook ended up invoking the test or not. // verifyTests("Passed", new String[] { }, getPassedTests()); Assert.assertTrue(HookFailureTest.m_hook); Assert.assertFalse(HookFailureTest.m_testWasRun); } @Test public void configurableSuccess() { addClass(ConfigurableSuccessTest.class); run(); Assert.assertEquals(BaseConfigurable.m_hookCount, 4); Assert.assertTrue(BaseConfigurable.m_bc); Assert.assertTrue(BaseConfigurable.m_bm); Assert.assertTrue(BaseConfigurable.m_bs); Assert.assertTrue(BaseConfigurable.m_bt); Assert.assertEquals(BaseConfigurable.m_methodName, "hookWasRun"); } @Test public void configurableSuccessWithListener() { addClass(ConfigurableSuccessWithListenerTest.class); run(); Assert.assertEquals(ConfigurableListener.m_hookCount, 4); Assert.assertTrue(ConfigurableSuccessWithListenerTest.m_bs); Assert.assertTrue(ConfigurableSuccessWithListenerTest.m_bt); Assert.assertTrue(ConfigurableSuccessWithListenerTest.m_bc); Assert.assertTrue(ConfigurableSuccessWithListenerTest.m_bm); Assert.assertEquals(ConfigurableListener.m_methodName, "hookWasRun"); } @Test public void configurableFailure() { addClass(ConfigurableFailureTest.class); run(); Assert.assertEquals(BaseConfigurable.m_hookCount, 4); Assert.assertFalse(BaseConfigurable.m_bc); Assert.assertFalse(BaseConfigurable.m_bm); Assert.assertFalse(BaseConfigurable.m_bs); Assert.assertFalse(BaseConfigurable.m_bt); } } testng-testng-6.9.5/src/test/java/test/hook/HookSuccessWithListenerTest.java0000644000175000017500000000043212551235562026554 0ustar eugeneeugenepackage test.hook; import org.testng.Assert; import org.testng.annotations.Listeners; import org.testng.annotations.Test; @Listeners(HookListener.class) public class HookSuccessWithListenerTest { @Test public void verify() { Assert.assertTrue(HookListener.m_hook); } } testng-testng-6.9.5/src/test/java/test/hook/HookSuccessTest.java0000644000175000017500000000237112551235562024216 0ustar eugeneeugenepackage test.hook; import org.testng.IHookCallBack; import org.testng.IHookable; import org.testng.ITestResult; import org.testng.Reporter; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Test harness for {@link IHookable} * * @author Cedric Beust * @since Aug 01, 2006 */ public class HookSuccessTest implements IHookable { static boolean m_hook = false; static boolean m_testWasRun = false; static String m_parameter = null; @Override public void run(IHookCallBack callBack, ITestResult testResult) { m_hook = true; Object[] parameters = callBack.getParameters(); if (parameters.length > 0) { m_parameter = parameters[0].toString(); } callBack.runTestMethod(testResult); } @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { "foo" } }; } @Test(dataProvider = "dp") public void verify(String name) { m_testWasRun = true; Reporter.log("output from hook test.verify"); } // @AfterMethod // public void tearDown() { // Assert.assertTrue(m_hook); // Assert.assertTrue(m_testWasRun); // } private void ppp(String string) { System.out.println("[HookTest] " + string); } } testng-testng-6.9.5/src/test/java/test/hook/HookSuccess599Test.java0000644000175000017500000000206412551235562024464 0ustar eugeneeugenepackage test.hook; import org.testng.IHookCallBack; import org.testng.IHookable; import org.testng.ITestResult; import org.testng.Reporter; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Test harness for {@link IHookable} * * @author Cedric Beust * @since Aug 01, 2006 */ public class HookSuccess599Test implements IHookable { static boolean m_hook = false; static boolean m_testWasRun = false; static String m_parameter = null; @Override public void run(IHookCallBack callBack, ITestResult testResult) { m_hook = true; Object[] parameters = callBack.getParameters(); if (parameters.length > 0) { m_parameter = parameters[0].toString(); } callBack.runTestMethod(testResult); } @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { "foo" } }; } @Test(dataProvider = "dp", timeOut = 100) public void verify(String name) { m_testWasRun = true; Reporter.log("output from hook test.verify"); } } testng-testng-6.9.5/src/test/java/test/hook/HookListener.java0000644000175000017500000000053612551235562023534 0ustar eugeneeugenepackage test.hook; import org.testng.IHookCallBack; import org.testng.IHookable; import org.testng.ITestResult; public class HookListener implements IHookable { public static boolean m_hook = false; @Override public void run(IHookCallBack callBack, ITestResult testResult) { m_hook = true; callBack.runTestMethod(testResult); } } testng-testng-6.9.5/src/test/java/test/hook/HookFailureTest.java0000644000175000017500000000133312551235562024172 0ustar eugeneeugenepackage test.hook; import org.testng.IHookCallBack; import org.testng.IHookable; import org.testng.ITestResult; import org.testng.annotations.Test; public class HookFailureTest implements IHookable { static boolean m_hook = false; static boolean m_testWasRun = false; @Override public void run(IHookCallBack callBack, ITestResult testResult) { m_hook = true; // Not invoking the callback: the method should not be run } @Test public void verify() { m_testWasRun = true; } // @AfterMethod // public void tearDown() { // Assert.assertTrue(m_hook); // Assert.assertFalse(m_testWasRun); // } private void ppp(String string) { System.out.println("[HookFailureTest] " + string); } } testng-testng-6.9.5/src/test/java/test/hook/ConfigurableSuccessWithListenerTest.java0000644000175000017500000000157412551235562030264 0ustar eugeneeugenepackage test.hook; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Listeners; import org.testng.annotations.Test; import java.lang.reflect.Method; @Listeners(ConfigurableListener.class) public class ConfigurableSuccessWithListenerTest { static boolean m_bm = false; static boolean m_bc = false; static boolean m_bt; static boolean m_bs; @BeforeSuite public void bs() { m_bs = true; } @BeforeMethod public void bt() { m_bt = true; } @BeforeMethod public void bm(Method m) { m_bm = true; } @BeforeClass public void bc() { m_bc = true; } @Test public void hookWasRun() { Assert.assertEquals(ConfigurableListener.m_hookCount, 2); Assert.assertTrue(m_bc); Assert.assertTrue(m_bm); } } testng-testng-6.9.5/src/test/java/test/hook/ConfigurableSuccessTest.java0000644000175000017500000000137212551235562025716 0ustar eugeneeugenepackage test.hook; import org.testng.IConfigurable; import org.testng.IConfigureCallBack; import org.testng.ITestResult; import org.testng.annotations.Test; import java.lang.reflect.Method; /** * Test harness for {@link IConfigurable} */ public class ConfigurableSuccessTest extends BaseConfigurable { @Override public void run(IConfigureCallBack callBack, ITestResult testResult) { m_hookCount++; Object[] parameters = callBack.getParameters(); if (parameters.length > 0) { m_methodName = ((Method) parameters[0]).getName(); } callBack.runConfigurationMethod(testResult); } @Test public void hookWasRun() { // Assert.assertEquals(m_hookCount, 2); // Assert.assertTrue(m_bc); // Assert.assertTrue(m_bm); } } testng-testng-6.9.5/src/test/java/test/hook/ConfigurableListener.java0000644000175000017500000000111312551235562025224 0ustar eugeneeugenepackage test.hook; import org.testng.IConfigurable; import org.testng.IConfigureCallBack; import org.testng.ITestResult; import java.lang.reflect.Method; public class ConfigurableListener implements IConfigurable { static int m_hookCount = 0; static String m_methodName; @Override public void run(IConfigureCallBack callBack, ITestResult testResult) { m_hookCount++; Object[] parameters = callBack.getParameters(); if (parameters.length > 0) { m_methodName = ((Method) parameters[0]).getName(); } callBack.runConfigurationMethod(testResult); } } testng-testng-6.9.5/src/test/java/test/hook/ConfigurableFailureTest.java0000644000175000017500000000104312551235562025670 0ustar eugeneeugenepackage test.hook; import org.testng.Assert; import org.testng.IConfigurable; import org.testng.IConfigureCallBack; import org.testng.ITestResult; import org.testng.annotations.Test; /** * Test harness for {@link IConfigurable} */ public class ConfigurableFailureTest extends BaseConfigurable { @Override public void run(IConfigureCallBack callBack, ITestResult testResult) { m_hookCount++; // Not calling the callback } @Test public void hookWasNotRun() { Assert.assertFalse(m_bc); Assert.assertFalse(m_bm); } } testng-testng-6.9.5/src/test/java/test/hook/BaseConfigurable.java0000644000175000017500000000137012551235562024316 0ustar eugeneeugenepackage test.hook; import org.testng.IConfigurable; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; import java.lang.reflect.Method; abstract public class BaseConfigurable implements IConfigurable { static int m_hookCount = 0; static boolean m_bs = false; static boolean m_bt = false; static boolean m_bm = false; static boolean m_bc = false; static String m_methodName = null; @BeforeSuite public void bs() { m_bs = true; } @BeforeTest public void bt() { m_bt = true; } @BeforeMethod public void bm(Method m) { m_bm = true; } @BeforeClass public void bc() { m_bc = true; } } testng-testng-6.9.5/src/test/java/test/guice/0000755000175000017500000000000012551235562020413 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/guice/MySession.java0000644000175000017500000000006112551235562023204 0ustar eugeneeugenepackage test.guice; public class MySession { } testng-testng-6.9.5/src/test/java/test/guice/MyServiceProvider.java0000644000175000017500000000042212551235562024675 0ustar eugeneeugenepackage test.guice; import com.google.inject.Provider; public class MyServiceProvider implements Provider { @Override public MyService get() { return new MyService() { @Override public void serve(MySession mySession) { } }; } } testng-testng-6.9.5/src/test/java/test/guice/MyService.java0000644000175000017500000000013012551235562023156 0ustar eugeneeugenepackage test.guice; public interface MyService { void serve(MySession mySession); } testng-testng-6.9.5/src/test/java/test/guice/MyContextImpl.java0000644000175000017500000000031212551235562024026 0ustar eugeneeugenepackage test.guice; public class MyContextImpl implements MyContext { private final MySession mySession = new MySession(); @Override public MySession getSession() { return mySession; } } testng-testng-6.9.5/src/test/java/test/guice/MyContext.java0000644000175000017500000000011712551235562023207 0ustar eugeneeugenepackage test.guice; public interface MyContext { MySession getSession(); } testng-testng-6.9.5/src/test/java/test/guice/ModuleFactory.java0000644000175000017500000000132412551235562024033 0ustar eugeneeugenepackage test.guice; import com.google.inject.Module; import org.testng.IModuleFactory; import org.testng.ITestContext; public class ModuleFactory implements IModuleFactory { @Override public Module createModule(ITestContext context, Class testClass) { String parameter = context.getCurrentXmlTest().getParameter("inject"); String expected = "guice"; if (! expected.equals(parameter)) { throw new RuntimeException("Excepted parameter to be " + expected + ", got " + parameter); } if (GuiceModuleFactoryTest.class == testClass) { return new GuiceExampleModule(); } else { throw new RuntimeException("Don't know how to create a module for class " + testClass); } } } testng-testng-6.9.5/src/test/java/test/guice/ISingleton.java0000644000175000017500000000011412551235562023325 0ustar eugeneeugenepackage test.guice; public interface ISingleton { void doSomething(); } testng-testng-6.9.5/src/test/java/test/guice/GuiceTestModule.java0000644000175000017500000000060312551235562024317 0ustar eugeneeugenepackage test.guice; import com.google.inject.AbstractModule; import com.google.inject.Inject; public class GuiceTestModule extends AbstractModule { private final MyContext myContext; @Inject GuiceTestModule(MyContext myContext) { this.myContext = myContext; } @Override protected void configure() { bind(MySession.class).toInstance(myContext.getSession()); } } testng-testng-6.9.5/src/test/java/test/guice/GuiceTest.java0000644000175000017500000000125312551235562023153 0ustar eugeneeugenepackage test.guice; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; import junit.framework.Assert; public class GuiceTest extends SimpleBaseTest { @Test public void guiceTest() { TestNG tng = create(new Class[] { Guice1Test.class, Guice2Test.class}); Guice1Test.m_object = null; Guice2Test.m_object = null; tng.run(); Assert.assertNotNull(Guice1Test.m_object); Assert.assertNotNull(Guice2Test.m_object); Assert.assertEquals(Guice1Test.m_object, Guice2Test.m_object); } @Test public void guiceWithNoModules() { TestNG tng = create(new Class[] { GuiceNoModuleTest.class }); tng.run(); } } testng-testng-6.9.5/src/test/java/test/guice/GuiceParentModuleTest.java0000644000175000017500000000124712551235562025476 0ustar eugeneeugenepackage test.guice; import org.testng.Assert; import org.testng.ITestContext; import org.testng.annotations.Guice; import org.testng.annotations.Test; import com.google.inject.Inject; @Test @Guice(modules = GuiceTestModule.class) public class GuiceParentModuleTest { @Inject 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"); } } testng-testng-6.9.5/src/test/java/test/guice/GuiceParentModule.java0000644000175000017500000000110212551235562024624 0ustar eugeneeugenepackage 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); } } testng-testng-6.9.5/src/test/java/test/guice/GuiceNoModuleTest.java0000644000175000017500000000025212551235562024614 0ustar eugeneeugenepackage test.guice; import org.testng.annotations.Guice; import org.testng.annotations.Test; @Guice public class GuiceNoModuleTest { @Test public void f() { } } testng-testng-6.9.5/src/test/java/test/guice/GuiceModuleFactoryTest.java0000644000175000017500000000051412551235562025650 0ustar eugeneeugenepackage test.guice; import com.google.inject.Inject; import org.testng.annotations.Guice; import org.testng.annotations.Test; @Guice(moduleFactory = ModuleFactory.class) public class GuiceModuleFactoryTest { @Inject ISingleton m_singleton; @Test public void singletonShouldWork() { m_singleton.doSomething(); } } testng-testng-6.9.5/src/test/java/test/guice/GuiceInheritanceTest.java0000644000175000017500000000041312551235562025322 0ustar eugeneeugenepackage test.guice; import com.google.inject.Inject; import org.testng.annotations.Test; public class GuiceInheritanceTest extends GuiceBase { @Inject ISingleton m_singleton; @Test public void singletonShouldWork() { m_singleton.doSomething(); } } testng-testng-6.9.5/src/test/java/test/guice/GuiceExampleModule.java0000644000175000017500000000047712551235562025004 0ustar eugeneeugenepackage test.guice; import com.google.inject.Binder; import com.google.inject.Module; import com.google.inject.Singleton; public class GuiceExampleModule implements Module { @Override public void configure(Binder binder) { binder.bind(ISingleton.class).to(ExampleSingleton.class).in(Singleton.class); } } testng-testng-6.9.5/src/test/java/test/guice/GuiceBase.java0000644000175000017500000000020212551235562023077 0ustar eugeneeugenepackage test.guice; import org.testng.annotations.Guice; @Guice(modules = GuiceExampleModule.class) public class GuiceBase { } testng-testng-6.9.5/src/test/java/test/guice/Guice2Test.java0000644000175000017500000000061712551235562023240 0ustar eugeneeugenepackage test.guice; import com.google.inject.Inject; import org.testng.annotations.Guice; import org.testng.annotations.Test; import test.SimpleBaseTest; @Guice(modules = GuiceExampleModule.class) public class Guice2Test extends SimpleBaseTest { static ISingleton m_object; @Inject ISingleton m_singleton; @Test public void singletonShouldWork() { m_object = m_singleton; } } testng-testng-6.9.5/src/test/java/test/guice/Guice1Test.java0000644000175000017500000000065612551235562023242 0ustar eugeneeugenepackage test.guice; import com.google.inject.Inject; import org.testng.annotations.Guice; import org.testng.annotations.Test; import test.SimpleBaseTest; @Guice(modules = GuiceExampleModule.class) public class Guice1Test extends SimpleBaseTest { static ISingleton m_object; @Inject ISingleton m_singleton; @Test public void singletonShouldWork() { m_singleton.doSomething(); m_object = m_singleton; } } testng-testng-6.9.5/src/test/java/test/guice/ExampleSingleton.java0000644000175000017500000000025212551235562024533 0ustar eugeneeugenepackage test.guice; public class ExampleSingleton implements ISingleton { @Override public void doSomething() { // System.out.println("Doing something"); } } testng-testng-6.9.5/src/test/java/test/groupinvocation/0000755000175000017500000000000012551235562022545 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/groupinvocation/testng.xml0000644000175000017500000000156712551235562024604 0ustar eugeneeugene testng-testng-6.9.5/src/test/java/test/groupinvocation/GroupSuiteTest.java0000644000175000017500000000406512551235562026363 0ustar eugeneeugenepackage test.groupinvocation; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; import java.util.Arrays; /** * Test that tags can have groups. */ @Test public class GroupSuiteTest extends SimpleBaseTest { public void includeFromSuite0() { runWithSuite(g(), g(), g("a", "b", "c")); } public void includeFromSuite1() { runWithSuite(g("a"), g(), g("a")); } public void includeFromSuite2() { runWithSuite(g("a", "b"), g(), g("a", "b")); } public void excludeFromSuite1() { runWithSuite(g(), g("a"), g("b", "c")); } public void excludeFromSuite2() { runWithSuite(g(), g("a", "b"), g("c")); } @Test(description = "Include in both suite and test") public void includeTestAndSuite1() { runWithSuite(g("a"), g(), g("b"), g(), g("a", "b")); } @Test(description = "Include in suite, exclude in test") public void excludeTestAndSuite2() { runWithSuite(g(), g("a"), g(), g("a"), g("b", "c")); } private void runWithSuite(String[] suiteGroups, String[] excludedSuiteGroups, String[] methods) { runWithSuite(suiteGroups, excludedSuiteGroups, g(), g(), methods); } private void runWithSuite(String[] suiteGroups, String[] excludedSuiteGroups, String[] testGroups, String[] excludedTestGroups, String[] methods) { XmlSuite s = createXmlSuite("Groups"); s.setIncludedGroups(Arrays.asList(suiteGroups)); s.setExcludedGroups(Arrays.asList(excludedSuiteGroups)); XmlTest t = createXmlTest(s, "Groups-test", GroupSuiteSampleTest.class.getName()); t.setIncludedGroups(Arrays.asList(testGroups)); t.setExcludedGroups(Arrays.asList(excludedTestGroups)); TestListenerAdapter tla = new TestListenerAdapter(); TestNG tng = create(); tng.addListener(tla); tng.setXmlSuites(Arrays.asList(new XmlSuite[] { s })); tng.run(); verifyPassedTests(tla, methods); } private String[] g(String... groups) { return groups; } } testng-testng-6.9.5/src/test/java/test/groupinvocation/GroupSuiteSampleTest.java0000644000175000017500000000034112551235562027516 0ustar eugeneeugenepackage test.groupinvocation; import org.testng.annotations.Test; public class GroupSuiteSampleTest { @Test(groups = "a") public void a() {} @Test(groups = "b") public void b() {} @Test public void c() {} } testng-testng-6.9.5/src/test/java/test/groupinvocation/GroupConfiguration.java0000644000175000017500000000071012551235562027232 0ustar eugeneeugenepackage test.groupinvocation; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; /** * This class/interface */ public class GroupConfiguration { @BeforeGroups(groups={"a"}) public void beforeGroups() { DummyTest.recordInvocation("beforeGroups", hashCode()); } @AfterGroups(groups={"a"}) public void afterGroups() { DummyTest.recordInvocation("afterGroups", hashCode()); } } testng-testng-6.9.5/src/test/java/test/groupinvocation/FailingBeforeGroupMethod.java0000644000175000017500000000046312551235562030265 0ustar eugeneeugenepackage test.groupinvocation; import org.testng.annotations.BeforeGroups; /** * This class/interface */ public class FailingBeforeGroupMethod { @BeforeGroups(groups={"A"}) public void beforeGroupA() { throw new RuntimeException("Failing @BeforeGroups beforeGroupA method"); } } testng-testng-6.9.5/src/test/java/test/groupinvocation/DummyTest2.java0000644000175000017500000000075212551235562025431 0ustar eugeneeugenepackage test.groupinvocation; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; /** * This class/interface */ public class DummyTest2 { private boolean m_invoked= false; @Test(groups={"A"}) public void dummyTest() { m_invoked= true; } @AfterClass(alwaysRun=true) public void checkInvocations() { Assert.assertFalse(m_invoked, "@Test method invoked even if @BeforeGroups failed"); } } testng-testng-6.9.5/src/test/java/test/groupinvocation/DummyTest.java0000644000175000017500000000223312551235562025343 0ustar eugeneeugenepackage test.groupinvocation; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import java.util.HashMap; import java.util.Map; /** * This class/interface */ public class DummyTest { private static Map s_externalClassGroups= new HashMap<>(); @Test(groups={"a"}) public void testA() { } @Test(groups={"b"}) public void testB() { } @Test(groups={"a", "b"}) public void testAB() { } @AfterClass(alwaysRun=true) public void checkInvocations() { Integer hashCode1= s_externalClassGroups.get("beforeGroups"); Assert.assertNotNull(hashCode1, "External @BeforeGroups not invoked"); Integer hashCode2= s_externalClassGroups.get("afterGroups"); Assert.assertNotNull(hashCode2, "External @AfterGroups not invoked"); Assert.assertEquals(hashCode1, hashCode2, "External @BeforeGroups and @AfterGroups were not invoked on the" + " same class instance"); } /** * @param string * @param i */ public static void recordInvocation(String string, int i) { s_externalClassGroups.put(string, i); } } testng-testng-6.9.5/src/test/java/test/groupbug/0000755000175000017500000000000012551235562021151 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/groupbug/ITCaseTwo.java0000644000175000017500000000133712551235562023622 0ustar eugeneeugenepackage test.groupbug; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class ITCaseTwo { @BeforeClass public void beforeClass() { System.out.printf("RUN %s.beforeClass()\n", getClass()); } @AfterClass(alwaysRun = true) public void afterClass() { System.out.printf("RUN %s.afterClass()\n", getClass()); } @Test(groups = "std-two") public void two1() { GroupBugTest.passed.add("two1"); System.out.printf("RUN %s.two1()\n", getClass()); } @Test(groups = "logic-two", dependsOnGroups = "std-two") public void two2() { GroupBugTest.passed.add("two2"); System.out.printf("RUN %s.two2()\n", getClass()); } }testng-testng-6.9.5/src/test/java/test/groupbug/ITCaseOne.java0000644000175000017500000000146312551235562023572 0ustar eugeneeugenepackage test.groupbug; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class ITCaseOne { @BeforeClass public void beforeClass() { System.out.printf("RUN %s.beforeClass()\n", getClass()); } @AfterClass(alwaysRun = true) public void afterClass() { System.out.printf("RUN %s.afterClass()\n", getClass()); } @Test(groups = "std-one") public void one1() { GroupBugTest.passed.add("one1"); System.out.printf("RUN %s.one1()\n", getClass()); } /** * Commenting out dependsOnGroups fixes the ordering, that's the bug. */ @Test(groups = "logic-one", dependsOnGroups = "std-one") public void one2() { GroupBugTest.passed.add("one2"); System.out.printf("RUN %s.one2()\n", getClass()); } }testng-testng-6.9.5/src/test/java/test/groupbug/GroupBugTest.java0000644000175000017500000000126512551235562024412 0ustar eugeneeugenepackage test.groupbug; import org.testng.Assert; import org.testng.annotations.Test; import org.testng.collections.Lists; import test.BaseTest; import java.util.Arrays; import java.util.List; public class GroupBugTest extends BaseTest { static List passed = Lists.newArrayList(); @Test(groups = "broken", description = "Comment out dependsOnGroups in ITCaseOne will fix the ordering, that's the bug") public void shouldOrderByClass() { passed.clear(); addClass(ITCaseOne.class); addClass(ITCaseTwo.class); run(); List expected = Arrays.asList( "one1", "one2", "two1", "two2" ); Assert.assertEquals(passed, expected); } } testng-testng-6.9.5/src/test/java/test/failures/0000755000175000017500000000000012551235562021131 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/failures/FailuresTest.java0000644000175000017500000000336412551235562024414 0ustar eugeneeugenepackage test.failures; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import test.TestHelper; import java.util.HashMap; import java.util.Map; public class FailuresTest extends BaseFailuresTest { @Test public void shouldIncludeFailedMethodsFromBaseClass() { XmlSuite suite = TestHelper.createSuite("test.failures.Child", getSuiteName()); TestNG tng = TestHelper.createTestNG(suite); tng.run(); String[] expected = new String[] { "", "", "", }; verify(getOutputDir(), expected); } @Test(enabled = false) public void shouldIncludeDependentMethods() { XmlSuite suite = TestHelper.createSuite("test.failures.DependentTest", getSuiteName()); TestNG tng = TestHelper.createTestNG(suite); tng.run(); String[] expected = new String[] { "", "" }; verify(getOutputDir(), expected); } @Test(enabled = false) public void shouldIncludeParameters() { XmlSuite suite = TestHelper.createSuite("test.failures.Child", getSuiteName()); Map params = new HashMap<>(); params.put("first-name", "Cedric"); params.put("last-name", "Beust"); suite.setParameters(params); TestNG tng = TestHelper.createTestNG(suite); tng.run(); String[] expected = new String[] { "", }; verify(getOutputDir(), expected); } private String getOutputDir() { return System.getProperty("java.io.tmpdir"); } private static void ppp(String s) { System.out.println("[FailuresTest] " + s); } } testng-testng-6.9.5/src/test/java/test/failures/DependentTest.java0000644000175000017500000000037112551235562024543 0ustar eugeneeugenepackage test.failures; import org.testng.annotations.Test; public class DependentTest { @Test public void f1() { } @Test(dependsOnMethods = {"f1"}, dependsOnGroups = { "f" }) public void f2() { throw new RuntimeException(); } } testng-testng-6.9.5/src/test/java/test/failures/Child.java0000644000175000017500000000036312551235562023021 0ustar eugeneeugenepackage test.failures; import org.testng.annotations.Test; public class Child extends Base1 { @Test public void pass() { assert true; } @Test public void fail() { throw new RuntimeException("VOLUNTARILY FAILED"); } } testng-testng-6.9.5/src/test/java/test/failures/BaseFailuresTest.java0000644000175000017500000000447312551235562025211 0ustar eugeneeugenepackage test.failures; import org.testng.Assert; import org.testng.TestNG; import org.testng.reporters.FailedReporter; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.regex.Pattern; public class BaseFailuresTest { // protected TestNG run(Class[] classes, String outputDir) { // return run(new TestNG(), classes, outputDir); // } protected String getSuiteName() { return "TmpSuite"; } protected TestNG run(TestNG result, Class[] classes, String outputDir) { result.setVerbose(0); result.setOutputDirectory(outputDir); result.setTestClasses(classes); result.run(); return result; } /** * @param f * @param regexps * @return true if the file contains at least one occurrence of each regexp */ protected boolean containsRegularExpressions(File f, String[] strRegexps) { Pattern[] matchers = new Pattern[strRegexps.length]; boolean[] results = new boolean[strRegexps.length]; for (int i = 0; i < strRegexps.length; i++) { matchers[i] = Pattern.compile(".*" + strRegexps[i] + ".*"); results[i] = false; } try { FileReader fr = new FileReader(f); BufferedReader br = new BufferedReader(fr); String line = br.readLine(); while (line != null) { for (int i = 0; i < strRegexps.length; i++) { if (matchers[i].matcher(line).matches()) { results[i] = true; } } line = br.readLine(); } fr.close(); br.close(); } catch (FileNotFoundException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } for (int i = 0; i < results.length; i++) { boolean result = results[i]; if (! result) { throw new AssertionError("Couldn't find " + strRegexps[i]); } } return true; } protected void verify(String outputDir, String[] expected) { File f = new File(outputDir + File.separatorChar + getSuiteName() + File.separator + FailedReporter.TESTNG_FAILED_XML); boolean passed = containsRegularExpressions(f, expected); Assert.assertTrue(passed); File tmpDir = new File(outputDir); tmpDir.delete(); } } testng-testng-6.9.5/src/test/java/test/failures/Base1.java0000644000175000017500000000040012551235562022721 0ustar eugeneeugenepackage test.failures; import org.testng.annotations.Test; public class Base1 extends Base0 { @Test public void base2() { assert true; } @Test public void failFromBase() { throw new RuntimeException("VOLUNTARILY FAILED"); } }testng-testng-6.9.5/src/test/java/test/failures/Base0.java0000644000175000017500000000021512551235562022724 0ustar eugeneeugenepackage test.failures; import org.testng.annotations.Test; public class Base0 { @Test public void base1() { assert true; } } testng-testng-6.9.5/src/test/java/test/failedreporter/0000755000175000017500000000000012551235562022326 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/failedreporter/FailedReporterTest.java0000644000175000017500000000340312551235562026740 0ustar eugeneeugenepackage test.failedreporter; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.testng.collections.Lists; import test.BaseTest; import java.io.File; import java.io.IOException; import java.util.List; public class FailedReporterTest extends BaseTest { private File mTempDirectory; @BeforeMethod public void setUp() { File slashTmpDir = new File(System.getProperty("java.io.tmpdir")); mTempDirectory = new File(slashTmpDir, "testng-tmp-" + System.currentTimeMillis() % 1000); mTempDirectory.mkdirs(); mTempDirectory.deleteOnExit(); } @AfterMethod public void tearDown() { deleteDir(mTempDirectory); } @Test public void failedAndSkippedMethodsShouldBeIncluded() throws IOException { testFailedReporter(FailedReporterSampleTest.class, new String[] { "f1", "f2" }, ""); } @Test public void failedMethodWithDataProviderShouldHaveInvocationNumbers() throws IOException { testFailedReporter(FailedReporter2SampleTest.class, new String[] { "f1" }, ""); } private void testFailedReporter(Class cls, String[] expectedMethods, String expectedLine) { TestNG tng = new TestNG(); tng.setVerbose(0); tng.setTestClasses(new Class[] { cls }); tng.setOutputDirectory(mTempDirectory.getAbsolutePath()); tng.run(); File failed = new File(mTempDirectory, "testng-failed.xml"); for (String s : expectedMethods) { List resultLines = Lists.newArrayList(); grep(failed, expectedLine.format(s), resultLines); Assert.assertEquals(1, resultLines.size()); } } } testng-testng-6.9.5/src/test/java/test/failedreporter/FailedReporterSampleTest.java0000644000175000017500000000047612551235562030111 0ustar eugeneeugenepackage test.failedreporter; import org.testng.SkipException; import org.testng.annotations.Test; public class FailedReporterSampleTest { @Test public void f2() { throw new RuntimeException(); } @Test public void f1() { throw new SkipException("Skipped"); } @Test public void f3() { } } testng-testng-6.9.5/src/test/java/test/failedreporter/FailedReporter2SampleTest.java0000644000175000017500000000067012551235562030167 0ustar eugeneeugenepackage test.failedreporter; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class FailedReporter2SampleTest { @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { 0 }, new Object[] { 1 }, new Object[] { 2 }, }; } @Test(dataProvider = "dp") public void f1(Integer ip) { if (ip == 1) { throw new RuntimeException(); } } } testng-testng-6.9.5/src/test/java/test/factory/0000755000175000017500000000000012551235562020766 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/factory/classconf/0000755000175000017500000000000012551235562022741 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/factory/classconf/XClassOrderWithFactoryTest.java0000644000175000017500000000123512551235562031022 0ustar eugeneeugenepackage test.factory.classconf; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; /** * This class/interface */ public class XClassOrderWithFactoryTest { @Test public void testBeforeAfterClassInvocationsWithFactory() { TestNG testng= new TestNG(); testng.setTestClasses(new Class[] {XClassOrderWithFactory.class}); TestListenerAdapter tla = new TestListenerAdapter(); testng.addListener(tla); testng.setVerbose(0); testng.run(); Assert.assertEquals(XClassOrderWithFactory.LOG.toString(), XClassOrderWithFactory.EXPECTED_LOG); } } testng-testng-6.9.5/src/test/java/test/factory/classconf/XClassOrderWithFactory.java0000644000175000017500000000154712551235562030170 0ustar eugeneeugenepackage test.factory.classconf; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Factory; import org.testng.annotations.Test; /** * This class/interface */ public class XClassOrderWithFactory { public static final String EXPECTED_LOG= "BTABTABTA"; public static final StringBuffer LOG= new StringBuffer(); @Factory public Object[] createInstances() throws Exception { return new Object[] { new XClassOrderTest(), new XClassOrderTest(), new XClassOrderTest() }; } public static class XClassOrderTest { @BeforeClass public void beforeClass() { LOG.append("B"); } public @Test void test() { LOG.append("T"); } public @AfterClass void afterClass() { LOG.append("A"); } } } testng-testng-6.9.5/src/test/java/test/factory/VerifyFactoryWithInstanceInfoTest.java0000644000175000017500000000076112551235562030426 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.Test; import java.util.Map; public class VerifyFactoryWithInstanceInfoTest { @Test(dependsOnGroups = { "first" } ) public void mainCheck() { Map numbers = FactoryWithInstanceInfoTest2.getNumbers(); assert null != numbers.get(42) : "Didn't find 42"; assert null != numbers.get(43) : "Didn't find 43"; assert 2 == numbers.size() : "Expected 2 numbers, found " + (numbers.size()); } } testng-testng-6.9.5/src/test/java/test/factory/VerifyFactoryTest.java0000644000175000017500000000072112551235562025265 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.Test; import java.util.Map; public class VerifyFactoryTest { @Test(dependsOnGroups = { "first" } ) public void mainCheck() { Map numbers = FactoryTest2.getNumbers(); assert null != numbers.get(42) : "Didn't find 42"; assert null != numbers.get(43) : "Didn't find 43"; assert 2 == numbers.size() : "Expected 2 numbers, found " + (numbers.size()); } } testng-testng-6.9.5/src/test/java/test/factory/TestClassAnnotationTest.java0000644000175000017500000000155712551235562026441 0ustar eugeneeugenepackage test.factory; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.Factory; import org.testng.annotations.Test; /** * Make sure that @Factory methods are not counted as @Test in the * presence of a class-scoped @Test annotation. * * Created on Mar 30, 2006 * @author Cedric Beust */ @Test public class TestClassAnnotationTest { private int m_count; @Factory public Object[] createFixture() { ppp("FACTORY"); m_count++; return new Object[] { new Object[] { new Object() }}; } public void testOne() { ppp("TESTONE"); m_count++; } @AfterClass public void verify() { ppp("VERIFY"); Assert.assertEquals(m_count, 2); } private static void ppp(String s) { if (false) { System.err.println("[FactoryTest] " + s); } } } testng-testng-6.9.5/src/test/java/test/factory/Sample2.java0000644000175000017500000000335212551235562023137 0ustar eugeneeugenepackage test.factory; import static org.testng.Assert.assertEquals; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.List; /** * Test that setUp methods are correctly interleaved even * when we use similar instances of a same test class. * * @author cbeust */ public class Sample2 { private static List m_methodList = new ArrayList<>(); @BeforeSuite public void init() { m_methodList = new ArrayList<>(); } @BeforeMethod public void setUp() { ppp("SET UP"); m_methodList.add("setUp"); } @AfterMethod public void tearDown() { ppp("TEAR DOWN"); m_methodList.add("tearDown"); } @AfterSuite public void afterSuite() { String[] expectedStrings = { "setUp", "testInputImages", "tearDown", "setUp", "testInputImages", "tearDown", "setUp", "testImages", "tearDown", "setUp", "testImages", "tearDown", }; List expected = new ArrayList<>(); for (String s : expectedStrings) { expected.add(s); } ppp("ORDER OF METHODS:"); for (String s : m_methodList) { ppp(" " + s); } assertEquals(m_methodList, expected); } @Test public void testInputImages() { m_methodList.add("testInputImages"); ppp("TESTINPUTIMAGES"); } @Test(dependsOnMethods={"testInputImages"}) public void testImages() { m_methodList.add("testImages"); } private static void ppp(String s) { if (false) { System.out.println("[Sample2] " + s); } } } testng-testng-6.9.5/src/test/java/test/factory/OddTest.java0000644000175000017500000000051612551235562023201 0ustar eugeneeugenepackage test.factory; import org.testng.Assert; import org.testng.annotations.Test; public class OddTest { private int m_n; public OddTest(int n) { m_n = n; } @Test public void verify() { Assert.assertTrue(m_n % 2 != 0); } private static void ppp(String s) { System.out.println("[OddTest] " + s); } } testng-testng-6.9.5/src/test/java/test/factory/NestedStaticFactoryTest.java0000644000175000017500000000230012551235562026406 0ustar eugeneeugenepackage test.factory; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import org.testng.annotations.Factory; import org.testng.annotations.Test; public class NestedStaticFactoryTest { private int m_capacity = 2; private float m_loadFactor = 0.4f; static public class NestedStaticFactory { @Factory public Object[] createInstances() { return new NestedStaticFactoryTest[] { new NestedStaticFactoryTest(1, 0.1f), new NestedStaticFactoryTest(10, 0.5f), }; } }; private static int m_instanceCount = 0; public NestedStaticFactoryTest() { m_instanceCount++; } public NestedStaticFactoryTest(int capacity, float loadFactor) { m_instanceCount++; this.m_capacity=capacity; this.m_loadFactor=loadFactor; } @Test public void verify() { // Should have three instances: the default one created by TestNG // and two created by the factory assertEquals(m_instanceCount, 2); assertTrue((m_capacity == 1 && m_loadFactor == 0.1f) || m_capacity == 10 && m_loadFactor == 0.5f); } private static void ppp(String s) { System.out.println("[NestedStaticFactoryTest] " + s); } } testng-testng-6.9.5/src/test/java/test/factory/NestedFactoryTest.java0000644000175000017500000000221112551235562025237 0ustar eugeneeugenepackage test.factory; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import org.testng.annotations.Factory; import org.testng.annotations.Test; public class NestedFactoryTest { private int m_capacity = 2; private float m_loadFactor = 0.4f; public class NestedFactory { @Factory public Object[] createInstances() { return new NestedFactoryTest[] { new NestedFactoryTest(1, 0.1f), new NestedFactoryTest(10, 0.5f), }; } }; private static int m_instanceCount = 0; public NestedFactoryTest() { m_instanceCount++; } public NestedFactoryTest(int capacity, float loadFactor) { m_instanceCount++; this.m_capacity=capacity; this.m_loadFactor=loadFactor; } @Test public void verify() { // Should have three instances: the default one created by TestNG // and two created by the factory assertEquals(m_instanceCount, 3); assertTrue((m_capacity == 1 && m_loadFactor == 0.1f) || m_capacity == 10 && m_loadFactor == 0.5f); } private static void ppp(String s) { System.out.println("[NestedFactoryTest] " + s); } } testng-testng-6.9.5/src/test/java/test/factory/MyTest.java0000644000175000017500000000140712551235562023060 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.Test; public class MyTest { private int i; // in this test, our default constructor sets s to a value that will cause a failure // the valid test instances should come from the factory public MyTest() { i = 0; } public MyTest(int i) { this.i = i; } @Test(groups = "MyTest") public void testMethod() { FactoryInSeparateClass.addToSum(i); // assert i > 0 : "MyTest was not constructed with correct params"; assert (i != 0) : "My test was not created by the factory"; } @Test(dependsOnGroups = "testMethodOnFactoryClass") public void verifyThatTestMethodOnFactoryClassWasRun() { assert FactoryInSeparateClass.wasRun() : "Test method on factory class wasn't run"; } }testng-testng-6.9.5/src/test/java/test/factory/FactoryWithInstanceInfoTest2.java0000644000175000017500000000142512551235562027321 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.Test; import java.util.HashMap; import java.util.Map; /** * This class is created by FactoryWithInstanceInfoTest2 * * @author cbeust */ public class FactoryWithInstanceInfoTest2 { private static Map m_numbers = new HashMap<>(); private int m_number; public FactoryWithInstanceInfoTest2() { throw new RuntimeException("Shouldn't be invoked"); } public static Map getNumbers() { return m_numbers; } public FactoryWithInstanceInfoTest2(int n) { m_number = n; } @Test(groups = { "first" }) public void testInt() { Integer n = m_number; m_numbers.put(n, n); } private static void ppp(String s) { System.out.println("[FactoryTest2] " + s); } } testng-testng-6.9.5/src/test/java/test/factory/FactoryWithInstanceInfoTest.java0000644000175000017500000000205412551235562027236 0ustar eugeneeugenepackage test.factory; import static org.testng.Assert.assertFalse; import org.testng.IInstanceInfo; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Factory; import org.testng.annotations.Parameters; import org.testng.internal.InstanceInfo; public class FactoryWithInstanceInfoTest { static boolean m_invoked = false; @Parameters({ "factory-param" }) @Factory public IInstanceInfo[] createObjectsWithInstanceInfo(String param) { assert "FactoryParam".equals(param) : "Incorrect param: " + param; assertFalse(m_invoked, "Should only be invoked once"); m_invoked = true; return new IInstanceInfo[] { new InstanceInfo(FactoryWithInstanceInfoTest2.class, new FactoryWithInstanceInfoTest2(42)), new InstanceInfo(FactoryWithInstanceInfoTest2.class, new FactoryWithInstanceInfoTest2(43)), }; } @BeforeSuite public void beforeSuite() { m_invoked = false; } private static void ppp(String s) { System.out.println("[FactoryWithInstanceInfoTest] " + s); } }testng-testng-6.9.5/src/test/java/test/factory/FactoryWithDataProviderTest.java0000644000175000017500000000127412551235562027245 0ustar eugeneeugenepackage test.factory; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; public class FactoryWithDataProviderTest { /** * Verify that a factory can receive a data provider */ @Test public void verifyDataProvider() { TestNG tng = new TestNG(); tng.setVerbose(0); tng.setTestClasses(new Class[] { FactoryWithDataProvider.class }); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 4); } private static void ppp(String s) { System.out.println("[FactoryWithDataProviderTest] " + s); } } testng-testng-6.9.5/src/test/java/test/factory/FactoryWithDataProvider.java0000644000175000017500000000126312551235562026403 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import java.util.ArrayList; import java.util.List; public class FactoryWithDataProvider { @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { new int[] { 3, 5 } }, new Object[] { new int [] { 7, 9 } }, }; } @Factory(dataProvider = "dp") public Object[] factory(int[] array) { List result = new ArrayList<>(); for (int n : array) { result.add(new OddTest(n)); } return result.toArray(); } private static void ppp(String s) { System.out.println("[FactoryWithDataProvider] " + s); } } testng-testng-6.9.5/src/test/java/test/factory/FactoryTest2.java0000644000175000017500000000142612551235562024165 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.Test; import java.util.HashMap; import java.util.Map; /** * This class * * @author cbeust */ public class FactoryTest2 { private static Map m_numbers = new HashMap<>(); private int m_number; public FactoryTest2() { throw new RuntimeException("Shouldn't be invoked"); } public static Map getNumbers() { return m_numbers; } public FactoryTest2(int n) { m_number = n; } @Test(groups = { "first" }) public void testInt() { Integer n = m_number; m_numbers.put(n, n); } @Override public String toString() { return "[FactoryTest2 " + m_number + "]"; } private static void ppp(String s) { System.out.println("[FactoryTest2] " + s); } } testng-testng-6.9.5/src/test/java/test/factory/FactoryTest.java0000644000175000017500000000124312551235562024100 0ustar eugeneeugenepackage test.factory; import static org.testng.Assert.assertFalse; import org.testng.Assert; import org.testng.annotations.AfterSuite; import org.testng.annotations.Factory; import org.testng.annotations.Parameters; public class FactoryTest { static boolean m_invoked = false; @Parameters({ "factory-param" }) @Factory public Object[] createObjects(String param) { Assert.assertEquals(param, "FactoryParam"); assertFalse(m_invoked, "Should only be invoked once"); m_invoked = true; return new Object[] { new FactoryTest2(42), new FactoryTest2(43) }; } @AfterSuite public void afterSuite() { m_invoked = false; } }testng-testng-6.9.5/src/test/java/test/factory/FactoryOrderTest.java0000644000175000017500000000106212551235562025073 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.Factory; import java.util.ArrayList; import java.util.List; public class FactoryOrderTest { public FactoryOrderTest() { // System.out.println("inside testFactory constructor"); } @Factory public static Object[] testF() throws Exception { List result = new ArrayList(); // System.out.println("inside factory: "); int i = 0; while (i < 5) { result.add(new FactoryOrderSampleTest(i)); i++; } return result.toArray(); } }testng-testng-6.9.5/src/test/java/test/factory/FactoryOrderSampleTest.java0000644000175000017500000000160712551235562026242 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class FactoryOrderSampleTest { int value; public FactoryOrderSampleTest(int j) { value = j; log("classC constructor " + value); } private void log(String string) { // System.out.println("[FactoryOrderSampleTest] " + string); } @BeforeClass(groups = { "s1ds" }) public void setup() { log("classC.BeforeClass " + value); } @Test(groups = { "s1ds" }) public void methodC1() throws Exception { // Thread.sleep(1000); log("classC.methodC1 " + value); } @AfterClass(groups = { "s1ds" }) public void cleanup() { log("classC.AfterClass " + value); } @Override public String toString() { return "[FactoryOrderSampleTest " + value + "]"; } public int getValue() { return value; } }testng-testng-6.9.5/src/test/java/test/factory/FactoryOrderMainTest.java0000644000175000017500000000132212551235562025677 0ustar eugeneeugenepackage test.factory; import org.testng.Assert; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; import java.util.List; public class FactoryOrderMainTest extends SimpleBaseTest { @Test public void factoriesShouldBeInvokedInTheOrderOfCreation() { TestNG tng = create(FactoryOrderTest.class); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); List passed = tla.getPassedTests(); for (int i = 0; i < passed.size(); i++) { Assert.assertEquals(((FactoryOrderSampleTest) passed.get(i).getInstance()).getValue(), i); } } } testng-testng-6.9.5/src/test/java/test/factory/FactoryInterleavingTest.java0000644000175000017500000000162312551235562026452 0ustar eugeneeugenepackage test.factory; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.collections.Lists; import test.SimpleBaseTest; import java.util.List; public class FactoryInterleavingTest extends SimpleBaseTest { public static List LOG = Lists.newArrayList(); @Test public void methodsShouldBeInterleaved() { TestNG tng = create(FactoryInterleavingSampleFactory.class); tng.run(); Integer[] valid1 = { 10, 11, 12, 13, 20, 21, 22, 23, }; Integer[] valid2 = { 20, 21, 22, 23, 10, 11, 12, 13, }; Integer[] logArray = LOG.toArray(new Integer[LOG.size()]); if (! logArray.equals(valid1)) { Assert.assertEquals(logArray, valid1); } else if (! logArray.equals(valid2)) { System.err.println(logArray + " " + valid2); Assert.assertEquals(logArray, valid2); } } } testng-testng-6.9.5/src/test/java/test/factory/FactoryInterleavingSampleFactory.java0000644000175000017500000000061212551235562030301 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.BeforeClass; import org.testng.annotations.Factory; public class FactoryInterleavingSampleFactory { @Factory public Object[] factory() { return new Object[] { new FactoryInterleavingSampleA(1), new FactoryInterleavingSampleA(2) }; } @BeforeClass public void beforeB() { System.out.println("Before B"); } } testng-testng-6.9.5/src/test/java/test/factory/FactoryInterleavingSampleA.java0000644000175000017500000000126212551235562027054 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class FactoryInterleavingSampleA { public int m_n; public FactoryInterleavingSampleA(int n) { m_n = n; } private void log(Integer s) { FactoryInterleavingTest.LOG.add(m_n * 10 + s); // System.out.println(" Instance " + m_n + " " + s); } @Override public String toString() { return "[A n:" + m_n + "]"; } @BeforeClass public void bc() { log(0); } @AfterClass public void ac() { log(3); } @Test public void f1() { log(1); } @Test public void f2() { log(2); } } testng-testng-6.9.5/src/test/java/test/factory/FactoryInSuperClassTest.java0000644000175000017500000000077212551235562026402 0ustar eugeneeugenepackage test.factory; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class FactoryInSuperClassTest extends SimpleBaseTest { @Test public void factoryInSuperClassShouldWork() { TestNG tng = create(FactoryChild.class); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 1); } } testng-testng-6.9.5/src/test/java/test/factory/FactoryInSeparateClass.java0000644000175000017500000000201212551235562026175 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.BeforeTest; import org.testng.annotations.Factory; import org.testng.annotations.Test; /** * this is like the FactoryTest, except it creates test instances in a separate * class from the test class */ public class FactoryInSeparateClass { static private boolean m_wasRun = false; static private int m_checkSum = 0; public static void addToSum(int i) { m_checkSum += i; } @BeforeTest public void beforeTest() { m_wasRun = false; m_checkSum = 0; } @Factory public Object[] createObjects() { return new Object[] { new MyTest(1), new MyTest(2), new MyTest(3), }; } @Test(groups = "testMethodOnFactoryClass", dependsOnGroups={"MyTest"}) public void checkSum() { m_wasRun = true; assert (m_checkSum == 6) : "Test instances made by factory did not invoke their test methods correctly. expected 6 but got " + m_checkSum; } public static boolean wasRun() { return m_wasRun; } } testng-testng-6.9.5/src/test/java/test/factory/FactoryFailureTest.java0000644000175000017500000000066412551235562025416 0ustar eugeneeugenepackage test.factory; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class FactoryFailureTest extends SimpleBaseTest { @Test public void factoryThrowingShouldNotRunTests() { TestNG tng = create(FactoryFailureSampleTest.class); try { tng.run(); Assert.fail(); } catch(Exception ex) { // success } } } testng-testng-6.9.5/src/test/java/test/factory/FactoryFailureSampleTest.java0000644000175000017500000000040212551235562026546 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.Factory; import org.testng.annotations.Test; public class FactoryFailureSampleTest { @Factory public Object[] factory() { throw new NullPointerException(); } @Test public void f() { } } testng-testng-6.9.5/src/test/java/test/factory/FactoryDataProviderWithNoArgCtorSampleErrorTest.java0000644000175000017500000000121212551235562033170 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; public class FactoryDataProviderWithNoArgCtorSampleErrorTest extends BaseFactory { public FactoryDataProviderWithNoArgCtorSampleErrorTest() { super(0); } @Factory(dataProvider = "dp") public FactoryDataProviderWithNoArgCtorSampleErrorTest(int n) { super(n); } @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { 45 }, new Object[] { 46 }, }; } @Override public String toString() { return "[FactoryDataProviderWithNoArgCtorSampleErrorTest " + getN() + "]"; } } testng-testng-6.9.5/src/test/java/test/factory/FactoryDataProviderTest.java0000644000175000017500000000364112551235562026411 0ustar eugeneeugenepackage test.factory; import org.testng.Assert; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.TestNGException; import org.testng.annotations.Test; import test.SimpleBaseTest; import java.util.Iterator; public class FactoryDataProviderTest extends SimpleBaseTest { @Test(description = "Test @Factory(dataProvider) on a local static data provider") public void factoryWithLocalDataProvider() { runTest(FactoryDataProviderSampleTest.class, 41, 42); } @Test(description = "Test @Factory(dataProvider) on a data provider in another class") public void factoryWithStaticDataProvider() { runTest(FactoryDataProviderStaticSampleTest.class, 43, 44); } @Test(description = "Test @Factory(dataProvider) on a non static data provider with no arg ctor") public void factoryWithNonStaticDataProvider() { runTest(FactoryDataProviderWithNoArgCtorSampleErrorTest.class, 45, 46); } @Test(expectedExceptions = TestNGException.class, description = "Should fail because the data provider is not static") public void factoryWithNonStaticDataProviderShouldFail() { runTest(FactoryDataProviderStaticSampleErrorTest.class, 43, 44); } private void runTest(Class cls, int n1, int n2) { TestNG tng = create(cls); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 2); Iterator iterator = tla.getPassedTests().iterator(); BaseFactory t1 = (BaseFactory) iterator.next().getInstance(); BaseFactory t2 = (BaseFactory) iterator.next().getInstance(); // Assert.assertTrue(t1.getN() == n1 || t1.getN() == n2); // Assert.assertTrue(t2.getN() == n1 || t2.getN() == n2); // System.out.println("Results:" + t1.getN() + " " + t2.getN()); Assert.assertEquals(t1.getN(), n1); Assert.assertEquals(t2.getN(), n2); } } testng-testng-6.9.5/src/test/java/test/factory/FactoryDataProviderStaticSampleTest.java0000644000175000017500000000042412551235562030717 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.Factory; public class FactoryDataProviderStaticSampleTest extends BaseFactory { @Factory(dataProvider = "dp", dataProviderClass = DPClass.class) public FactoryDataProviderStaticSampleTest(int n) { super(n); } } testng-testng-6.9.5/src/test/java/test/factory/FactoryDataProviderStaticSampleErrorTest.java0000644000175000017500000000066012551235562031733 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; public class FactoryDataProviderStaticSampleErrorTest extends BaseFactory { @Factory(dataProvider = "dp") public FactoryDataProviderStaticSampleErrorTest(int n) { super(n); } @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { 41 }, new Object[] { 42 }, }; } } testng-testng-6.9.5/src/test/java/test/factory/FactoryDataProviderSampleTest.java0000644000175000017500000000117512551235562027553 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; public class FactoryDataProviderSampleTest extends BaseFactory { @Factory(dataProvider = "dp") public FactoryDataProviderSampleTest(int n) { super(n); } @DataProvider static public Object[][] dp() { return new Object[][] { new Object[] { 41 }, new Object[] { 42 }, }; } @Override public String toString() { return "[FactoryDataProviderSampleTest " + getN() + "]"; } @Test public void f() { // System.out.println("Test:" + getN()); } } testng-testng-6.9.5/src/test/java/test/factory/FactoryChild.java0000644000175000017500000000011212551235562024176 0ustar eugeneeugenepackage test.factory; public class FactoryChild extends FactoryBase { } testng-testng-6.9.5/src/test/java/test/factory/FactoryBaseSampleTest.java0000644000175000017500000000020112551235562026026 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.Test; public class FactoryBaseSampleTest { @Test public void f() {} } testng-testng-6.9.5/src/test/java/test/factory/FactoryBase.java0000644000175000017500000000031412551235562024031 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.Factory; public class FactoryBase { @Factory public Object[] create() { return new Object[] { new FactoryBaseSampleTest() }; } } testng-testng-6.9.5/src/test/java/test/factory/FactoryAndTestMethodTest.java0000644000175000017500000000133612551235562026527 0ustar eugeneeugenepackage test.factory; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; @Test(groups = { "x" }) public class FactoryAndTestMethodTest { @Factory(dataProvider = "data") public Object[] ohNo(String s) { return makeNullArgTests(s); } public static class NullArgsTest { public final String s; public NullArgsTest(String s) { this.s = s; } @Test public void test() { Assert.assertNotNull(s); } } private Object[] makeNullArgTests(String s) { return new Object[0]; } @DataProvider(name = "data") public Object[][] makeData() { return new Object[][] { { "foo" } }; }; } testng-testng-6.9.5/src/test/java/test/factory/Factory2Test.java0000644000175000017500000000070112551235562024160 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.Factory; /** * Factory to test that setUp methods are correctly interleaved even * when we use similar instances of a same test class. * * @author cbeust */ public class Factory2Test { @Factory() public Object[] createObjects() { return new Object[] { new Sample2(), new Sample2() }; } private static void ppp(String s) { System.out.println("[FactoryTest] " + s); } }testng-testng-6.9.5/src/test/java/test/factory/DisabledFactoryTest.java0000644000175000017500000000113212551235562025525 0ustar eugeneeugenepackage test.factory; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class DisabledFactoryTest extends SimpleBaseTest { @Test public void disabledFactoryShouldNotRun() { TestNG tng = create(DisabledFactorySampleTest.class); TestListenerAdapter tla = new TestListenerAdapter(); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 0); Assert.assertEquals(tla.getSkippedTests().size(), 0); Assert.assertEquals(tla.getFailedTests().size(), 0); } } testng-testng-6.9.5/src/test/java/test/factory/DisabledFactorySampleTest.java0000644000175000017500000000032312551235562026670 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.Factory; public class DisabledFactorySampleTest { @Factory(enabled = false) public Object[] factory() { return new Object[] { new MyTest() }; } } testng-testng-6.9.5/src/test/java/test/factory/DPClass.java0000644000175000017500000000035512551235562023125 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.DataProvider; public class DPClass { @DataProvider static public Object[][] dp() { return new Object[][] { new Object[] { 43 }, new Object[] { 44 }, }; } } testng-testng-6.9.5/src/test/java/test/factory/BaseFactory.java0000644000175000017500000000075012551235562024035 0ustar eugeneeugenepackage test.factory; import org.testng.annotations.Test; public class BaseFactory { private int m_n; public BaseFactory(int n) { m_n = n; } public int getN() { return m_n; } @Test public void f() { } /** * @@@ for some reason, the test results get added in the wrong order if * I don't define a toString() method. Need to investigate. */ @Override public String toString() { return "[" + getClass().getName() + " " + getN() + "]"; } } testng-testng-6.9.5/src/test/java/test/expectedexceptions/0000755000175000017500000000000012551235562023222 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/expectedexceptions/WrappedExpectedExceptionTest.java0000644000175000017500000000052312551235562031670 0ustar eugeneeugenepackage test.expectedexceptions; import org.testng.annotations.ExpectedExceptions; import org.testng.annotations.Test; public class WrappedExpectedExceptionTest { @Test(timeOut = 1000L) @ExpectedExceptions({ IllegalStateException.class }) public void testTimeout() { throw new IllegalStateException("expected failure"); } } testng-testng-6.9.5/src/test/java/test/expectedexceptions/SampleExceptions2.java0000644000175000017500000000261312551235562027434 0ustar eugeneeugenepackage test.expectedexceptions; import org.testng.annotations.Test; /** * This class tests @ExpectedExceptions * * @author cbeust */ public class SampleExceptions2 { @Test(expectedExceptions = NumberFormatException.class ) public void shouldPass() { throw new NumberFormatException(); } @Test(expectedExceptions = NumberFormatException.class) public void shouldFail1() { throw new RuntimeException(); } @Test(expectedExceptions = NumberFormatException.class) public void shouldFail2() { } @Test(expectedExceptions = NumberFormatException.class, expectedExceptionsMessageRegExp = ".*bomb.*") public void shouldPass2() { throw new NumberFormatException("This should not bomb at all"); } @Test(expectedExceptions = NumberFormatException.class, expectedExceptionsMessageRegExp = ".*bombc.*") public void shouldFail3() { throw new NumberFormatException("This should bomb for good"); } @Test(expectedExceptions = NumberFormatException.class, expectedExceptionsMessageRegExp = ".*") public void shouldPass3() { 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() { } } testng-testng-6.9.5/src/test/java/test/expectedexceptions/SampleExceptions.java0000644000175000017500000000176312551235562027357 0ustar eugeneeugenepackage test.expectedexceptions; import org.testng.annotations.ExpectedExceptions; import org.testng.annotations.Test; /** * This class tests @ExpectedExceptions * * @author cbeust */ public class SampleExceptions { @Test @ExpectedExceptions({ NumberFormatException.class} ) public void shouldPass() { throw new NumberFormatException(); } @Test @ExpectedExceptions({ NumberFormatException.class} ) public void shouldFail1() { throw new RuntimeException(); } @Test @ExpectedExceptions({ NumberFormatException.class} ) public void shouldFail2() { } @Test @ExpectedExceptions(RuntimeException.class) public void shouldFail3() { } // @Test(expectedExceptions = NumberFormatException.class) // public void throwWrongException() { // throw new NullPointerException(); // } // @Test // @ExpectedExceptions({ FileNotFoundException.class, IOException.class }) // public void shouldPass2() throws Exception { // throw new FileNotFoundException(); // } } testng-testng-6.9.5/src/test/java/test/expectedexceptions/ParametersExceptionTest.java0000644000175000017500000000135612551235562030714 0ustar eugeneeugenepackage test.expectedexceptions; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.xml.sax.SAXException; import java.io.IOException; import java.lang.reflect.Method; /** * This class/interface */ public class ParametersExceptionTest { @Test(dataProvider="A") public void testA(Exception err) { System.out.println("testA"); } @DataProvider(name="A") protected Object[][] dp() { return new Object[][] { {new IOException(), new SAXException() } }; } @AfterMethod protected void verify(Method method) { Assert.assertTrue(false, "forced failure"); } } testng-testng-6.9.5/src/test/java/test/expectedexceptions/ExpectedExceptionsTest.java0000644000175000017500000000131112551235562030524 0ustar eugeneeugenepackage test.expectedexceptions; import org.testng.annotations.Test; import test.BaseTest; public class ExpectedExceptionsTest extends BaseTest { @Test public void expectedExceptionsDeprecatedSyntax() { runTest("test.expectedexceptions.SampleExceptions", new String[] { "shouldPass" }, new String[] { "shouldFail1", "shouldFail2", "shouldFail3" }, new String[] {}); } @Test public void expectedExceptions() { runTest("test.expectedexceptions.SampleExceptions2", new String[] { "shouldPass", "shouldPass2", "shouldPass3", "shouldPass4" }, new String[] { "shouldFail1", "shouldFail2", "shouldFail3", "shouldFail4" }, new String[] {}); } } testng-testng-6.9.5/src/test/java/test/enable/0000755000175000017500000000000012551235562020545 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/enable/Issue420SecondSample.java0000644000175000017500000000027412551235562025227 0ustar eugeneeugenepackage test.enable; import org.testng.annotations.Test; @Test public class Issue420SecondSample extends Issue420BaseTestCase { @Test public void verifySomethingSecondSample() {} } testng-testng-6.9.5/src/test/java/test/enable/Issue420FirstSample.java0000644000175000017500000000031312551235562025075 0ustar eugeneeugenepackage test.enable; import org.testng.annotations.Test; @Test(enabled = false) public class Issue420FirstSample extends Issue420BaseTestCase { @Test public void verifySomethingFirstSample() {} } testng-testng-6.9.5/src/test/java/test/enable/Issue420BaseTestCase.java0000644000175000017500000000070512551235562025157 0ustar eugeneeugenepackage test.enable; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeSuite; public abstract class Issue420BaseTestCase { @BeforeSuite(alwaysRun = true) public static void alwaysBeforeSuite() {} @BeforeSuite(alwaysRun = false) public static void beforeSuite() {} @AfterSuite(alwaysRun = false) public static void afterSuite() {} @AfterSuite(alwaysRun = true) public static void alwaysAfterSuite() {} } testng-testng-6.9.5/src/test/java/test/enable/InvokedMethodListener.java0000644000175000017500000000126312551235562025660 0ustar eugeneeugenepackage 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 { private final List invokedMethods = new ArrayList<>(); @Override public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { invokedMethods.add(method.getTestMethod().getMethodName()); } @Override public void afterInvocation(IInvokedMethod method, ITestResult testResult) { } public List getInvokedMethods() { return invokedMethods; } } testng-testng-6.9.5/src/test/java/test/enable/EnableTest.java0000644000175000017500000000327112551235562023441 0ustar eugeneeugenepackage test.enable; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; import static org.assertj.core.api.Assertions.assertThat; 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(); assertThat(listener.getInvokedMethods()).containsExactly( "beforeSuiteA", "beforeSuiteA2", "beforeSuiteNoRunA", "beforeSuiteNoRunA2", "beforeSuiteRunA", "beforeSuiteRunA2", "beforeSuiteRunB", "beforeSuiteRunB2", "beforeSuiteC", "beforeSuiteC2", "beforeSuiteNoRunC", "beforeSuiteNoRunC2", "beforeSuiteRunC", "beforeSuiteRunC2", "testA2", "testA3", "testB2", "testB3", "testC", "testC2", "testC3", "afterSuiteA", "afterSuiteA2", "afterSuiteNoRunA", "afterSuiteNoRunA2", "afterSuiteRunA", "afterSuiteRunA2", "afterSuiteRunB", "afterSuiteRunB2", "afterSuiteC", "afterSuiteC2", "afterSuiteNoRunC", "afterSuiteNoRunC2", "afterSuiteRunC", "afterSuiteRunC2" ); } @Test(description = "https://github.com/cbeust/testng/issues/420") public void issue420() { TestNG tng = create(Issue420FirstSample.class, Issue420SecondSample.class); InvokedMethodListener listener = new InvokedMethodListener(); tng.addListener(listener); tng.run(); assertThat(listener.getInvokedMethods()).containsExactly( "alwaysBeforeSuite", "beforeSuite", "verifySomethingFirstSample", "verifySomethingSecondSample", "afterSuite", "alwaysAfterSuite" ); } } testng-testng-6.9.5/src/test/java/test/enable/C.java0000644000175000017500000000325012551235562021572 0ustar eugeneeugenepackage test.enable; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; @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() {} @AfterSuite public void afterSuiteC() {} @AfterSuite(enabled = true) public void afterSuiteC2() {} @AfterSuite(enabled = false) public void disabledAfterSuiteC() {} @AfterSuite(alwaysRun = false) public void afterSuiteNoRunC() {} @AfterSuite(enabled = true, alwaysRun = false) public void afterSuiteNoRunC2() {} @AfterSuite(enabled = false, alwaysRun = false) public void disabledAfterSuiteNoRunC() {} @AfterSuite(alwaysRun = true) public void afterSuiteRunC() {} @AfterSuite(enabled = true, alwaysRun = true) public void afterSuiteRunC2() {} @AfterSuite(enabled = false, alwaysRun = true) public void disabledAfterSuiteRunC() {} } testng-testng-6.9.5/src/test/java/test/enable/B.java0000644000175000017500000000331212551235562021570 0ustar eugeneeugenepackage test.enable; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; @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() {} @AfterSuite public void afterSuiteB() {} @AfterSuite(enabled = true) public void afterSuiteB2() {} @AfterSuite(enabled = false) public void disabledAfterSuiteB() {} @AfterSuite(alwaysRun = false) public void afterSuiteNoRunB() {} @AfterSuite(enabled = true, alwaysRun = false) public void afterSuiteNoRunB2() {} @AfterSuite(enabled = false, alwaysRun = false) public void disabledAfterSuiteNoRunB() {} @AfterSuite(alwaysRun = true) public void afterSuiteRunB() {} @AfterSuite(enabled = true, alwaysRun = true) public void afterSuiteRunB2() {} @AfterSuite(enabled = false, alwaysRun = true) public void disabledAfterSuiteRunB() {} } testng-testng-6.9.5/src/test/java/test/enable/A.java0000644000175000017500000000324212551235562021571 0ustar eugeneeugenepackage test.enable; import org.testng.annotations.AfterSuite; 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() {} @AfterSuite public void afterSuiteA() {} @AfterSuite(enabled = true) public void afterSuiteA2() {} @AfterSuite(enabled = false) public void disabledAfterSuiteA() {} @AfterSuite(alwaysRun = false) public void afterSuiteNoRunA() {} @AfterSuite(enabled = true, alwaysRun = false) public void afterSuiteNoRunA2() {} @AfterSuite(enabled = false, alwaysRun = false) public void disabledAfterSuiteNoRunA() {} @AfterSuite(alwaysRun = true) public void afterSuiteRunA() {} @AfterSuite(enabled = true, alwaysRun = true) public void afterSuiteRunA2() {} @AfterSuite(enabled = false, alwaysRun = true) public void disabledAfterSuiteRunA() {} } testng-testng-6.9.5/src/test/java/test/distributed/0000755000175000017500000000000012551235562021641 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/distributed/Test2.java0000644000175000017500000000032512551235562023505 0ustar eugeneeugenepackage test.distributed; import org.testng.annotations.Test; public class Test2 { @Test public void f2() { // ppp("f2"); } private void ppp(String s) { System.out.println("[Test2] " + s); } } testng-testng-6.9.5/src/test/java/test/distributed/Test1.java0000644000175000017500000000032612551235562023505 0ustar eugeneeugenepackage test.distributed; import org.testng.annotations.Test; public class Test1 { @Test public void f1() { // ppp("f1"); } private void ppp(String s) { System.out.println("[Test1] " + s); } } testng-testng-6.9.5/src/test/java/test/distributed/DistributedTest.java0000644000175000017500000001207112551235562025627 0ustar eugeneeugenepackage test.distributed; import org.testng.Assert; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.remote.SuiteDispatcher; import org.testng.xml.XmlClass; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.BaseDistributedTest; import testhelper.OutputDirectoryPatch; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Random; public class DistributedTest extends BaseDistributedTest { private List m_hostThreads = new ArrayList<>(); protected Thread startSlave(final String filename) { Thread result = new Thread(new Runnable() { @Override public void run() { TestNG.main(new String[] { "-slave", filename, "-d", OutputDirectoryPatch.getOutputDirectory() }); } }); result.setName("Slave-" + filename); result.start(); m_hostThreads.add(result); return result; } private File createMasterProperties(String strategy) throws IOException { String fileName = "remote"; File result = File.createTempFile(fileName, ".properties"); result.deleteOnExit(); Properties p = new Properties(); p.setProperty("testng.hosts", "localhost:" + m_ports[0] + " localhost:" + m_ports[1]); p.setProperty("testng.master.strategy", strategy); p.setProperty("testng.verbose", "0"); p.setProperty("testng.master.adpter", "org.testng.remote.adapter.DefaultMastertAdapter"); FileOutputStream fos = new FileOutputStream(result); p.store(fos, "Automatically generated by tests"); fos.close(); return result; } private File createSlaveProperties(String port) throws IOException { String fileName = "remote"; File result = File.createTempFile(fileName, ".properties"); result.deleteOnExit(); Properties p = new Properties(); p.setProperty("testng.verbose", "0"); p.setProperty("slave.port", port); p.setProperty("testng.slave.adpter", "org.testng.remote.adapter.DefaultWorkerAdapter"); FileOutputStream fos = new FileOutputStream(result); p.store(fos, "Automatically generated by tests"); fos.close(); return result; } private XmlSuite createSuite(String name, Class[] classes) { XmlSuite result = new XmlSuite(); result.setName(name); for (Class c : classes) { XmlTest test1 = new XmlTest(result); test1.setName(c.getName()); XmlClass class1 = new XmlClass(c); test1.getXmlClasses().add(class1); } return result; } // @ Configuration(beforeTestClass = true) private void startSlaves() throws IOException{ int port = new Random().nextInt(50000) + 2000; m_ports = new String[] { Integer.toString(port), Integer.toString(port+1)}; File slaveFile = createSlaveProperties(m_ports[0]); startSlave( slaveFile.getCanonicalPath()); slaveFile = createSlaveProperties(m_ports[1]); startSlave( slaveFile.getCanonicalPath()); } private String[] m_ports = new String[2]; public TestListenerAdapter twoHosts(String strategy) throws IOException { TestNG tng = new TestNG(); tng.setOutputDirectory(OutputDirectoryPatch.getOutputDirectory()); File masterFile = createMasterProperties(strategy); tng.setMaster(masterFile.getAbsolutePath()); XmlSuite suite = createSuite("DistributedSuite1", new Class[] { Test1.class, Test2.class }); tng.setXmlSuites(Arrays.asList(new XmlSuite[] { suite })); TestListenerAdapter result = new TestListenerAdapter(); tng.addListener(result); tng.run(); String[] passed = { "f1", "f2" }; String[] failed = {}; String[] skipped = {}; verifyTests("Passed", passed, toMap(result.getPassedTests())); verifyTests("Failed", failed, toMap(result.getFailedTests())); verifyTests("Skipped", skipped, toMap(result.getSkippedTests())); return result; } @Test public void twoHostsWithTestStrategy() throws IOException { startSlaves(); TestListenerAdapter listener = twoHosts(SuiteDispatcher.STRATEGY_TEST); boolean found1 = false; boolean found2 = false; for (ITestResult tr : listener.getPassedTests()) { String host = tr.getHost(); if (! found1) { found1 = host.contains(m_ports[0]); } if (! found2) { found2 = host.contains(m_ports[1]); } } Assert.assertTrue(found1, "No tests ran on port " + m_ports[0]); Assert.assertTrue(found2, "No tests ran on port " + m_ports[1]); } @Test public void twoHostsWithSuiteStrategy() throws IOException { startSlaves(); twoHosts(SuiteDispatcher.STRATEGY_SUITE); } private Map toMap(List results) { Map result = new HashMap<>(); for (ITestResult tr : results) { result.put(tr.getName(), tr); } return result; } private void ppp(String string) { System.out.println("[DistributedTest] " + string); } } testng-testng-6.9.5/src/test/java/test/dependsongroup/0000755000175000017500000000000012551235562022353 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/dependsongroup/suite.xml0000644000175000017500000000054112551235562024226 0ustar eugeneeugene testng-testng-6.9.5/src/test/java/test/dependsongroup/ZeroSampleTest.java0000644000175000017500000000042012551235562026133 0ustar eugeneeugenepackage test.dependsongroup; import org.testng.annotations.Test; @Test(groups = { "zero" }) public class ZeroSampleTest { @Test public void zeroA() { // System.out.println("zeroA"); } @Test public void zeroB() { // System.out.println("zeroB"); } } testng-testng-6.9.5/src/test/java/test/dependsongroup/TestFixture2.java0000644000175000017500000000044712551235562025573 0ustar eugeneeugenepackage test.dependsongroup; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class TestFixture2 { @BeforeTest(groups={"test"}, dependsOnGroups={"testgroup"}) public void setup() { } @Test(groups={"test"}) //@@ public void testMethod() { } } testng-testng-6.9.5/src/test/java/test/dependsongroup/TestFixture1.java0000644000175000017500000000026112551235562025564 0ustar eugeneeugenepackage test.dependsongroup; import org.testng.annotations.BeforeTest; public class TestFixture1 { @BeforeTest(groups={"test", "testgroup"}) public void setup() { } } testng-testng-6.9.5/src/test/java/test/dependsongroup/SecondSampleTest.java0000644000175000017500000000047012551235562026434 0ustar eugeneeugenepackage test.dependsongroup; import org.testng.annotations.Test; @Test(groups = { "second" }, dependsOnGroups = { "zero" }) public class SecondSampleTest { @Test public void secondA() { // System.out.println("secondA"); } @Test public void secondB() { // System.out.println("secondB"); } }testng-testng-6.9.5/src/test/java/test/dependsongroup/FirstSampleTest.java0000644000175000017500000000046412551235562026313 0ustar eugeneeugenepackage test.dependsongroup; import org.testng.annotations.Test; @Test(groups = { "first" }, dependsOnGroups = { "zero" }) public class FirstSampleTest { @Test public void firstA() { // System.out.println("firstA"); } @Test public void firstB() { // System.out.println("firstB"); } } testng-testng-6.9.5/src/test/java/test/dependsongroup/DependsOnGroupsTest.java0000644000175000017500000000156512551235562027144 0ustar eugeneeugenepackage test.dependsongroup; import org.testng.Assert; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class DependsOnGroupsTest extends SimpleBaseTest { @Test public void methodsShouldBeGroupedByClasses() { TestNG tng = create(new Class[] { ZeroSampleTest.class, FirstSampleTest.class, SecondSampleTest.class }); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); String[] expected = new String[] { "zeroA", "zeroB", "firstA", "firstB", "secondA", "secondB" }; for (int i = 0; i < expected.length; i++) { ITestResult testResult = tla.getPassedTests().get(i); Assert.assertEquals(testResult.getMethod().getMethodName(), expected[i]); } } } testng-testng-6.9.5/src/test/java/test/dependent/0000755000175000017500000000000012551235562021265 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/dependent/xml/0000755000175000017500000000000012551235562022065 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/dependent/xml/GroupDependencyTest.java0000644000175000017500000000416112551235562026665 0ustar eugeneeugenepackage test.dependent.xml; import org.testng.Assert; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; import java.util.Arrays; import java.util.List; public class GroupDependencyTest extends SimpleBaseTest { @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { new String[] { "a", "b", "c", "a1", "b1", "c1" } }, new Object[] { new String[] { "a", "c", "b", "a1", "c1", "b1" } }, new Object[] { new String[] { "b", "a", "c", "b1", "a1", "c1" } }, new Object[] { new String[] { "b", "c", "a", "b1", "c1", "a1" } }, new Object[] { new String[] { "c", "b", "a", "c1", "b1", "a1" } }, new Object[] { new String[] { "c", "a", "b", "c1", "a1", "b1" } }, }; } @Test(dataProvider = "dp") public void verifyGroupSingle(String[] a) { configureGroup(a, false /* single */); } @Test(dataProvider = "dp") public void verifyGroupMulti(String[] a) { configureGroup(a, true /* multi */); } private void configureGroup(String[] a, boolean multi) { XmlSuite suite = createXmlSuite("Dependencies"); XmlTest test = createXmlTest(suite, "DependencyTest", GroupDependencySampleTest.class.getName()); if (multi) { test.addXmlDependencyGroup(a[2], a[1] + " " + a[0]); } else { test.addXmlDependencyGroup(a[2], a[1]); test.addXmlDependencyGroup(a[1], a[0]); } TestNG tng = create(); tng.setXmlSuites(Arrays.asList(suite)); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); List t = tla.getPassedTests(); String method2 = t.get(2).getMethod().getMethodName(); if (multi) { // When we have "a depends on groups b and c", the only certainty is that "a" // will be run last Assert.assertEquals(method2, a[5]); } else { assertTestResultsEqual(tla.getPassedTests(), Arrays.asList(a[3], a[4], a[5])); } } } testng-testng-6.9.5/src/test/java/test/dependent/xml/GroupDependencySampleTest.java0000644000175000017500000000036412551235562030030 0ustar eugeneeugenepackage test.dependent.xml; import org.testng.annotations.Test; public class GroupDependencySampleTest { @Test(groups = "a") public void a1() {} @Test(groups = "b") public void b1() {} @Test(groups = "c") public void c1() {} } testng-testng-6.9.5/src/test/java/test/dependent/functionality1/0000755000175000017500000000000012551235562024236 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/dependent/functionality1/Test2.java0000644000175000017500000000050212551235562026077 0ustar eugeneeugenepackage test.dependent.functionality1; import org.testng.annotations.Test; @Test(groups = "tests.functional.upload", dependsOnGroups = "tests.functional.package") public class Test2 { public void test2_1() { System.out.println("Test 2_1"); } public void test2_2() { System.out.println("Test 2_2"); } } testng-testng-6.9.5/src/test/java/test/dependent/functionality1/Test1.java0000644000175000017500000000043512551235562026103 0ustar eugeneeugenepackage test.dependent.functionality1; import org.testng.annotations.Test; @Test (groups = "tests.functional.package") public class Test1 { public void test1_1(){ System.out.println("Test 1_1"); } public void test1_2(){ System.out.println("Test 1_2"); } } testng-testng-6.9.5/src/test/java/test/dependent/functionality1/Config.java0000644000175000017500000000035312551235562026307 0ustar eugeneeugenepackage test.dependent.functionality1; import org.testng.annotations.BeforeSuite; public class Config { @BeforeSuite (groups = "other") public void beforeSuite(){ System.out.println("BeforeSuite group 'other'"); } } testng-testng-6.9.5/src/test/java/test/dependent/Test1.java0000644000175000017500000000006112551235562023125 0ustar eugeneeugenepackage test.dependent; public class Test1 { } testng-testng-6.9.5/src/test/java/test/dependent/SampleDependentTest.java0000644000175000017500000000147312551235562026045 0ustar eugeneeugenepackage test.dependent; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class SampleDependentTest extends SimpleBaseTest { @Test public void test2() { TestNG tng = create(SD2.class); SD2.m_log.clear(); tng.run(); boolean oneA = false; boolean oneB = false; boolean secondA = false; for (String s : SD2.m_log) { if ("oneA".equals(s)) { oneA = true; } if ("oneB".equals(s)) { oneB = true; } if ("secondA".equals(s)) { Assert.assertTrue(oneA); Assert.assertTrue(oneB); secondA = true; } if ("thirdA".equals(s)) { Assert.assertTrue(oneA); Assert.assertTrue(oneB); Assert.assertTrue(secondA); } } } } testng-testng-6.9.5/src/test/java/test/dependent/SampleDependentMethods6.java0000644000175000017500000000043312551235562026612 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; /** * This class * * @author cbeust */ public class SampleDependentMethods6 { @Test(dependsOnMethods = { "step2" }) public void step1() { } @Test(dependsOnMethods = { "step1" }) public void step2() { } } testng-testng-6.9.5/src/test/java/test/dependent/SampleDependentMethods5.java0000644000175000017500000000041112551235562026605 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; /** * This class * * @author cbeust */ public class SampleDependentMethods5 { @Test public void step1() { } @Test(dependsOnMethods = { "step1", "blablabla" }) public void step2() { } } testng-testng-6.9.5/src/test/java/test/dependent/SampleDependentMethods4.java0000644000175000017500000000061512551235562026612 0ustar eugeneeugenepackage test.dependent; import org.testng.Assert; import org.testng.annotations.Test; /** * This class * * @author cbeust */ public class SampleDependentMethods4 { @Test public void step1() { } @Test(dependsOnMethods = { "step1" }) public void step2() { Assert.assertTrue(false, "Problem in step2"); } @Test(dependsOnMethods = { "step2" }) public void step3() { } } testng-testng-6.9.5/src/test/java/test/dependent/SampleDependentMethods3.java0000644000175000017500000000243012551235562026606 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.AfterClass; import org.testng.annotations.Parameters; import org.testng.annotations.Test; /** * This class tests overloaded dependent methods * * @author Cedric Beust, Aug 19, 2004 * */ public class SampleDependentMethods3 { private boolean m_oneA = false; private boolean m_oneB = false; private boolean m_secondA = false; @Test public void one() { // ppp("oneA"); assert ! m_secondA : "secondA shouldn't have been run yet"; m_oneA = true; } @Parameters({ "foo" }) @Test public void one(String s) { // ppp("oneB"); assert ! m_secondA : "secondA shouldn't have been run yet"; assert "Cedric".equals(s) : "Expected parameter value Cedric but got " + s; m_oneB = true; } @Test(dependsOnMethods = { "one" } ) public void secondA() { // ppp("secondA"); assert m_oneA : "oneA wasn't run"; assert m_oneB : "oneB wasn't run"; assert ! m_secondA : "secondA shouldn't have been run yet"; m_secondA = true; } @AfterClass public void tearDown() { assert m_oneA : "oneA wasn't run"; assert m_oneB : "oneB wasn't run"; assert m_secondA : "secondA wasn't run"; } public static void ppp(String s) { System.out.println("[SampleDependentMethods] " + s); } }testng-testng-6.9.5/src/test/java/test/dependent/SampleDependentMethods2.java0000644000175000017500000000311012551235562026601 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; /** * This class exercises dependent methods * * @author Cedric Beust, Aug 19, 2004 * */ public class SampleDependentMethods2 { private boolean m_oneA = false; private boolean m_oneB = false; private boolean m_secondA = false; private boolean m_thirdA = false; @Test(groups = { "one" }) public void oneA() { // ppp("oneA"); assert ! m_secondA : "secondA shouldn't have been run yet"; m_oneA = true; } @Test public void canBeRunAnytime() { } @Test(dependsOnGroups = { "one" } ) public void secondA() { // ppp("secondA"); assert m_oneA : "oneA wasn't run"; assert m_oneB : "oneB wasn't run"; assert ! m_secondA : "secondA shouldn't have been run yet"; m_secondA = true; } @Test(dependsOnMethods= { "secondA" }) public void thirdA() { // ppp("thirdA"); assert m_oneA : "oneA wasn't run"; assert m_oneB : "oneB wasn't run"; assert m_secondA : "secondA wasn't run"; assert ! m_thirdA : "thirdA shouldn't have been run yet"; m_thirdA = true; } @Test(groups = { "one" }) public void oneB() { // ppp("oneB"); assert ! m_secondA : "secondA shouldn't have been run yet"; m_oneB = true; } @AfterClass public void tearDown() { assert m_oneA : "oneA wasn't run"; assert m_oneB : "oneB wasn't run"; assert m_secondA : "secondA wasn't run"; assert m_thirdA : "thirdA wasn't run"; } public static void ppp(String s) { System.out.println("[SampleDependentMethods] " + s); } }testng-testng-6.9.5/src/test/java/test/dependent/SampleDependentMethods.java0000644000175000017500000000312112551235562026521 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; /** * This class exercises dependent methods * * @author Cedric Beust, Aug 19, 2004 * */ public class SampleDependentMethods { private boolean m_oneA = false; private boolean m_oneB = false; private boolean m_secondA = false; private boolean m_thirdA = false; @Test public void oneA() { // ppp("oneA"); // assert false : "TEMPORARY FAILURE"; assert ! m_secondA : "secondA shouldn't have been run yet"; m_oneA = true; } @Test public void canBeRunAnytime() { } @Test(dependsOnMethods= { "oneA", "oneB" }) public void secondA() { // ppp("secondA"); assert m_oneA : "oneA wasn't run"; assert m_oneB : "oneB wasn't run"; assert ! m_secondA : "secondA shouldn't have been run yet"; m_secondA = true; } @Test(dependsOnMethods= { "secondA" }) public void thirdA() { // ppp("thirdA"); assert m_oneA : "oneA wasn't run"; assert m_oneB : "oneB wasn't run"; assert m_secondA : "secondA wasn't run"; assert ! m_thirdA : "thirdA shouldn't have been run yet"; m_thirdA = true; } @Test public void oneB() { // ppp("oneB"); assert ! m_secondA : "secondA shouldn't have been run yet"; m_oneB = true; } @AfterClass public void tearDown() { assert m_oneA : "oneA wasn't run"; assert m_oneB : "oneB wasn't run"; assert m_secondA : "secondA wasn't run"; assert m_thirdA : "thirdA wasn't run"; } public static void ppp(String s) { System.out.println("[SampleDependentMethods] " + s); } }testng-testng-6.9.5/src/test/java/test/dependent/SampleDependentConfigurationMethods.java0000644000175000017500000000120512551235562031252 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class SampleDependentConfigurationMethods { private boolean m_create = false; private boolean m_first = false; @BeforeMethod public void createInstance() { m_create = true; } @BeforeMethod(dependsOnMethods = { "createInstance"}) public void firstInvocation() { assert m_create : "createInstance() was never called"; m_first = true; } @Test public void verifyDependents() { assert m_create : "createInstance() was never called"; assert m_first : "firstInvocation() was never called"; } } testng-testng-6.9.5/src/test/java/test/dependent/SampleDependent1.java0000644000175000017500000000057412551235562025267 0ustar eugeneeugenepackage test.dependent; import org.testng.Assert; import org.testng.annotations.Test; /** * This class exercises dependent groups * * @author Cedric Beust, Aug 19, 2004 * */ public class SampleDependent1 { @Test(groups = { "fail" }) public void fail() { Assert.assertTrue(false); } @Test(dependsOnGroups = { "fail" }) public void shouldBeSkipped() { } } testng-testng-6.9.5/src/test/java/test/dependent/SD2.java0000644000175000017500000000115512551235562022522 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.List; public class SD2 { public static List m_log = new ArrayList<>(); @Test(groups = { "one" }) public void oneA() { m_log.add("oneA"); } @Test public void canBeRunAnytime() { m_log.add("canBeRunAnytime"); } @Test(dependsOnGroups = { "one" } ) public void secondA() { m_log.add("secondA"); } @Test(dependsOnMethods= { "secondA" }) public void thirdA() { m_log.add("thirdA"); } @Test(groups = { "one" }) public void oneB() { m_log.add("oneB"); } }testng-testng-6.9.5/src/test/java/test/dependent/OrderMethodTest.java0000644000175000017500000000121212551235562025200 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; /** * This class verifies that when methods have dependents, they are run * in the correct order. * * @author Cedric Beust, Aug 19, 2004 * */ public class OrderMethodTest extends BaseOrderMethodTest { @Test(groups = { "1.0" }) public void z_first0() { // ppp("1.0"); m_group1[0] = true; } @Test(groups = { "2.1" }, dependsOnGroups = { "1.0", "1.1" }) public void a_second1() { // ppp("2.1"); verifyGroup(2, m_group1); m_group2[1] = true; } @Test(groups = { "1.1" }) public void z_premiere1() { // ppp("1.1"); m_group1[1] = true; } } testng-testng-6.9.5/src/test/java/test/dependent/MultipleDependentSampleTest.java0000644000175000017500000000056312551235562027560 0ustar eugeneeugenepackage test.dependent; import org.testng.Assert; import org.testng.annotations.Test; public class MultipleDependentSampleTest { @Test public void init() {} @Test(dependsOnMethods = "init") public void fail() { Assert.fail(); } @Test(dependsOnMethods = "fail") public void skip1() {} @Test(dependsOnMethods = "skip1") public void skip2() {} } testng-testng-6.9.5/src/test/java/test/dependent/MultiGroupTest.java0000644000175000017500000000116512551235562025102 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; import test.BaseTest; public class MultiGroupTest extends BaseTest { @Test public void verifyDependsOnMultiGroups() { addClass(MultiGroup1SampleTest.class.getName()); addClass(MultiGroup2SampleTest.class.getName()); run(); String[] passed = { "testA", }; String[] failed = { "test1" }; String[] skipped = { "test2" }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } } testng-testng-6.9.5/src/test/java/test/dependent/MultiGroup2SampleTest.java0000644000175000017500000000032712551235562026325 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; @Test(groups = {"integration"}, dependsOnGroups = {"checkin", "a"}) public class MultiGroup2SampleTest { public void test2() throws Exception { } } testng-testng-6.9.5/src/test/java/test/dependent/MultiGroup1SampleTest.java0000644000175000017500000000041012551235562026315 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; @Test(groups = { "checkin" }) public class MultiGroup1SampleTest { @Test(groups = {"a"}) public void testA() { } public void test1() throws Exception { throw new Exception("fail"); } } testng-testng-6.9.5/src/test/java/test/dependent/MissingMethodTest.java0000644000175000017500000000115312551235562025542 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; import test.BaseTest; public class MissingMethodTest extends BaseTest { @Test public void verifyThatExceptionIsThrownIfMissingMethod() { addClass("test.dependent.MissingMethodSampleTest"); run(); String[] passed = { "explicitlyIgnoreMissingMethod", "alwaysRunDespiteMissingMethod" }; String[] failed = { }; String[] skipped = { }; verifyTests("Failed", failed, getFailedTests()); verifyTests("Passed", passed, getPassedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } } testng-testng-6.9.5/src/test/java/test/dependent/MissingMethodSampleTest.java0000644000175000017500000000156412551235562026712 0ustar eugeneeugenepackage test.dependent; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.Parser; import java.io.ByteArrayInputStream; public class MissingMethodSampleTest { @Test(dependsOnMethods="missingMethod", ignoreMissingDependencies=true) public void explicitlyIgnoreMissingMethod() { } @Test(dependsOnMethods="missingMethod", alwaysRun=true) public void alwaysRunDespiteMissingMethod() {} public static void main(String[] args) throws Exception { TestNG tng = new TestNG(); String xml = "" + "" + ""; System.out.println(xml); ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes()); tng.setXmlSuites(new Parser(is).parseToList()); tng.run(); } } testng-testng-6.9.5/src/test/java/test/dependent/MissingGroupTest.java0000644000175000017500000000111412551235562025413 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; import test.BaseTest; public class MissingGroupTest extends BaseTest { @Test public void verifyThatExceptionIsThrownIfMissingGroup() { addClass("test.dependent.MissingGroupSampleTest"); run(); String[] passed = { "shouldNotBeSkipped" }; String[] failed = { }; String[] skipped = { "shouldBeSkipped" }; verifyTests("Failed", failed, getFailedTests()); verifyTests("Passed", passed, getPassedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } } testng-testng-6.9.5/src/test/java/test/dependent/MissingGroupSampleTest.java0000644000175000017500000000150412551235562026560 0ustar eugeneeugenepackage test.dependent; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.Parser; import java.io.ByteArrayInputStream; public class MissingGroupSampleTest { @Test(dependsOnGroups = {"missing-group"}) public void shouldBeSkipped() { } @Test(dependsOnGroups = {"missing-group"}, ignoreMissingDependencies=true) public void shouldNotBeSkipped() { } public static void main(String[] args) throws Exception { TestNG tng = new TestNG(); String xml = ""; System.out.println(xml); ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes()); tng.setXmlSuites(new Parser(is).parseToList()); tng.run(); } } testng-testng-6.9.5/src/test/java/test/dependent/InstanceSkipSampleTest.java0000644000175000017500000000214712551235562026531 0ustar eugeneeugenepackage test.dependent; import java.util.List; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; import org.testng.collections.Lists; /** * Verify that only instances that fail cause dependency failures. In other words, * when run, this test should show: * passed = [f#1 f#3 g#1 g#3], failed = [f#2], skipped = [g#2] * * @author Cedric Beust */ public class InstanceSkipSampleTest { private int m_n; public static List m_list = Lists.newArrayList(); @Factory(dataProvider = "dp") public InstanceSkipSampleTest(int n) { m_n = n; } @DataProvider public static Object[][] dp() { return new Object[][] { new Object[] { 1 }, new Object[] { 2 }, new Object[] { 3 }, }; } @Test public void f() { if (m_n == 2) throw new RuntimeException(); log("f"); } @Test(dependsOnMethods = "f") public void g() { log("g"); } private void log(String s) { m_list.add(s + "#" + m_n); } @Override public String toString() { return "" + m_n; } } testng-testng-6.9.5/src/test/java/test/dependent/ImplicitMethodInclusionSampleTest.java0000644000175000017500000000057012551235562030733 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; public class ImplicitMethodInclusionSampleTest { @Test(groups = {"linux"}) public void a() { // ppp("A"); } @Test(groups = {"linux", "windows"} , dependsOnMethods={"a"}) public void b() { // ppp("B"); } private void ppp(String string) { System.out.println("[Implicit] " + string); } } testng-testng-6.9.5/src/test/java/test/dependent/ImplicitGroupInclusionTest.java0000644000175000017500000000452212551235562027446 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; import test.BaseTest; public class ImplicitGroupInclusionTest extends BaseTest { @Test public void verifyImplicitGroupInclusion() { addClass("test.dependent.ImplicitGroupInclusionSampleTest"); addIncludedGroup("b"); run(); String[] passed = { "a", "b", "z" }; String[] failed = { }; String[] skipped = { }; verifyTests("Failed", failed, getFailedTests()); verifyTests("Passed", passed, getPassedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test public void verifyImplicitGroupInclusion2() { addClass("test.dependent.ImplicitGroupInclusion2SampleTest"); addIncludedGroup("g2"); run(); String[] passed = { "m3" }; String[] failed = { }; String[] skipped = { }; verifyTests("Failed", failed, getFailedTests()); verifyTests("Passed", passed, getPassedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test public void verifyImplicitGroupInclusion4() { addClass("test.dependent.ImplicitGroupInclusion4SampleTest"); addIncludedGroup("g2"); run(); String[] passed = { "m3", "m4" }; String[] failed = { }; String[] skipped = { }; verifyTests("Failed", failed, getFailedTests()); verifyTests("Passed", passed, getPassedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test public void verifyImplicitGroupInclusion3() { addClass("test.dependent.ImplicitGroupInclusion3SampleTest"); addIncludedGroup("inc"); addExcludedGroup("exc"); run(); String[] passed = { "test1" }; String[] failed = { }; String[] skipped = { }; verifyTests("Failed", failed, getFailedTests()); verifyTests("Passed", passed, getPassedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test public void verifyImplicitMethodInclusion() { addClass("test.dependent.ImplicitMethodInclusionSampleTest"); addIncludedGroup("windows"); run(); String[] passed = { "a", "b" }; String[] failed = { }; String[] skipped = { }; verifyTests("Failed", failed, getFailedTests()); verifyTests("Passed", passed, getPassedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } } testng-testng-6.9.5/src/test/java/test/dependent/ImplicitGroupInclusionSampleTest.java0000644000175000017500000000046212551235562030607 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; public class ImplicitGroupInclusionSampleTest { @Test(groups = "z") public void z() { } @Test(groups = "a", dependsOnGroups = {"z"}) public void a() { } @Test(groups = "b", dependsOnGroups = {"a"}) public void b() { } } testng-testng-6.9.5/src/test/java/test/dependent/ImplicitGroupInclusion4SampleTest.java0000644000175000017500000000156212551235562030675 0ustar eugeneeugenepackage test.dependent; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class ImplicitGroupInclusion4SampleTest { private boolean m_m1, m_m2, m_m3, m_m4; @BeforeClass(groups = {"g2"}) public void init() { m_m1 = m_m2 = m_m3 = m_m4 = false; } @Test (groups = {"g1"}) public void m1() { m_m1 = true; } @Test (groups = {"g1"}, dependsOnMethods="m1") public void m2() { m_m2 = true; } @Test (groups = {"g2"}) public void m3() { m_m3 = true; } @Test (groups = {"g2"}, dependsOnMethods="m3") public void m4() { m_m4 = true; } @AfterClass(groups = {"g2"}) public void verify() { Assert.assertFalse(m_m1, "Shouldn't have invoked m1()"); Assert.assertFalse(m_m2); Assert.assertTrue(m_m3); Assert.assertTrue(m_m4); } }testng-testng-6.9.5/src/test/java/test/dependent/ImplicitGroupInclusion3SampleTest.java0000644000175000017500000000060612551235562030672 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; public class ImplicitGroupInclusion3SampleTest { @Test( groups = {"inc"} ) public void test1() {} @Test( groups = {"exc"} ) public void test2() { throw new RuntimeException("exclude me"); } @Test( groups = {"exc"}, dependsOnMethods={"test2"} ) public void test3() { throw new RuntimeException("exclude me"); } }testng-testng-6.9.5/src/test/java/test/dependent/ImplicitGroupInclusion2SampleTest.java0000644000175000017500000000136112551235562030670 0ustar eugeneeugenepackage test.dependent; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class ImplicitGroupInclusion2SampleTest { private boolean m_m1, m_m2, m_m3; @BeforeClass(groups = {"g2"}) public void init() { m_m1 = m_m2 = m_m3 = false; } @Test (groups = {"g1"}) public void m1() { m_m1 = true; } @Test (groups = {"g1"}, dependsOnMethods="m1") public void m2() { m_m2 = true; } @Test (groups = {"g2"}) public void m3() { m_m3 = true; } @AfterClass(groups = {"g2"}) public void verify() { Assert.assertFalse(m_m1, "Shouldn't have invoked m1()"); Assert.assertFalse(m_m2); Assert.assertTrue(m_m3); } }testng-testng-6.9.5/src/test/java/test/dependent/GroupByInstancesTest.java0000644000175000017500000000230112551235562026223 0ustar eugeneeugenepackage test.dependent; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.collections.Lists; import test.SimpleBaseTest; import java.util.List; public class GroupByInstancesTest extends SimpleBaseTest { @Test public void dontGroupByInstances() { runTest(false); } @Test public void groupByInstances() { runTest(true); } private void runTest(boolean group) { TestNG tng = create(GroupByInstancesSampleTest.class); GroupByInstancesSampleTest.m_log = Lists.newArrayList(); tng.setGroupByInstances(group); tng.run(); List log = GroupByInstancesSampleTest.m_log; int i = 0; if (group) { Assert.assertTrue(log.get(i++).startsWith("signIn")); Assert.assertTrue(log.get(i++).startsWith("signOut")); Assert.assertTrue(log.get(i++).startsWith("signIn")); Assert.assertTrue(log.get(i++).startsWith("signOut")); } else { Assert.assertTrue(log.get(i++).startsWith("signIn")); Assert.assertTrue(log.get(i++).startsWith("signIn")); Assert.assertTrue(log.get(i++).startsWith("signOut")); Assert.assertTrue(log.get(i++).startsWith("signOut")); } } } testng-testng-6.9.5/src/test/java/test/dependent/GroupByInstancesSampleTest.java0000644000175000017500000000206312551235562027372 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; import org.testng.collections.Lists; import java.util.List; public class GroupByInstancesSampleTest { private String m_country; public static List m_log = Lists.newArrayList(); private static void log(String method, String country) { // System.out.println("LOG:" + method + "#" + country + " " + Thread.currentThread().getId()); m_log.add(method + "#" + country); } @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { "usa" }, new Object[] { "uk" }, }; } @Factory(dataProvider = "dp") public GroupByInstancesSampleTest(String country) { m_country = country; } @Test public void signIn() { log("signIn", m_country); } @Test(dependsOnMethods = "signIn") public void signOut() { log("signOut", m_country); } @Override public String toString() { return "[GroupByInstancesSampleTest: " + m_country + "]"; } } testng-testng-6.9.5/src/test/java/test/dependent/DifferentClassDependsOnGroupsTest2.java0000644000175000017500000000027312551235562030750 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; public class DifferentClassDependsOnGroupsTest2 { @Test(dependsOnGroups = { "mainGroup" }) public void test1() { } } testng-testng-6.9.5/src/test/java/test/dependent/DifferentClassDependsOnGroupsTest1.java0000644000175000017500000000051712551235562030750 0ustar eugeneeugenepackage test.dependent; import static org.testng.Assert.assertTrue; import org.testng.annotations.Test; public class DifferentClassDependsOnGroupsTest1 { @Test(groups = { "mainGroup" }) public void test0() { assertTrue(1 == 0); // Force a failure } @Test(dependsOnGroups= {"mainGroup"}) public void test2() { } } testng-testng-6.9.5/src/test/java/test/dependent/DepthDependencyTest.java0000644000175000017500000000052512551235562026035 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; public class DepthDependencyTest { @Test(groups = { "1"} ) public void f1() { throw new RuntimeException(); } @Test(groups = { "2"}, dependsOnGroups = {"1"} ) public void f2() { } @Test(groups = { "3"}, dependsOnGroups = {"2"} ) public void f3() { } } testng-testng-6.9.5/src/test/java/test/dependent/DependsOnProtectedMethodTest.java0000644000175000017500000000122012551235562027655 0ustar eugeneeugenepackage test.dependent; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * This class/interface */ public class DependsOnProtectedMethodTest { private boolean m_before1 = false; private boolean m_before2 = false; @BeforeMethod(dependsOnMethods = { "before2" }) protected void before() { m_before1 = true; } @BeforeMethod protected void before2() { m_before2 = true; } @Test public void verifyBeforeInvocations() { Assert.assertTrue(m_before1 && m_before2, "Protected dependent @BeforeMethods should have been invoked"); } } testng-testng-6.9.5/src/test/java/test/dependent/DependentWithDataProviderSampleTest.java0000644000175000017500000000217412551235562031205 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; import org.testng.collections.Lists; import java.util.List; public class DependentWithDataProviderSampleTest { public static List m_log = Lists.newArrayList(); private String param; @Factory( dataProvider = "prov" ) public DependentWithDataProviderSampleTest( String param ) { this.param = param; } @DataProvider( name = "prov" ) public static Object[][] dataProvider() { return new Object[][] { { "One" }, { "Two" }, { "Three" }, }; } private void log(String s) { m_log.add(s + "#" + param); } @BeforeClass public void prepare() { log("prepare"); } @Test public void test1() { log("test1"); } @Test( dependsOnMethods = "test1" ) public void test2() { log("test2"); } @AfterClass public void clean() { log("clean"); } @Override public String toString() { return "[" + param + "]"; } } testng-testng-6.9.5/src/test/java/test/dependent/DependentTest.java0000644000175000017500000000720212551235562024677 0ustar eugeneeugenepackage test.dependent; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.ExpectedExceptions; import org.testng.annotations.Test; import test.BaseTest; import test.SimpleBaseTest; import java.util.List; public class DependentTest extends BaseTest { @Test public void simpleSkip() { addClass(SampleDependent1.class.getName()); run(); String[] passed = {}; String[] failed = { "fail" }; String[] skipped = { "shouldBeSkipped" }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test public void dependentMethods() { addClass(SampleDependentMethods.class.getName()); run(); String[] passed = { "oneA", "oneB", "secondA", "thirdA", "canBeRunAnytime" }; String[] failed = {}; String[] skipped = {}; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test public void dependentMethodsWithSkip() { addClass(SampleDependentMethods4.class.getName()); run(); String[] passed = { "step1", }; String[] failed = { "step2", }; String[] skipped = { "step3" }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test @ExpectedExceptions({ org.testng.TestNGException.class }) public void dependentMethodsWithNonExistentMethod() { addClass(SampleDependentMethods5.class.getName()); run(); String[] passed = { "step1", "step2" }; String[] failed = {}; String[] skipped = {}; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test(expectedExceptions = org.testng.TestNGException.class) public void dependentMethodsWithCycle() { addClass(SampleDependentMethods6.class.getName()); run(); } @Test(expectedExceptions = org.testng.TestNGException.class) public void dependentGroupsWithCycle() { addClass("test.dependent.SampleDependentMethods7"); run(); } @Test public void multipleSkips() { addClass(MultipleDependentSampleTest.class.getName()); run(); String[] passed = { "init", }; String[] failed = { "fail", }; String[] skipped = { "skip1", "skip2" }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test public void instanceDependencies() { addClass(InstanceSkipSampleTest.class.getName()); run(); verifyInstanceNames("Passed", getPassedTests(), new String[] { "f#1", "f#3", "g#1", "g#3"}); verifyInstanceNames("Failed", getFailedTests(), new String[] { "f#2" }); verifyInstanceNames("Skipped", getSkippedTests(), new String[] { "g#" }); } @Test public void dependentWithDataProvider() { TestNG tng = SimpleBaseTest.create(DependentWithDataProviderSampleTest.class); tng.setGroupByInstances(true); List log = DependentWithDataProviderSampleTest.m_log; log.clear(); tng.run(); for (int i = 0; i < 12; i += 4) { String[] s = log.get(i).split("#"); String instance = s[1]; Assert.assertEquals(log.get(i), "prepare#" + instance); Assert.assertEquals(log.get(i + 1), "test1#" + instance); Assert.assertEquals(log.get(i + 2), "test2#" + instance); Assert.assertEquals(log.get(i + 3), "clean#" + instance); } } } // DependentTest testng-testng-6.9.5/src/test/java/test/dependent/DependentOnMethod1AlwaysRunSampleTest.java0000644000175000017500000000114112551235562031422 0ustar eugeneeugenepackage test.dependent; import org.testng.Assert; import org.testng.annotations.Test; /** * a will fail but b should run anyway because of alwaysRun=true * * Created on Nov 18, 2005 * @author cbeust */ public class DependentOnMethod1AlwaysRunSampleTest { private boolean m_ok = false; @Test public void a() { throw new RuntimeException("Voluntary failure"); } @Test(dependsOnMethods = {"a"}, alwaysRun = true) public void b() { m_ok = true; } @Test(dependsOnMethods = {"b"}) public void verify() { Assert.assertTrue(m_ok, "method b() should have been invoked"); } } testng-testng-6.9.5/src/test/java/test/dependent/DependentOnGroup2AlwaysRunSampleTest.java0000644000175000017500000000126512551235562031306 0ustar eugeneeugenepackage test.dependent; import org.testng.Assert; import org.testng.annotations.Test; /** * a will fail but b should run anyway because of alwaysRun=true * * Created on Nov 18, 2005 * @author cbeust */ public class DependentOnGroup2AlwaysRunSampleTest { private boolean m_ok = false; @Test(groups = { "group-a"}) public void a() { throw new RuntimeException("Voluntary failure"); } @Test(groups = { "group-a"}) public void a2() { } @Test(dependsOnGroups = {"group-a"}, alwaysRun = true) public void b() { m_ok = true; } @Test(dependsOnMethods = {"b"}) public void verify() { Assert.assertTrue(m_ok, "method b() should have been invoked"); } } testng-testng-6.9.5/src/test/java/test/dependent/DependentOnGroup1AlwaysRunSampleTest.java0000644000175000017500000000117412551235562031304 0ustar eugeneeugenepackage test.dependent; import org.testng.Assert; import org.testng.annotations.Test; /** * a will fail but b should run anyway because of alwaysRun=true * * Created on Nov 18, 2005 * @author cbeust */ public class DependentOnGroup1AlwaysRunSampleTest { private boolean m_ok = false; @Test(groups = { "group-a"}) public void a() { throw new RuntimeException("Voluntary failure"); } @Test(dependsOnGroups = {"group-a"}, alwaysRun = true) public void b() { m_ok = true; } @Test(dependsOnMethods = {"b"}) public void verify() { Assert.assertTrue(m_ok, "method b() should have been invoked"); } } testng-testng-6.9.5/src/test/java/test/dependent/DependentAlwaysRunTest.java0000644000175000017500000000265312551235562026552 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; import test.BaseTest; public class DependentAlwaysRunTest extends BaseTest { @Test public void verifyDependsOnMethodsAlwaysRun() { addClass("test.dependent.DependentOnMethod1AlwaysRunSampleTest"); run(); String[] passed = { "b", "verify" }; String[] failed = { "a" }; String[] skipped = { }; verifyTests("Failed", failed, getFailedTests()); verifyTests("Passed", passed, getPassedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test public void verifyDependsOnGroups1AlwaysRun() { addClass("test.dependent.DependentOnGroup1AlwaysRunSampleTest"); run(); String[] passed = { "b", "verify" }; String[] failed = { "a" }; String[] skipped = { }; verifyTests("Failed", failed, getFailedTests()); verifyTests("Passed", passed, getPassedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test public void verifyDependsOnGroups2AlwaysRun() { addClass("test.dependent.DependentOnGroup2AlwaysRunSampleTest"); run(); String[] passed = { "a2", "b", "verify" }; String[] failed = { "a" }; String[] skipped = { }; verifyTests("Failed", failed, getFailedTests()); verifyTests("Passed", passed, getPassedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } } testng-testng-6.9.5/src/test/java/test/dependent/DependencyFixTest.java0000644000175000017500000000111312551235562025511 0ustar eugeneeugenepackage test.dependent; import static org.testng.Assert.assertTrue; import org.testng.annotations.Test; public class DependencyFixTest { @Test(dependsOnMethods = "helloWorld", ignoreMissingDependencies = true) public void dependentOnNonExistingMethod() { assertTrue(true); } @Test(dependsOnMethods = "dependentOnNonExistingMethod") public void dependentOnExistingMethod() { assertTrue(true); } @Test(groups = "selfSufficient", dependsOnGroups = "nonExistingGroup", ignoreMissingDependencies = true) public void dependentOnNonExistingGroup() { assertTrue(true); } } testng-testng-6.9.5/src/test/java/test/dependent/DepBugVerifyTest.java0000644000175000017500000000064512551235562025330 0ustar eugeneeugenepackage test.dependent; import org.testng.Assert; import org.testng.annotations.Test; import java.util.List; public class DepBugVerifyTest { @Test public void verify() { List log = DepBugSampleTest.getLog(); String[] expected = new String[] { "setup", "send", "get", "destroy" }; for (int i = 0; i < log.size(); i++) { Assert.assertEquals(expected[i], log.get(i)); } } } testng-testng-6.9.5/src/test/java/test/dependent/DepBugSampleTest.java0000644000175000017500000000151712551235562025304 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.List; @Test public class DepBugSampleTest { private static List m_log = new ArrayList<>(); private static void log(String s) { // ppp(s); m_log.add(s); } private static void ppp(String s) { System.out.println("[DepBugSampleTest] " + s); } public static List getLog() { return m_log; } @BeforeClass public void setup() throws Exception { log("setup"); } @AfterClass public void destroy() throws Exception { log("destroy"); } @Test(dependsOnMethods = "send") public void get() throws Exception { log("get"); } public void send() throws Exception { log("send"); } } testng-testng-6.9.5/src/test/java/test/dependent/ClassWide2Test.java0000644000175000017500000000053012551235562024726 0ustar eugeneeugenepackage test.dependent; import org.testng.Assert; import org.testng.annotations.Test; public class ClassWide2Test { // @Test(dependsOnMethods = {"m1" }) @Test(dependsOnMethods = {"test.dependent.ClassWide1Test.m1" }) public void m2() { Assert.assertTrue(ClassWide1Test.m1WasRun()); } // @Test // public void m1() { // // } } testng-testng-6.9.5/src/test/java/test/dependent/ClassWide1Test.java0000644000175000017500000000053112551235562024726 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class ClassWide1Test { private static boolean m_ok = false; @BeforeTest public void init() { m_ok = false; } @Test public void m1() { m_ok = true; } public static boolean m1WasRun() { return m_ok; } } testng-testng-6.9.5/src/test/java/test/dependent/ClassDependsOnGroups.java0000644000175000017500000000173312551235562026201 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; import test.BaseTest; public class ClassDependsOnGroups extends BaseTest { @Test public void verifyDependsOnGroups() { addClass(test.dependent.DifferentClassDependsOnGroupsTest1.class.getName()); addClass(test.dependent.DifferentClassDependsOnGroupsTest2.class.getName()); run(); String[] failed = { "test0" }; String[] skipped = { "test1", "test2" }; verifyTests("Failed", failed, getFailedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test public void verifyGroupsAcrossClasses() { addClass(test.dependent.C1.class.getName()); addClass(test.dependent.C2.class.getName()); run(); String[] failed = { "failingTest" }; String[] skipped = { "shouldBeSkipped" }; verifyTests("Failed", failed, getFailedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } } testng-testng-6.9.5/src/test/java/test/dependent/C2.java0000644000175000017500000000047712551235562022404 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; @Test(groups={"group2"}, dependsOnGroups={"group1"}) public class C2 { public void shouldBeSkipped() { // the expectation is that this test will be SKIPPED because // a test in group1 failed and we have a dependsOnGroups={"group1"} } } testng-testng-6.9.5/src/test/java/test/dependent/C1.java0000644000175000017500000000032212551235562022370 0ustar eugeneeugenepackage test.dependent; import static org.testng.Assert.fail; import org.testng.annotations.Test; @Test(groups="group1") public class C1 { public void failingTest() { fail("always fails"); } } testng-testng-6.9.5/src/test/java/test/dependent/BaseOrderMethodTest.java0000644000175000017500000000177212551235562026006 0ustar eugeneeugenepackage test.dependent; import org.testng.annotations.Test; /** * This class * * @author Cedric Beust, Aug 20, 2004 * */ public class BaseOrderMethodTest { protected boolean[] m_group1 = { false, false }; protected boolean[] m_group2 = { false, false }; protected boolean[] m_group3 = { false }; @Test(groups = { "2.0" }, dependsOnGroups = { "1.0", "1.1" }) public void a_second0() { verifyGroup(2, m_group1); m_group2[0] = true; } @Test(groups = { "3" }, dependsOnGroups = { "2.0" }) public void third0() { verifyGroup(3, m_group2); m_group3[0] = true; } public static void ppp(String s) { System.out.println("[BaseOrderMethodTest] " + s); } protected void verifyGroup(int groupNumber, boolean[] group) { for (int i = 0; i < group.length; i++) { assert group[i] : "Error while running group " + groupNumber + ": " + " index " + i + " of previous group should have been run before."; } } } testng-testng-6.9.5/src/test/java/test/dataprovider/0000755000175000017500000000000012551235562022003 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/dataprovider/VarArgsDataProviderTest.java0000644000175000017500000000071212551235562027360 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class VarArgsDataProviderTest { private static final String[] S = new String[] { "a", "b", "c" }; @DataProvider public Object[][] data() { return new Object[][] { S }; } @Test(dataProvider = "data") public void testWithTwoEntriesInTestToolWindow(String... o) { Assert.assertEquals(o, S); } } testng-testng-6.9.5/src/test/java/test/dataprovider/UnnamedDataProviderTest.java0000644000175000017500000000137712551235562027412 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * This class/interface */ public class UnnamedDataProviderTest { private boolean m_false = false; private boolean m_true = false; @Test(dataProvider = "unnamedDataProvider") public void doStuff(boolean t) { if (t) { m_true = true; } if (! t) { m_false = true; } } @Test(dependsOnMethods = {"doStuff"} ) public void verify() { Assert.assertTrue(m_true); Assert.assertTrue(m_false); } @DataProvider public Object[][] unnamedDataProvider() { return new Object[][] { {Boolean.TRUE}, {Boolean.FALSE} }; } } testng-testng-6.9.5/src/test/java/test/dataprovider/TestNG411Test.java0000644000175000017500000000125712551235562025105 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; public class TestNG411Test { @Test public void verify() { TestNG tng = new TestNG(); tng.setVerbose(0); tng.setTestClasses(new Class[] { TestNG411SampleTest.class }); TestListenerAdapter al = new TestListenerAdapter(); tng.addListener(al); tng.run(); Assert.assertEquals(al.getPassedTests().size(), 1); Assert.assertEquals(al.getPassedTests().get(0).getMethod().getMethodName(), "checkMinTest_injection"); Assert.assertEquals(al.getFailedTests().size(), 2); } } testng-testng-6.9.5/src/test/java/test/dataprovider/TestNG411SampleTest.java0000644000175000017500000000313412551235562026243 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.ITestContext; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Used by {@link TestNG411Test}. Do not change number of methods or method names * @author nullin * */ public class TestNG411SampleTest { private static final String CHECK_MAX_DATA = "checkMaxData"; private static final String CHECK_MIN_DATA = "checkMinData"; @DataProvider(name = CHECK_MAX_DATA) public Object[][] dataProviderCheckMax() { return new Object[][] { { 1, 2, 3, 3 }, }; } @Test(description = "Number of parameters to this test don't match the " + "ones passed by data provider", dataProvider = CHECK_MAX_DATA) public void checkMaxTest(int nr1, int nr2, int expected) { Assert.fail("This code shouldnt be executed"); } @DataProvider(name = CHECK_MIN_DATA) public Object[][] dataProviderCheckMin() { return new Object[][] { { 1, 2, }, }; } @Test(description = "Number of parameters to this test don't match the " + "ones passed by data provider", dataProvider = CHECK_MIN_DATA) public void checkMinTest(int nr1, int nr2, int expected) { Assert.fail("This code shouldnt be executed"); } @Test(description = "Number of parameters to this test don't match the " + "ones passed by data provider. But an ojbect will be injected", dataProvider = CHECK_MIN_DATA) public void checkMinTest_injection(int nr1, int nr2, ITestContext ctx) { int result = Math.min(nr1, nr2); Assert.assertEquals(result, nr1); Assert.assertNotNull(ctx); } } testng-testng-6.9.5/src/test/java/test/dataprovider/TestInstanceTest.java0000644000175000017500000000162712551235562026120 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.testng.annotations.TestInstance; import java.lang.reflect.Method; public class TestInstanceTest { private int m_n; private static int m_instanceCount = 0; public TestInstanceTest() {} public TestInstanceTest(int n) { this.m_n = n; } @DataProvider public Object[][] dp(Method m, @TestInstance Object instance) { TestInstanceTest o0 = (TestInstanceTest) instance; Assert.assertTrue(o0.m_n == 1 || o0.m_n == 2); m_instanceCount++; return new Object[][] { new Object[] {42}, new Object[] {43}, }; } @Test(dataProvider = "dp") public void f(int o) { } @Override public String toString() { return "[A n:" + m_n + "]"; } private static void ppp(String s) { System.out.println("[A] " + s); } }testng-testng-6.9.5/src/test/java/test/dataprovider/TestInstanceFactory.java0000644000175000017500000000036712551235562026610 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.Factory; public class TestInstanceFactory { @Factory public Object[] init() { return new Object[] { new TestInstanceTest(1), new TestInstanceTest(2) }; } } testng-testng-6.9.5/src/test/java/test/dataprovider/TestContextTest.java0000644000175000017500000000227012551235562025773 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; public class TestContextTest { @Test public void verifyTen() { verify("10", "verifyTen", 1, 0); } @Test public void verifyFive() { verify("5", "verifyFive", 1, 0); } @Test public void verifySix() { // Not including any group, so the two test methods should fail verify(null, null, 0, 2); } private void verify(String groupName, String passed, int passedCount, int failedCount) { TestNG tng = new TestNG(); tng.setVerbose(0); tng.setTestClasses(new Class[] { TestContextSampleTest.class }); if (groupName != null) { tng.setGroups(groupName); } TestListenerAdapter al = new TestListenerAdapter(); tng.addListener(al); tng.run(); if (passedCount > 0) { Assert.assertEquals(al.getPassedTests().size(), passedCount); Assert.assertEquals(al.getPassedTests().get(0).getMethod().getMethodName(), passed); } if (failedCount > 0) { Assert.assertEquals(al.getFailedTests().size(), failedCount); } } } testng-testng-6.9.5/src/test/java/test/dataprovider/TestContextSampleTest.java0000644000175000017500000000246612551235562027144 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.ITestContext; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Tests that when a DataProvider is declared with an ITestContext, * this parameter is correctly passed. * * Created on Dec 28, 2006 * @author Cedric Beust */ public class TestContextSampleTest { /** * @return As many parameters as the name of the included group */ @DataProvider(name = "testContext") public Object[][] createContext(ITestContext ctx) { // ppp("CONTEXT:" + ctx); String[] groups = ctx.getIncludedGroups(); int n = groups.length > 0 ? new Integer(groups[0]): 0; Object[] result = new Object[n]; for (int i = 0; i < n; i++) { result[i] = "foo"; } return new Object[][] { new Object[] { result }, }; } private static void ppp(String s) { System.out.println("[TestContextSampleTest] " + s); } @Test(dataProvider = "testContext", groups="10") public void verifyTen(Object[] objects) { Assert.assertEquals(objects.length, 10); } @Test(dataProvider = "testContext", groups="5") public void verifyFive(Object[] objects) { Assert.assertEquals(objects.length, 5); } } testng-testng-6.9.5/src/test/java/test/dataprovider/StaticProvider.java0000644000175000017500000000037312551235562025613 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.DataProvider; public class StaticProvider { @DataProvider(name = "static") public static Object[][] create() { return new Object[][] { new Object[] { "Cedric" }, }; } } testng-testng-6.9.5/src/test/java/test/dataprovider/StaticDataProviderSampleTest.java0000644000175000017500000000231312551235562030403 0ustar eugeneeugenepackage 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; @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"); } } } testng-testng-6.9.5/src/test/java/test/dataprovider/Sample1Test.java0000644000175000017500000000167612551235562025022 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class Sample1Test { private boolean m_ok1 = false; private boolean m_ok2 = false; private static final String FN2 = "Anne Marie"; private static final Integer LN2 = 37; private static final String FN1 = "Cedric"; private static final Integer LN1 = 36; @DataProvider(name = "test1") public Object[][] createData() { return new Object[][] { new Object[] { FN1, LN1 }, new Object[] { FN2, LN2 }, }; } @Test(dataProvider = "test1") public void verifyNames(String firstName, Integer age) { if (firstName.equals(FN1) && age.equals(LN1)) { m_ok1 = true; } if (firstName.equals(FN2) && age.equals(LN2)) { m_ok2 = true; } } @Test(dependsOnMethods = {"verifyNames"}) public void verifyCount() { Assert.assertTrue(m_ok1 && m_ok2); } } testng-testng-6.9.5/src/test/java/test/dataprovider/ParallelDataProviderTest.java0000644000175000017500000000220112551235562027542 0ustar eugeneeugenepackage test.dataprovider; import org.testng.ITestContext; import org.testng.TestNG; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import test.SimpleBaseTest; /** * Data providers were not working properly with parallel=true * @author cbeust */ public class ParallelDataProviderTest extends SimpleBaseTest { // protected static Logger logger = Logger // .getLogger(SampleMessageLoaderTest2.class); // // This method will provide data to any test method that declares that its // Data Provider // is named "test1" @DataProvider(name = "test1", parallel = true) public Object[][] createData1() { return new Object[][] { { "Cedric", 36}, { "Anne", 37}, { "A", 36}, { "B", 37} }; } // This test method declares that its data should be supplied by the Data // Provider // named "test1" @Test(dataProvider = "test1", threadPoolSize = 5) public void verifyData1(ITestContext testContext, String n1, Integer n2) { } @Test public void shouldNotThrowConcurrentModificationException() { TestNG tng = create(ParallelDataProvider2Test.class); tng.run(); } } testng-testng-6.9.5/src/test/java/test/dataprovider/ParallelDataProvider2Test.java0000644000175000017500000000142712551235562027635 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.testng.collections.Lists; import java.util.Iterator; import java.util.List; /** * @author Jacek Pulut * * Make sure this class can run without causing a ConcurrentModificationException. */ public class ParallelDataProvider2Test { @DataProvider(parallel = true) Iterator provide() { final List ret = Lists.newArrayList(); for (int i = 0; i < 1000; i++) { ret.add(new Integer[] { i }); } return ret.iterator(); } @Test(groups = "cme", dataProvider = "provide", invocationCount = 2, threadPoolSize = 2) public void checkCME(final Integer i) { // Reporter.log("" + i, true); } }testng-testng-6.9.5/src/test/java/test/dataprovider/NonStaticProvider.java0000644000175000017500000000037112551235562026264 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.DataProvider; public class NonStaticProvider { @DataProvider(name = "external") public Object[][] create() { return new Object[][] { new Object[] { "Cedric" }, }; } } testng-testng-6.9.5/src/test/java/test/dataprovider/MyIterator.java0000644000175000017500000000116012551235562024743 0ustar eugeneeugenepackage test.dataprovider; import java.util.Iterator; public class MyIterator implements Iterator { private static int m_count = 0; private Object[][] m_data; public MyIterator(Object[][] data) { m_data = data; } @Override public boolean hasNext() { return m_count < m_data.length; } @Override public Object[] next() { ppp("RETURNING INDEX " + m_count); return m_data[m_count++]; } @Override public void remove() { } public static int getCount() { return m_count; } private static void ppp(String s) { System.out.println("[MyIterator] " + s); } } testng-testng-6.9.5/src/test/java/test/dataprovider/MethodTest.java0000644000175000017500000000301212551235562024722 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.lang.reflect.Method; public class MethodTest { @DataProvider(name = "dp1") public Object[][] createData(Method m) { Assert.assertEquals("test1", m.getName()); Assert.assertEquals("test.dataprovider.MethodTest", m.getDeclaringClass().getName()); return new Object[][] { new Object[] { "Cedric" }, new Object[] { "Alois" }, }; } @Test(dataProvider = "dp1") public void test1(String s) { Assert.assertTrue("Cedric".equals(s) || "Alois".equals(s)); } private int m_test2 = 0; private int m_test3 = 0; @DataProvider(name = "dp2") public Object[][] createData2(Method m) { if ("test2".equals(m.getName())) { m_test2++; } else if ("test3".equals(m.getName())) { m_test3++; } else { throw new RuntimeException("Received method " + m + ", expected test2 or test3"); } Assert.assertEquals("test.dataprovider.MethodTest", m.getDeclaringClass().getName()); return new Object[][] { new Object[] { "Cedric" }, }; } @Test(dataProvider = "dp2") public void test2(String s) { Assert.assertTrue("Cedric".equals(s)); } @Test(dataProvider = "dp2") public void test3(String s) { Assert.assertTrue("Cedric".equals(s)); } @Test(dependsOnMethods = {"test2", "test3"}) public void multipleTestMethods() { Assert.assertEquals(1, m_test2); Assert.assertEquals(1, m_test3); } } testng-testng-6.9.5/src/test/java/test/dataprovider/IterableTest.java0000644000175000017500000000227012551235562025236 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import java.util.Iterator; public class IterableTest { private boolean m_ok1 = false; private boolean m_ok2 = false; public static final String FN2 = "Anne Marie"; public static final Integer LN2 = 37; public static final String FN1 = "Cedric"; public static final Integer LN1 = 36; public static final Object[][] DATA = new Object[][] { new Object[] { FN1, LN1 }, new Object[] { FN2, LN2 }, }; /** * @testng.data-provider name="test1" */ public Iterator createData() { return new MyIterator(DATA); } /** * @testng.test dataProvider="test1" */ public void verifyNames(String firstName, Integer age) { if (firstName.equals(FN1) && age.equals(LN1)) { m_ok1 = true; Assert.assertEquals(MyIterator.getCount(), 1); } if (firstName.equals(FN2) && age.equals(LN2)) { m_ok2 = true; Assert.assertEquals(MyIterator.getCount(), 2); } } /** * @testng.test dependsOnMethods = "verifyNames" */ public void verifyCount() { Assert.assertTrue(m_ok1 && m_ok2); } private static void ppp(String s) { System.out.println("[IterableTest] " + s); } } testng-testng-6.9.5/src/test/java/test/dataprovider/InstanceDataProviderTest.java0000644000175000017500000000043012551235562027554 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.Factory; public class InstanceDataProviderTest { @Factory public Object[] create() { return new Object[] { new InstanceDataProviderSampleTest(), new InstanceDataProviderSampleTest() }; } } testng-testng-6.9.5/src/test/java/test/dataprovider/InstanceDataProviderSampleTest.java0000644000175000017500000000142312551235562030721 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class InstanceDataProviderSampleTest { @DataProvider public Object[][] dp() { p("DATA PROVIDER"); return new Object[][] { new Object[] {hashCode()}, }; } @BeforeClass public void beforeTest() { p("BEFORE"); } @Test(dataProvider = "dp") public void f(Integer n) { p(" PARAM:" + n); Assert.assertEquals(n, Integer.valueOf(hashCode())); } @AfterClass public void afterTest() { p("AFTER"); } private void p(String s) { if (false) { System.out.println(hashCode() + " " + s); } } } testng-testng-6.9.5/src/test/java/test/dataprovider/InnexistentDataProvider.java0000644000175000017500000000040012551235562027455 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.Test; /** * This class/interface */ public class InnexistentDataProvider { @Test(dataProvider="doesnotexist") public void testMethod(String s) { // doesn't matter } } testng-testng-6.9.5/src/test/java/test/dataprovider/InheritedDataProviderTest.java0000644000175000017500000000036512551235562027732 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.Test; //@Test(description = "class") public class InheritedDataProviderTest extends InheritedDataProviderBaseSampleTest { @Test(dataProvider = "dp") public void f(String a) { } } testng-testng-6.9.5/src/test/java/test/dataprovider/InheritedDataProviderSample1Test.java0000644000175000017500000000036012551235562031150 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.DataProvider; public class InheritedDataProviderSample1Test { @DataProvider static public Object[][] dp() { return new Object[][] { new Object[] { "a" } }; } } testng-testng-6.9.5/src/test/java/test/dataprovider/InheritedDataProviderBaseSampleTest.java0000644000175000017500000000033012551235562031657 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.Test; //@Test(description = "parent") @Test (dataProviderClass=InheritedDataProviderSample1Test.class) public class InheritedDataProviderBaseSampleTest { } testng-testng-6.9.5/src/test/java/test/dataprovider/InheritanceBTest.java0000644000175000017500000000027212551235562026042 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.Test; public class InheritanceBTest extends InheritanceATest { @Test(dataProvider = "dp") public void f(String s) { } } testng-testng-6.9.5/src/test/java/test/dataprovider/InheritanceATest.java0000644000175000017500000000033412551235562026040 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.DataProvider; public class InheritanceATest { @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { "a"} }; } } testng-testng-6.9.5/src/test/java/test/dataprovider/IndicesTest.java0000644000175000017500000000075212551235562025070 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class IndicesTest { @DataProvider(indices = { 0, 2 }) public Object[][] dp1() { return new Object[][] { new Object[] { 1 }, new Object[] { 2 }, new Object[] { 3 }, }; } @Test(dataProvider = "dp1") public void indicesShouldWork(int n) { if (n == 2) throw new RuntimeException("This method should not have received a 1"); } } testng-testng-6.9.5/src/test/java/test/dataprovider/FieldInjectionProvider.java0000644000175000017500000000056512551235562027255 0ustar eugeneeugenepackage 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 }, }; } } testng-testng-6.9.5/src/test/java/test/dataprovider/FailingIterableDataProviderTest.java0000644000175000017500000000175412551235562031043 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; /** * TESTNG-291: * Exceptions thrown by Iterable DataProviders are not caught, no failed test reported */ public class FailingIterableDataProviderTest { @Test public void failingDataProvider() { TestNG testng= new TestNG(false); testng.setTestClasses(new Class[] {FailingIterableDataProvider.class}); TestListenerAdapter tla = new TestListenerAdapter(); testng.addListener(tla); testng.setVerbose(0); try { testng.run(); } catch (RuntimeException e) { Assert.fail("Exceptions thrown during tests should always be caught!", e); } Assert.assertEquals(tla.getFailedTests().size(), 1, "Should have 1 failure from a bad data-provider iteration"); Assert.assertEquals(tla.getPassedTests().size(), 5, "Should have 5 passed test from before the bad data-provider iteration"); } }testng-testng-6.9.5/src/test/java/test/dataprovider/FailingIterableDataProvider.java0000644000175000017500000000124512551235562030176 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.Iterator; public class FailingIterableDataProvider { @DataProvider(name = "dp") public Iterator createData() { return new Iterator() { int count=0; @Override public boolean hasNext() { return count<10; } @Override public Object[] next() { if (++count==6) { throw new RuntimeException(); } return new Object[] { count }; } @Override public void remove() {} }; } @Test(dataProvider="dp") public void happyTest(int count) { //pass } } testng-testng-6.9.5/src/test/java/test/dataprovider/FailingDataProviderTest.java0000644000175000017500000000227312551235562027370 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class FailingDataProviderTest extends SimpleBaseTest { private void shouldSkip(Class cls, String message, int expected) { TestNG testng = create(cls); TestListenerAdapter tla = new TestListenerAdapter(); testng.addListener(tla); testng.run(); Assert.assertEquals(tla.getSkippedTests().size(), expected, message); } @Test(description = "TESTNG-142: Exceptions in DataProvider are not reported as failed test") public void failingDataProvider() { shouldSkip(FailingDataProvider.class, "Test method should be marked as skipped", 1); } @Test(description = "TESTNG-447: Abort when two data providers have the same name") public void duplicateDataProviders() { shouldSkip(DuplicateDataProviderSampleTest.class, "", 1); } @Test public void failingDataProviderAndInvocationCount() throws Exception { shouldSkip(DataProviderWithError.class, "Test should be skipped even if invocation counter and success percentage set", 4); } } testng-testng-6.9.5/src/test/java/test/dataprovider/FailingDataProvider.java0000644000175000017500000000076412551235562026533 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * This class/interface */ public class FailingDataProvider { @DataProvider public Object[][] throwsExpectedException() { throw new RuntimeException("expected exception from @DP"); } @Test(dataProvider="throwsExpectedException") public void dpThrowingException() { Assert.fail("Method should never get invoked"); } } testng-testng-6.9.5/src/test/java/test/dataprovider/FailedDataProviderTest.java0000644000175000017500000000215612551235562027203 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import test.BaseTest; public class FailedDataProviderTest extends BaseTest { static int m_total = 0; @BeforeMethod public void init() { m_total = 0; } /** * Make sure that if a test method fails in the middle of a data provider, the rest * of the data set is still run. */ @Test public void allMethodsShouldBeInvoked() { TestNG tng = new TestNG(); tng.setTestClasses(new Class[] { FailedDataProviderSample.class }); tng.setVerbose(0); tng.run(); Assert.assertEquals(m_total, 6); } @Test public void failedDataProviderShouldCauseSkip() { addClass("test.dataprovider.DependentSampleTest"); run(); String[] passed = { "method1" }; String[] failed = { "method1" }; String[] skipped = { "method2" }; verifyTests("Failed", failed, getFailedTests()); verifyTests("Passed", passed, getPassedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } } testng-testng-6.9.5/src/test/java/test/dataprovider/FailedDataProviderSample.java0000644000175000017500000000075412551235562027507 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class FailedDataProviderSample { @DataProvider public Object[][] dp() { return new Integer[][] { new Integer[] { 1 }, new Integer[] { 2 }, new Integer[] { 3 }, }; } @Test(dataProvider = "dp") public void f(int n) { FailedDataProviderTest.m_total += n; if (n == 2) { throw new RuntimeException("Failed") ; } } } testng-testng-6.9.5/src/test/java/test/dataprovider/ExplicitDataProviderNameTest.java0000644000175000017500000000123312551235562030374 0ustar eugeneeugenepackage test.dataprovider; import static org.testng.Assert.assertEquals; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class ExplicitDataProviderNameTest extends SimpleBaseTest { @Test(description = "TESTNG-576: Prefer DataProvider explicit name") public void should_prefer_dataProvider_explicit_name() { TestNG testng = create(ExplicitDataProviderNameSample.class); TestListenerAdapter tla = new TestListenerAdapter(); testng.addListener(tla); testng.run(); assertEquals(tla.getPassedTests().size(), 1, "All tests should success"); } }testng-testng-6.9.5/src/test/java/test/dataprovider/ExplicitDataProviderNameSample.java0000644000175000017500000000066412551235562030705 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class ExplicitDataProviderNameSample { @Test(dataProvider="dp_name") public void should_find_exactly_one_data_provider(int i) {} @DataProvider(name="dp_name") Object[][] whatever_implicit_name() {return new Object[][] {{1}};} @DataProvider(name="whatever_explicit_name") Object[][] dp_name() {return null;} }testng-testng-6.9.5/src/test/java/test/dataprovider/DuplicateDataProviderSampleTest.java0000644000175000017500000000063112551235562031067 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DuplicateDataProviderSampleTest { @Test(dataProvider = "duplicate") public void f() { } @DataProvider(name = "duplicate") public Object[] dp1() { return new Object[0][]; } @DataProvider(name = "duplicate") public Object[] dp2() { return new Object[0][]; } } testng-testng-6.9.5/src/test/java/test/dataprovider/DependentSampleTest.java0000644000175000017500000000105212551235562026554 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DependentSampleTest { @DataProvider(name = "data") public Object[][] dp() { return new Object[][] { { "ok" }, { "not ok" }, }; } @Test(groups = { "a" }, dataProvider = "data") public void method1(String s) { if (!"ok".equals(s)) { throw new RuntimeException("error " + s); } } @Test(groups = { "b" }, dependsOnGroups = { "a" }) public void method2() throws InterruptedException { } } testng-testng-6.9.5/src/test/java/test/dataprovider/DataProviderWithError.java0000644000175000017500000000115712551235562027104 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Vladislav.Rassokhin */ public class DataProviderWithError { @Test(dataProvider = "Data", invocationCount = 2) public void testShouldSkip() throws Exception { Assert.fail(); } @Test(dataProvider = "Data", invocationCount = 2, successPercentage = 10) public void testShouldSkipEvenIfSuccessPercentage() throws Exception { Assert.fail(); } @DataProvider(name = "Data") public static Object[][] Data() { throw new RuntimeException("Fail"); } } testng-testng-6.9.5/src/test/java/test/dataprovider/DataProviderAsTest.java0000644000175000017500000000057012551235562026360 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Test that if a class @Test is used, the @DataProvider * method won't be considered as a test. */ @Test public class DataProviderAsTest { public void f() { } @DataProvider public Object[][] dataProvider() { throw new RuntimeException(); } } testng-testng-6.9.5/src/test/java/test/dataprovider/CreateDataTest.java0000644000175000017500000000105612551235562025505 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class CreateDataTest { /** * @testng.data-provider name = "create-data" */ @DataProvider(name = "create-data") public Object[][] create() { return new Object[][] { new Object[] { new MyObject() } }; } /** * @testng.test data-provider = "create-data" */ @Test(dataProvider = "create-data") public void testMyTest(MyObject o) { // do something with o } } class MyObject {} testng-testng-6.9.5/src/test/java/test/dataprovider/ConstructorInjectionProvider.java0000644000175000017500000000072412551235562030554 0ustar eugeneeugenepackage 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 }, }; } } testng-testng-6.9.5/src/test/java/test/dataprovider/ConfigurationAndDataProvidersTest.java0000644000175000017500000000342412551235562031433 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Make sure that all before methods except beforeTestMethod are invoked * before DataProvider. * * Created on Jan 19, 2006 * @author Cedric Beust */ public class ConfigurationAndDataProvidersTest { private boolean m_beforeSuite = false; private boolean m_beforeTest = false; private boolean m_beforeClass = false; private boolean m_beforeTestMethod = false; @DataProvider(name = "test1") public Object[][] createData() { Assert.assertTrue(m_beforeSuite, "beforeSuite should have been invoked"); Assert.assertTrue(m_beforeTest, "beforeTest should have been invoked"); Assert.assertTrue(m_beforeClass, "beforeClass should have been invoked"); Assert.assertFalse(m_beforeTestMethod, "beforeMethod should not have been invoked"); return new Object[][] { new Object[] { "Test" } }; } @Test(dataProvider = "test1") public void verifyNames(Object p) { // do nothing } @BeforeSuite public void setUpSuite () { m_beforeSuite = true; ppp("BEFORE SUITE"); } @BeforeTest public void setUpTest() { m_beforeTest = true; ppp("BEFORE TEST"); } @BeforeClass public void setUpClass() { m_beforeClass = true; ppp("BEFORE TEST CLASS"); } @BeforeMethod public void setUp() { m_beforeTestMethod = true; ppp("BEFORE TEST METHOD"); } private static void ppp(String s) { if (false) { System.out.println("[ConfigurationAndDataProvidersTest] " + s); } } } testng-testng-6.9.5/src/test/java/test/dataprovider/ClassTest.java0000644000175000017500000000067612551235562024564 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.Test; import test.BaseTest; public class ClassTest extends BaseTest { @Test(groups = { "current" }) public void includeMethodsOnly() { addClass(ClassSampleTest.class.getName()); run(); String[] passed = { "f", "g" }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } } testng-testng-6.9.5/src/test/java/test/dataprovider/ClassSampleTest.java0000644000175000017500000000057312551235562025722 0ustar eugeneeugenepackage test.dataprovider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @Test(dataProvider = "dp") public class ClassSampleTest { @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { "a" }, new Object[] { "b" }, }; } public void f(String a) { } public void g(String a) { } } testng-testng-6.9.5/src/test/java/test/dataprovider/BooleanTest.java0000644000175000017500000000143112551235562025064 0ustar eugeneeugenepackage test.dataprovider; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class BooleanTest { private boolean m_false = false; private boolean m_true = false; @Test(dataProvider = "allBooleans") public void doStuff(boolean t) { if (t) { m_true = true; } if (! t) { m_false = true; } } @Test(dependsOnMethods = {"doStuff"} ) public void verify() { Assert.assertTrue(m_true); Assert.assertTrue(m_false); } private void ppp(String string) { System.out.println("[BooleanTest] " + string); } @DataProvider(name = "allBooleans") public Object[][] createData() { return new Object[][] { new Object[] { true }, new Object[] { false }, }; } } testng-testng-6.9.5/src/test/java/test/cyclic/0000755000175000017500000000000012551235562020565 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/cyclic/SomeConcreteTests.java0000644000175000017500000000032712551235562025043 0ustar eugeneeugenepackage test.cyclic; import org.testng.annotations.Test; public class SomeConcreteTests extends AbstractGenericTests { @Test(groups="integration") public void testSomethingElse() { //... } }testng-testng-6.9.5/src/test/java/test/cyclic/HibernateConcreteTests.java0000644000175000017500000000033412551235562026037 0ustar eugeneeugenepackage test.cyclic; import org.testng.annotations.Test; public class HibernateConcreteTests extends AbstractGenericTests { @Test(groups="integration") public void testSomethingElse() { //... } }testng-testng-6.9.5/src/test/java/test/cyclic/BaseIntegrationTest.java0000644000175000017500000000050512551235562025346 0ustar eugeneeugenepackage test.cyclic; import org.testng.annotations.BeforeClass; public abstract class BaseIntegrationTest { @BeforeClass(groups="integration") protected void initIntegrationTesting() { //... } @BeforeClass(groups="integration") void executeBeforeClassDbOperations() { //... } } testng-testng-6.9.5/src/test/java/test/cyclic/AbstractGenericTests.java0000644000175000017500000000034612551235562025516 0ustar eugeneeugenepackage test.cyclic; import org.testng.annotations.Test; public abstract class AbstractGenericTests extends BaseIntegrationTest { @Test(groups="integration") public final void testSomething() { //... } } testng-testng-6.9.5/src/test/java/test/converter/0000755000175000017500000000000012551235562021326 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/converter/ConverterSample1.java0000644000175000017500000000067512551235562025373 0ustar eugeneeugenepackage test.converter; import junit.framework.TestCase; public class ConverterSample1 extends TestCase { @Override protected void setUp() throws Exception { super.setUp(); } @Override protected void tearDown() throws Exception { super.tearDown(); } public final void testClassJunit() { } public final void testSetClassId() { } public final void testSetClassName() { } } testng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/0000755000175000017500000000000012551235562024756 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/FailurePolicyTest.java0000644000175000017500000001077612551235562031243 0ustar eugeneeugenepackage test.configurationfailurepolicy; import static org.testng.Assert.assertEquals; import org.testng.ITestContext; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import testhelper.OutputDirectoryPatch; public class FailurePolicyTest { // only if this is run from an xml file that sets this on the suite @BeforeClass(enabled=false) public void setupClass( ITestContext testContext) { assertEquals(testContext.getSuite().getXmlSuite().getConfigFailurePolicy(), XmlSuite.CONTINUE); } @DataProvider( name="dp" ) public Object[][] getData() { Object[][] data = new Object[][] { // params - confFail, confSkip, skipedTests new Object[] { new Class[] { ClassWithFailedBeforeClassMethod.class }, 1, 1, 1 }, new Object[] { new Class[] { ClassWithFailedBeforeMethodAndMultipleTests.class }, 2, 0, 2 }, new Object[] { new Class[] { ClassWithFailedBeforeMethodAndMultipleInvocations.class }, 4, 0, 4 }, new Object[] { new Class[] { ExtendsClassWithFailedBeforeMethod.class }, 2, 2, 2 }, new Object[] { new Class[] { ClassWithFailedBeforeClassMethod.class }, 1, 1, 1 }, new Object[] { new Class[] { ExtendsClassWithFailedBeforeClassMethod.class }, 1, 2, 2 }, new Object[] { new Class[] { ClassWithFailedBeforeClassMethod.class, ExtendsClassWithFailedBeforeClassMethod.class }, 2, 3, 3 }, new Object[] { new Class[] { ClassWithSkippingBeforeMethod.class }, 0, 1, 1 }, new Object[] { new Class[] { FactoryClassWithFailedBeforeMethod.class }, 2, 0, 2 }, new Object[] { new Class[] { FactoryClassWithFailedBeforeMethodAndMultipleInvocations.class }, 8, 0, 8 }, new Object[] { new Class[] { FactoryClassWithFailedBeforeClassMethod.class }, 2, 2, 2 }, }; return data; } @Test( dataProvider = "dp" ) public void confFailureTest(Class[] classesUnderTest, int configurationFailures, int configurationSkips, int skippedTests) { TestListenerAdapter tla = new TestListenerAdapter(); TestNG testng = new TestNG(); testng.setOutputDirectory(OutputDirectoryPatch.getOutputDirectory()); testng.setTestClasses(classesUnderTest); testng.addListener(tla); testng.setVerbose(0); testng.setConfigFailurePolicy(XmlSuite.CONTINUE); testng.run(); verify(tla, configurationFailures, configurationSkips, skippedTests); } @Test public void commandLineTest_policyAsSkip() { String[] argv = new String[] { "-log", "0", "-d", OutputDirectoryPatch.getOutputDirectory(), "-configfailurepolicy", "skip", "-testclass", "test.configurationfailurepolicy.ClassWithFailedBeforeMethodAndMultipleTests" }; TestListenerAdapter tla = new TestListenerAdapter(); TestNG.privateMain(argv, tla); verify(tla, 1, 1, 2); } @Test public void commandLineTest_policyAsContinue() { String[] argv = new String[] { "-log", "0", "-d", OutputDirectoryPatch.getOutputDirectory(), "-configfailurepolicy", "continue", "-testclass", "test.configurationfailurepolicy.ClassWithFailedBeforeMethodAndMultipleTests" }; TestListenerAdapter tla = new TestListenerAdapter(); TestNG.privateMain(argv, tla); verify(tla, 2, 0, 2); } @Test public void commandLineTestWithXMLFile_policyAsSkip() { String[] argv = new String[] { "-log", "0", "-d", OutputDirectoryPatch.getOutputDirectory(), "-configfailurepolicy", "skip", "src/test/resources/testng-configfailure.xml" }; TestListenerAdapter tla = new TestListenerAdapter(); TestNG.privateMain(argv, tla); verify(tla, 1, 1, 2); } @Test public void commandLineTestWithXMLFile_policyAsContinue() { String[] argv = new String[] { "-log", "0", "-d", OutputDirectoryPatch.getOutputDirectory(), "-configfailurepolicy", "continue", "src/test/resources/testng-configfailure.xml" }; TestListenerAdapter tla = new TestListenerAdapter(); TestNG.privateMain(argv, tla); verify(tla, 2, 0, 2); } private void verify( TestListenerAdapter tla, int configurationFailures, int configurationSkips, int skippedTests ) { assertEquals(tla.getConfigurationFailures().size(), configurationFailures, "wrong number of configuration failures"); assertEquals(tla.getConfigurationSkips().size(), configurationSkips, "wrong number of configuration skips"); assertEquals(tla.getSkippedTests().size(), skippedTests, "wrong number of skipped tests"); } } ././@LongLink0000644000000000000000000000020000000000000011573 Lustar rootroottestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/FactoryClassWithFailedBeforeMethodAndMultipleInvocations.javatestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/FactoryClassWithFailedBeforeMethod0000644000175000017500000000075312551235562033530 0ustar eugeneeugenepackage test.configurationfailurepolicy; import org.testng.annotations.Factory; public class FactoryClassWithFailedBeforeMethodAndMultipleInvocations extends ClassWithFailedBeforeMethodAndMultipleInvocations { @Factory public Object[] createTests() { Object[] instances = new Object[2]; instances[0] = new FactoryClassWithFailedBeforeMethodAndMultipleInvocations(); instances[1] = new FactoryClassWithFailedBeforeMethodAndMultipleInvocations(); return instances; } } ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootroottestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/FactoryClassWithFailedBeforeMethod.javatestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/FactoryClassWithFailedBeforeMethod0000644000175000017500000000062312551235562033524 0ustar eugeneeugenepackage test.configurationfailurepolicy; import org.testng.annotations.Factory; public class FactoryClassWithFailedBeforeMethod extends ClassWithFailedBeforeMethod { @Factory public Object[] createTests() { Object[] instances = new Object[2]; instances[0] = new FactoryClassWithFailedBeforeMethod(); instances[1] = new FactoryClassWithFailedBeforeMethod(); return instances; } } ././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootroottestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/FactoryClassWithFailedBeforeClassMethod.javatestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/FactoryClassWithFailedBeforeClassM0000644000175000017500000000064712551235562033474 0ustar eugeneeugenepackage test.configurationfailurepolicy; import org.testng.annotations.Factory; public class FactoryClassWithFailedBeforeClassMethod extends ClassWithFailedBeforeClassMethod { @Factory public Object[] createTests() { Object[] instances = new Object[2]; instances[0] = new FactoryClassWithFailedBeforeClassMethod(); instances[1] = new FactoryClassWithFailedBeforeClassMethod(); return instances; } } ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootroottestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/ExtendsClassWithFailedBeforeMethod.javatestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/ExtendsClassWithFailedBeforeMethod0000644000175000017500000000046012551235562033526 0ustar eugeneeugenepackage test.configurationfailurepolicy; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class ExtendsClassWithFailedBeforeMethod extends ClassWithFailedBeforeMethod { @BeforeMethod public void setupExtension() { } @Test public void test2() { } } ././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootroottestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/ExtendsClassWithFailedBeforeClassMethod.javatestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/ExtendsClassWithFailedBeforeClassM0000644000175000017500000000043312551235562033470 0ustar eugeneeugenepackage test.configurationfailurepolicy; import org.testng.annotations.Test; public class ExtendsClassWithFailedBeforeClassMethod extends ClassWithFailedBeforeClassMethod { @Test public void test2() { // should be skipped, but BeforeClass method attempted again } } testng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/ClassWithSkippingBeforeMethod.java0000644000175000017500000000071212551235562033513 0ustar eugeneeugenepackage test.configurationfailurepolicy; import org.testng.SkipException; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class ClassWithSkippingBeforeMethod { private int invocations = 0; @BeforeMethod public void beforeMethod() { invocations++; if (invocations ==2) { throw new SkipException("skipping"); } } @Test public void test1() {} @Test public void test2() {} } ././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootroottestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/ClassWithFailedBeforeMethodAndMultipleTests.javatestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/ClassWithFailedBeforeMethodAndMult0000644000175000017500000000055712551235562033467 0ustar eugeneeugenepackage test.configurationfailurepolicy; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class ClassWithFailedBeforeMethodAndMultipleTests { @BeforeMethod public void setupShouldFail() { throw new RuntimeException("Failing in setUp"); } @Test public void test1() { } @Test public void test2() { } } ././@LongLink0000644000000000000000000000017100000000000011602 Lustar rootroottestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/ClassWithFailedBeforeMethodAndMultipleInvocations.javatestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/ClassWithFailedBeforeMethodAndMult0000644000175000017500000000124612551235562033463 0ustar eugeneeugenepackage test.configurationfailurepolicy; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class ClassWithFailedBeforeMethodAndMultipleInvocations { @BeforeMethod public void setupShouldFail() { throw new RuntimeException("Failing in setUp"); } @DataProvider( name = "data.provider" ) public Object[][] dataProvider() { return new Object[][] { new Object[] { "data1" }, new Object[] { "data2" } }; } @Test( dataProvider = "data.provider" ) public void test1( String s ) { } @Test( invocationCount = 2 ) public void test2() { } } testng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/ClassWithFailedBeforeMethod.java0000644000175000017500000000047112551235562033115 0ustar eugeneeugenepackage test.configurationfailurepolicy; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class ClassWithFailedBeforeMethod { @BeforeMethod public void setupShouldFail() { throw new RuntimeException("Failing in setUp"); } @Test public void test1() { } } ././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootroottestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/ClassWithFailedBeforeClassMethod.javatestng-testng-6.9.5/src/test/java/test/configurationfailurepolicy/ClassWithFailedBeforeClassMethod.j0000644000175000017500000000063612551235562033416 0ustar eugeneeugenepackage test.configurationfailurepolicy; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class ClassWithFailedBeforeClassMethod { @BeforeClass public void setupClassFails() { throw new RuntimeException( "setup class fail" ); } @BeforeMethod public void setupMethod() { } @Test public void test1() { } } testng-testng-6.9.5/src/test/java/test/configuration/0000755000175000017500000000000012551235562022166 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/configuration/VerifySuiteTest.java0000644000175000017500000000043312551235562026147 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.AfterSuite; import java.util.Arrays; public class VerifySuiteTest { @AfterSuite public void verify() { Assert.assertEquals(Arrays.asList(1, 2, 3), SuiteTest.m_order); } } testng-testng-6.9.5/src/test/java/test/configuration/SuiteTest.java0000644000175000017500000000100312551235562024754 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; public class SuiteTest extends BaseSuiteTest { @BeforeSuite(dependsOnMethods={"beforeSuiteParent"}) public void beforeSuiteChild(){ m_order.add(2); } // @AfterSuite(dependsOnMethods={"afterSuiteParent"}) // public void afterSuiteChild(){ // m_order.add(4); // System.out.println("AFTER SUITE CHILD"); // } @Test public void test1(){ m_order.add(3); } } testng-testng-6.9.5/src/test/java/test/configuration/SuiteFactoryOnceTest.java0000644000175000017500000000107512551235562027122 0ustar eugeneeugenepackage test.configuration; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; import junit.framework.Assert; public class SuiteFactoryOnceTest extends SimpleBaseTest { @Test public void suiteMethodsShouldOnlyRunOnce() { TestNG tng = create(SuiteFactoryOnceSample2Test.class); SuiteFactoryOnceSample1Test.m_before = 0; SuiteFactoryOnceSample1Test.m_after = 0; tng.run(); Assert.assertEquals(1, SuiteFactoryOnceSample1Test.m_before); Assert.assertEquals(1, SuiteFactoryOnceSample1Test.m_after); } } testng-testng-6.9.5/src/test/java/test/configuration/SuiteFactoryOnceSample2Test.java0000644000175000017500000000040212551235562030337 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.Factory; public class SuiteFactoryOnceSample2Test { @Factory public Object[] factory() { return new Object[] { new SuiteFactoryOnceSample1Test(), new SuiteFactoryOnceSample1Test() }; } } testng-testng-6.9.5/src/test/java/test/configuration/SuiteFactoryOnceSample1Test.java0000644000175000017500000000063112551235562030342 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; public class SuiteFactoryOnceSample1Test { public static int m_before = 0; public static int m_after = 0; @BeforeSuite public void bs() { m_before++; } @AfterSuite public void as() { m_after++; } @Test public void g1() { } }testng-testng-6.9.5/src/test/java/test/configuration/SingleConfigurationTest.java0000644000175000017500000000145712551235562027651 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; /** * Make sure that @BeforeTest is only called once if a factory is used * * @author Cedric Beust */ public class SingleConfigurationTest { private static int m_before; @Factory(dataProvider = "dp") public SingleConfigurationTest(int n) { } @DataProvider public static Object[][] dp() { return new Object[][] { new Object[] { 42 }, new Object[] { 43 }, }; } @BeforeTest public void bt() { m_before++; } @Test public void verify() { Assert.assertEquals(m_before, 1); } } ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootroottestng-testng-6.9.5/src/test/java/test/configuration/ReflectMethodParametrizedConfigurationMethodTest.javatestng-testng-6.9.5/src/test/java/test/configuration/ReflectMethodParametrizedConfigurationMethodTes0000644000175000017500000000265612551235562033564 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * This class/interface */ public class ReflectMethodParametrizedConfigurationMethodTest { private Map m_before= new HashMap<>(); private Map m_after= new HashMap<>(); @BeforeMethod public void beforeMethod(Method tobeInvokedTestMethod) { m_before.put(tobeInvokedTestMethod.getName(), tobeInvokedTestMethod.getName()); } @Test public void test1() {} @Test public void test2() {} @AfterMethod public void afterMethod(Method invokedTestMethod) { m_after.put(invokedTestMethod.getName(), invokedTestMethod.getName()); } @AfterClass public void assertBeforeAfterMethodsInvocations() { Assert.assertTrue(m_before.containsKey("test1"), "@Test method should have been passed to @BeforeMethod"); Assert.assertTrue(m_before.containsKey("test2"), "@Test method should have been passed to @BeforeMethod"); Assert.assertTrue(m_after.containsKey("test1"), "@Test method should have been passed to @AfterMethod"); Assert.assertTrue(m_before.containsKey("test2"), "@Test method should have been passed to @AfterMethod"); } } testng-testng-6.9.5/src/test/java/test/configuration/MultipleBeforeGroupTest.java0000644000175000017500000000072612551235562027631 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; @Test( groups = "foo" ) public class MultipleBeforeGroupTest { private int m_count = 0; @BeforeGroups( "foo" ) public void beforeGroups() { m_count++; } @Test() public void test() { } @Test(dependsOnMethods = "test") public void verify() { Assert.assertEquals(1, m_count); } } testng-testng-6.9.5/src/test/java/test/configuration/MethodCallOrderTest.java0000644000175000017500000000404012551235562026677 0ustar eugeneeugenepackage test.configuration; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class MethodCallOrderTest { public static boolean s_beforeSuite; public static boolean s_beforeTest; public static boolean s_beforeClass; public static boolean s_beforeMethod; @BeforeClass public void beforeClass() { assertTrue(s_beforeSuite); assertTrue(s_beforeTest); assertFalse(s_beforeClass); assertFalse(s_beforeMethod); s_beforeClass = true; } @AfterSuite public void cleanUp() { s_beforeSuite = false; s_beforeTest = false; s_beforeClass = false; s_beforeMethod = false; } @BeforeMethod public void beforeMethod() { assertTrue(s_beforeSuite); assertTrue(s_beforeTest); assertTrue(s_beforeClass); assertFalse(s_beforeMethod); s_beforeMethod = true; } @Test public void realTest() { assertTrue(s_beforeSuite); assertTrue(s_beforeTest); assertTrue(s_beforeClass); assertTrue(s_beforeMethod); } @AfterMethod public void afterMethod() { assertFalse(ExternalConfigurationClass.s_afterMethod, "afterTestMethod shouldn't have been run"); assertFalse(ExternalConfigurationClass.s_afterClass, "afterTestClass shouldn't have been run"); assertFalse(ExternalConfigurationClass.s_afterTest, "afterTest should haven't been run"); ExternalConfigurationClass.s_afterMethod = true; } @AfterClass public void afterClass() { assertTrue(ExternalConfigurationClass.s_afterMethod, "afterTestMethod should have been run"); assertFalse(ExternalConfigurationClass.s_afterClass, "afterTestClass shouldn't have been run"); assertFalse(ExternalConfigurationClass.s_afterTest, "afterTest should haven't been run"); ExternalConfigurationClass.s_afterClass = true; } } testng-testng-6.9.5/src/test/java/test/configuration/GroupsTest.java0000644000175000017500000000246512551235562025157 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.Arrays; import java.util.List; public class GroupsTest { private TestNG m_testNg; @BeforeMethod public void setUp() { m_testNg = new TestNG(); m_testNg.setVerbose(0); } @Test public void verifyDataProviderAfterGroups() { runTest(ConfigurationGroupDataProviderSampleTest.class, ConfigurationGroupDataProviderSampleTest.m_list, Arrays.asList(new Integer[] { 1, 2, 2, 2, 3 })); } @Test public void verifyParametersAfterGroups() { runTest(ConfigurationGroupInvocationCountSampleTest.class, ConfigurationGroupInvocationCountSampleTest.m_list, Arrays.asList(new Integer[] { 1, 2, 2, 2, 3 })); } @Test public void verifyBothAfterGroups() { runTest(ConfigurationGroupBothSampleTest.class, ConfigurationGroupBothSampleTest.m_list, Arrays.asList(new Integer[] { 1, 2, 2, 2, 2, 2, 2, 3 })); } private void runTest(Class cls, List list, List expected) { m_testNg.setTestClasses(new Class[] { cls }); m_testNg.run(); Assert.assertEquals(list, expected); } } testng-testng-6.9.5/src/test/java/test/configuration/ExternalConfigurationClass.java0000644000175000017500000000272712551235562030341 0ustar eugeneeugenepackage test.configuration; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.AfterSuite; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; public class ExternalConfigurationClass { public static boolean s_afterMethod; public static boolean s_afterClass; public static boolean s_afterTest; @BeforeSuite public void beforeSuite() { MethodCallOrderTest.s_beforeSuite = true; } @AfterSuite public void cleanUp() { s_afterMethod = false; s_afterClass = false; s_afterTest = false; } @BeforeTest public void beforeTest() { assertTrue(MethodCallOrderTest.s_beforeSuite); assertFalse(MethodCallOrderTest.s_beforeTest); assertFalse(MethodCallOrderTest.s_beforeClass); assertFalse(MethodCallOrderTest.s_beforeMethod); MethodCallOrderTest.s_beforeTest = true; } @AfterTest public void afterTest() { assertTrue(s_afterMethod, "afterTestMethod should have been run"); assertTrue(s_afterClass, "afterTestClass should have been run"); assertFalse(s_afterTest, "afterTest should haven't been run"); s_afterTest = true; } @AfterSuite public void afterSuite() { assertTrue(s_afterMethod, "afterTestMethod should have been run"); assertTrue(s_afterClass, "afterTestClass should have been run"); assertTrue(s_afterTest, "afterTest should have been run"); } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationWithParameters.java0000644000175000017500000000073412551235562030524 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Parameters; import org.testng.annotations.Test; public class ConfigurationWithParameters { private String m_param; @Parameters({ "param" }) @BeforeTest public void testInit(String param) { m_param = param; } @Parameters({ "param" }) @Test public void testMethod(String param) { Assert.assertEquals(m_param, param); } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationTest.java0000644000175000017500000000771212551235562026507 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; /** * Test @Configuration * * @author cbeust */ public class ConfigurationTest { private boolean m_beforeSuite = false; private boolean m_afterSuite = false; private boolean m_beforeClass = false; private boolean m_afterClass = false; private boolean m_beforeMethod = false; private boolean m_afterMethod = false; @BeforeSuite public void beforeSuite() { ppp("@@@@ BEFORE_SUITE"); assert ! m_afterSuite : "afterSuite shouldn't have run"; assert ! m_beforeClass : "beforeClass shouldn't have run"; assert ! m_afterClass : "afterClass shouldn't have run"; assert ! m_beforeMethod: "beforeMethod shouldn't have run"; assert ! m_afterMethod: "afterMethod shouldn't have run"; m_beforeSuite = true; } @BeforeClass public void beforeClass() { ppp("@@@@ BEFORE_CLASS"); assert m_beforeSuite : "beforeSuite should have run"; assert ! m_afterSuite : "afterSuite shouldn't have run"; assert ! m_beforeClass : "beforeClass shouldn't have run"; assert ! m_afterClass : "afterClass shouldn't have run"; assert ! m_beforeMethod: "beforeMethod shouldn't have run"; assert ! m_afterMethod: "afterMethod shouldn't have run"; m_beforeClass = true; } @BeforeMethod public void beforeMethod() { ppp("@@@@ BEFORE_METHOD"); assert m_beforeSuite : "beforeSuite should have run"; assert m_beforeClass : "beforeClass have run"; assert ! m_afterSuite : "afterSuite shouldn't have run"; assert ! m_afterClass : "afterClass shouldn't have run"; assert ! m_beforeMethod: "beforeMethod shouldn't have run"; assert ! m_afterMethod: "afterMethod shouldn't have run"; m_beforeMethod = true; } @AfterMethod public void afterMethod() { ppp("@@@@ AFTER_METHOD"); assert m_beforeSuite : "beforeSuite should have run"; assert m_beforeClass : "beforeClass have run"; assert m_beforeMethod: "beforeMethod should have run"; assert ! m_afterSuite : "afterSuite shouldn't have run"; assert ! m_afterClass : "afterClass shouldn't have run"; assert ! m_afterMethod: "afterMethod shouldn't have run"; m_afterMethod = true; } @AfterClass public void afterClass() { ppp("@@@@ AFTER_CLASS"); assert m_beforeSuite : "beforeSuite should have run"; assert m_beforeClass : "beforeClass have run"; assert m_beforeMethod: "beforeMethod should have run"; assert m_afterMethod: "afterMethod should have run"; assert ! m_afterClass : "afterClass shouldn't have run"; assert ! m_afterSuite : "afterSuite shouldn't have run"; m_afterClass = true; } @AfterSuite public void afterSuite() { ppp("@@@@ AFTER_SUITE"); ppp(m_beforeSuite + " " + m_beforeClass + " " + m_beforeMethod + " " + m_afterMethod + " " + m_afterClass + " " + m_afterSuite); assert m_beforeSuite : "beforeSuite should have run"; assert m_beforeClass : "beforeClass have run"; assert m_beforeMethod: "beforeMethod should have run"; assert m_afterMethod: "afterMethod should have run"; assert m_afterClass : "afterClass should have run"; assert ! m_afterSuite : "afterSuite shouldn't have run"; m_afterSuite = true; } @Test public void verify() { ppp("@@@@ VERIFY"); assert m_beforeSuite : "beforeSuite should have run"; assert m_beforeClass : "beforeClass have run"; assert m_beforeMethod: "beforeMethod should have run"; assert ! m_afterSuite : "afterSuite shouldn't have run"; assert ! m_afterClass : "afterClass shouldn't have run"; assert ! m_afterMethod: "afterMethod shouldn't have run"; } private static void ppp(String s) { if (false) { System.out.println("[ConfigurationTest] " + s); } } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationListenerTest.java0000644000175000017500000000073512551235562030213 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class ConfigurationListenerTest extends SimpleBaseTest { @Test public void listenerShouldBeCalled() { TestNG tng = create(ConfigurationListenerSampleTest.class); Assert.assertFalse(ConfigurationListenerSampleTest.m_passed); tng.run(); Assert.assertTrue(ConfigurationListenerSampleTest.m_passed); } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationListenerSampleTest.java0000644000175000017500000000126012551235562031347 0ustar eugeneeugenepackage test.configuration; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.annotations.BeforeClass; import org.testng.annotations.Listeners; import org.testng.annotations.Test; import test.configuration.ConfigurationListenerSampleTest.MyTLA; @Listeners(MyTLA.class) public class ConfigurationListenerSampleTest { static boolean m_passed = false; public static class MyTLA extends TestListenerAdapter { @Override public void onConfigurationFailure(ITestResult itr) { m_passed = true; } } @BeforeClass public void bm() { m_passed = false; throw new RuntimeException(); } @Test public void f1() { } }testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationInheritGroupsSampleTest.java0000644000175000017500000000073612551235562032373 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @Test(groups = { "group1" }) public class ConfigurationInheritGroupsSampleTest { private boolean m_ok = false; @BeforeMethod public void setUp() { m_ok = true; } public void test1() { Assert.assertTrue(m_ok); } private void ppp(String s) { System.out.println("[ConfigurationInheritGroupsSampleTest] " + s); } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationGroups8SampleTest.java0000644000175000017500000000205512551235562031134 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Run with group "A" and "B" * Make sure that only methods and configurations belonging to that group * get invoked. * * @author cbeust * @date Mar 9, 2006 */ public class ConfigurationGroups8SampleTest { private List m_log = new ArrayList<>(); @Test public void dummy() { m_log.add("should not be invoked"); } @Test(groups = { "A" }) public void testSomething() { m_log.add("1"); } @Test(groups = { "A" }) public void testSomethingMore() { m_log.add("1"); } @AfterMethod private void cleanUpDummy() { m_log.add("should not be invoked"); } @AfterMethod(groups = "A") private void cleanUpA() { m_log.add("a"); } @Test(dependsOnGroups = "A", groups = "B") public void verify() { Assert.assertEquals(Arrays.asList(new String[] { "1", "a", "1", "a" }), m_log); } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationGroups7SampleTest.java0000644000175000017500000000150112551235562031126 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class ConfigurationGroups7SampleTest { private List m_log = new ArrayList<>(); @BeforeGroups({"A"}) private void initA() { m_log.add("1"); } @Test(groups = {"A"}) public void testSomething() { m_log.add("2"); } @Test(groups = {"A"}) public void testSomethingMore() { m_log.add("2"); } @AfterGroups({"A"}) private void cleanUpA() { m_log.add("3"); } @Test(dependsOnGroups = "A") public void verify() { Assert.assertEquals(Arrays.asList(new String[] { "1", "2", "2", "3"}), m_log); } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationGroups6SampleTest.java0000644000175000017500000000244112551235562031131 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.AfterGroups; import org.testng.annotations.Test; /** * afterGroups test when the group contains more than one method * * @author cbeust * @date Mar 7, 2006 */ public class ConfigurationGroups6SampleTest { private boolean m_after = false; private boolean m_run1 = false; private boolean m_run2 = false; @Test public void f() { log("f"); } @Test(groups = "cg6-1") public void run1() { log("run1"); Assert.assertFalse(m_after); m_run1 = true; } @Test(groups = "cg6-1") public void run2() { log("run2"); Assert.assertFalse(m_after); m_run2 = true; } @AfterGroups("cg6-1") public void after() { log("after"); Assert.assertTrue(m_run1); Assert.assertTrue(m_run2); Assert.assertFalse(m_after); m_after = true; } @Test(dependsOnGroups = { "cg6-1" }) public void verify() { log("verify"); Assert.assertTrue(m_run1, "run1() wasn't run"); Assert.assertTrue(m_run2, "run2() wasn't run"); Assert.assertTrue(m_after, "after1() wasn't run"); } private void log(String string) { ppp(string); } private void ppp(String s) { if (false) { System.out.println("[ConfigurationGroups4SampleTest] " + s); } } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationGroups5SampleTest.java0000644000175000017500000000273212551235562031133 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.AfterGroups; import org.testng.annotations.Test; /** * afterGroups test with more than one group * * @author cbeust * @date Mar 7, 2006 */ public class ConfigurationGroups5SampleTest { private boolean m_after = false; private boolean m_run1 = false; private boolean m_run2 = false; private int m_afterCount = 0; @Test public void f() { log("f"); } @Test(groups = "cg5-1") public void run1() { log("run1"); if (m_afterCount == 0) { Assert.assertFalse(m_after); } m_run1 = true; } @Test(groups = "cg5-2") public void run2() { log("run2"); if (m_afterCount == 0) { Assert.assertFalse(m_after); } m_run2 = true; } @AfterGroups({ "cg5-1", "cg5-2"}) public void after() { log("after"); m_afterCount++; Assert.assertTrue(m_run1 || m_run2); if (m_afterCount == 0) { Assert.assertFalse(m_after); } m_after = true; } @Test(dependsOnGroups = { "cg5-1", "cg5-2" }) public void verify() { log("verify"); Assert.assertTrue(m_run1, "run1() wasn't run"); Assert.assertTrue(m_run2, "run2() wasn't run"); Assert.assertTrue(m_after, "after1() wasn't run"); Assert.assertEquals(2, m_afterCount); } private void log(String string) { ppp(string); } private void ppp(String s) { if (false) { System.out.println("[ConfigurationGroups5SampleTest] " + s); } } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationGroups4SampleTest.java0000644000175000017500000000200212551235562031120 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.AfterGroups; import org.testng.annotations.Test; /** * Simple afterGroups test * * @author cbeust * @date Mar 7, 2006 */ public class ConfigurationGroups4SampleTest { private boolean m_after = false; private boolean m_run = false; @Test public void f() { log("f"); } @Test(groups = "cg4-1") public void run() { log("run"); Assert.assertFalse(m_after); m_run = true; } @AfterGroups("cg4-1") public void after1() { log("after1"); Assert.assertTrue(m_run); Assert.assertFalse(m_after); m_after = true; } @Test(dependsOnGroups = "cg4-1") public void verify() { log("verify"); Assert.assertTrue(m_run, "run() wasn't run"); Assert.assertTrue(m_after, "after1() wasn't run"); } private void log(String string) { ppp(string); } private void ppp(String s) { if (false) { System.out.println("[ConfigurationGroups4SampleTest] " + s); } } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationGroups3SampleTest.java0000644000175000017500000000254412551235562031132 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.List; /** * beforeGroups test: make sure that if before methods are scattered on * more than one class, they are still taken into account * * @author cbeust * @date Mar 3, 2006 */ public class ConfigurationGroups3SampleTest extends Base3 { private boolean m_before = false; static private boolean m_f1 = false; @BeforeGroups("cg34-1") public void before1() { Assert.assertFalse(m_before); Assert.assertFalse(m_f1); m_before = true; log("before1"); } @Test(groups = "cg34-a") public void fa() { log("fa"); } @Test(groups = "cg34-1") public void f1() { Assert.assertTrue(m_before); Assert.assertTrue(Base3.getBefore()); m_f1 = true; log("f1"); } private List m_list = new ArrayList<>(); @Test(dependsOnGroups = {"cg34-a", "cg34-1"}) public void verify() { Assert.assertTrue(m_before); Assert.assertTrue(Base3.getBefore()); Assert.assertTrue(m_f1); } private void log(String s) { m_list.add(s); ppp(s); } private void ppp(String s) { if (false) { System.out.println("[ConfigurationGroups3SampleTest] " + s); } } public static boolean getF1() { return m_f1; } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationGroups2SampleTest.java0000644000175000017500000000261612551235562031131 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.List; /** * beforeGroups test: make sure that the beforeGroups method is invoked * only once even if two test methods belong to the group * * @author cbeust * @date Mar 3, 2006 */ public class ConfigurationGroups2SampleTest { private boolean m_before = false; private boolean m_f1 = false; private boolean m_g1 = false; @BeforeGroups("cg2-1") public void before1() { Assert.assertFalse(m_before); Assert.assertFalse(m_f1); Assert.assertFalse(m_g1); m_before = true; log("before1"); } @Test(groups = "cg2-a") public void fa() { log("fa"); } @Test(groups = "cg2-1") public void f1() { Assert.assertTrue(m_before); m_f1 = true; log("f1"); } @Test(groups = "cg2-1") public void g1() { Assert.assertTrue(m_before); m_g1 = true; log("g1"); } private List m_list = new ArrayList<>(); @Test(dependsOnGroups = {"cg2-a", "cg2-1"}) public void verify() { Assert.assertTrue(m_before); Assert.assertTrue(m_f1); Assert.assertTrue(m_g1); } private void log(String s) { m_list.add(s); ppp(s); } private void ppp(String s) { if (false) { System.out.println("[ConfigurationGroups2SampleTest] " + s); } } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationGroups1SampleTest.java0000644000175000017500000000217312551235562031126 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.List; /** * Simple beforeGroups test: 1 before method and 2 test method * * @author cbeust * @date Mar 3, 2006 */ public class ConfigurationGroups1SampleTest { private boolean m_before = false; private boolean m_f1 = false; @BeforeGroups("cg1-1") public void before1() { Assert.assertFalse(m_before); Assert.assertFalse(m_f1); m_before = true; log("before1"); } @Test(groups = "cg1-a") public void fa() { log("fa"); } @Test(groups = "cg1-1") public void f1() { Assert.assertTrue(m_before); m_f1 = true; log("f1"); } private List m_list = new ArrayList<>(); @Test(dependsOnGroups = {"cg1-a", "cg1-1"}) public void verify() { Assert.assertTrue(m_before); Assert.assertTrue(m_f1); } private void log(String s) { m_list.add(s); ppp(s); } private void ppp(String s) { if (false) { System.out.println("[ConfigurationGroups1SampleTest] " + s); } } } ././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootroottestng-testng-6.9.5/src/test/java/test/configuration/ConfigurationGroupInvocationCountSampleTest.javatestng-testng-6.9.5/src/test/java/test/configuration/ConfigurationGroupInvocationCountSampleTest.jav0000644000175000017500000000137312551235562033565 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.List; public class ConfigurationGroupInvocationCountSampleTest { static List m_list = new ArrayList<>(); @BeforeGroups(groups={"twice"}, value={"twice"}) public void a(){ ppp("BEFORE()"); m_list.add(1); } @Test(groups = {"twice"}, invocationCount = 3) public void b() { m_list.add(2); ppp("B()"); } @AfterGroups(groups={"twice"}, value={"twice"}) public void c(){ m_list.add(3); ppp("AFTER()"); } private void ppp(String string) { if (false) { System.out.println("[A] " + string); } } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationGroupDataProviderSampleTest.java0000644000175000017500000000166112551235562033170 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.List; public class ConfigurationGroupDataProviderSampleTest { static List m_list = new ArrayList<>(); @BeforeGroups(groups={"twice"}, value={"twice"}) public void a(){ ppp("BEFORE()"); m_list.add(1); } @Test(groups={"twice"}, dataProvider="MyData") public void b(int a, int b) { m_list.add(2); ppp("B()" + a + "," + b); } @AfterGroups(groups={"twice"}, value={"twice"}) public void c(){ m_list.add(3); ppp("AFTER()"); } @DataProvider(name="MyData") public Object[][] input(){ return new Object[][]{ {1,1}, {2,2}, {3,3}}; } private void ppp(String string) { if (false) { System.out.println("[A] " + string); } } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationGroupBothSampleTest.java0000644000175000017500000000227412551235562031501 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class ConfigurationGroupBothSampleTest { static List m_list = Collections.synchronizedList(new ArrayList()); private synchronized static void addToList(Integer n) { m_list.add(n); } @BeforeGroups(groups={"twice"}, value={"twice"}) public void a(){ ppp("BEFORE()"); addToList(1); } @Test(groups={"twice"}, dataProvider="MyData", invocationCount = 2, threadPoolSize=2) public void b(int a, int b) { addToList(2); ppp("B()" + a + "," + b); } @AfterGroups(groups={"twice"}, value={"twice"}) public void c(){ addToList(3); ppp("AFTER()"); } @DataProvider(name="MyData") public Object[][] input(){ return new Object[][]{ {1,1}, {2,2}, {3,3}}; } private void ppp(String string) { if (false) { System.out.println("[A] " + string + " on Thread:" + Thread.currentThread()); } } } testng-testng-6.9.5/src/test/java/test/configuration/ConfigurationDisabledSampleTest.java0000644000175000017500000000075712551235562031303 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class ConfigurationDisabledSampleTest { public static boolean m_afterWasRun; @BeforeClass(alwaysRun = true) public void before() { m_afterWasRun = false; } @AfterClass(alwaysRun = true) public void after() { m_afterWasRun = true; } @Test public void f1() {} @Test(enabled = false) public void f2() {} }testng-testng-6.9.5/src/test/java/test/configuration/BeforeTestOrderingTest.java0000644000175000017500000000300012551235562027416 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.Reporter; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; import org.testng.xml.XmlClass; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.TestHelper; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class BeforeTestOrderingTest { private static List m_testNames; @BeforeSuite public void init() { m_testNames = new ArrayList<>(); } static void addTest(String testName) { m_testNames.add(testName); } @Test public void verifyBeforeTestOrdering() { XmlSuite s = new XmlSuite(); Reporter.log("BEFORE"); XmlTest t1 = new XmlTest(s); XmlClass c1 = new XmlClass("test.configuration.BeforeTestOrdering1Test"); t1.getXmlClasses().add(c1); XmlTest t2 = new XmlTest(s); XmlClass c2 = new XmlClass("test.configuration.BeforeTestOrdering2Test"); t2.getXmlClasses().add(c2); TestNG tng = TestHelper.createTestNG(); TestListenerAdapter tl = new TestListenerAdapter(); tng.addListener(tl); tng.setXmlSuites(Arrays.asList(new XmlSuite[] { s })); tng.run(); List expected = Arrays.asList(new String[] { "bt1", "f1", "at1", "bt2", "f2", "at2", }); Assert.assertEquals(expected, m_testNames); } private static void ppp(String s) { System.out.println("[BeforeTestOrderingTest] " + s); } } testng-testng-6.9.5/src/test/java/test/configuration/BeforeTestOrdering2Test.java0000644000175000017500000000074412551235562027514 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class BeforeTestOrdering2Test extends BaseBeforeTestOrdering{ @BeforeTest public void bt2() { log("bt2"); } @AfterTest public void at2() { log("at2"); } @Test public void f2() { log("f2"); } private static void ppp(String s) { System.out.println("[BeforeTestOrdering2Test] " + s); } } testng-testng-6.9.5/src/test/java/test/configuration/BeforeTestOrdering1Test.java0000644000175000017500000000074512551235562027514 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class BeforeTestOrdering1Test extends BaseBeforeTestOrdering { @BeforeTest public void bt1() { log("bt1"); } @AfterTest public void at1() { log("at1"); } @Test public void f1() { log("f1"); } private static void ppp(String s) { System.out.println("[BeforeTestOrdering1Test] " + s); } } testng-testng-6.9.5/src/test/java/test/configuration/BeforeMethodTest.java0000644000175000017500000000131312551235562026232 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.lang.reflect.Method; public class BeforeMethodTest { private Method m_method; private ITestContext m_context; @BeforeMethod public void before(Method m, ITestContext ctx) { m_method = m; m_context = ctx; } @Test public void mainTest() { Assert.assertEquals(m_method.getName(), "mainTest"); ITestNGMethod[] methods = m_context.getAllTestMethods(); Assert.assertEquals(1, methods.length); Assert.assertEquals(methods[0].getMethod().getName(), "mainTest"); } } testng-testng-6.9.5/src/test/java/test/configuration/BeforeClassWithDisabledTest.java0000644000175000017500000000105212551235562030343 0ustar eugeneeugenepackage test.configuration; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; import junit.framework.Assert; public class BeforeClassWithDisabledTest extends SimpleBaseTest { @Test public void afterClassShouldRunEvenWithDisabledMethods() { TestNG tng = create(new Class[] { ConfigurationDisabledSampleTest.class }); Assert.assertFalse(ConfigurationDisabledSampleTest.m_afterWasRun); tng.run(); Assert.assertTrue(ConfigurationDisabledSampleTest.m_afterWasRun); } } testng-testng-6.9.5/src/test/java/test/configuration/BeforeClassThreadTest.java0000644000175000017500000000103012551235562027203 0ustar eugeneeugenepackage test.configuration; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; import junit.framework.Assert; public class BeforeClassThreadTest extends SimpleBaseTest{ @Test public void beforeClassMethodsShouldRunInParallel() { TestNG tng = create(new Class[] { BeforeClassThreadA.class, BeforeClassThreadB.class }); tng.setParallel("methods"); tng.run(); Assert.assertTrue(Math.abs(BeforeClassThreadA.WHEN - BeforeClassThreadB.WHEN) < 1000); } } testng-testng-6.9.5/src/test/java/test/configuration/BeforeClassThreadB.java0000644000175000017500000000060212551235562026451 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class BeforeClassThreadB { public static long WHEN; @BeforeClass(alwaysRun = true) public void setup() throws InterruptedException { WHEN = System.currentTimeMillis(); Thread.sleep(2000); } @Test public void execute() { } } testng-testng-6.9.5/src/test/java/test/configuration/BeforeClassThreadA.java0000644000175000017500000000060212551235562026450 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class BeforeClassThreadA { public static long WHEN; @BeforeClass(alwaysRun = true) public void setup() throws InterruptedException { WHEN = System.currentTimeMillis(); Thread.sleep(2000); } @Test public void execute() { } } testng-testng-6.9.5/src/test/java/test/configuration/BaseSuiteTest.java0000644000175000017500000000070612551235562025560 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.BeforeSuite; import java.util.ArrayList; import java.util.List; public class BaseSuiteTest { public static List m_order; @BeforeSuite public void beforeSuiteParent(){ m_order = new ArrayList<>(); m_order.add(1); } // @AfterSuite // public void afterSuiteParent(){ // m_order.add(5); // System.out.println("AFTER SUITE PARENT"); // } } testng-testng-6.9.5/src/test/java/test/configuration/BaseGroupsTest.java0000644000175000017500000000165112551235562025746 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; /** * Verify that a base class with a BeforeGroups method only gets invoked * once, no matter how many subclasses it has * * Created on Jan 23, 2007 * @author Cedric Beust */ public class BaseGroupsTest { @Test public void verifySingleInvocation() { TestNG tng = new TestNG(); tng.setVerbose(0); tng.setTestClasses(new Class[] { BaseGroupsASampleTest.class, BaseGroupsBSampleTest.class, }); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(Base.m_count, 1); } private static void ppp(String s) { System.out.println("[BaseGroupsTest] " + s); } } testng-testng-6.9.5/src/test/java/test/configuration/BaseGroupsBSampleTest.java0000644000175000017500000000032512551235562027207 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.Test; public class BaseGroupsBSampleTest extends Base { @Test(groups = "foo") public void b() { // System.out.println( "b" ); } }testng-testng-6.9.5/src/test/java/test/configuration/BaseGroupsASampleTest.java0000644000175000017500000000032512551235562027206 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.Test; public class BaseGroupsASampleTest extends Base { @Test(groups = "foo") public void a() { // System.out.println( "a" ); } }testng-testng-6.9.5/src/test/java/test/configuration/BaseBeforeTestOrdering.java0000644000175000017500000000021712551235562027360 0ustar eugeneeugenepackage test.configuration; public class BaseBeforeTestOrdering { public void log(String s) { BeforeTestOrderingTest.addTest(s); } } testng-testng-6.9.5/src/test/java/test/configuration/Base3.java0000644000175000017500000000117712551235562023774 0ustar eugeneeugenepackage test.configuration; import org.testng.Assert; import org.testng.annotations.BeforeGroups; public class Base3 { static private boolean m_before = false; /** * @return the m_before */ public static boolean getBefore() { return m_before; } @BeforeGroups("cg34-1") public void anotherBefore1() { log("anotherBefore1"); Assert.assertFalse(m_before); Assert.assertFalse(ConfigurationGroups3SampleTest.getF1()); m_before = true; } private void log(String string) { ppp(string); } private void ppp(String s) { if (false) { System.out.println("[Base3] " + s); } } } testng-testng-6.9.5/src/test/java/test/configuration/Base.java0000644000175000017500000000072312551235562023705 0ustar eugeneeugenepackage test.configuration; import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; @Test(groups = {"base"}) public class Base { static int m_count; @BeforeTest public void init() { m_count = 0; } @BeforeGroups(groups = "foo") public void beforeGroups() { m_count++; } private static void ppp(String s) { System.out.println("[Base] " + s); } }testng-testng-6.9.5/src/test/java/test/conffailure/0000755000175000017500000000000012551235562021614 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/conffailure/ConfigurationFailure.java0000644000175000017500000000303612551235562026600 0ustar eugeneeugenepackage test.conffailure; import static org.testng.Assert.assertTrue; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import testhelper.OutputDirectoryPatch; /** * Test various cases where the @Configuration methods fail * * Created on Jul 20, 2005 * @author cbeust */ public class ConfigurationFailure { @Test public void beforeTestClassFails() { TestListenerAdapter tla = new TestListenerAdapter(); TestNG testng = new TestNG(); testng.setOutputDirectory(OutputDirectoryPatch.getOutputDirectory()); testng.setTestClasses(new Class[] { ClassWithFailedBeforeTestClass.class, ClassWithFailedBeforeTestClassVerification.class }); testng.addListener(tla); testng.setVerbose(0); testng.run(); assertTrue(ClassWithFailedBeforeTestClassVerification.success(), "Not all the @Configuration methods of Run2 were run"); } @Test public void beforeTestSuiteFails() { TestListenerAdapter tla = new TestListenerAdapter(); TestNG testng = new TestNG(); testng.setOutputDirectory(OutputDirectoryPatch.getOutputDirectory()); testng.setTestClasses(new Class[] { ClassWithFailedBeforeSuite.class, ClassWithFailedBeforeSuiteVerification.class }); testng.addListener(tla); testng.setVerbose(0); testng.run(); assertTrue(ClassWithFailedBeforeSuiteVerification.success(), "No @Configuration methods should have run"); } private static void ppp(String s) { System.out.println("[AlwaysRunTest] " + s); } } testng-testng-6.9.5/src/test/java/test/conffailure/ClassWithFailedBeforeTestClassVerification.java0000644000175000017500000000144712551235562033007 0ustar eugeneeugenepackage test.conffailure; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class ClassWithFailedBeforeTestClassVerification { private static boolean m_success1 = false; private static boolean m_success2 = false; // Should be run even though ClassWithFailedBeforeTestClass failed in its configuration @BeforeClass public void setUpShouldPass() { m_success1 = true; } // Should be run even though ClassWithFailedBeforeTestClass failed in its configuration @AfterClass public void tearDown() { m_success2 = true; } // Adding this method or @Configuration will never be invoked @Test public void dummy() { } static public boolean success() { return m_success1 && m_success2; } } testng-testng-6.9.5/src/test/java/test/conffailure/ClassWithFailedBeforeTestClass.java0000644000175000017500000000055312551235562030441 0ustar eugeneeugenepackage test.conffailure; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class ClassWithFailedBeforeTestClass { @BeforeClass public void setUpShouldFail() { throw new RuntimeException("Failing in setUp"); } // Adding this method or @Configuration will never be invoked @Test public void dummy() { } } testng-testng-6.9.5/src/test/java/test/conffailure/ClassWithFailedBeforeSuiteVerification.java0000644000175000017500000000114412551235562032165 0ustar eugeneeugenepackage test.conffailure; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; public class ClassWithFailedBeforeSuiteVerification { private static boolean m_success1 = true; private static boolean m_success2 = true; // Should not be run because beforeSuite failed on the other class @BeforeClass public void setUp() { m_success1 = false; } // Should not be run because beforeSuite failed on the other class @AfterClass public void tearDown() { m_success2 = false; } static public boolean success() { return m_success1 && m_success2; } } testng-testng-6.9.5/src/test/java/test/conffailure/ClassWithFailedBeforeSuite.java0000644000175000017500000000033612551235562027624 0ustar eugeneeugenepackage test.conffailure; import org.testng.annotations.BeforeSuite; public class ClassWithFailedBeforeSuite { @BeforeSuite public void setUpShouldFail() { throw new RuntimeException("Failing in setUp"); } } testng-testng-6.9.5/src/test/java/test/commandline/0000755000175000017500000000000012551235562021605 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/commandline/OverrideSampleTest.java0000644000175000017500000000026112551235562026230 0ustar eugeneeugenepackage test.commandline; import org.testng.annotations.Test; public class OverrideSampleTest { @Test public void f1() {} @Test(groups = "go") public void f2() {} } testng-testng-6.9.5/src/test/java/test/commandline/CommandLineOverridesXml.java0000644000175000017500000000270412551235562027205 0ustar eugeneeugenepackage test.commandline; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; import java.util.Arrays; import java.util.List; public class CommandLineOverridesXml extends SimpleBaseTest { @Test(description = "Specifying -groups on the command line should override testng.xml") public void commandLineGroupsShouldOverrideXml() { runTest("go", null, Arrays.asList(new String[] { "f2" })); } @Test(description = "Specifying -excludegroups on the command line should override testng.xml") public void commandLineExcludedGroupsShouldOverrideXml() { runTest(null, "go", Arrays.asList(new String[] { "f1" })); } @Test public void shouldRunBothMethods() { runTest(null, null, Arrays.asList(new String[] { "f1", "f2" })); } private void runTest(String group, String excludedGroups, List methods) { XmlSuite s = createXmlSuite(getClass().getName()); XmlTest t = createXmlTest(s, "Test", OverrideSampleTest.class.getName()); TestNG tng = create(); if (group != null) tng.setGroups(group); if (excludedGroups != null) tng.setExcludedGroups(excludedGroups); tng.setXmlSuites(Arrays.asList(new XmlSuite[] { s })); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); assertTestResultsEqual(tla.getPassedTests(), methods); } } testng-testng-6.9.5/src/test/java/test/classgroup/0000755000175000017500000000000012551235562021501 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/classgroup/Second.java0000644000175000017500000000037112551235562023560 0ustar eugeneeugenepackage test.classgroup; import org.testng.annotations.Test; @Test(dependsOnGroups = { "first" }) public class Second { @Test public void verify() { assert First.allRun() : "Methods for class First should have been invoked first."; } }testng-testng-6.9.5/src/test/java/test/classgroup/First.java0000644000175000017500000000060012551235562023427 0ustar eugeneeugenepackage test.classgroup; import org.testng.annotations.Test; @Test(groups = { "first" }) public class First { private static boolean m_first1 = false; private static boolean m_first2 = false; @Test public void first1() { m_first1 = true; } @Test public void first2() { m_first2 = true; } static boolean allRun() { return m_first1 && m_first2; } }testng-testng-6.9.5/src/test/java/test/bug92/0000755000175000017500000000000012551235562020247 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/bug92/TestBravo.java0000644000175000017500000000025112551235562023021 0ustar eugeneeugenepackage test.bug92; import org.testng.annotations.Test; public class TestBravo extends TestBase { @Test public void test1() { } @Test public void test2() { } }testng-testng-6.9.5/src/test/java/test/bug92/TestBase.java0000644000175000017500000000052512551235562022626 0ustar eugeneeugenepackage test.bug92; import org.testng.annotations.BeforeTest; public class TestBase { static int beforeTestCount = 0; static int beforeTestAlwaysCount = 0; @BeforeTest public void baseTestBeforeTest() { beforeTestCount++; } @BeforeTest(alwaysRun = true) public void baseTestBeforeTestAlways() { beforeTestAlwaysCount++; } }testng-testng-6.9.5/src/test/java/test/bug92/TestAlpha.java0000644000175000017500000000025112551235562022775 0ustar eugeneeugenepackage test.bug92; import org.testng.annotations.Test; public class TestAlpha extends TestBase { @Test public void test1() { } @Test public void test2() { } }testng-testng-6.9.5/src/test/java/test/bug92/Bug92Test.java0000644000175000017500000000147612551235562022652 0ustar eugeneeugenepackage test.bug92; import java.util.Arrays; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; public class Bug92Test extends SimpleBaseTest { @Test(description = "Fix for https://github.com/cbeust/testng/issues/92") public void BeforeTestShouldRunOnce() { XmlSuite s = createXmlSuite("Bug92"); XmlTest t = createXmlTest(s, "Bug92 test", TestAlpha.class.getName(), TestBravo.class.getName()); s.setTests(Arrays.asList(t)); TestNG tng = create(); tng.setXmlSuites(Arrays.asList(s)); TestBase.beforeTestCount = 0; TestBase.beforeTestAlwaysCount = 0; tng.run(); Assert.assertEquals(TestBase.beforeTestCount, 1); Assert.assertEquals(TestBase.beforeTestAlwaysCount, 1); } } testng-testng-6.9.5/src/test/java/test/bug90/0000755000175000017500000000000012551235562020245 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/bug90/Sample.java0000644000175000017500000000050512551235562022331 0ustar eugeneeugenepackage test.bug90; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; public class Sample { static boolean m_afterClassWasRun = false; @Test public void test1() { } @Test public void test2() { } @AfterClass public void afterClass() { m_afterClassWasRun = true; } } testng-testng-6.9.5/src/test/java/test/bug90/Bug90Test.java0000644000175000017500000000152712551235562022643 0ustar eugeneeugenepackage test.bug90; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import test.SimpleBaseTest; import java.util.Arrays; public class Bug90Test extends SimpleBaseTest { @Test(description = "Fix for https://github.com/cbeust/testng/issues/90") public void afterClassShouldRun() { XmlSuite s = createXmlSuite("Bug90"); XmlTest t = createXmlTest(s, "Bug90 test", Sample.class.getName()); XmlClass c = t.getClasses().get(0); c.setIncludedMethods(Arrays.asList(new XmlInclude("test1"))); TestNG tng = create(); tng.setXmlSuites(Arrays.asList(s)); Sample.m_afterClassWasRun = false; tng.run(); Assert.assertTrue(Sample.m_afterClassWasRun); } } testng-testng-6.9.5/src/test/java/test/attributes/0000755000175000017500000000000012551235562021505 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/attributes/AttributeTest.java0000644000175000017500000000166212551235562025160 0ustar eugeneeugenepackage test.attributes; import org.testng.ITestContext; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.util.Set; import junit.framework.Assert; public class AttributeTest { @BeforeClass public void bc(ITestContext ctx) { ctx.setAttribute("test", "1"); } @Test public void f1(ITestContext ctx) { Set names = ctx.getAttributeNames(); Assert.assertEquals(1, names.size()); Assert.assertTrue(names.contains("test")); Assert.assertEquals(ctx.getAttribute("test"), "1"); Object v = ctx.removeAttribute("test"); Assert.assertNotNull(v); ctx.setAttribute("test2", "2"); } @Test(dependsOnMethods = "f1") public void f2(ITestContext ctx) { Set names = ctx.getAttributeNames(); Assert.assertEquals(1, names.size()); Assert.assertTrue(names.contains("test2")); Assert.assertTrue(ctx.getAttribute("test2").equals("2")); } } testng-testng-6.9.5/src/test/java/test/asserttests/0000755000175000017500000000000012551235562021703 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/asserttests/AssertTest.java0000644000175000017500000001012412551235562024645 0ustar eugeneeugenepackage test.asserttests; import org.testng.Assert; import org.testng.Assert.ThrowingRunnable; import org.testng.annotations.Test; import org.testng.collections.Sets; import java.io.IOException; import java.util.Set; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; import static org.testng.Assert.expectThrows; public class AssertTest { @Test public void noOrderSuccess() { String[] rto1 = { "boolean", "BigInteger", "List",}; String[] rto2 = { "List", "BigInteger", "boolean",}; Assert.assertEqualsNoOrder(rto1, rto2); } @Test(expectedExceptions = AssertionError.class) public void noOrderFailure() { String[] rto1 = { "a", "a", "b",}; String[] rto2 = { "a", "b", "b",}; Assert.assertEqualsNoOrder(rto1, rto2); } @Test public void intArray_Issue4() { int[] intArr00 = {1}; int[] intArr01 = {1}; Assert.assertEquals(intArr00, intArr01); } @Test public void int_Integer_Arrays() { int[] intArr = {1, 2}; Integer[] integerArr = {1, 2}; Assert.assertEquals(intArr, integerArr); Assert.assertEquals(integerArr, intArr); } @Test(expectedExceptions = AssertionError.class) public void arraysFailures_1() { int[] intArr = {1, 2}; long[] longArr = {1, 2}; Assert.assertEquals(intArr, longArr); } @Test(expectedExceptions = AssertionError.class) public void arraysFailures_2() { int[] intArr = {1, 2}; Assert.assertEquals(intArr, (long) 1); } @Test(expectedExceptions = AssertionError.class) public void arraysFailures_3() { long[] longArr = {1}; Assert.assertEquals((long) 1, longArr); } @Test public void setsSuccess() { Set set1 = Sets.newHashSet(); Set set2 = Sets.newHashSet(); set1.add(1); set2.add(1); set1.add(3); set2.add(3); set1.add(2); set2.add(2); Assert.assertEquals(set1, set2); Assert.assertEquals(set2, set1); } @Test(expectedExceptions = AssertionError.class) public void expectThrowsRequiresAnExceptionToBeThrown() { expectThrows(Throwable.class, nonThrowingRunnable()); } @Test public void expectThrowsIncludesAnInformativeDefaultMessage() { try { expectThrows(Throwable.class, nonThrowingRunnable()); } catch (AssertionError ex) { assertEquals("Expected Throwable to be thrown, but nothing was thrown", ex.getMessage()); return; } fail(); } @Test public void expectThrowsReturnsTheSameObjectThrown() { NullPointerException npe = new NullPointerException(); Throwable throwable = expectThrows(Throwable.class, throwingRunnable(npe)); assertSame(npe, throwable); } @Test(expectedExceptions = AssertionError.class) public void expectThrowsDetectsTypeMismatchesViaExplicitTypeHint() { NullPointerException npe = new NullPointerException(); expectThrows(IOException.class, throwingRunnable(npe)); } @Test public void expectThrowsWrapsAndPropagatesUnexpectedExceptions() { NullPointerException npe = new NullPointerException("inner-message"); try { expectThrows(IOException.class, throwingRunnable(npe)); } catch (AssertionError ex) { assertSame(npe, ex.getCause()); assertEquals("inner-message", ex.getCause().getMessage()); return; } fail(); } @Test public void expectThrowsSuppliesACoherentErrorMessageUponTypeMismatch() { NullPointerException npe = new NullPointerException(); try { expectThrows(IOException.class, throwingRunnable(npe)); } catch (AssertionError error) { assertEquals("Expected IOException to be thrown, but NullPointerException was thrown", error.getMessage()); assertSame(npe, error.getCause()); return; } fail(); } private static ThrowingRunnable nonThrowingRunnable() { return new ThrowingRunnable() { public void run() throws Throwable { } }; } private static ThrowingRunnable throwingRunnable(final Throwable t) { return new ThrowingRunnable() { public void run() throws Throwable { throw t; } }; } } testng-testng-6.9.5/src/test/java/test/assertion/0000755000175000017500000000000012551235562021326 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/assertion/SoftAssertTest.java0000644000175000017500000000246112551235562025131 0ustar eugeneeugenepackage test.assertion; import org.testng.Assert; import org.testng.annotations.Test; import org.testng.asserts.IAssert; import org.testng.asserts.SoftAssert; import java.util.ArrayList; import java.util.Collection; public class SoftAssertTest { @Test public void testOnSucceedAndFailureCalled() throws Exception { final Collection succeed = new ArrayList<>(); final Collection failures = new ArrayList<>(); final SoftAssert sa = new SoftAssert() { @Override public void onAssertSuccess(IAssert assertCommand) { succeed.add(assertCommand); } @Override public void onAssertFailure(IAssert assertCommand, AssertionError ex) { failures.add(assertCommand); } }; sa.assertTrue(true); sa.assertTrue(false); Assert.assertEquals(succeed.size(), 1, succeed.toString()); Assert.assertEquals(failures.size(), 1, failures.toString()); } @Test public void testAssertAllCount() throws Exception { final SoftAssert sa = new SoftAssert(); sa.assertTrue(true); sa.assertTrue(false); try { sa.assertAll(); Assert.fail("Exception expected"); } catch (AssertionError e) { final String message = e.getMessage(); Assert.assertEquals(message.split("\r?\n").length, 2, message); } } } testng-testng-6.9.5/src/test/java/test/assertion/MyRawAssertion.java0000644000175000017500000000317012551235562025121 0ustar eugeneeugenepackage test.assertion; import org.testng.Assert; import org.testng.asserts.Assertion; import org.testng.asserts.IAssert; import java.util.ArrayList; import java.util.List; public class MyRawAssertion extends Assertion { private final List methods = new ArrayList<>(); @Override public void onAssertSuccess(IAssert assertCommand) { methods.add("onAssertSuccess"); super.onAssertSuccess(assertCommand); } @Override public void onAssertFailure(IAssert assertCommand) { methods.add("deprecated_onAssertFailure"); super.onAssertFailure(assertCommand); } @Override public void onAssertFailure(IAssert assertCommand, AssertionError ex) { methods.add("onAssertFailure"); super.onAssertFailure(assertCommand, ex); } @Override public void onBeforeAssert(IAssert assertCommand) { methods.add("onBeforeAssert"); super.onBeforeAssert(assertCommand); } @Override public void onAfterAssert(IAssert assertCommand) { methods.add("onAfterAssert"); super.onAfterAssert(assertCommand); } public List getMethods() { return methods; } public void myAssert(final String actual, final boolean expected, final String message) { doAssert(new IAssert() { @Override public String getMessage() { return message; } @Override public void doAssert() { Assert.assertNotNull(actual, message); Assert.assertTrue(expected, message); } @Override public Object getActual() { return actual; } @Override public Object getExpected() { return expected; } }); } } testng-testng-6.9.5/src/test/java/test/assertion/AssertionTest.java0000644000175000017500000000263612551235562025007 0ustar eugeneeugenepackage test.assertion; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.testng.asserts.LoggingAssert; import static org.assertj.core.api.Assertions.assertThat; public class AssertionTest { private LoggingAssert m_assert; private MyRawAssertion rawAssertion; @BeforeMethod public void bm() { m_assert = new LoggingAssert(); rawAssertion = new MyRawAssertion(); } @Test(expectedExceptions = AssertionError.class) public void test1() { m_assert.assertTrue(false, "new TestNG Assertion Failed"); } @Test public void test2() { rawAssertion.assertTrue(true); rawAssertion.myAssert("test", true, "Raw test"); assertThat(rawAssertion.getMethods()) .containsExactly("onBeforeAssert", "onAssertSuccess", "onAfterAssert", "onBeforeAssert", "onAssertSuccess", "onAfterAssert"); } @Test(expectedExceptions = AssertionError.class, expectedExceptionsMessageRegExp = "Raw test .*") public void test2_fails() { try { rawAssertion.assertTrue(true); rawAssertion.myAssert("test", false, "Raw test"); } catch (AssertionError error) { assertThat(rawAssertion.getMethods()) .containsExactly("onBeforeAssert", "onAssertSuccess", "onAfterAssert", "onBeforeAssert", "onAssertFailure", "deprecated_onAssertFailure", "onAfterAssert"); throw error; } } } testng-testng-6.9.5/src/test/java/test/ant/0000755000175000017500000000000012551235562020101 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/ant/TestCommandLineArgs.java0000644000175000017500000000174112551235562024612 0ustar eugeneeugenepackage test.ant; import static org.testng.AssertJUnit.assertEquals; import org.testng.annotations.Test; import java.io.File; /** * Tests some of the functionality in {@link TestNGCommandLineArgs}. * * @author jkuhnert */ public class TestCommandLineArgs { @Test public void testUnixPathResolution() { String path = "/wee/wom/flibble.txt"; String[] segments = path.split("[/\\\\]", -1); assertEquals(4, segments.length); assertEquals("wee", segments[1]); } @Test public void testDOSPathResolution() { String path = "c:\\\\com\\pants\\wibble.txt"; String[] segments = path.split("[/\\\\]", -1); assertEquals(5, segments.length); assertEquals("com", segments[2]); // because c: is actually \\ which will be split twice } @Test public void testPathResolution() { File file = new File("pom.xml"); assert file.exists(); String path = file.getAbsolutePath(); assert path.split("[/\\\\]", -1).length > 1; } } testng-testng-6.9.5/src/test/java/test/ant/NoPackageTest.java0000644000175000017500000000061112551235562023432 0ustar eugeneeugenepackage test.ant; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; /** * @author Filippo Diotalevi */ public class NoPackageTest { private boolean m_run = false; @Test(groups = {"nopackage"}) public void test() { m_run = true; } @AfterMethod(groups = {"nopackage"}) public void after() { assert m_run : "test method was not run"; } } testng-testng-6.9.5/src/test/java/test/ant/MultipleThreadTest.java0000644000175000017500000000472512551235562024537 0ustar eugeneeugenepackage test.ant; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.util.Collections; import java.util.HashSet; import java.util.Set; /** * Tests that more than one thread is used for running tests * @author micheb10 2 Oct 2006 * */ public class MultipleThreadTest { public static Set _threads; @BeforeClass public void prepareHashSet() { _threads=Collections.synchronizedSet(new HashSet()); } @Test public void recordThread00() { _threads.add(Thread.currentThread()); } @Test public void recordThread01() { _threads.add(Thread.currentThread()); } @Test public void recordThread02() { _threads.add(Thread.currentThread()); } @Test public void recordThread03() { _threads.add(Thread.currentThread()); } @Test public void recordThread04() { _threads.add(Thread.currentThread()); } @Test public void recordThread05() { _threads.add(Thread.currentThread()); } @Test public void recordThread06() { _threads.add(Thread.currentThread()); } @Test public void recordThread07() { _threads.add(Thread.currentThread()); } @Test public void recordThread08() { _threads.add(Thread.currentThread()); } @Test public void recordThread09() { _threads.add(Thread.currentThread()); } @Test public void recordThread10() { _threads.add(Thread.currentThread()); } @Test public void recordThread11() { _threads.add(Thread.currentThread()); } @Test public void recordThread12() { _threads.add(Thread.currentThread()); } @Test public void recordThread13() { _threads.add(Thread.currentThread()); } @Test public void recordThread14() { _threads.add(Thread.currentThread()); } @Test public void recordThread15() { _threads.add(Thread.currentThread()); } @Test public void recordThread16() { _threads.add(Thread.currentThread()); } @Test public void recordThread17() { _threads.add(Thread.currentThread()); } @Test public void recordThread18() { _threads.add(Thread.currentThread()); } @Test public void recordThread19() { _threads.add(Thread.currentThread()); } @AfterClass public void confirmMultipleThreads() { Assert.assertTrue(_threads.size()>1,"More than one thread should have been used for running the tests - "+_threads.size()+" was used"); } } testng-testng-6.9.5/src/test/java/test/ant/DontOverrideSuiteNameTest.java0000644000175000017500000000032412551235562026022 0ustar eugeneeugenepackage test.ant; import org.testng.annotations.Test; @Test public class DontOverrideSuiteNameTest { private boolean m_run = false; @Test(groups = {"nopackage"}) public void test() { m_run = true; } } testng-testng-6.9.5/src/test/java/test/ant/AntSystemPropertySet.java0000644000175000017500000000170012551235562025112 0ustar eugeneeugenepackage test.ant; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import org.testng.annotations.Test; /** * Test whether nested propertysets are passed passed from the ant task. Executed by the "run:antprop" target * in test/build.xml. * * @author Todd Wells */ public class AntSystemPropertySet { @Test public void outputTestProperties() { assertNotNull(System.getProperty("syspropset1"), "syspropset1 not found"); assertEquals(System.getProperty("syspropset1"), "value 1", "Wrong value for syspropset1"); assertNotNull(System.getProperty("syspropset2"), "syspropset2 not found"); assertEquals(System.getProperty("syspropset2"), "value 2", "Wrong value for syspropset2"); assertNotNull(System.getProperty("sysprop1"), "sysprop1 not found"); assertEquals(System.getProperty("sysprop1"), "value 3", "Wrong value for sysprop1"); } } testng-testng-6.9.5/src/test/java/test/annotationtransformer/0000755000175000017500000000000012551235562023754 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/annotationtransformer/SimpleTest.java0000644000175000017500000000040712551235562026711 0ustar eugeneeugenepackage test.annotationtransformer; import org.testng.Assert; import org.testng.annotations.Test; public class SimpleTest { private int m_n; public SimpleTest(int n) { m_n = n; } @Test public void run() { Assert.assertEquals(m_n, 42); } } testng-testng-6.9.5/src/test/java/test/annotationtransformer/MyTransformer.java0000644000175000017500000000174612551235562027437 0ustar eugeneeugenepackage test.annotationtransformer; import org.testng.IAnnotationTransformer; 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 methodNames = new ArrayList<>(); @Override public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { annotation.setTimeOut(10000); if (testMethod != null) { 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()); } } public List getMethodNames() { return methodNames; } } testng-testng-6.9.5/src/test/java/test/annotationtransformer/MyTimeOutTransformer.java0000644000175000017500000000071712551235562030743 0ustar eugeneeugenepackage test.annotationtransformer; import org.testng.IAnnotationTransformer; import org.testng.annotations.ITestAnnotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class MyTimeOutTransformer implements IAnnotationTransformer { @Override public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { annotation.setTimeOut(5000); // 5 seconds } } testng-testng-6.9.5/src/test/java/test/annotationtransformer/MyParamTransformer.java0000644000175000017500000000170112551235562030407 0ustar eugeneeugenepackage test.annotationtransformer; import org.testng.IAnnotationTransformer; import org.testng.annotations.ITestAnnotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class MyParamTransformer implements IAnnotationTransformer { private boolean success = true; @Override public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { if (!onlyOneNonNull(testClass, testConstructor, testMethod)) { success = false; } } public static boolean onlyOneNonNull(Class testClass, Constructor testConstructor, Method testMethod) { return ((testClass != null && testConstructor == null && testMethod == null) || (testClass == null && testConstructor != null && testMethod == null) || (testClass == null && testConstructor == null && testMethod != null) ); } public boolean isSuccess() { return success; } } testng-testng-6.9.5/src/test/java/test/annotationtransformer/FactoryTransformer.java0000644000175000017500000000171012551235562030450 0ustar eugeneeugenepackage test.annotationtransformer; import org.testng.IAnnotationTransformer2; import org.testng.annotations.IConfigurationAnnotation; import org.testng.annotations.IDataProviderAnnotation; import org.testng.annotations.IFactoryAnnotation; import org.testng.annotations.ITestAnnotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class FactoryTransformer implements IAnnotationTransformer2 { @Override public void transform(IConfigurationAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { } @Override public void transform(IDataProviderAnnotation annotation, Method testMethod) { } @Override public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { } @Override public void transform(IFactoryAnnotation annotation, Method testMethod) { annotation.setDataProvider("dataProvider"); } } testng-testng-6.9.5/src/test/java/test/annotationtransformer/DataProviderTransformer.java0000644000175000017500000000170512551235562031431 0ustar eugeneeugenepackage test.annotationtransformer; import org.testng.IAnnotationTransformer2; import org.testng.annotations.IConfigurationAnnotation; import org.testng.annotations.IDataProviderAnnotation; import org.testng.annotations.IFactoryAnnotation; import org.testng.annotations.ITestAnnotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class DataProviderTransformer implements IAnnotationTransformer2 { @Override public void transform(IConfigurationAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { } @Override public void transform(IDataProviderAnnotation annotation, Method testMethod) { annotation.setName("dataProvider"); } @Override public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { } @Override public void transform(IFactoryAnnotation annotation, Method testMethod) { } } testng-testng-6.9.5/src/test/java/test/annotationtransformer/ConfigurationTransformer.java0000644000175000017500000000176512551235562031662 0ustar eugeneeugenepackage test.annotationtransformer; import org.testng.IAnnotationTransformer2; import org.testng.annotations.IConfigurationAnnotation; import org.testng.annotations.IDataProviderAnnotation; import org.testng.annotations.IFactoryAnnotation; import org.testng.annotations.ITestAnnotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class ConfigurationTransformer implements IAnnotationTransformer2 { @Override public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { } @Override public void transform(IConfigurationAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { if (annotation.getBeforeTestMethod()) { annotation.setEnabled(false); } } @Override public void transform(IDataProviderAnnotation annotation, Method testMethod) { } @Override public void transform(IFactoryAnnotation annotation, Method testMethod) { } } testng-testng-6.9.5/src/test/java/test/annotationtransformer/ConfigurationSampleTest.java0000644000175000017500000000131012551235562031423 0ustar eugeneeugenepackage test.annotationtransformer; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class ConfigurationSampleTest { private static String m_before = "uninitialized"; @BeforeClass public void beforeClass() { m_before = "correct"; } @BeforeMethod(enabled = false) public void testingEnabledOnConfiguration() { m_before = "this method is not enabled, we should not be here"; } // will be disabled by the configuration transformer @BeforeMethod public void beforeMethod() { m_before = "incorrect"; } @Test public void f() {} public static String getBefore() { return m_before; } } testng-testng-6.9.5/src/test/java/test/annotationtransformer/AnnotationTransformerTest.java0000644000175000017500000001602612551235562032021 0ustar eugeneeugenepackage test.annotationtransformer; import org.assertj.core.api.iterable.Extractor; import org.testng.Assert; import org.testng.IAnnotationTransformer; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.Parser; import org.testng.xml.XmlSuite; import test.SimpleBaseTest; import java.io.ByteArrayInputStream; 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() { @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 = create(AnnotationTransformerSampleTest.class); tng.setPreserveOrder(true); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); 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"); } /** * Test a transformer on a method-level @Test */ @Test public void verifyAnnotationTransformerMethod() { TestNG tng = create(AnnotationTransformerSampleTest.class); tng.setPreserveOrder(true); MyTransformer transformer = new MyTransformer(); tng.setAnnotationTransformer(transformer); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); 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(); } @Test public void verifyAnnotationTransformerHasOnlyOneNonNullArgument() { TestNG tng = create(AnnotationTransformerSampleTest.class); MyParamTransformer transformer = new MyParamTransformer(); tng.setAnnotationTransformer(transformer); tng.run(); assertThat(transformer.isSuccess()).isTrue(); } @Test public void verifyMyParamTransformerOnlyOneNonNull() { assertThat(MyParamTransformer.onlyOneNonNull(null, null, null)).isFalse(); assertThat(MyParamTransformer.onlyOneNonNull( MyParamTransformer.class, MyParamTransformer.class.getConstructors()[0], null)).isFalse(); assertThat(MyParamTransformer.onlyOneNonNull(MyParamTransformer.class, null, null)).isTrue(); } /** * Without an annotation transformer, we should have zero * passed tests and one failed test called "one". */ @Test public void verifyAnnotationTransformerClass2() { runTest(null, null, "one"); } /** * With an annotation transformer, we should have one passed * test called "one" and zero failed tests. */ @Test public void verifyAnnotationTransformerClass() { runTest(new MyTimeOutTransformer(), "one", null); } private void runTest(IAnnotationTransformer transformer, String passedName, String failedName) { TestNG tng = new TestNG(); tng.setVerbose(0); if (transformer != null) { tng.setAnnotationTransformer(transformer); } tng.setTestClasses(new Class[] { AnnotationTransformerClassSampleTest.class}); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); List results = passedName != null ? tla.getPassedTests() : tla.getFailedTests(); String name = passedName != null ? passedName : failedName; Assert.assertEquals(results.size(), 1); Assert.assertEquals(name, results.get(0).getMethod().getMethodName()); } @Test public void verifyConfigurationTransformer() { TestNG tng = new TestNG(); tng.setAnnotationTransformer(new ConfigurationTransformer()); tng.setVerbose(0); tng.setTestClasses(new Class[] { ConfigurationSampleTest.class}); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(ConfigurationSampleTest.getBefore(), "correct"); } @Test public void verifyDataProviderTransformer() { TestNG tng = create(); tng.setAnnotationTransformer(new DataProviderTransformer()); tng.setTestClasses(new Class[] { AnnotationTransformerDataProviderSampleTest.class}); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 1); } @Test public void verifyFactoryTransformer() { TestNG tng = create(); tng.setAnnotationTransformer(new FactoryTransformer()); tng.setTestClasses(new Class[] { AnnotationTransformerFactorySampleTest.class}); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); 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 = "" + " " + " " + " " + " " + " " + " " + " " + " " + "" ; ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes()); Collection suites = new Parser(is).parse(); TestNG tng = create(); tng.setXmlSuites(Arrays.asList(suites.toArray(new XmlSuite[0]))); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 1); } } testng-testng-6.9.5/src/test/java/test/annotationtransformer/AnnotationTransformerSampleTest.java0000644000175000017500000000141212551235562033154 0ustar eugeneeugenepackage test.annotationtransformer; import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; public class AnnotationTransformerSampleTest { private int m_two = 0; private int m_five = 0; private int m_three = 0; private int m_four = 0; @Test(invocationCount = 2) public void two() { m_two++; } @Test(invocationCount = 5) public void four() { m_four++; } @Test(invocationCount = 5) public void three() { m_three++; } @Test public void five() { m_five++; } @Test(dependsOnMethods = {"two", "three", "four", "five"}) public void verify() { Assert.assertEquals(m_two, 2); Assert.assertEquals(m_three, 3); Assert.assertEquals(m_four, 4); Assert.assertEquals(m_five, 5); } } ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootroottestng-testng-6.9.5/src/test/java/test/annotationtransformer/AnnotationTransformerInvocationCountTest.javatestng-testng-6.9.5/src/test/java/test/annotationtransformer/AnnotationTransformerInvocationCountTes0000644000175000017500000000160112551235562033751 0ustar eugeneeugenepackage 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() { } } testng-testng-6.9.5/src/test/java/test/annotationtransformer/AnnotationTransformerInTestngXml.java0000644000175000017500000000107012551235562033307 0ustar eugeneeugenepackage 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 AnnotationTransformerInTestngXml implements IAnnotationTransformer { @Test(enabled = false) public void shouldRunAfterTransformation() {} @Override public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { annotation.setEnabled(true); } } ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootroottestng-testng-6.9.5/src/test/java/test/annotationtransformer/AnnotationTransformerFactorySampleTest.javatestng-testng-6.9.5/src/test/java/test/annotationtransformer/AnnotationTransformerFactorySampleTest.0000644000175000017500000000065412551235562033651 0ustar eugeneeugenepackage test.annotationtransformer; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; public class AnnotationTransformerFactorySampleTest { @DataProvider public Object[][] dataProvider() { return new Integer[][] { new Integer[] { 42 }, }; } @Factory(dataProvider = "dp") public Object[] init(int n) { return new Object[] { new SimpleTest(n) }; } } ././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootroottestng-testng-6.9.5/src/test/java/test/annotationtransformer/AnnotationTransformerDataProviderSampleTest.javatestng-testng-6.9.5/src/test/java/test/annotationtransformer/AnnotationTransformerDataProviderSample0000644000175000017500000000067112551235562033707 0ustar eugeneeugenepackage test.annotationtransformer; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class AnnotationTransformerDataProviderSampleTest { @DataProvider public Object[][] dp() { return new Integer[][] { new Integer[] { 42 }, }; } @Test(dataProvider = "dataProvider") public void f(Integer n) { Assert.assertEquals(n, Integer.valueOf(42)); } } ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootroottestng-testng-6.9.5/src/test/java/test/annotationtransformer/AnnotationTransformerClassSampleTest.javatestng-testng-6.9.5/src/test/java/test/annotationtransformer/AnnotationTransformerClassSampleTest.ja0000644000175000017500000000111712551235562033615 0ustar eugeneeugenepackage test.annotationtransformer; import org.testng.annotations.Test; /** * This test will fail unless a time out transformer * is applied to it. * * @author cbeust * */ @Test(timeOut = 1000) public class AnnotationTransformerClassSampleTest { public void one() { try { Thread.sleep(2000); // ppp("FINISHED SLEEPING"); } catch (InterruptedException handled) { Thread.currentThread().interrupt(); // ppp("WAS INTERRUPTED"); // ignore } } private void ppp(String string) { System.out.println("[Transformer] " + string); } } ././@LongLink0000644000000000000000000000016100000000000011601 Lustar rootroottestng-testng-6.9.5/src/test/java/test/annotationtransformer/AnnotationTransformerClassInvocationSampleTest.javatestng-testng-6.9.5/src/test/java/test/annotationtransformer/AnnotationTransformerClassInvocationSam0000644000175000017500000000032312551235562033713 0ustar eugeneeugenepackage test.annotationtransformer; import org.testng.annotations.Test; @Test(invocationCount = 3) public class AnnotationTransformerClassInvocationSampleTest { public void f1() {} public void f2() {} } testng-testng-6.9.5/src/test/java/test/alwaysrun/0000755000175000017500000000000012551235562021344 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/alwaysrun/AlwaysRunTest.java0000644000175000017500000000315612551235562025001 0ustar eugeneeugenepackage test.alwaysrun; import static org.testng.Assert.assertTrue; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; import testhelper.OutputDirectoryPatch; public class AlwaysRunTest extends SimpleBaseTest { @Test public void withAlwaysRunAfter() { TestListenerAdapter tla = new TestListenerAdapter(); TestNG testng = create(); testng.setOutputDirectory(OutputDirectoryPatch.getOutputDirectory()); testng.setTestClasses(new Class[] { AlwaysRunAfter1.class }); testng.addListener(tla); testng.run(); assertTrue(AlwaysRunAfter1.success(), "afterTestMethod should have run"); } @Test public void withoutAlwaysRunAfter() { TestListenerAdapter tla = new TestListenerAdapter(); TestNG testng = create(); testng.setOutputDirectory(OutputDirectoryPatch.getOutputDirectory()); testng.setTestClasses(new Class[] { AlwaysRunAfter2.class }); testng.addListener(tla); testng.run(); assertTrue(AlwaysRunAfter2.success(), "afterTestMethod should not have run"); } @Test public void withoutAlwaysRunBefore() { TestListenerAdapter tla = new TestListenerAdapter(); TestNG testng = create(); testng.setOutputDirectory(OutputDirectoryPatch.getOutputDirectory()); testng.setTestClasses(new Class[] { AlwaysRunBefore1.class }); testng.setGroups("A"); testng.addListener(tla); testng.run(); assertTrue(AlwaysRunBefore1.success(), "before alwaysRun methods should have been run"); } private static void ppp(String s) { System.out.println("[AlwaysRunTest] " + s); } } testng-testng-6.9.5/src/test/java/test/alwaysrun/AlwaysRunBefore1.java0000644000175000017500000000270612551235562025345 0ustar eugeneeugenepackage test.alwaysrun; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; /** * Tests alwaysRun on a before Configuration method. Invoke this test * by running group "A" * * @author cbeust * @date Mar 11, 2006 */ public class AlwaysRunBefore1 { private static boolean m_beforeSuiteSuccess = false; private static boolean m_beforeTestSuccess = false; private static boolean m_beforeTestClassSuccess = false; private static boolean m_beforeTestMethodSuccess = false; @BeforeSuite(alwaysRun = true) public void initSuite() { m_beforeSuiteSuccess = true; } @BeforeTest(alwaysRun = true) public void initTest() { m_beforeTestSuccess = true; } @BeforeClass(alwaysRun = true) public void initTestClass() { m_beforeTestClassSuccess = true; } @BeforeMethod(alwaysRun = true) public void initTestMethod() { m_beforeTestMethodSuccess = true; } @Test(groups = "A") public void foo() { Assert.assertTrue(m_beforeSuiteSuccess); Assert.assertTrue(m_beforeTestSuccess); Assert.assertTrue(m_beforeTestClassSuccess); Assert.assertTrue(m_beforeTestMethodSuccess); } public static boolean success() { return m_beforeSuiteSuccess && m_beforeTestSuccess && m_beforeTestClassSuccess && m_beforeTestMethodSuccess; } } testng-testng-6.9.5/src/test/java/test/alwaysrun/AlwaysRunAfter2.java0000644000175000017500000000070112551235562025176 0ustar eugeneeugenepackage test.alwaysrun; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; public class AlwaysRunAfter2 { private static boolean m_success = true; @BeforeClass public void setUpShouldFail() { throw new RuntimeException("Failing in setUp"); } // Should not be run @AfterClass public void tearDown() { m_success = false; } static public boolean success() { return m_success; } } testng-testng-6.9.5/src/test/java/test/alwaysrun/AlwaysRunAfter1.java0000644000175000017500000000110512551235562025174 0ustar eugeneeugenepackage test.alwaysrun; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class AlwaysRunAfter1 { private static boolean m_success = false; @BeforeClass public void setUpShouldFail() { throw new RuntimeException("Failing in setUp"); } @AfterClass(alwaysRun = true) public void tearDown() { m_success = true; } // Adding this method or @Configuration will never be invoked @Test public void dummy() { } static public boolean success() { return m_success; } } testng-testng-6.9.5/src/test/java/test/access/0000755000175000017500000000000012551235562020560 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/access/PrivateAccessConfigurationMethods.java0000644000175000017500000000271012551235562030233 0ustar eugeneeugenepackage test.access; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * Test that private and protected @Configuration methods are run * * @author cbeust */ public class PrivateAccessConfigurationMethods extends BasePrivateAccessConfigurationMethods { private boolean m_private = false; private boolean m_default = false; private boolean m_protected = false; private boolean m_public = false; @BeforeMethod private void privateConfBeforeMethod() { m_private = true; } @BeforeMethod void defaultConfBeforeMethod() { m_default = true; } @BeforeMethod protected void protectedConfBeforeMethod() { m_protected = true; } @BeforeMethod public void publicConfBeforeMethod() { m_public = true; } @Test public void allAccessModifiersConfiguration() { Assert.assertTrue(m_private, "private @Configuration should have been run"); Assert.assertTrue(m_default, "default @Configuration should have been run"); Assert.assertTrue(m_protected, "protected @Configuration should have been run"); Assert.assertTrue(m_public, "public @Configuration should have been run"); Assert.assertTrue(m_baseProtected, "protected base @Configuration should have been run"); Assert.assertTrue(m_baseDefault, "default base @Configuration should have been run"); Assert.assertTrue(m_basePrivate, "private base @Configuration should not have been run"); } } testng-testng-6.9.5/src/test/java/test/access/BasePrivateAccessConfigurationMethods.java0000644000175000017500000000102512551235562031024 0ustar eugeneeugenepackage test.access; import org.testng.annotations.BeforeMethod; public class BasePrivateAccessConfigurationMethods { protected boolean m_baseProtected = false; protected boolean m_baseDefault = false; protected boolean m_basePrivate = true; @BeforeMethod void baseDefaultConfBeforeMethod() { m_baseDefault = true; } @BeforeMethod protected void baseProtectedConfBeforeMethod() { m_baseProtected = true; } @BeforeMethod private void basePrivateConfBeforeMethod() { m_basePrivate = false; } } testng-testng-6.9.5/src/test/java/test/abstractmethods/0000755000175000017500000000000012551235562022506 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/abstractmethods/CRUDTest2.java0000644000175000017500000000023612551235562025031 0ustar eugeneeugenepackage test.abstractmethods; public class CRUDTest2 extends CRUDTest { @Override public void create() { } @Override public void read() { } } testng-testng-6.9.5/src/test/java/test/abstractmethods/CRUDTest.java0000644000175000017500000000032612551235562024747 0ustar eugeneeugenepackage test.abstractmethods; import org.testng.annotations.Test; abstract public class CRUDTest { @Test public abstract void create(); @Test(dependsOnMethods = "create") public abstract void read(); } testng-testng-6.9.5/src/test/java/test/abstractmethods/AbstractTest.java0000644000175000017500000000105712551235562025757 0ustar eugeneeugenepackage test.abstractmethods; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.SimpleBaseTest; public class AbstractTest extends SimpleBaseTest { @Test(description = "Abstract methods defined in a superclass should be run") public void abstractShouldRun() { TestNG tng = create(CRUDTest2.class); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 2); } } testng-testng-6.9.5/src/test/java/test/abstractconfmethod/0000755000175000017500000000000012551235562023171 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/abstractconfmethod/foo/0000755000175000017500000000000012551235562023754 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/test/abstractconfmethod/foo/A.java0000644000175000017500000000014712551235562025001 0ustar eugeneeugenepackage test.abstractconfmethod.foo; public abstract class A { public abstract void testSetup(); } testng-testng-6.9.5/src/test/java/test/abstractconfmethod/C.java0000644000175000017500000000050612551235562024217 0ustar eugeneeugenepackage test.abstractconfmethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class C extends B { @Override @BeforeMethod public void testSetup() {} @Test(description="Test depends on a config method that has implements an abstract methods") public void test1() {} } testng-testng-6.9.5/src/test/java/test/abstractconfmethod/B.java0000644000175000017500000000037012551235562024215 0ustar eugeneeugenepackage test.abstractconfmethod; import org.testng.annotations.BeforeMethod; import test.abstractconfmethod.foo.A; public abstract class B extends A { @BeforeMethod(dependsOnMethods = {"testSetup"}) public void doSomethingInMiddle() {} } testng-testng-6.9.5/src/test/java/test/TestHelper.java0000644000175000017500000000346012551235562022244 0ustar eugeneeugenepackage test; import org.testng.TestNG; import org.testng.collections.Lists; import org.testng.xml.XmlClass; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Random; public class TestHelper { public static XmlSuite createSuite(String cls, String suiteName) { XmlSuite result = new XmlSuite(); result.setName(suiteName); XmlTest test = new XmlTest(result); test.setName("TmpTest"); List classes = new ArrayList<>(); classes.add(new XmlClass(cls)); test.setXmlClasses(classes); return result; } public static TestNG createTestNG(String outputDir) { return createTestNG(null, outputDir); } public static TestNG createTestNG() { return createTestNG(null, null); } public static TestNG createTestNG(XmlSuite suite) { return createTestNG(suite, System.getProperty("java.io.tmpdir")); } public static TestNG createTestNG(XmlSuite suite, String outputDir) { TestNG result = new TestNG(); if (suite != null) { List suites = Lists.newArrayList(); suites.add(suite); result.setXmlSuites(suites); } if (outputDir == null) { outputDir = createRandomDirectory().getAbsolutePath(); } result.setOutputDirectory(outputDir); result.setVerbose(-1); return result; } public static File createRandomDirectory() { String dir = System.getProperty("java.io.tmpdir"); Random r = new Random(System.currentTimeMillis()); String name = "testng-tmp-" + r.nextInt(); File result = new File(dir + File.separatorChar + name); result.deleteOnExit(); result.mkdirs(); return result; } private static void ppp(String string) { System.out.println("[TestHelper] " + string); } } testng-testng-6.9.5/src/test/java/test/Test2.java0000644000175000017500000000424712551235562021172 0ustar eugeneeugenepackage test; import org.testng.Assert; import org.testng.annotations.Configuration; import org.testng.annotations.Test; /** * * @author Cedric Beust, May 5, 2004 * */ public class Test2 extends BaseTest { private boolean m_initializedCorrectly = false; @Configuration(beforeTestMethod = true) // @BeforeMethod public void correctSetup() { m_initializedCorrectly = true; } // Shouldn't be called @Configuration(beforeTestMethod = true, groups = "excludeThisGroup") // @BeforeMethod(groups = { "excludeThisGroup"} ) public void incorrectSetup() { throw new RuntimeException("Should never be run"); } @Test public void noGroups() { addClass("test.sample.Sample1"); run(); String[] passed = { "method1", "method2", "method3", "broken", "throwExpectedException1ShouldPass", "throwExpectedException2ShouldPass" }; String[] failed = { "throwExceptionShouldFail", "verifyLastNameShouldFail" }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void setUpWithGroups() { run(); Assert.assertTrue(m_initializedCorrectly, "Should have run the correctSetup method"); } @Test public void partialGroupsClass() { addClass("test.sample.PartialGroupTest"); addIncludedGroup("classGroup"); run(); String[] passed = { "testMethodGroup", "testClassGroup" }; String[] failed = { "testMethodGroupShouldFail", "testClassGroupShouldFail" }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); // ppp("@@@@@@@@@@@@@@@@@@ PASSED TESTS"); // for (Object o : getPassedTests().values()) { // ppp("@@@@@@@@@@ PASSED:" + o); // } } @Test public void partialGroupsMethod() { addClass("test.sample.PartialGroupTest"); addIncludedGroup("methodGroup"); run(); String[] passed = { "testMethodGroup", }; String[] failed = { "testMethodGroupShouldFail" }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } } testng-testng-6.9.5/src/test/java/test/Test1.java0000644000175000017500000000706712551235562021174 0ustar eugeneeugenepackage test; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.List; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; public class Test1 extends BaseTest { /** * This constructor is package protected on purpose, to test that * TestNG can still instantiate the class. */ Test1() {} @Test(groups = { "current" }) public void includedGroups() { addClass("test.sample.Sample1"); assert 1 == getTest().getXmlClasses().size(); addIncludedGroup("odd"); run(); String[] passed = { "method1", "method3", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void groupsOfGroupsSimple() { addClass("test.sample.Sample1"); assert 1 == getTest().getXmlClasses().size(); // should match all methods belonging to group "odd" and "even" addIncludedGroup("evenodd"); List l = new ArrayList<>(); l.add("even"); l.add("odd"); addMetaGroup("evenodd", l); run(); String passed[] = { "method1", "method2", "method3", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void groupsOfGroupsWithIndirections() { addClass("test.sample.Sample1"); addIncludedGroup("all"); List l = new ArrayList<>(); l.add("methods"); l.add("broken"); addMetaGroup("all", l); l = new ArrayList<>(); l.add("odd"); l.add("even"); addMetaGroup("methods", l); addMetaGroup("broken", "broken"); run(); String[] passed = { "method1", "method2", "method3", "broken" }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void groupsOfGroupsWithCycle() { addClass("test.sample.Sample1"); addIncludedGroup("all"); addMetaGroup("all", "all2"); addMetaGroup("all2", "methods"); addMetaGroup("methods", "all"); run(); String[] passed = { }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test // (groups = { "one" }) public void excludedGroups() { addClass("test.sample.Sample1"); addExcludedGroup("odd"); run(); String passed[] = { "method2", "broken", "throwExpectedException1ShouldPass", "throwExpectedException2ShouldPass" }; String[] failed = { "throwExceptionShouldFail", "verifyLastNameShouldFail" }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void regexp() { addClass("test.sample.Sample1"); // should matches all methods belonging to group "odd" addIncludedGroup("o.*"); run(); String passed[] = { "method1", "method3" }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test(groups = { "currentold" }) public void logger() { Logger logger = Logger.getLogger(""); // System.out.println("# HANDLERS:" + logger.getHandlers().length); for (Handler handler : logger.getHandlers()) { handler.setLevel(Level.WARNING); handler.setFormatter(new org.testng.log.TextFormatter()); } logger.setLevel(Level.SEVERE); } static public void ppp(String s) { System.out.println("[Test1] " + s); } } // Test1 testng-testng-6.9.5/src/test/java/test/StaticTest.java0000644000175000017500000000036012551235562022250 0ustar eugeneeugenepackage test; import org.testng.annotations.Test; /** * This used to create a StackOverflowError. */ public class StaticTest { @Test public void test() { } @Test public static class InnerStaticClass extends StaticTest { } }testng-testng-6.9.5/src/test/java/test/SimpleBaseTest.java0000644000175000017500000000551012551235562023047 0ustar eugeneeugenepackage test; import org.testng.Assert; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.collections.Lists; import org.testng.internal.Utils; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import java.io.File; import java.util.Iterator; import java.util.List; public class SimpleBaseTest { // System property specifying where the resources (e.g. xml files) can be found private static final String TEST_RESOURCES_DIR = "test.resources.dir"; public static TestNG create() { TestNG result = new TestNG(); result.setUseDefaultListeners(false); result.setVerbose(0); return result; } public static TestNG create(Class testClass) { TestNG result = create(); result.setTestClasses(new Class[] { testClass}); return result; } protected TestNG create(Class... testClasses) { TestNG result = create(); result.setTestClasses(testClasses); return result; } protected XmlSuite createXmlSuite(String name) { XmlSuite result = new XmlSuite(); result.setName(name); return result; } protected XmlTest createXmlTest(XmlSuite suite, String name, String... classes) { XmlTest result = new XmlTest(suite); int index = 0; result.setName(name); for (String c : classes) { XmlClass xc = new XmlClass(c, index++, true /* load classes */); result.getXmlClasses().add(xc); } return result; } protected void addMethods(XmlClass cls, String... methods) { int index = 0; for (String m : methods) { XmlInclude include = new XmlInclude(m, index++); cls.getIncludedMethods().add(include); } } protected String getPathToResource(String fileName) { String result = System.getProperty(TEST_RESOURCES_DIR); if (result == null) { Utils.log("SimpleBaseTest", 2, "Warning: System property " + TEST_RESOURCES_DIR + " was not defined."); return "target/test-classes/" + fileName; } else { return result + File.separatorChar + fileName; } } protected void verifyPassedTests(TestListenerAdapter tla, String... methodNames) { Iterator it = tla.getPassedTests().iterator(); Assert.assertEquals(tla.getPassedTests().size(), methodNames.length); int i = 0; while (it.hasNext()) { Assert.assertEquals(it.next().getName(), methodNames[i++]); } } /** * Compare a list of ITestResult with a list of String method names, */ public static void assertTestResultsEqual(List results, List methods) { List resultMethods = Lists.newArrayList(); for (ITestResult r : results) { resultMethods.add(r.getMethod().getMethodName()); } Assert.assertEquals(resultMethods, methods); } } testng-testng-6.9.5/src/test/java/test/SerializationTest.java0000644000175000017500000000151512551235562023641 0ustar eugeneeugenepackage test; import org.testng.ITestContext; import org.testng.annotations.Test; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class SerializationTest { @Test(groups = "broken") public void iSuiteShouldBeSerializable(ITestContext context) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(out); oos.writeObject(context.getSuite()); oos.close(); } @Test(groups = { "broken", "maven-broken" }) public void testngMethodShouldBeSerializable(ITestContext context) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(out); oos.writeObject(context.getAllTestMethods()[0]); oos.close(); } } testng-testng-6.9.5/src/test/java/test/SampleInheritance.java0000644000175000017500000000276612551235562023570 0ustar eugeneeugenepackage test; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import test.sample.BaseSampleInheritance; public class SampleInheritance extends BaseSampleInheritance { // Test dependency of configuration methods @BeforeClass(groups= { "configuration0"}) public void configuration0() { addConfiguration("configuration0"); // System.out.println("CONFIGURATION 0"); } @BeforeClass(dependsOnGroups = { "configuration1"}) public void configuration2() { assert m_configurations.size() == 2 : "Expected size 2 found " + m_configurations.size(); assert "configuration0".equals(m_configurations.get(0)) : "Expected configuration0 to be run"; assert "configuration1".equals(m_configurations.get(1)) : "Expected configuration1 to be run"; addConfiguration("configuration2"); } @Test(dependsOnGroups = { "inheritedTestMethod"} ) public void inheritedMethodsWereCalledInOrder() { assert m_invokedBaseMethod : "Didn't invoke test method in base class"; assert m_invokedBaseConfiguration : "Didn't invoke configuration method in base class"; } @Test public void configurationsWereCalledInOrder() { assert m_configurations.size() == 3; assert "configuration0".equals(m_configurations.get(0)) : "Expected configuration0 to be run"; assert "configuration1".equals(m_configurations.get(1)) : "Expected configuration1 to be run"; assert "configuration2".equals(m_configurations.get(2)) : "Expected configuration1 to be run"; } } testng-testng-6.9.5/src/test/java/test/ReturnValueTest.java0000644000175000017500000000276512551235562023310 0ustar eugeneeugenepackage test; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import java.util.Arrays; public class ReturnValueTest extends SimpleBaseTest { private XmlSuite m_suite; private XmlTest m_test; @BeforeMethod public void before() { m_suite = createXmlSuite("suite"); m_test = createXmlTest(m_suite, "test", ReturnValueSampleTest.class.getName()); } @Test public void suiteReturnValueTestShouldBeRun() { m_suite.setAllowReturnValues(true); runTest(true); } @Test public void suiteReturnValueTestShouldNotBeRun() { runTest(false); } @Test public void testReturnValueTestShouldBeRun() { m_test.setAllowReturnValues(true); runTest(true); } private void runTest(boolean allowed) { TestNG tng = create(); tng.setXmlSuites(Arrays.asList(m_suite)); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); if (allowed) { Assert.assertEquals(tla.getFailedTests().size(), 0); Assert.assertEquals(tla.getSkippedTests().size(), 0); assertTestResultsEqual(tla.getPassedTests(), Arrays.asList("shouldRun")); } else { Assert.assertEquals(tla.getFailedTests().size(), 0); Assert.assertEquals(tla.getPassedTests().size(), 0); Assert.assertEquals(tla.getSkippedTests().size(), 0); } } } testng-testng-6.9.5/src/test/java/test/ReturnValueSampleTest.java0000644000175000017500000000022112551235562024433 0ustar eugeneeugenepackage test; import org.testng.annotations.Test; public class ReturnValueSampleTest { @Test public int shouldRun() { return 0; } } testng-testng-6.9.5/src/test/java/test/ReporterApiTest.java0000644000175000017500000000057712551235562023267 0ustar eugeneeugenepackage test; import org.testng.Reporter; import org.testng.annotations.Test; /** * Make sure we don't remove public API's from Reporter. * * @author Cedric Beust */ public class ReporterApiTest { @Test public void testApi() { Reporter.log("foo"); Reporter.log("foo", false); Reporter.log("foo", 2); Reporter.log("foo", 2, false); } } testng-testng-6.9.5/src/test/java/test/ParameterConstructorTest.java0000644000175000017500000000241612551235562025213 0ustar eugeneeugenepackage test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import org.testng.annotations.Parameters; import org.testng.annotations.Test; /** * Test parameters passed to constructors * * @author cbeust */ public class ParameterConstructorTest { private String m_string = null; private int m_int = -1; private boolean m_boolean = false; private byte m_byte = -1; private char m_char = 0; private double m_double = 0.0; private float m_float = 0.0f; private long m_long = 0; private short m_short = 0; @Parameters({ "string", "int", "boolean", "byte", "char", "double", "float", "long", "short" }) public ParameterConstructorTest(String s, int i, boolean bo, byte b, char c, double d, float f, long l, short sh) { m_string = s; m_int = i; m_boolean = bo; m_byte = b; m_char = c; m_double = d; m_float = f; m_long = l; m_short = sh; } @Test public void verify() { assertEquals("Cedric", m_string); assertEquals(42, m_int); assertTrue(m_boolean); assertEquals(43, m_byte); assertEquals('c', m_char); assertEquals(44.0, m_double, 0.1); assertEquals(45.0f, m_float, 0.1); assertEquals(46, m_long); assertEquals(47, m_short); } } testng-testng-6.9.5/src/test/java/test/NestedStaticTest.java0000644000175000017500000000157212551235562023421 0ustar eugeneeugenepackage test; import org.testng.Assert; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.collections.Sets; import java.util.HashSet; import java.util.List; import java.util.Set; public class NestedStaticTest extends SimpleBaseTest { @Test public void nestedClassShouldBeIncluded() { TestNG tng = create(NestedStaticSampleTest.class); TestListenerAdapter tla = new TestListenerAdapter(); tng.addListener(tla); tng.run(); Set expected = new HashSet() {{ add("nested"); add("f"); }}; Set actual = Sets.newHashSet(); List passedTests = tla.getPassedTests(); for (ITestResult t : passedTests) { actual.add(t.getMethod().getMethodName()); } Assert.assertEquals(actual, expected); } } testng-testng-6.9.5/src/test/java/test/NestedStaticSampleTest.java0000644000175000017500000000030512551235562024554 0ustar eugeneeugenepackage test; import org.testng.annotations.Test; public class NestedStaticSampleTest { @Test public void f() { } public class Nested { @Test public void nested() { } } } testng-testng-6.9.5/src/test/java/test/Misc.java0000644000175000017500000000127612551235562021063 0ustar eugeneeugenepackage test; import org.testng.annotations.Test; /** * This class * * @author cbeust */ public class Misc extends BaseTest { @Test public void makeSureSetUpWithParameterWithNoParametersFails() { addClass("test.sample.SetUpWithParameterTest"); setVerbose(0); // setParallel(XmlSuite.PARALLEL_METHODS); run(); String[] passed = { }; // @Configuration failures are not reported in the ITestListener String[] failed = { }; String[] skipped = { "test", }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); verifyTests("Failed", skipped, getSkippedTests()); } } testng-testng-6.9.5/src/test/java/test/MethodTest.java0000644000175000017500000000254712551235562022252 0ustar eugeneeugenepackage test; import org.testng.Assert; import org.testng.annotations.Test; import test.sample.Sample2; public class MethodTest extends BaseTest { private static final String CLASS_NAME = Sample2.class.getName(); @Test(groups = { "current" }) public void includeMethodsOnly() { addClass(CLASS_NAME); Assert.assertEquals(getTest().getXmlClasses().size(), 1); addIncludedMethod(CLASS_NAME, ".*method2"); run(); String[] passed = { "method2", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test(groups = { "current" }) public void excludeMethodsOnly() { addClass(CLASS_NAME); Assert.assertEquals(getTest().getXmlClasses().size(), 1); addExcludedMethod(CLASS_NAME, ".*method2"); run(); String[] passed = { "method1", "method3" }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void excludePackage() { addClass(CLASS_NAME); assert 1 == getTest().getXmlClasses().size(); addExcludedMethod(CLASS_NAME, ".*"); run(); String[] passed = { }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } }testng-testng-6.9.5/src/test/java/test/MapTest.java0000644000175000017500000000074412551235562021544 0ustar eugeneeugenepackage test; import org.testng.Assert; import org.testng.annotations.Test; import java.util.HashMap; import java.util.Map; public class MapTest { @Test(description = "Make sure that arrays as map values work with assert") public void testMap() { Map mapA = new HashMap<>(); Map mapB = new HashMap<>(); mapA.put("A", new boolean[] { true }); mapB.put("A", new boolean[] { true }); Assert.assertEquals(mapA, mapB); } }testng-testng-6.9.5/src/test/java/test/JUnitTest1.java0000644000175000017500000000614712551235562022144 0ustar eugeneeugenepackage test; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import test.junit.SetNameTest; import test.sample.JUnitSample1; import test.sample.JUnitSample2; /** * This class * * @author Cedric Beust, May 5, 2004 * */ public class JUnitTest1 extends BaseTest { @BeforeMethod(dependsOnGroups = { "initTest"} ) public void initJUnitFlag() { getTest().setJUnit(true); } @Test public void methodsThatStartWithTest() { addClass("test.sample.JUnitSample1"); assert getTest().isJUnit(); run(); String[] passed = { JUnitSample1.EXPECTED1, JUnitSample1.EXPECTED2 }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void methodsWithSetup() { addClass("test.sample.JUnitSample2"); run(); String[] passed = { "testSample2ThatSetUpWasRun", }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void testSuite() { addClass("test.sample.AllJUnitTests"); run(); String[] passed = { JUnitSample1.EXPECTED1, /*JUnitSample1.EXPECTED2,*/ JUnitSample2.EXPECTED, }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void testNewInstance() { addClass("test.sample.JUnitSample3"); run(); String[] passed = { "test1", "test2" }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void setUpFailingShouldCauseMethodsToBeSkipped() { addClass("test.junit.SetUpExceptionSampleTest"); run(); String[] passed = { }; String[] failed = { "testM1"/*, "testM1", "tearDown"*/ }; String[] skipped = { /*"testM1", "tearDown"*/ }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Skipped", skipped, getSkippedTests()); verifyTests("Failed", failed, getFailedTests()); } @Test public void setNameShouldBeInvoked() { addClass("test.junit.SetNameTest"); SetNameTest.m_ctorCount = 0; run(); String[] passed = { "testFoo", "testBar", }; String[] failed = { }; String[] skipped = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Skipped", skipped, getSkippedTests()); verifyTests("Failed", failed, getFailedTests()); Assert.assertEquals(SetNameTest.m_ctorCount, 2, "Expected 2 instances to be created, found " + SetNameTest.m_ctorCount); } public static void ppp(String s) { System.out.println("[JUnitTest1] " + s); } @Test public void testAbstract() { addClass("test.sample.JUnitSample4"); run(); String[] passed = { "testXY", "testXY", "testXY" }; String[] failed = { }; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } } testng-testng-6.9.5/src/test/java/test/JUnit4Test.java0000644000175000017500000000542312551235562022143 0ustar eugeneeugenepackage 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; /** * * @author lukas */ public class JUnit4Test extends BaseTest { @BeforeMethod(dependsOnGroups = {"initTest"}) public void initJUnitFlag() { getTest().setJUnit(true); } @Test public void testTests() { addClass("test.junit4.JUnit4Sample2"); assert getTest().isJUnit(); run(); String[] passed = JUnit4Sample2.EXPECTED; String[] failed = JUnit4Sample2.FAILED; String[] skipped = JUnit4Sample2.SKIPPED; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test public void testSuite() { addClass("test.junit4.JUnit4SampleSuite"); assert getTest().isJUnit(); run(); String[] passed = JUnit4SampleSuite.EXPECTED; String[] failed = JUnit4SampleSuite.FAILED; String[] skipped = JUnit4SampleSuite.SKIPPED; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test public void testSuiteInheritance() { addClass("test.junit4.JUnit4Child"); assert getTest().isJUnit(); run(); String[] passed = JUnit4Child.EXPECTED; String[] failed = {}; String[] skipped = {}; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } @Test public void testTestInheritance() { addClass("test.junit4.InheritedTest"); addClass("test.junit4.JUnit4Sample1"); assert getTest().isJUnit(); run(); String[] passed = {"t1", "t1"}; String[] failed = {}; String[] skipped = {}; verifyTests("Passed", passed, getPassedTests()); 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()); } } testng-testng-6.9.5/src/test/java/test/InvokedMethodNameListener.java0000644000175000017500000000326612551235562025240 0ustar eugeneeugenepackage 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; // TODO replace other test IInvokedMethodListener by this one public class InvokedMethodNameListener implements IInvokedMethodListener { private final List invokedMethodNames = new ArrayList<>(); private final List failedMethodNames = new ArrayList<>(); private final List skippedMethodNames = new ArrayList<>(); private final List succeedMethodNames = new ArrayList<>(); @Override public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { invokedMethodNames.add(method.getTestMethod().getConstructorOrMethod().getName()); } @Override public void afterInvocation(IInvokedMethod method, ITestResult testResult) { switch (testResult.getStatus()) { case ITestResult.FAILURE: failedMethodNames.add(method.getTestMethod().getConstructorOrMethod().getName()); break; case ITestResult.SKIP: skippedMethodNames.add(method.getTestMethod().getConstructorOrMethod().getName()); break; case ITestResult.SUCCESS: succeedMethodNames.add(method.getTestMethod().getConstructorOrMethod().getName()); break; } } public List getInvokedMethodNames() { return Collections.unmodifiableList(invokedMethodNames); } public List getFailedMethodNames() { return failedMethodNames; } public List getSkippedMethodNames() { return skippedMethodNames; } public List getSucceedMethodNames() { return succeedMethodNames; } } testng-testng-6.9.5/src/test/java/test/InvocationAndSuccessPercentageTest.java0000644000175000017500000000616412551235562027114 0ustar eugeneeugenepackage test; import org.testng.annotations.Test; /** * This class tests invocationCount and successPercentage * * @author cbeust */ public class InvocationAndSuccessPercentageTest extends BaseTest { @Test public void invocationCount() { addClass("test.sample.InvocationCountTest"); addIncludedGroup("invocationOnly"); run(); String[] passed = { "tenTimesShouldSucceed", }; String[] failed = { }; verifyResults(getPassedTests(), 10, "passed tests"); // Map passedTests = getPassedTests(); // Set keys = passedTests.keySet(); // Object firstKey = keys.iterator().next(); // ITestResult passedResult = (ITestResult) passedTests.get(firstKey); // int n = passedResult.getPassedMethods().size(); // assert n == 10 : // "Expected 10 tests to have passed, but only found " + n; verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); } /** * Result expected: * 8 passed * 2 failed but within success percentage */ @Test public void successPercentageThatSucceeds() { addClass("test.sample.InvocationCountTest"); addIncludedGroup("successPercentageThatSucceedsOnly"); run(); String[] passed = { "successPercentageShouldSucceed", }; String[] failed = { }; String[] failedButWithinSuccessPercentage = { "successPercentageShouldSucceed", }; verifyTests("FailedButWithinSuccessPercentage", failedButWithinSuccessPercentage, getFailedButWithinSuccessPercentageTests()); verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); // Should have 8 passed, 2 failed but within success percentage verifyResults(getPassedTests(), 8, "passed tests"); verifyResults( getFailedButWithinSuccessPercentageTests(), 2, "failed_but_within_success_percentage_tests"); } /** * Result expected: * 8 passed * 1 failed but within success percentage * 1 failed */ @Test public void successPercentageThatFails() { addClass(test.sample.InvocationCountTest.class); addIncludedGroup("successPercentageThatFailsOnly"); run(); String[] passed = { "successPercentageShouldFail", }; String[] failed = { "successPercentageShouldFail", }; String[] failedButWithinSuccessPercentage = { "successPercentageShouldFail", }; verifyTests("FailedButWithinSuccessPercentage", failedButWithinSuccessPercentage, getFailedButWithinSuccessPercentageTests()); verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); // Should have 8 passed, 2 failed but within success percentage verifyResults(getPassedTests(), 8, "passed tests"); verifyResults(getFailedTests(), 1, "failed tests"); verifyResults( getFailedButWithinSuccessPercentageTests(), 1, "failed_but_within_success_percentage_tests"); } public static void ppp(String s) { System.out.println("[Invocation] " + s); } } testng-testng-6.9.5/src/test/java/test/IndividualMethodsTest.java0000644000175000017500000000116312551235562024437 0ustar eugeneeugenepackage test; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * Test that if an individual method is specified on testng.xml, the @Configuration * method still runs. * * Created on Aug 1, 2005 * @author cbeust */ public class IndividualMethodsTest { private boolean m_setUpCalled = false; @BeforeMethod public void setUp() { m_setUpCalled = true; } @Test public void testMethod() { // this line causes the test to fail, showing that setUp() hadn't been run Assert.assertTrue(m_setUpCalled); } } testng-testng-6.9.5/src/test/java/test/GraphTest.java0000644000175000017500000001361612551235562022072 0ustar eugeneeugenepackage test; import org.testng.Assert; import org.testng.TestNGException; import org.testng.annotations.Test; import org.testng.internal.Graph; import org.testng.internal.Tarjan; import java.util.List; /** * This class * * @author cbeust */ public class GraphTest { @Test public void sort() { Graph g = new Graph<>(); g.addNode("3"); g.addNode("1"); g.addNode("2.2"); g.addNode("independent"); g.addNode("2.1"); g.addNode("2"); g.addPredecessor("3", "2"); g.addPredecessor("3", "2.1"); g.addPredecessor("3", "2.2"); g.addPredecessor("2", "1"); g.addPredecessor("2.1", "1"); g.addPredecessor("2.2", "1"); g.topologicalSort(); List l = g.getStrictlySortedNodes(); int i = 0; Assert.assertTrue("1".equals(l.get(i))); i++; Assert.assertTrue("2".equals(l.get(i)) || "2.1".equals(l.get(i)) || "2.2".equals(l.get(i))); i++; Assert.assertTrue("2".equals(l.get(i)) || "2.1".equals(l.get(i)) || "2.2".equals(l.get(i))); i++; Assert.assertTrue("2".equals(l.get(i)) || "2.1".equals(l.get(i)) || "2.2".equals(l.get(i))); i++; Assert.assertTrue("3".equals(l.get(i))); Assert.assertTrue(1 == g.getIndependentNodes().size()); } @Test(expectedExceptions = org.testng.TestNGException.class) public void cycleShouldFail() { Graph g = createCyclicGraph(); g.topologicalSort(); } @Test public void cycleShouldBeCorrect() { Graph g = null; try { g = createCyclicGraph(); g.topologicalSort(); } catch(TestNGException ex) { Tarjan t = new Tarjan<>(g, "1"); Assert.assertEquals(t.getCycle().size(), 3); } } private Graph createCyclicGraph() { Graph g = new Graph<>(); g.addNode("3"); g.addNode("2"); g.addNode("1"); g.addPredecessor("3", "2"); g.addPredecessor("2", "1"); g.addPredecessor("1", "3"); return g; } @Test public void findPredecessors() { Graph g = new Graph<>(); g.addNode("3"); g.addNode("1"); g.addNode("2.2"); g.addNode("independent"); g.addNode("2.1"); g.addNode("2"); // 1 -> 2.1, 2.2, 2.3 --> 3 g.addPredecessor("3", "2"); g.addPredecessor("3", "2.1"); g.addPredecessor("3", "2.2"); g.addPredecessor("2", "1"); g.addPredecessor("2.1", "1"); g.addPredecessor("2.2", "1"); // Invoke sort to make sure there is no side effect g.topologicalSort(); // // Test findPredecessors // { List predecessors = g.findPredecessors("2"); Assert.assertTrue(predecessors.size() == 1); Assert.assertTrue(predecessors.get(0).equals("1")); } { List predecessors = g.findPredecessors("3"); Assert.assertTrue(predecessors.size() == 4); Assert.assertTrue(predecessors.get(0).equals("1")); Assert.assertTrue(predecessors.get(1).equals("2.1") || predecessors.get(1).equals("2.2") || predecessors.get(1).equals("2")); Assert.assertTrue(predecessors.get(2).equals("2.1") || predecessors.get(2).equals("2.2") || predecessors.get(2).equals("2")); Assert.assertTrue(predecessors.get(3).equals("2.1") || predecessors.get(3).equals("2.2") || predecessors.get(3).equals("2")); } } // Using an earlier implementation of Graph.findPrecessors, finding // predecessors in certain kinds of graphs where many nodes have the // same predecessors could be very slow, since the old implementation // would explore the same nodes repeatedly. This situation could // happen when test methods are organized in several groups, with // dependsOnGroups annotations so that each method in one group depends // on all of the methods in another group. If there were several // such groups depending on each other in a chain, the combinatorics // of the old method became excessive. This test builds a 72-node graph that // emulates this situation, then call Graph.findPredecessors. The old // implementation run this in 70+ seconds on my computer, the new implementation // takes a few milliseconds. In practice, with larger graphs, the former // slowness could get very extreme, taking hours or more to complete // in some real user situations. // @Test(timeOut = 5000) // If this takes more than 5 seconds we've definitely regressed. public void findPredecessorsTiming() { Graph g = new Graph<>(); final String rootNode = "myroot"; final String independentNode = "independent"; g.addNode(rootNode); g.addNode(independentNode); final int maxDepth = 7; final int nodesPerDepth = 10; // must be < 100 // // Add maxDepth groups of new nodes, where each group contains nodesPerDepth // nodes, and each node in a group a depth N has each node in the group // at depth (N-1) as a predecessor. // for (int depth = 1; depth <= maxDepth; depth++) { for (int i = 0; i < nodesPerDepth; i++) { String newNode = String.valueOf(i + (100 * depth)); g.addNode(newNode); if (depth == 1) { continue; } for (int j = 0; j < nodesPerDepth; j++) { String prevNode = String.valueOf(j + (100 * (depth - 1))); g.addPredecessor(newNode, prevNode); } } } // Finally, make all of the nodes in the group at depth maxDepth // be predecessors of rootNode. // for (int i = 0; i < nodesPerDepth; i++) { String node = String.valueOf(i + (100 * maxDepth)); g.addPredecessor(rootNode, node); } // Now we're done building the graph, which has (maxDepth * nodesPerDepth) + 2 // nodes. rootNode has all of the other nodes except independentNode // as predecessors. // // Test findPredecessors // { List predecessors = g.findPredecessors(rootNode); Assert.assertTrue(predecessors.size() == (maxDepth * nodesPerDepth)); } } } testng-testng-6.9.5/src/test/java/test/FileStringBufferTest.java0000644000175000017500000000114712551235562024225 0ustar eugeneeugenepackage test; import org.testng.annotations.Test; import org.testng.reporters.FileStringBuffer; public class FileStringBufferTest { @Test public void basic() { { FileStringBuffer fsb = new FileStringBuffer(5); String s = "0123456789"; String s3 = s + s + s; fsb.append(s3); // Assert.assertEquals(s3, fsb.toString()); } { FileStringBuffer fsb = new FileStringBuffer(5); String s = "0123456789"; String s3 = s + s + s; fsb.append(s); fsb.append(s); fsb.append(s); // Assert.assertEquals(s3, fsb.toString()); } } } testng-testng-6.9.5/src/test/java/test/Exclude.java0000644000175000017500000000207712551235562021561 0ustar eugeneeugenepackage test; import org.testng.annotations.Test; public class Exclude { private boolean m_included1 = false; private boolean m_included2 = false; private boolean m_excluded1 = true; private boolean m_excluded2 = true; @Test(groups = { "group1"} ) public void included1() { ppp("INCLUDED1"); m_included1 = true; } @Test(groups = { "group1"} ) public void included2() { ppp("INCLUDED2"); m_included2 = true; } @Test(groups = { "group1"} ) public void excluded1() { ppp("EXCLUDED1"); m_excluded1 = false; } @Test(groups = { "group1"} ) public void excluded2() { ppp("EXCLUDED1"); m_excluded2 = false; } @Test(dependsOnGroups = { "group1" }, groups = {"group2"} ) public void verify() { ppp("VERIFY"); assert m_included1 && m_included2 && m_excluded1 && m_excluded2: "Should all be true: " + m_included1 + " " + m_included2 + " " + m_excluded1 + " " + m_excluded2; } static private void ppp(String s) { if (false) { System.out.println("[Exclude] " + s); } } } testng-testng-6.9.5/src/test/java/test/EclipseTest.java0000644000175000017500000000076412551235562022415 0ustar eugeneeugenepackage test; import org.testng.Assert; import org.testng.ITestContext; import org.testng.annotations.Test; /** * Make sure that these test pass when run by the Eclipse plug-in. * * @author Cedric Beust * */ public class EclipseTest { @Test public void xmlFileShouldBeRunAtItsPlaceAndNotCopied(ITestContext ctx) { String fileName = ctx.getSuite().getXmlSuite().getFileName().replace("\\", "/"); Assert.assertTrue(fileName.contains("src/test/resources")); } } testng-testng-6.9.5/src/test/java/test/DynamicGraphTest.java0000644000175000017500000000361312551235562023373 0ustar eugeneeugenepackage test; import org.testng.Assert; import org.testng.annotations.Test; import org.testng.internal.DynamicGraph; import org.testng.internal.DynamicGraph.Status; import java.util.List; import java.util.Set; public class DynamicGraphTest { private static void assertFreeNodesEquals(DynamicGraph graph, T[] expected) { Assert.assertEqualsNoOrder(graph.getFreeNodes().toArray(), expected); } @Test public void test8() { DynamicGraph dg = new DynamicGraph<>(); dg.addEdge("b1", "a1"); dg.addEdge("b1", "a2"); dg.addEdge("b2", "a1"); dg.addEdge("b2", "a2"); dg.addEdge("c1", "b1"); dg.addEdge("c1", "b2"); dg.addNode("x"); dg.addNode("y"); List freeNodes = dg.getFreeNodes(); assertFreeNodesEquals(dg, new String[] {"a1", "a2", "y", "x"}); dg.setStatus(freeNodes, Status.RUNNING); dg.setStatus("a1", Status.FINISHED); assertFreeNodesEquals(dg, new String[] {}); dg.setStatus("a2", Status.FINISHED); assertFreeNodesEquals(dg, new String[] { "b1", "b2"}); dg.setStatus("b2", Status.RUNNING); dg.setStatus("b1", Status.FINISHED); assertFreeNodesEquals(dg, new String[] {}); dg.setStatus("b2", Status.FINISHED); assertFreeNodesEquals(dg, new String[] { "c1" }); } @Test public void test2() { DynamicGraph dg = new DynamicGraph<>(); dg.addEdge("b1", "a1"); dg.addEdge("b1", "a2"); dg.addNode("x"); List freeNodes = dg.getFreeNodes(); assertFreeNodesEquals(dg, new String[] { "a1", "a2", "x" }); dg.setStatus(freeNodes, Status.RUNNING); dg.setStatus("a1", Status.FINISHED); assertFreeNodesEquals(dg, new String[] {}); dg.setStatus("a2", Status.FINISHED); assertFreeNodesEquals(dg, new String[] { "b1" }); dg.setStatus("b2", Status.RUNNING); dg.setStatus("b1", Status.FINISHED); assertFreeNodesEquals(dg, new String[] {}); } } testng-testng-6.9.5/src/test/java/test/CtorCalledOnce.java0000644000175000017500000000152512551235562023006 0ustar eugeneeugenepackage test; import org.testng.annotations.AfterTest; import org.testng.annotations.Test; /** * this test verifys that the test class is instantiated exactly once * regardless of how many test methods we have, showing that TestNG * semantics is quite different from JUnit */ public class CtorCalledOnce { public static int instantiated = 0; public CtorCalledOnce() { instantiated++; } @Test public void testMethod1(){ assert instantiated == 1 : "Expected 1, was invoked " + instantiated + " times"; } @Test public void testMethod2(){ assert instantiated == 1 : "Expected 1, was invoked " + instantiated + " times"; } @Test public void testMethod3(){ assert instantiated == 1 : "Expected 1, was invoked " + instantiated + " times"; } @AfterTest public void afterTest() { instantiated = 0; } }testng-testng-6.9.5/src/test/java/test/CountTest.java0000644000175000017500000000170712551235562022117 0ustar eugeneeugenepackage test; import org.testng.Assert; import org.testng.IReporter; import org.testng.ISuite; import org.testng.ISuiteResult; import org.testng.ITestContext; import org.testng.TestNG; import org.testng.annotations.Test; import org.testng.xml.XmlSuite; import java.util.List; public class CountTest extends SimpleBaseTest { @Test(description = "Make sure that skipped methods are accurately counted") public void skippedMethodsShouldBeCounted() { TestNG tng = create(CountSampleTest.class); IReporter r = new IReporter() { @Override public void generateReport(List xmlSuites, List suites, String outputDirectory) { for (ISuite s : suites) { for (ISuiteResult sr : s.getResults().values()) { ITestContext ctx = sr.getTestContext(); Assert.assertEquals(2, ctx.getSkippedTests().size()); } } } }; tng.addListener(r); tng.run(); } } testng-testng-6.9.5/src/test/java/test/CountSampleTest.java0000644000175000017500000000200212551235562023246 0ustar eugeneeugenepackage test; import org.testng.Assert; import org.testng.SkipException; import org.testng.annotations.Test; /** * Use this test to show run/failed/skip result * differences between testng-5.12 and testng-5-14 * * @author CA Technologies */ public class CountSampleTest { @Test(groups = {"functional"}) public void testInvokedAndSkipped() throws SkipException { // System.out.println("Skipping this test after it is invoked."); throw new SkipException("This test is skipped after invocation"); } @Test(groups = {"functional"}) public static void testInvokedAndFailed() { // System.out.println("Failing this test after it is invoked."); Assert.fail("Failing this test on purpose"); } @Test(groups = {"functional"}, dependsOnMethods = {"testInvokedAndFailed"}) public static void testWillNotBeInvokedOnlySkipped() { // System.out.println("This test will be skipped, " + // "but not invoked because its dependsOnMethod fails."); } } testng-testng-6.9.5/src/test/java/test/CommandLineTest.java0000644000175000017500000000756612551235562023226 0ustar eugeneeugenepackage test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import org.testng.Assert; import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; import test.sample.JUnitSample1; import testhelper.OutputDirectoryPatch; import java.util.List; public class CommandLineTest { /** * Test -junit */ @Test(groups = { "current" } ) public void junitParsing() { String[] argv = { "-log", "0", "-d", OutputDirectoryPatch.getOutputDirectory(), "-junit", "-testclass", "test.sample.JUnitSample1" }; TestListenerAdapter tla = new TestListenerAdapter(); TestNG.privateMain(argv, tla); List passed = tla.getPassedTests(); assertEquals(passed.size(), 2); String test1 = passed.get(0).getMethod().getMethodName(); String test2 = passed.get(1).getMethod().getMethodName(); assertTrue(JUnitSample1.EXPECTED1.equals(test1) && JUnitSample1.EXPECTED2.equals(test2) || JUnitSample1.EXPECTED1.equals(test2) && JUnitSample1.EXPECTED2.equals(test1)); } /** * Test the absence of -junit */ @Test(groups = { "current" } ) public void junitParsing2() { String[] argv = { "-log", "0", "-d", OutputDirectoryPatch.getOutputDirectory(), "-testclass", "test.sample.JUnitSample1" }; TestListenerAdapter tla = new TestListenerAdapter(); TestNG.privateMain(argv, tla); List passed = tla.getPassedTests(); assertEquals(passed.size(), 0); } /** * Test the ability to override the default command line Suite name */ @Test(groups = { "current" } ) public void suiteNameOverride() { String suiteName="MySuiteName"; String[] argv = { "-log", "0", "-d", OutputDirectoryPatch.getOutputDirectory(), "-junit", "-testclass", "test.sample.JUnitSample1", "-suitename", "\""+suiteName+"\"" }; TestListenerAdapter tla = new TestListenerAdapter(); TestNG.privateMain(argv, tla); List contexts = tla.getTestContexts(); assertTrue(contexts.size()>0); for (ITestContext context:contexts) { assertEquals(context.getSuite().getName(),suiteName); } } /** * Test the ability to override the default command line test name */ @Test(groups = { "current" } ) public void testNameOverride() { String testName="My Test Name"; String[] argv = { "-log", "0", "-d", OutputDirectoryPatch.getOutputDirectory(), "-junit", "-testclass", "test.sample.JUnitSample1", "-testname", "\""+testName+"\"" }; TestListenerAdapter tla = new TestListenerAdapter(); TestNG.privateMain(argv, tla); List contexts = tla.getTestContexts(); assertTrue(contexts.size()>0); for (ITestContext context:contexts) { assertEquals(context.getName(),testName); } } @Test public void testUseDefaultListenersArgument() { TestNG.privateMain(new String[] { "-log", "0", "-usedefaultlisteners", "false", "-testclass", "test.sample.JUnitSample1" }, null); } @Test public void testMethodParameter() { String[] argv = { "-log", "0", "-d", OutputDirectoryPatch.getOutputDirectory(), "-methods", "test.sample.Sample2.method1,test.sample.Sample2.method3", }; TestListenerAdapter tla = new TestListenerAdapter(); TestNG.privateMain(argv, tla); List passed = tla.getPassedTests(); Assert.assertEquals(passed.size(), 2); Assert.assertTrue((passed.get(0).getName().equals("method1") && passed.get(1).getName().equals("method3")) || (passed.get(1).getName().equals("method1") && passed.get(0).getName().equals("method3"))); } private static void ppp(String s) { System.out.println("[CommandLineTest] " + s); } } testng-testng-6.9.5/src/test/java/test/ClassConfigurations.java0000644000175000017500000000203712551235562024144 0ustar eugeneeugenepackage test; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class ClassConfigurations { static int beforeCount = 0; static int afterCount = 0; @BeforeClass public void beforeTestClass() { ++beforeCount; // System.out.println("@@@@@@ beforeTestClass has been called " + beforeCount + " time(s)"); } @AfterTest public void afterTest() { beforeCount = 0; afterCount = 0; } @AfterTest public void afterTestClass() { ++afterCount; // System.out.println("@@@@@@@ afterTestClass has been called " + afterCount + " time(s)"); } @Test public void testOne() { // System.out.println("testOne"); assert beforeCount == 1; assert afterCount == 0; } @Test public void testTwo() { // System.out.println("testTwo"); assert beforeCount == 1; assert afterCount == 0; } @Test public void testThree() { // System.out.println("testThree"); assert beforeCount == 1; assert afterCount == 0; } }testng-testng-6.9.5/src/test/java/test/CheckSuitesInitializationTest.java0000644000175000017500000000242112551235562026143 0ustar eugeneeugenepackage test; import java.util.Arrays; import org.testng.Assert; import org.testng.TestListenerAdapter; import org.testng.TestNG; import org.testng.annotations.Test; /** * Check for a bug in how relative paths in suite files were being handled. * * All paths were being resolved using the initial suite's location and not * that of the current suite being parsed/processed. * * This test checks that TestNG can handle cases where we have the following set of * files (all linked using relative paths): * * - parent-suite -> [child-suite-1, children/child-suite-3] * - children/child-suite-3 -> [../child-suite-2, child-suite-4, morechildren/child-suite-5] * * Check the checksuitesinitialization folder under test resources * * @author Nalin Makar */ public class CheckSuitesInitializationTest extends SimpleBaseTest { /** * Child suites and tests within different suites have same names */ @Test public void check() { TestListenerAdapter tla = new TestListenerAdapter(); TestNG tng = create(); String testngXmlPath = getPathToResource("checksuitesinitialization/parent-suite.xml"); tng.setTestSuites(Arrays.asList(testngXmlPath)); tng.addListener(tla); tng.run(); Assert.assertEquals(tla.getPassedTests().size(), 4); } } testng-testng-6.9.5/src/test/java/test/BaseTest.java0000644000175000017500000003605512551235562021705 0ustar eugeneeugenepackage test; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import org.testng.Assert; import org.testng.IInvokedMethodListener; import org.testng.ISuite; import org.testng.ITestResult; import org.testng.ITestRunnerFactory; import org.testng.SuiteRunner; import org.testng.TestListenerAdapter; import org.testng.TestRunner; import org.testng.annotations.BeforeMethod; import org.testng.collections.Lists; import org.testng.internal.Configuration; import org.testng.internal.IConfiguration; import org.testng.reporters.JUnitXMLReporter; import org.testng.reporters.TestHTMLReporter; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlMethodSelector; import org.testng.xml.XmlPackage; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; /** * Base class for tests * * @author Cedric Beust, May 5, 2004 * */ public class BaseTest extends BaseDistributedTest { private static final String m_outputDirectory= "test-output-tests"; private XmlSuite m_suite= null; private ITestRunnerFactory m_testRunnerFactory; private IConfiguration m_configuration; private Integer m_verbose = null; public BaseTest() { m_testRunnerFactory= new InternalTestRunnerFactory(this); m_configuration = new Configuration(); } private IConfiguration getConfiguration() { return m_configuration; } protected void setDebug() { getTest().setVerbose(9); } protected void setParallel(String parallel) { getTest().setParallel(parallel); } protected void setVerbose(int n) { m_verbose = n; } protected void setTestTimeOut(long n) { getTest().setTimeOut(n); } protected void setSuiteTimeOut(long n) { m_suite.setTimeOut(Long.toString(n)); } protected void setJUnit(boolean f) { getTest().setJUnit(f); } protected void setThreadCount(int count) { getTest().getSuite().setThreadCount(count); } private Map m_tests= new HashMap<>(); private Map m_passedTests= new HashMap<>(); private Map m_failedTests= new HashMap<>(); private Map m_skippedTests= new HashMap<>(); private Map m_testConfigs= new HashMap<>(); private Map m_passedConfigs= new HashMap<>(); private Map m_failedConfigs= new HashMap<>(); private Map m_skippedConfigs= new HashMap<>(); private Map m_failedButWithinSuccessPercentageTests= new HashMap<>(); protected Map> getTests(Map map) { Map> result= map.get(getId()); if(null == result) { result= new HashMap<>(); map.put(getId(), result); } return result; } protected XmlTest getTest() { return m_tests.get(getId()); } protected void setTests(Map map, Map m) { map.put(getId(), m); } public Map> getFailedTests() { return getTests(m_failedTests); } public Map> getFailedButWithinSuccessPercentageTests() { return getTests(m_failedButWithinSuccessPercentageTests); } public Map> getPassedTests() { return getTests(m_passedTests); } public Map> getSkippedTests() { return getTests(m_skippedTests); } public Map> getFailedConfigs() { return getTests(m_failedConfigs); } public Map> getPassedConfigs() { return getTests(m_passedConfigs); } public Map> getSkippedConfigs() { return getTests(m_skippedConfigs); } public void setSkippedTests(Map m) { setTests(m_skippedTests, m); } public void setPassedTests(Map m) { setTests(m_passedTests, m); } public void setFailedTests(Map m) { setTests(m_failedTests, m); } public void setFailedButWithinSuccessPercentageTests(Map m) { setTests(m_failedButWithinSuccessPercentageTests, m); } public void setSkippedConfigs(Map m) { setTests(m_skippedConfigs, m); } public void setPassedConfigs(Map m) { setTests(m_passedConfigs, m); } public void setFailedConfigs(Map m) { setTests(m_failedConfigs, m); } protected void run() { assert null != getTest() : "Test wasn't set, maybe @Configuration methodSetUp() was never called"; setPassedTests(new HashMap()); setFailedTests(new HashMap()); setSkippedTests(new HashMap()); setPassedConfigs(new HashMap()); setFailedConfigs(new HashMap()); setSkippedConfigs(new HashMap()); setFailedButWithinSuccessPercentageTests(new HashMap()); m_suite.setVerbose(m_verbose != null ? m_verbose : 0); SuiteRunner suite = new SuiteRunner(m_configuration, m_suite, m_outputDirectory, m_testRunnerFactory); suite.run(); } protected void addMethodSelector(String className, int priority) { XmlMethodSelector methodSelector= new XmlMethodSelector(); methodSelector.setName(className); methodSelector.setPriority(priority); getTest().getMethodSelectors().add(methodSelector); } protected XmlClass addClass(Class cls) { return addClass(cls.getName()); } protected XmlClass addClass(String className) { XmlClass result= new XmlClass(className); getTest().getXmlClasses().add(result); return result; } protected void setBeanShellExpression(String expression) { getTest().setBeanShellExpression(expression); } protected void addPackage(String pkgName, String[] included, String[] excluded) { XmlPackage pkg= new XmlPackage(); pkg.setName(pkgName); pkg.getInclude().addAll(Arrays.asList(included)); pkg.getExclude().addAll(Arrays.asList(excluded)); getTest().getSuite().getXmlPackages().add(pkg); } private XmlClass findClass(String className) { for(XmlClass cl : getTest().getXmlClasses()) { if(cl.getName().equals(className)) { return cl; } } XmlClass result= addClass(className); return result; } public void addIncludedMethod(String className, String m) { XmlClass xmlClass= findClass(className); xmlClass.getIncludedMethods().add(new XmlInclude(m)); getTest().getXmlClasses().add(xmlClass); } public void addExcludedMethod(String className, String m) { XmlClass xmlClass= findClass(className); xmlClass.getExcludedMethods().add(m); getTest().getXmlClasses().add(xmlClass); } public void addIncludedGroup(String g) { getTest().addIncludedGroup(g); } public void addExcludedGroup(String g) { getTest().addExcludedGroup(g); } public void addMetaGroup(String mg, List l) { getTest().getMetaGroups().put(mg, l); } public void addMetaGroup(String mg, String n) { List l= new ArrayList<>(); l.add(n); addMetaGroup(mg, l); } public void setParameter(String key, String value) { getTest().addParameter(key, value); } // @Configuration(beforeTestMethod = true, groups = { "init", "initTest"}) @BeforeMethod(groups= { "init", "initTest" }) public void methodSetUp() { m_suite= new XmlSuite(); m_suite.setName("Internal_suite"); XmlTest xmlTest= new XmlTest(m_suite); xmlTest.setName("Internal_test_failures_are_expected"); m_tests.put(getId(), xmlTest); } private void addTest(Map> tests, ITestResult t) { List l= tests.get(t.getMethod().getMethodName()); if(null == l) { l= new ArrayList<>(); tests.put(t.getMethod().getMethodName(), l); } l.add(t); } public void addPassedTest(ITestResult t) { addTest(getPassedTests(), t); } public void addFailedTest(ITestResult t) { addTest(getFailedTests(), t); } public void addFailedButWithinSuccessPercentageTest(ITestResult t) { addTest(getFailedButWithinSuccessPercentageTests(), t); } public void addSkippedTest(ITestResult t) { addTest(getSkippedTests(), t); } public void addPassedConfig(ITestResult t) { addTest(getPassedConfigs(), t); } public void addFailedConfig(ITestResult t) { addTest(getFailedConfigs(), t); } public void addSkippedConfig(ITestResult t) { addTest(getSkippedConfigs(), t); } private void ppp(String s) { System.out.println("[BaseTest " + getId() + "] " + s); } protected Long getId() { return 42L; // long result = Thread.currentThread().getId(); //// System.out.println("RETURNING ID " + result); // return result; } public XmlSuite getSuite() { return m_suite; } public void setSuite(XmlSuite suite) { m_suite = suite; } /** * Used for instanceCount testing, when we need to look inside the * TestResult to count the various SUCCESS/FAIL/FAIL_BUT_OK */ protected void verifyResults(Map> tests, int expected, String message) { if(tests.size() > 0) { Set keys= tests.keySet(); Object firstKey= keys.iterator().next(); List passedResult= tests.get(firstKey); int n= passedResult.size(); assert n == expected : "Expected " + expected + " " + message + " but found " + n; } else { assert expected == 0 : "Expected " + expected + " " + message + " but found " + tests.size(); } } protected void dumpResults(String name, Map> tests) { ppp("============= " + name); for(Map.Entry> entry : tests.entrySet()) { ppp("TEST:" + entry.getKey()); List l= entry.getValue(); for(ITestResult tr : l) { ppp(" " + tr); } } } protected static void verifyInstanceNames(String title, Map> actual, String[] expected) { List actualNames = Lists.newArrayList(); for (Map.Entry> es : actual.entrySet()) { for (ITestResult tr : es.getValue()) { Object instance = tr.getInstance(); actualNames.add(es.getKey() + "#" + (instance != null ? instance.toString() : "")); } } Assert.assertEqualsNoOrder(actualNames.toArray(), expected); } protected void verifyPassedTests(String... expectedPassed) { verifyTests("Passed", expectedPassed, getPassedTests()); } protected void verifyFailedTests(String... expectedFailed) { verifyTests("Failed", expectedFailed, getFailedTests()); } /** * * @param fileName The filename to parse * @param regexp The regular expression * @param resultLines An out parameter that will contain all the lines * that matched the regexp * @return A List containing the lines of all the matches * * Note that the size() of the returned valuewill always be equal to * result.size() at the end of this function. */ public static List grep(File fileName, String regexp, List resultLines) { List resultLineNumbers = new ArrayList<>(); BufferedReader fr = null; try { fr = new BufferedReader(new FileReader(fileName)); String line = fr.readLine(); int currentLine = 0; Pattern p = Pattern.compile(".*" + regexp + ".*"); while(null != line) { // ppp("COMPARING " + p + " TO @@@" + line + "@@@"); if(p.matcher(line).matches()) { resultLines.add(line); resultLineNumbers.add(currentLine); } line = fr.readLine(); currentLine++; } } catch(IOException e) { e.printStackTrace(); } finally { if(null != fr) { try { fr.close(); } catch(IOException ex) { ex.printStackTrace(); } } } return resultLineNumbers; } private static class InternalTestRunnerFactory implements ITestRunnerFactory { private final BaseTest m_baseTest; public InternalTestRunnerFactory(final BaseTest baseTest) { m_baseTest= baseTest; } /** * @see org.testng.ITestRunnerFactory#newTestRunner(org.testng.ISuite, org.testng.xml.XmlTest) */ @Override public TestRunner newTestRunner(ISuite suite, XmlTest test, List listeners) { TestRunner testRunner= new TestRunner(m_baseTest.getConfiguration(), suite, test, false, listeners); testRunner.addTestListener(new TestHTMLReporter()); testRunner.addTestListener(new JUnitXMLReporter()); testRunner.addListener(new TestListener(m_baseTest)); if (listeners != null) { for (IInvokedMethodListener l : listeners) { testRunner.addListener(l); } } return testRunner; } } /** * Deletes all files and subdirectories under dir. * @return true if all deletions were successful. * If a deletion fails, the method stops attempting to delete and returns false. */ public static boolean deleteDir(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); for (String element : children) { boolean success = deleteDir(new File(dir, element)); if (!success) { return false; } } } // The directory is now empty so delete it return dir.delete(); } protected void runTest(String cls, String[] passed, String[] failed, String[] skipped) { addClass(cls); run(); verifyTests("Passed", passed, getPassedTests()); verifyTests("Failed", failed, getFailedTests()); verifyTests("Skipped", skipped, getSkippedTests()); } } // BaseTest //////////////////////////// class TestListener extends TestListenerAdapter { private static BaseTest m_test= null; public TestListener(BaseTest t1) { m_test= t1; } @Override public void onTestSuccess(ITestResult tr) { m_test.addPassedTest(tr); } @Override public void onTestFailure(ITestResult tr) { m_test.addFailedTest(tr); } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult result) { m_test.addFailedButWithinSuccessPercentageTest(result); } @Override public void onTestSkipped(ITestResult tr) { m_test.addSkippedTest(tr); } @Override public void onConfigurationSuccess(ITestResult tr) { m_test.addPassedConfig(tr); } @Override public void onConfigurationFailure(ITestResult tr) { m_test.addFailedConfig(tr); } @Override public void onConfigurationSkip(ITestResult tr) { m_test.addSkippedConfig(tr); } } // TestListener testng-testng-6.9.5/src/test/java/test/BaseLogTest.java0000644000175000017500000000074212551235562022341 0ustar eugeneeugenepackage test; import org.testng.annotations.BeforeSuite; import org.testng.collections.Lists; import java.util.List; /** * Base class for tests that need to log methods as they get called. * * @author cbeust */ public class BaseLogTest { private static List m_log; @BeforeSuite public void bc() { m_log = Lists.newArrayList(); } public static void log(String s) { m_log.add(s); } public static List getLog() { return m_log; } } testng-testng-6.9.5/src/test/java/test/BaseDistributedTest.java0000644000175000017500000000227512551235562024105 0ustar eugeneeugenepackage test; import org.testng.Assert; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class BaseDistributedTest { private boolean m_verbose = false; protected void verifyTests(String title, String[] exp, Map found) { Map expected = new HashMap(); for (String element : exp) { expected.put(element, element); } Assert.assertEquals(found.size(), expected.size(), "Verification for " + title + " tests failed:"); for (Object o : expected.values()) { String name = (String) o; if (null == found.get(name)) { dumpMap("Expected", expected); dumpMap("Found", found); } Assert.assertNotNull(found.get(name), "Expected to find method " + name + " in " + title + " but didn't find it."); } } protected void dumpMap(String title, Map m) { if (m_verbose) { System.out.println("==== " + title); for (Map.Entry entry : m.entrySet()) { ppp(entry.getKey() + " => " + entry.getValue()); } } } private void ppp(String s) { if (m_verbose) { System.out.println("[BaseDistributedTest] " + s); } } } testng-testng-6.9.5/src/test/java/org/0000755000175000017500000000000012551235562017127 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/org/testng/0000755000175000017500000000000012551235562020433 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/org/testng/remote/0000755000175000017500000000000012551235562021726 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/org/testng/remote/strprotocol/0000755000175000017500000000000012551235562024320 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/org/testng/remote/strprotocol/TestResultMessageTest.java0000644000175000017500000000412412551235562031447 0ustar eugeneeugenepackage org.testng.remote.strprotocol; import java.util.Arrays; import java.util.List; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class TestResultMessageTest { private TestResultMessage testResultMessage = new TestResultMessage(0, "suiteName", "testName", "className", "methodName", "testDescriptor", "testinstanceName", new String[] {}, 0, 0, "stackTrace", 1, 0); @DataProvider(name = "testGen") private Object[][] getP() { return new Object[][] { { null, new Class[] { null }, Arrays.asList() }, { new Object[] { new byte[] { 1 } }, new Class[] { byte[].class }, Arrays.asList("[1]") }, { new Object[] { new short[] { 1 } }, new Class[] { short[].class }, Arrays.asList("[1]") }, { new Object[] { new long[] { 1 } }, new Class[] { long[].class }, Arrays.asList("[1]") }, { new Object[] { new int[] { 1, 2, 3 } }, new Class[] { int[].class }, Arrays.asList("[1,2,3]") }, { new Object[] { new boolean[] { true, false } }, new Class[] { boolean[].class }, Arrays.asList("[true,false]") }, { new Object[] { new char[] { 'a', 'b', 'c' } }, new Class[] { int[].class }, Arrays.asList("[a,b,c]") }, { new Object[] { new float[] { 1.1f, 2.2f, 3.3f } }, new Class[] { float[].class }, Arrays.asList("[1.1,2.2,3.3]") }, { new Object[] { new double[] { 1.1, 2.2, 3.3 } }, new Class[] { double[].class }, Arrays.asList("[1.1,2.2,3.3]") }, { new Object[] { new Object[] { "this is a string", false } }, new Class[] { String.class, Boolean.class }, Arrays.asList("[this is a string,false]") }, { new Object[] { new Object[] { null, "" } }, new Class[] { String.class, Boolean.class }, Arrays.asList("[null,\"\"]") }, }; } @Test(dataProvider = "testGen") public void toStringTest(Object[] objects, Class[] objectClasses, List expectedResults) throws Exception { String[] results = testResultMessage.toString(objects, objectClasses); Assert.assertEquals(Arrays.asList(results), expectedResults); } } testng-testng-6.9.5/src/test/java/org/testng/internal/0000755000175000017500000000000012551235562022247 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/org/testng/internal/invokers/0000755000175000017500000000000012551235562024107 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/org/testng/internal/invokers/InvokedMethodListenerSubtypeTest.java0000644000175000017500000000363012551235562033436 0ustar eugeneeugenepackage org.testng.internal.invokers; import org.testng.Assert; import org.testng.IInvokedMethod; import org.testng.IInvokedMethodListener; import org.testng.IInvokedMethodListener2; import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.annotations.Test; @Test public class InvokedMethodListenerSubtypeTest { @Test public void testFromListenerUsingSimpleListenerInstance() { final IInvokedMethodListener simpleListenerInstance = new SimpleInvokedMethodListenerDummy(); InvokedMethodListenerSubtype listenerSubtype = InvokedMethodListenerSubtype.fromListener(simpleListenerInstance); Assert.assertEquals(listenerSubtype, InvokedMethodListenerSubtype.SIMPLE_LISTENER); } @Test public void testFromListenerUsingExtendedListenerInstance() { IInvokedMethodListener2 extendedListenerInstance = new ExtendedInvokedMethodListenerDummy(); InvokedMethodListenerSubtype listenerSubtype = InvokedMethodListenerSubtype.fromListener(extendedListenerInstance); Assert.assertEquals(listenerSubtype, InvokedMethodListenerSubtype.EXTENDED_LISTENER); } static class SimpleInvokedMethodListenerDummy implements IInvokedMethodListener { public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { } public void afterInvocation(IInvokedMethod method, ITestResult testResult) { } } static class ExtendedInvokedMethodListenerDummy implements IInvokedMethodListener2 { public void beforeInvocation(IInvokedMethod method, ITestResult testResult, ITestContext context) { } public void afterInvocation(IInvokedMethod method, ITestResult testResult, ITestContext context) { } public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { } public void afterInvocation(IInvokedMethod method, ITestResult testResult) { } } } testng-testng-6.9.5/src/test/java/org/testng/internal/conflistener/0000755000175000017500000000000012551235562024742 5ustar eugeneeugenetestng-testng-6.9.5/src/test/java/org/testng/internal/conflistener/testng.xml0000644000175000017500000000164412551235562026775 0ustar eugeneeugene testng-testng-6.9.5/src/test/java/org/testng/internal/conflistener/FailingBeforeTest.java0000644000175000017500000000070412551235562031142 0ustar eugeneeugenepackage org.testng.internal.conflistener; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; /** * This class/interface */ public class FailingBeforeTest { @BeforeSuite public void passingBeforeSuite() { } @BeforeTest public void beforeTest() { throw new RuntimeException("Test exception"); } @Test public void dummytest() { } } testng-testng-6.9.5/src/test/java/org/testng/internal/conflistener/FailingBeforeSuite.java0000644000175000017500000000053712551235562031320 0ustar eugeneeugenepackage org.testng.internal.conflistener; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; /** * This class/interface */ public class FailingBeforeSuite { @BeforeSuite public void beforeSuite() { throw new RuntimeException("Test exception"); } @Test public void dummytest() { } } testng-testng-6.9.5/src/test/java/org/testng/internal/conflistener/FailingBeforeClass.java0000644000175000017500000000061212551235562031266 0ustar eugeneeugenepackage org.testng.internal.conflistener; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * This class/interface does XXX */ public class FailingBeforeClass { @BeforeClass public void failingBeforeClass() { throw new RuntimeException("expected @BeforeClass failure"); } @Test public void testAfterFailingBeforeClass() {} } testng-testng-6.9.5/src/test/java/org/testng/internal/conflistener/FailingAfterTest.java0000644000175000017500000000064012551235562031000 0ustar eugeneeugenepackage org.testng.internal.conflistener; import org.testng.annotations.AfterTest; import org.testng.annotations.Test; /** * This class/interface */ public class FailingAfterTest { @AfterTest(alwaysRun=true) public void afterTest() { throw new RuntimeException("Test exception"); } @AfterTest public void skippedAfterTest() { } @Test public void dummytest() { } } testng-testng-6.9.5/src/test/java/org/testng/internal/conflistener/FailingAfterSuite.java0000644000175000017500000000055312551235562031155 0ustar eugeneeugenepackage org.testng.internal.conflistener; import org.testng.annotations.AfterSuite; import org.testng.annotations.Test; /** * This class/interface */ public class FailingAfterSuite { @AfterSuite(alwaysRun=true) public void afterSuite() { throw new RuntimeException("Test exception"); } @Test public void dummytest() { } } testng-testng-6.9.5/src/test/java/org/testng/internal/conflistener/FailingAfterClass.java0000644000175000017500000000060512551235562031127 0ustar eugeneeugenepackage org.testng.internal.conflistener; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; /** * This class/interface does XXX */ public class FailingAfterClass { @AfterClass public void failingAfterClass() { throw new RuntimeException("expected @AfterClass failure"); } @Test public void testBeforeFailingAfterClass() {} } testng-testng-6.9.5/src/test/java/org/testng/internal/UtilsTest.java0000644000175000017500000000227212551235562025055 0ustar eugeneeugenepackage org.testng.internal; import java.util.List; import org.testng.annotations.Test; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static org.testng.Assert.assertEquals; import static org.testng.internal.Utils.join; /** * Unit tests for {@link Utils}. * * @author Tomas Pollak */ public class UtilsTest { private static final char INVALID_CHAR = 0xFFFE; private static final char REPLACEMENT_CHAR = 0xFFFD; @Test public void escapeUnicode() { assertEquals(Utils.escapeUnicode("test"), "test"); assertEquals(Utils.escapeUnicode(String.valueOf(INVALID_CHAR)), String.valueOf(REPLACEMENT_CHAR)); } @Test public void createEmptyStringWhenJoiningEmptyListWithJoin() throws Exception { List emptyList = emptyList(); assertEquals("", join(emptyList, ",")); } @Test public void joinTwoStringsWithJoinStrings() throws Exception { List twoStrings = asList("one", "two"); assertEquals("one,two", Utils.join(twoStrings, ",")); } @Test public void createEmptyStringWhenJoiningEmptyListWithJoinStrings() throws Exception { List emptyList = emptyList(); assertEquals("", Utils.join(emptyList, ",")); } } testng-testng-6.9.5/src/test/java/org/testng/internal/MethodInstanceTest.java0000644000175000017500000003200412551235562026656 0ustar eugeneeugenepackage org.testng.internal; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import org.testng.Assert; import org.testng.IClass; import org.testng.IRetryAnalyzer; import org.testng.ITestClass; import org.testng.ITestNGMethod; import org.testng.annotations.Test; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlTest; /** * Unit tests for {@link MethodInstance}. * * @author Andreas Kluth */ public class MethodInstanceTest { public static void main(String[] args) { new MethodInstanceTest().sortByIndexSatisfiesContract(); } @Test public void sortByIndexSatisfiesContract() { // Build a list of entries imposing the same behavior as the live suite, reduced to the // minimum to create the same condition. List methods = new ArrayList<>(); methods.add(buildMethodInstance("unittests", "StateTest", 1, "aCategorization")); methods.add(buildMethodInstance("unittests", "StateTest", 1, "bCategorization")); methods.add(buildMethodInstance("unittests", "StateTest", 1, "cCategorization")); methods.add(buildMethodInstance("unittests", "StateTest", 1, "dCategorization")); methods.add(buildMethodInstance("unittests", "StateTest", 1, "eCategorization")); methods.add(buildMethodInstance("unittests", "StateTest", 1, "fCategorization")); methods.add(buildMethodInstance("unittests", "StatusTest", 2, "aStatus")); methods.add(buildTestNgFactoryMethodInstance("unittests")); methods.add(buildTestNgFactoryMethodInstance("unittests")); methods.add(buildTestNgFactoryMethodInstance("unittests")); methods.add(buildTestNgFactoryMethodInstance("unittests")); methods.add(buildTestNgFactoryMethodInstance("unittests")); methods.add(buildTestNgFactoryMethodInstance("unittests")); methods.add(buildTestNgFactoryMethodInstance("unittests")); methods.add(buildTestNgFactoryMethodInstance("unittests")); methods.add(buildTestNgFactoryMethodInstance("unittests")); methods.add(buildTestNgFactoryMethodInstance("unittests")); methods.add(buildMethodInstance("unittests", "ChangeTest", 3, "aChangeTest")); methods.add(buildMethodInstance("unittests", "ChangeTest", 3, "bChangeTest")); methods.add(buildMethodInstance("unittests", "ChangeTest", 3, "cChangeTest")); methods.add(buildMethodInstance("unittests", "ChangeTest", 3, "dChangeTest")); methods.add(buildMethodInstance("unittests", "ChangeTest", 3, "eChangeTest")); methods.add(buildMethodInstance("unittests", "ChangeTest", 3, "fChangeTest")); methods.add(buildMethodInstance("unittests", "ChangeTest", 3, "gChangeTest")); methods.add(buildMethodInstance("unittests", "ChangeTest", 3, "eChangeTest")); methods.add(buildMethodInstance("unittests", "ChangeTest", 3, "hChangeTest")); methods.add(buildMethodInstance("unittests", "ChangeTest", 3, "iChangeTest")); methods.add(buildMethodInstance("unittests", "IdentifierClassTest", 4, "aIdentifier")); methods.add(buildMethodInstance("unittests", "IdentifierClassTest", 4, "bIdentifier")); methods.add(buildMethodInstance("unittests", "StatisticsTest", 0, "aStatistics")); methods.add(buildMethodInstance("unittests", "StatisticsTest", 0, "bStatistics")); methods.add(buildMethodInstance("unittests", "StatisticsTest", 0, "cStatistics")); try { Collections.sort(methods, MethodInstance.SORT_BY_INDEX); } catch (IllegalArgumentException ex) { Assert.fail("Comparison method violates its general contract!"); } } private MethodInstance buildTestNgFactoryMethodInstance(String xmlTestName) { TestClassStub testClass = new TestClassStub(new XmlTestStub(xmlTestName), null); return new MethodInstance(new TestNGMethodStub(null, testClass)); } private MethodInstance buildMethodInstance(String xmlTestName, String xmlClassName, int xmlClassIndex, String methodName) { TestClassStub testClass = new TestClassStub(new XmlTestStub(xmlTestName), new XmlClassStub(xmlClassName, xmlClassIndex)); return new MethodInstance(new TestNGMethodStub(methodName, testClass)); } public static class XmlClassStub extends XmlClass { private static final long serialVersionUID = 1L; private int index; private String name; public XmlClassStub(String name, int index) { this.name = name; this.index = index; } @Override public String getName() { return name; } @Override public int getIndex() { return index; } @Override public List getIncludedMethods() { return Collections.emptyList(); } } public static class XmlTestStub extends XmlTest { private static final long serialVersionUID = 1L; private String name; public XmlTestStub(String name) { this.name = name; } @Override public String getName() { return name; } } public static class TestClassStub implements ITestClass { private static final long serialVersionUID = 1L; private XmlTest xmlTest; private XmlClass xmlClass; public TestClassStub(XmlTest xmlTest, XmlClass xmlClass) { this.xmlTest = xmlTest; this.xmlClass = xmlClass; } @Override public String getName() { return null; } @Override public XmlTest getXmlTest() { return xmlTest; } @Override public XmlClass getXmlClass() { return xmlClass; } @Override public String getTestName() { return null; } @SuppressWarnings("rawtypes") @Override public Class getRealClass() { return null; } @Override public void addInstance(Object instance) { } @Override public Object[] getInstances(boolean reuse) { return null; } @Override public long[] getInstanceHashCodes() { return null; } @Override public int getInstanceCount() { return 0; } @Override public ITestNGMethod[] getTestMethods() { return null; } @Override public ITestNGMethod[] getBeforeTestMethods() { return null; } @Override public ITestNGMethod[] getAfterTestMethods() { return null; } @Override public ITestNGMethod[] getBeforeClassMethods() { return null; } @Override public ITestNGMethod[] getAfterClassMethods() { return null; } @Override public ITestNGMethod[] getBeforeSuiteMethods() { return null; } @Override public ITestNGMethod[] getAfterSuiteMethods() { return null; } @Override public ITestNGMethod[] getBeforeTestConfigurationMethods() { return null; } @Override public ITestNGMethod[] getAfterTestConfigurationMethods() { return null; } @Override public ITestNGMethod[] getBeforeGroupsMethods() { return null; } @Override public ITestNGMethod[] getAfterGroupsMethods() { return null; } } public static class TestNGMethodStub implements ITestNGMethod { private static final long serialVersionUID = 1L; private TestClassStub testClassStub; private String methodName; public TestNGMethodStub(String methodName, TestClassStub testClassStub) { this.methodName = methodName; this.testClassStub = testClassStub; } @Override public ITestNGMethod clone() { return (TestNGMethodStub) this; }; @Override public int compareTo(Object o) { return 0; } @SuppressWarnings("rawtypes") @Override public Class getRealClass() { return null; } @Override public ITestClass getTestClass() { return testClassStub; } @Override public void setTestClass(ITestClass cls) { } @Override public Method getMethod() { return null; } @Override public String getMethodName() { return methodName; } @Override public Object[] getInstances() { return null; } @Override public Object getInstance() { return null; } @Override public long[] getInstanceHashCodes() { return null; } @Override public String[] getGroups() { return null; } @Override public String[] getGroupsDependedUpon() { return null; } @Override public String getMissingGroup() { return null; } @Override public void setMissingGroup(String group) { } @Override public String[] getBeforeGroups() { return null; } @Override public String[] getAfterGroups() { return null; } @Override public String[] getMethodsDependedUpon() { return null; } @Override public void addMethodDependedUpon(String methodName) { } @Override public boolean isTest() { return false; } @Override public boolean isBeforeMethodConfiguration() { return false; } @Override public boolean isAfterMethodConfiguration() { return false; } @Override public boolean isBeforeClassConfiguration() { return false; } @Override public boolean isAfterClassConfiguration() { return false; } @Override public boolean isBeforeSuiteConfiguration() { return false; } @Override public boolean isAfterSuiteConfiguration() { return false; } @Override public boolean isBeforeTestConfiguration() { return false; } @Override public boolean isAfterTestConfiguration() { return false; } @Override public boolean isBeforeGroupsConfiguration() { return false; } @Override public boolean isAfterGroupsConfiguration() { return false; } @Override public long getTimeOut() { return 0; } @Override public void setTimeOut(long timeOut) { } @Override public int getInvocationCount() { return 0; } @Override public int getTotalInvocationCount() { return 0; } @Override public void setInvocationCount(int count) { } @Override public int getSuccessPercentage() { return 0; } @Override public String getId() { return null; } @Override public void setId(String id) { } @Override public long getDate() { return 0; } @Override public void setDate(long date) { } @Override public boolean canRunFromClass(IClass testClass) { return false; } @Override public boolean isAlwaysRun() { return false; } @Override public int getThreadPoolSize() { return 0; } @Override public void setThreadPoolSize(int threadPoolSize) { } @Override public boolean getEnabled() { return false; } @Override public String getDescription() { return null; } @Override public void setDescription(String description) { } @Override public void incrementCurrentInvocationCount() { } @Override public int getCurrentInvocationCount() { return 0; } @Override public void setParameterInvocationCount(int n) { } @Override public int getParameterInvocationCount() { return 0; } @Override public IRetryAnalyzer getRetryAnalyzer() { return null; } @Override public void setRetryAnalyzer(IRetryAnalyzer retryAnalyzer) { } @Override public boolean skipFailedInvocations() { return false; } @Override public void setSkipFailedInvocations(boolean skip) { } @Override public long getInvocationTimeOut() { return 0; } @Override public boolean ignoreMissingDependencies() { return false; } @Override public void setIgnoreMissingDependencies(boolean ignore) { } @Override public List getInvocationNumbers() { return null; } @Override public void setInvocationNumbers(List numbers) { } @Override public void addFailedInvocationNumber(int number) { } @Override public List getFailedInvocationNumbers() { return null; } @Override public int getPriority() { return 0; } @Override public void setPriority(int priority) { } @Override public XmlTest getXmlTest() { return null; } @Override public ConstructorOrMethod getConstructorOrMethod() { return null; } @Override public Map findMethodParameters(XmlTest test) { return null; } } } testng-testng-6.9.5/src/test/java/org/testng/AssertTest.java0000644000175000017500000001034612551235562023403 0ustar eugeneeugenepackage org.testng; import org.testng.annotations.Test; import org.testng.collections.Maps; import org.testng.collections.Sets; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * This class/interface */ public class AssertTest { @Test public void nullObjectArrayAssertEquals() { Object[] expected= null; Object[] actual= null; Assert.assertEquals(actual, expected); } @Test public void nullObjectArrayAssertNoOrder() { Object[] expected= null; Object[] actual= null; Assert.assertEqualsNoOrder(actual, expected); } @Test public void nullCollectionAssertEquals() { Collection expected = null; Collection actual = null; Assert.assertEquals(actual, expected); } @Test public void nullSetAssertEquals() { Set expected = null; Set actual = null; Assert.assertEquals(actual, expected); } @Test public void nullMapAssertEquals() { Map expected = null; Map actual = null; Assert.assertEquals(actual, expected); } @Test public void setAssertEquals() { Set expected = Sets.newHashSet(); Set actual = Sets.newHashSet(); expected.add(1); expected.add("a"); actual.add("a"); actual.add(1); Assert.assertEquals(actual, expected); } @Test public void mapAssertEquals() { Map expected = Maps.newHashMap(); Map actual = Maps.newHashMap(); expected.put(null, "a"); expected.put("a", "a"); expected.put("b", "c"); actual.put("b", "c"); actual.put(null, "a"); actual.put("a", "a"); Assert.assertEquals(actual, expected); } @Test public void oneNullMapAssertEquals() { Map expected = Maps.newHashMap(); Map actual = null; try { Assert.assertEquals(actual, expected); Assert.fail("AssertEquals didn't fail"); } catch (AssertionError error) { //do nothing } } @Test public void oneNullSetAssertEquals() { Set expected = null; Set actual = Sets.newHashSet(); try { Assert.assertEquals(actual, expected); Assert.fail("AssertEquals didn't fail"); } catch (AssertionError error) { //do nothing } } @Test(expectedExceptions = AssertionError.class) public void assertEqualsMapShouldFail() { Map mapActual = new HashMap() {{ put("a","1"); }}; Map mapExpected = new HashMap() {{ put("a","1"); put("b","2"); }}; 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 = {1, new Asymmetric(42, 'd'), "inDay"}; Object[] expected = {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; } } } testng-testng-6.9.5/src/test/java/NoPackageTest.java0000644000175000017500000000056712551235562021703 0ustar eugeneeugene import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; /** * @author Filippo Diotalevi */ public class NoPackageTest { private boolean m_run = false; @Test(groups = {"nopackage"}) public void test() { m_run = true; } @AfterMethod(groups = {"nopackage"}) public void after() { assert m_run : "test method was not run"; } } testng-testng-6.9.5/src/test/java/ConverterSample4.java0000644000175000017500000000346512551235562022410 0ustar eugeneeugene /* * Created on 12-Sep-2006 by micheb10 * it is at the wrong location, but it's easier to leave it here. * Also, do not change the line numbers since the test will make sure * that the tags are generated in hardcoded line numbers */ /** * Sample file for the Javadocv annotations to Java 5 annotations converter for the default package * @author micheb10 12-Sep-2006 * */ public class ConverterSample4 { /** * This comment line should be preserved * @testng.before-suite alwaysRun = "true" */ public void beforeSuiteAlwaysRun() { // We are just checking appropriate annotations are added so we don't care about body } /** * @testng.test */ public void plainTest() { // Empty body } /** * @testng.test * @testng.expected-exceptions * value = "java.lang.NullPointerException java.lang.NumberFormatException" */ public void expectedExceptions() { // Empty body } /** * @testng.test groups = "groupA groupB" */ public void testGroups() { // Empty body } /** * @testng.after-method */ public void afterMethod() { // Empty body } /** * This key should be preserved * @author The author is a standard tag and should not be touched * @testng.test groups = "groupA" * dependsOnMethods = "expectedExceptions" timeOut="3000" unrecognised="futureProof" * @version another standard tag should not be changed * @testng.expected-exceptions * value = "java.lang.NullPointerException java.lang.NumberFormatException" * */ public void testEverything() { } /** * @testng.data-provider name="test1" */ public Object[][] dataProvider() { return null; } /** * @testng.factory */ @SuppressWarnings({"unchecked", "deprecation"}) public Object[] factory() { return null; } } testng-testng-6.9.5/src/test/java/ConverterSample2.java0000644000175000017500000000126412551235562022401 0ustar eugeneeugene// Not that this file has no package (that's what we are testing) and therefore, // it is at the wrong location, but it's easier to leave it here. // Also, do not change the line numbers since the test will make sure // that the tags are generated in hardcoded line numbers import junit.framework.TestCase; public class ConverterSample2 extends TestCase { @Override protected void setUp() throws Exception { super.setUp(); } @Override protected void tearDown() throws Exception { super.tearDown(); } public final void testClassJunit() { } public final void testSetClassId() { } public final void testSetClassName() { } } testng-testng-6.9.5/src/main/0000755000175000017500000000000012551235562015364 5ustar eugeneeugenetestng-testng-6.9.5/src/main/resources/0000755000175000017500000000000012551235562017376 5ustar eugeneeugenetestng-testng-6.9.5/src/main/resources/testngtasks0000644000175000017500000000004012551235562021665 0ustar eugeneeugenetestng=org.testng.TestNGAntTask testng-testng-6.9.5/src/main/resources/testng.css0000644000175000017500000000047012551235562021415 0ustar eugeneeugene.invocation-failed, .test-failed { background-color: #DD0000; } .invocation-percent, .test-percent { background-color: #006600; } .invocation-passed, .test-passed { background-color: #00AA00; } .invocation-skipped, .test-skipped { background-color: #CCCC00; } .main-page { font-size: x-large; } testng-testng-6.9.5/src/main/resources/testng-reports.js0000644000175000017500000000674312551235562022746 0ustar eugeneeugene$(document).ready(function() { $('a.navigator-link').click(function() { // Extract the panel for this link var panel = getPanelName($(this)); // Mark this link as currently selected $('.navigator-link').parent().removeClass('navigator-selected'); $(this).parent().addClass('navigator-selected'); showPanel(panel); }); installMethodHandlers('failed'); installMethodHandlers('skipped'); installMethodHandlers('passed', true); // hide passed methods by default $('a.method').click(function() { showMethod($(this)); return false; }); // Hide all the panels and display the first one (do this last // to make sure the click() will invoke the listeners) $('.panel').hide(); $('.navigator-link').first().click(); // Collapse/expand the suites $('a.collapse-all-link').click(function() { var contents = $('.navigator-suite-content'); if (contents.css('display') == 'none') { contents.show(); } else { contents.hide(); } }); }); // The handlers that take care of showing/hiding the methods function installMethodHandlers(name, hide) { function getContent(t) { return $('.method-list-content.' + name + "." + t.attr('panel-name')); } function getHideLink(t, name) { var s = 'a.hide-methods.' + name + "." + t.attr('panel-name'); return $(s); } function getShowLink(t, name) { return $('a.show-methods.' + name + "." + t.attr('panel-name')); } function getMethodPanelClassSel(element, name) { var panelName = getPanelName(element); var sel = '.' + panelName + "-class-" + name; return $(sel); } $('a.hide-methods.' + name).click(function() { var w = getContent($(this)); w.hide(); getHideLink($(this), name).hide(); getShowLink($(this), name).show(); getMethodPanelClassSel($(this), name).hide(); }); $('a.show-methods.' + name).click(function() { var w = getContent($(this)); w.show(); getHideLink($(this), name).show(); getShowLink($(this), name).hide(); showPanel(getPanelName($(this))); getMethodPanelClassSel($(this), name).show(); }); if (hide) { $('a.hide-methods.' + name).click(); } else { $('a.show-methods.' + name).click(); } } function getHashForMethod(element) { return element.attr('hash-for-method'); } function getPanelName(element) { return element.attr('panel-name'); } function showPanel(panelName) { $('.panel').hide(); var panel = $('.panel[panel-name="' + panelName + '"]'); panel.show(); } function showMethod(element) { var hashTag = getHashForMethod(element); var panelName = getPanelName(element); showPanel(panelName); var current = document.location.href; var base = current.substring(0, current.indexOf('#')) document.location.href = base + '#' + hashTag; var newPosition = $(document).scrollTop() - 65; $(document).scrollTop(newPosition); } function drawTable() { for (var i = 0; i < suiteTableInitFunctions.length; i++) { window[suiteTableInitFunctions[i]](); } for (var k in window.suiteTableData) { var v = window.suiteTableData[k]; var div = v.tableDiv; var data = v.tableData var table = new google.visualization.Table(document.getElementById(div)); table.draw(data, { showRowNumber : false }); } } testng-testng-6.9.5/src/main/resources/testng-reports.css0000644000175000017500000001165212551235562023115 0ustar eugeneeugenebody { margin: 0px 0px 5px 5px; } ul { margin: 0px; } li { list-style-type: none; } a { text-decoration: none; } a:hover { text-decoration: underline; } .navigator-selected { background: #ffa500; } .wrapper { position: absolute; top: 60px; bottom: 0; left: 400px; right: 0; overflow: auto; } .navigator-root { position: absolute; top: 60px; bottom: 0; left: 0; width: 400px; overflow-y: auto; } .suite { margin: 0px 10px 10px 0px; background-color: #fff8dc; } .suite-name { padding-left: 10px; font-size: 25px; font-family: Times; } .main-panel-header { padding: 5px; background-color: #9FB4D9; //afeeee; font-family: monospace; font-size: 18px; } .main-panel-content { padding: 5px; margin-bottom: 10px; background-color: #DEE8FC; //d0ffff; } .rounded-window { border-radius: 10px; border-style: solid; border-width: 1px; } .rounded-window-top { border-top-right-radius: 10px 10px; border-top-left-radius: 10px 10px; border-style: solid; border-width: 1px; overflow: auto; } .light-rounded-window-top { border-top-right-radius: 10px 10px; border-top-left-radius: 10px 10px; } .rounded-window-bottom { border-style: solid; border-width: 0px 1px 1px 1px; border-bottom-right-radius: 10px 10px; border-bottom-left-radius: 10px 10px; overflow: auto; } .method-name { font-size: 12px; font-family: monospace; } .method-content { border-style: solid; border-width: 0px 0px 1px 0px; margin-bottom: 10; padding-bottom: 5px; width: 80%; } .parameters { font-size: 14px; font-family: monospace; } .stack-trace { white-space: pre; font-family: monospace; font-size: 12px; font-weight: bold; margin-top: 0px; margin-left: 20px; } .testng-xml { font-family: monospace; } .method-list-content { margin-left: 10px; } .navigator-suite-content { margin-left: 10px; font: 12px 'Lucida Grande'; } .suite-section-title { margin-top: 10px; width: 80%; border-style: solid; border-width: 1px 0px 0px 0px; font-family: Times; font-size: 18px; font-weight: bold; } .suite-section-content { list-style-image: url(bullet_point.png); } .top-banner-root { position: absolute; top: 0; height: 45px; left: 0; right: 0; padding: 5px; margin: 0px 0px 5px 0px; background-color: #0066ff; font-family: Times; color: #fff; text-align: center; } .top-banner-title-font { font-size: 25px; } .test-name { font-family: 'Lucida Grande'; font-size: 16px; } .suite-icon { padding: 5px; float: right; height: 20; } .test-group { font: 20px 'Lucida Grande'; margin: 5px 5px 10px 5px; border-width: 0px 0px 1px 0px; border-style: solid; padding: 5px; } .test-group-name { font-weight: bold; } .method-in-group { font-size: 16px; margin-left: 80px; } table.google-visualization-table-table { width: 100%; } .reporter-method-name { font-size: 14px; font-family: monospace; } .reporter-method-output-div { padding: 5px; margin: 0px 0px 5px 20px; font-size: 12px; font-family: monospace; border-width: 0px 0px 0px 1px; border-style: solid; } .ignored-class-div { font-size: 14px; font-family: monospace; } .ignored-methods-div { padding: 5px; margin: 0px 0px 5px 20px; font-size: 12px; font-family: monospace; border-width: 0px 0px 0px 1px; border-style: solid; } .border-failed { border-top-left-radius: 10px 10px; border-bottom-left-radius: 10px 10px; border-style: solid; border-width: 0px 0px 0px 10px; border-color: #f00; } .border-skipped { border-top-left-radius: 10px 10px; border-bottom-left-radius: 10px 10px; border-style: solid; border-width: 0px 0px 0px 10px; border-color: #edc600; } .border-passed { border-top-left-radius: 10px 10px; border-bottom-left-radius: 10px 10px; border-style: solid; border-width: 0px 0px 0px 10px; border-color: #19f52d; } .times-div { text-align: center; padding: 5px; } .suite-total-time { font: 16px 'Lucida Grande'; } .configuration-suite { margin-left: 20px; } .configuration-test { margin-left: 40px; } .configuration-class { margin-left: 60px; } .configuration-method { margin-left: 80px; } .test-method { margin-left: 100px; } .chronological-class { background-color: #0ccff; border-style: solid; border-width: 0px 0px 1px 1px; } .method-start { float: right; } .chronological-class-name { padding: 0px 0px 0px 5px; color: #008; } .after, .before, .test-method { font-family: monospace; font-size: 14px; } .navigator-suite-header { font-size: 22px; margin: 0px 10px 5px 0px; background-color: #deb887; text-align: center; } .collapse-all-icon { padding: 5px; float: right; } testng-testng-6.9.5/src/main/resources/testng-1.0.dtd0000755000175000017500000001763312551235562021710 0ustar eugeneeugene testng-testng-6.9.5/src/main/resources/skipped.png0000644000175000017500000000170712551235562021550 0ustar eugeneeugenePNG  IHDR Vu\iCCPICC ProfilexTkPe:g >hndStCkWZ6!Hm\$~ًo:w> كo{ a"L"4M'S9'^qZ/USO^C+hMJ&G@Ӳylto߫c՚  5"Yi\t։15LsX g8ocግ#f45@ B:K@8i ΁'&.)@ry[:Vͦ#wQ?HBd(B acĪL"JitTy8;(Gx_^[%׎ŷQ麲uan7m QH^eOQu6Su 2%vX ^*l O—ޭˀq,>S%LdB1CZ$M9P 'w\/].r#E|!3>_oa۾d1Zӑz'=~V+cjJtO%mN |-bWO+ o ^ IH.;S]i_s9*p.7U^s.3u |^,<;c=ma>Vt.[՟Ϫ x# ¡_2dIDAT(c|{? `p B-BkxwYf3H $p tMAjX@2@քl2L 0A|43mB6EL1L6Mp qibyL^*#IENDB`testng-testng-6.9.5/src/main/resources/passed.png0000644000175000017500000000177312551235562021373 0ustar eugeneeugenePNG  IHDR Vu\iCCPICC ProfilexTkPe:g >hndStCkWZ6!Hm\$~ًo:w> كo{ a"L"4M'S9'^qZ/USO^C+hMJ&G@Ӳylto߫c՚  5"Yi\t։15LsX g8ocግ#f45@ B:K@8i ΁'&.)@ry[:Vͦ#wQ?HBd(B acĪL"JitTy8;(Gx_^[%׎ŷQ麲uan7m QH^eOQu6Su 2%vX ^*l O—ޭˀq,>S%LdB1CZ$M9P 'w\/].r#E|!3>_oa۾d1Zӑz'=~V+cjJtO%mN |-bWO+ o ^ IH.;S]i_s9*p.7U^s.3u |^,<;c=ma>Vt.[՟Ϫ x# ¡_2IDAT(cDZR5`+"a 5I !J`k[8Y%߿q;C k@qȤSV_gC(&e`\VTu×P48 $s]B8").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;g=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
a",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="
"+""+"
",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="
t
",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="
",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")}; f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&i.push({elem:this,matches:d.slice(e)});for(j=0;j0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function() {for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);testng-testng-6.9.5/src/main/resources/header0000644000175000017500000000134412551235562020553 0ustar eugeneeugene TestNG reports testng-testng-6.9.5/src/main/resources/failed.png0000644000175000017500000000172112551235562021331 0ustar eugeneeugenePNG  IHDR Vu\iCCPICC ProfilexTkPe:g >hndStCkWZ6!Hm\$~ًo:w> كo{ a"L"4M'S9'^qZ/USO^C+hMJ&G@Ӳylto߫c՚  5"Yi\t։15LsX g8ocግ#f45@ B:K@8i ΁'&.)@ry[:Vͦ#wQ?HBd(B acĪL"JitTy8;(Gx_^[%׎ŷQ麲uan7m QH^eOQu6Su 2%vX ^*l O—ޭˀq,>S%LdB1CZ$M9P 'w\/].r#E|!3>_oa۾d1Zӑz'=~V+cjJtO%mN |-bWO+ o ^ IH.;S]i_s9*p.7U^s.3u |^,<;c=ma>Vt.[՟Ϫ x# ¡_2nIDAT(c&DZRpEkĮ, \H]bFlلl2H1Obh9y0cP4$ik@WKVOc6`&y+IENDB`testng-testng-6.9.5/src/main/resources/collapseall.gif0000644000175000017500000000023512551235562022360 0ustar eugeneeugeneGIF89aFz! ,JpI6C D(h9tMNj{0#RP(0Z1rqbL4f;testng-testng-6.9.5/src/main/resources/bullet_point.png0000644000175000017500000000054412551235562022607 0ustar eugeneeugenePNG  IHDR pHYs  gAMA|Q cHRMz%u0`:o_FIDATxb?[\ > A|b 334 AJ(/Knb>%Ͱί??~c|A@Uu2Ā>~g0Tg@ 10p*`d`Rݗ @{Q  u @ jvo|h ;+3 @74~} @N)[q71`PqP .IENDB`testng-testng-6.9.5/src/main/resources/META-INF/0000755000175000017500000000000012551235562020536 5ustar eugeneeugenetestng-testng-6.9.5/src/main/resources/META-INF/services/0000755000175000017500000000000012551235562022361 5ustar eugeneeugenetestng-testng-6.9.5/src/main/resources/META-INF/services/org.testng.xml.ISuiteParser0000644000175000017500000000003612551235562027552 0ustar eugeneeugeneorg.testng.internal.YamlParsertestng-testng-6.9.5/src/main/java/0000755000175000017500000000000012551235562016305 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/testng-1.0.dtd.html0000644000175000017500000002154412551235562021553 0ustar eugeneeugene DTD for TestNG 1.0
<!--

Here is a quick overview of the main parts of this DTD.  For more information,
refer to the <a href="http://testng.org" >main web site</a>.

                                                      
A <b>suite</b> is made of <b>tests</b> and <b>parameters</b>.
                                                      

A <b>test</b> is made of three parts:                        

<ul>
<li> <b>parameters</b>, which override the suite parameters     
<li> <b>groups</b>, made of two parts                           

<li> <b>classes</b>, defining which classes are going to be part
  of this test run                                    
</ul>
                                                      
In turn, <b>groups</b> are made of two parts:                

<ul>
<li> Definitions, which allow you to group groups into   
  bigger groups                                       
<li> Runs, which defines the groups that the methods     
  must belong to in order to be run during this test  
</ul>
                                                      
Cedric Beust & Alexandru Popescu                      
@title DTD for TestNG                                    
@root suite

-->


<!-- A suite is the top-level element of a testng.xml file                  -->

<!ELEMENT suite (listeners|packages|test|parameter|method-selectors|suite-files)* >

<!-- Attributes: -->
<!--
@attr  name        The name of this suite (as it will appear in the reports)
@attr  junit       Whether to run in JUnit mode.
@attr  verbose     How verbose the output on the console will be.  
                This setting has no impact on the HTML reports.
@attr  parallel   Whether TestNG should use different threads
                to run your tests (might speed up the process)
@attr  configfailurepolicy  Whether to continue attempting Before/After
                Class/Methods after they've failed once or just skip remaining.
@attr  thread-count An integer giving the size of the thread pool to use
                if you set parallel.
@attr  annotations  If "javadoc", TestNG will look for
                JavaDoc annotations in your sources, otherwise it will
                use JDK5 annotations.
@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.
@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.
-->
<!ATTLIST suite 
    name CDATA #REQUIRED
    junit (true | false) "false"
    verbose CDATA #IMPLIED
    parallel (false | methods | tests | classes) "false"
    configfailurepolicy (skip | continue) "skip"
    thread-count CDATA "5"
    annotations CDATA #IMPLIED
    time-out CDATA #IMPLIED
    skipfailedinvocationCounts (true | false) "false"
    data-provider-thread-count CDATA "10"
    object-factory CDATA #IMPLIED
>

<!-- A list of XML files that contain more suite descriptions -->
<!ELEMENT suite-files (suite-file)* >

<!ELEMENT suite-file ANY >
<!ATTLIST suite-file
    path CDATA #REQUIRED
>

<!--
Parameters can be defined at the <suite> or at the <test> level.
Parameters defined at the <test> level override parameters of the same name in <suite>

Parameters are used to link Java method parameters to their actual value, defined here.
-->
<!ELEMENT parameter ANY>
<!ATTLIST parameter
    name CDATA #REQUIRED
    value CDATA #REQUIRED >

<!--
Method selectors define user classes used to select which methods to run.
They need to implement <tt>org.testng.IMethodSelector</tt> 
-->
<!ELEMENT method-selectors (method-selector*) >

<!ELEMENT method-selector ((selector-class)*|script) >
<!ELEMENT selector-class ANY>
<!ATTLIST selector-class
    name CDATA #REQUIRED
  priority CDATA #IMPLIED
>
<!ELEMENT script ANY>
<!ATTLIST script
    language CDATA #REQUIRED
>

<!--
A test contains parameters and classes.  Additionally, you can define additional groups ("groups of groups")
-->

<!ELEMENT test (method-selectors?,parameter*,groups?,packages?,classes?) >

<!--
@attr  name         The name of this test (as it will appear in the reports)
@attr  junit        Whether to run in JUnit mode.
@attr  verbose      How verbose the output on the console will be.
                This setting has no impact on the HTML reports.
                Default value: suite level verbose.
@attr  parallel     Whether TestNG should use different threads
                to run your tests (might speed up the process)
@attr  thread-count An integer giving the size of the thread pool to be used if
                parallel mode is used. Overrides the suite level value.
@attr  annotations  If "javadoc", TestNG will look for
                JavaDoc annotations in your sources, otherwise it will
                use JDK5 annotations.
@attr  time-out     the time to wait in milliseconds before aborting
                the method (if parallel="methods" ) or the test (if parallel="tests" )
@attr  enabled      flag to enable/disable current test. Default value: true 
@attr  skipfailedinvocationCounts Whether to skip failed invocations.
-->
<!ATTLIST test
    name CDATA #REQUIRED 
    junit (true | false) "false"
    verbose  CDATA #IMPLIED
    parallel  CDATA #IMPLIED
    thread-count CDATA #IMPLIED
    annotations  CDATA #IMPLIED
    time-out CDATA #IMPLIED
    enabled CDATA #IMPLIED
    skipfailedinvocationCounts (true | false) "false"
>

<!--
Defines additional groups ("groups of groups") and also which groups to include in this test run
-->
<!ELEMENT groups (define*,run?) >

<!ELEMENT define (include*)>

<!ATTLIST define
    name CDATA #REQUIRED>

<!-- Defines which groups to include in the current group of groups         -->
<!ELEMENT include ANY>
<!ATTLIST include
    name CDATA #REQUIRED>

<!-- Defines which groups to exclude from the current group of groups       -->
<!ELEMENT exclude ANY>
<!ATTLIST exclude
    name CDATA #REQUIRED>

<!-- The subtag of groups used to define which groups should be run         -->
<!ELEMENT run (include?,exclude?)* >

<!-- The list of classes to include in this test                            -->
<!ELEMENT classes (class*) >
<!ELEMENT class (methods*) >
<!ATTLIST class
    name CDATA #REQUIRED >

<!-- The list of packages to include in this test                           -->
<!ELEMENT packages (package*) >

<!-- The package description. 
     If the package name ends with .* then subpackages are included too.
-->
<!ELEMENT package (include?,exclude?)*>
<!ATTLIST package
    name CDATA #REQUIRED >

<!-- The list of methods to include/exclude from this test                 -->
<!ELEMENT methods (include?,exclude?)* >

<!-- The list of listeners that will be passed to TestNG -->
<!ELEMENT listeners (listener*) >

<!ELEMENT listener ANY>
<!ATTLIST listener
    class-name CDATA #REQUIRED >
testng-testng-6.9.5/src/main/java/org/0000755000175000017500000000000012551235562017074 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/0000755000175000017500000000000012551235562020400 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/xml/0000755000175000017500000000000012551235562021200 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/xml/dom/0000755000175000017500000000000012551235562021757 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/xml/dom/XDom.java0000644000175000017500000003133712551235562023500 0ustar eugeneeugenepackage org.testng.xml.dom; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; 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; import org.testng.xml.XmlMethodSelector; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import org.xml.sax.SAXException; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import java.util.Map; public class XDom { // private static Map> m_map = Maps.newHashMap(); private Document m_document; private ITagFactory m_tagFactory; public XDom(ITagFactory tagFactory, Document document) throws XPathExpressionException, InstantiationException, IllegalAccessException { m_tagFactory = tagFactory; m_document = document; } public Object parse() throws XPathExpressionException, InstantiationException, IllegalAccessException, SecurityException, IllegalArgumentException, NoSuchMethodException, InvocationTargetException { Object result = null; NodeList nodes = m_document.getChildNodes(); for (int i = 0; i < nodes.getLength(); i++) { Node item = nodes.item(i); if (item.getAttributes() != null) { String nodeName = item.getNodeName(); System.out.println("Node name:" + nodeName); Class c = m_tagFactory.getClassForTag(nodeName); if (c == null) { throw new RuntimeException("No class found for tag " + nodeName); } result = c.newInstance(); populateAttributes(item, result); if (ITagSetter.class.isAssignableFrom(result.getClass())) { throw new RuntimeException("TAG SETTER"); } populateChildren(item, result); } } return result; } public void populateChildren(Node root, Object result) throws InstantiationException, IllegalAccessException, XPathExpressionException, SecurityException, IllegalArgumentException, NoSuchMethodException, InvocationTargetException { p("populateChildren: " + root.getLocalName()); NodeList childNodes = root.getChildNodes(); ListMultiMap children = Maps.newListMultiMap(); for (int i = 0; i < childNodes.getLength(); i++) { Node item = childNodes.item(i); if (item.getAttributes() != null) { String nodeName = item.getNodeName(); if ("suite-files".equals(nodeName)) { System.out.println("BREAK"); } Class c = m_tagFactory.getClassForTag(nodeName); if (c == null) { System.out.println("Warning: No class found for tag " + nodeName); boolean foundSetter = invokeOnSetter(result, (Element) item, nodeName, null); System.out.println(" found setter:" + foundSetter); } else { Object object = instantiateElement(c, result); if (ITagSetter.class.isAssignableFrom(object.getClass())) { System.out.println("Tag setter:" + result); ((ITagSetter) object).setProperty(nodeName, result, item); } else { children.put(nodeName, object); populateAttributes(item, object); populateContent(item, object); } boolean foundSetter = invokeOnSetter(result, (Element) item, nodeName, object); // setProperty(result, nodeName, object); populateChildren(item, object); } // boolean foundSetter = invokeOnSetter(result, (Element) item, nodeName); // if (! foundSetter) { // boolean foundListSetter = invokeOnListSetter(result, nodeName, item); // if (! foundListSetter) { // } // } } } // System.out.println("Found children:" + children); // for (String s : children.getKeys()) { // setCollectionProperty(result, s, children.get(s), object); // } } /** * Try to find a @ParentSetter. If this fails, try to find a constructor that takes the parent as a parameter. * If this fails, use the default constructor. */ private Object instantiateElement(Class c, Object parent) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { Object result = null; Method m = findMethodAnnotatedWith(c, ParentSetter.class); if (m != null) { result = c.newInstance(); m.invoke(result, parent); } else { try { result = c.getConstructor(parent.getClass()).newInstance(parent); } catch(NoSuchMethodException ex) { result = c.newInstance(); } } return result; } // private List> // findMethodsWithAnnotation(Class c, Class ac) { // List> result = Lists.newArrayList(); // for (Method m : c.getMethods()) { // Annotation a = m.getAnnotation(ac); // if (a != null) { // result.add(Pair.of(m, a)); // } // } // return result; // } private Method findMethodAnnotatedWith(Class c, Class annotation) { for (Method m : c.getMethods()) { if (m.getAnnotation(annotation) != null) { return m; } } return null; } private void populateContent(Node item, Object object) { for (int i = 0; i < item.getChildNodes().getLength(); i++) { Node child = item.getChildNodes().item(i); if (child instanceof Text) { setText(object, (Text) child); } } } private void setText(Object bean, Text child) { List> pairs = Reflect.findMethodsWithAnnotation(bean.getClass(), TagContent.class, bean); for (Pair pair : pairs) { try { pair.first().invoke(bean, child.getTextContent()); } catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException | DOMException e) { e.printStackTrace(); } } } private boolean invokeOnSetter(Object object, Element element, String nodeName, Object bean) { Pair pair = Reflect.findSetterForTag(object.getClass(), nodeName, bean); List allParameters = null; if (pair != null) { Method m = pair.first(); try { if (pair.second() != null) { allParameters = pair.second().getParameters(element); } else { allParameters = Lists.newArrayList(); allParameters.add(new Object[] { bean }); } for (Object[] p : allParameters) { m.invoke(object, p); } return true; } catch (IllegalArgumentException e) { System.out.println("Parameters: " + allParameters); e.printStackTrace(); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } return false; } private void populateAttributes(Node node, Object object) throws XPathExpressionException { for (int j = 0; j < node.getAttributes().getLength(); j++) { Node item = node.getAttributes().item(j); setProperty(object, item.getLocalName(), item.getNodeValue()); } } private void setProperty(Object object, String name, Object value) { Pair setter = Reflect.findSetterForTag(object.getClass(), name, value); if (setter != null) { Method foundMethod = setter.first(); try { Class type = foundMethod.getParameterTypes()[0]; if (type == Boolean.class || type == boolean.class) { foundMethod.invoke(object, Boolean.parseBoolean(value.toString())); } else if (type == Integer.class || type == int.class) { foundMethod.invoke(object, Integer.parseInt(value.toString())); } else { foundMethod.invoke(object, value); } } catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } else { e("Couldn't find setter method for property" + name + " on " + object.getClass()); } } // private Method findSetter(Object object, String name) { // String methodName = toCamelCaseSetter(name); // Method foundMethod = null; // for (Method m : object.getClass().getDeclaredMethods()) { // if (m.getName().equals(methodName)) { // foundMethod = m; // break; // } // } // return foundMethod; // } private void p(String string) { System.out.println("[XDom] " + string); } private void e(String string) { System.out.println("[XDom] [Error] " + string); } public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException, XPathExpressionException, InstantiationException, IllegalAccessException, SecurityException, IllegalArgumentException, NoSuchMethodException, InvocationTargetException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); // never forget this! DocumentBuilder builder = factory.newDocumentBuilder(); FileInputStream inputStream = new FileInputStream(new File(System.getProperty("user.home") + "/java/testng/src/test/resources/testng-all.xml")); Document doc = builder.parse(inputStream); XmlSuite result = (XmlSuite) new XDom(new TestNGTagFactory(), doc).parse(); test(result); System.out.println(result.toXml()); } private static void test(XmlSuite s) { Assert.assertEquals("TestNG", s.getName()); Assert.assertEquals(s.getDataProviderThreadCount(), 3); Assert.assertEquals(s.getThreadCount(), 2); { // method-selectors List selectors = s.getMethodSelectors(); Assert.assertEquals(selectors.size(), 2); XmlMethodSelector s1 = selectors.get(0); Assert.assertEquals(s1.getLanguage(), "javascript"); Assert.assertEquals(s1.getExpression(), "foo()"); XmlMethodSelector s2 = selectors.get(1); Assert.assertEquals(s2.getClassName(), "SelectorClass"); Assert.assertEquals(s2.getPriority(), 3); } { // child-suites List suiteFiles = s.getSuiteFiles(); Assert.assertEquals(suiteFiles, Arrays.asList("./junit-suite.xml")); } { // parameters Map p = s.getParameters(); Assert.assertEquals(p.size(), 2); Assert.assertEquals(p.get("suiteParameter"), "suiteParameterValue"); Assert.assertEquals(p.get("first-name"), "Cedric"); } { // run Assert.assertEquals(s.getIncludedGroups(), Arrays.asList("includeThisGroup")); Assert.assertEquals(s.getExcludedGroups(), Arrays.asList("excludeThisGroup")); XmlGroups groups = s.getGroups(); // define List defines = groups.getDefines(); Assert.assertEquals(defines.size(), 1); XmlDefine define = defines.get(0); Assert.assertEquals(define.getName(), "bigSuite"); Assert.assertEquals(define.getIncludes(), Arrays.asList("suite1", "suite2")); // packages Assert.assertEquals(s.getPackageNames(), Arrays.asList("com.example1", "com.example2")); // listeners Assert.assertEquals(s.getListeners(), Arrays.asList("com.beust.Listener1", "com.beust.Listener2")); // dependencies // only defined on test for now } { // tests Assert.assertEquals(s.getTests().size(), 3); for (int i = 0; i < s.getTests().size(); i++) { if ("Nopackage".equals(s.getTests().get(i).getName())) { testNoPackage(s.getTests().get(i)); } } } } private static void testNoPackage(XmlTest t) { Assert.assertEquals(t.getThreadCount(), 42); Assert.assertTrue(t.getAllowReturnValues()); // define Map> metaGroups = t.getMetaGroups(); Assert.assertEquals(metaGroups.get("evenodd"), Arrays.asList("even", "odd")); // run Assert.assertEquals(t.getIncludedGroups(), Arrays.asList("nopackage", "includeThisGroup")); Assert.assertEquals(t.getExcludedGroups(), Arrays.asList("excludeThisGroup")); // dependencies Map dg = t.getXmlDependencyGroups(); Assert.assertEquals(dg.size(), 2); Assert.assertEquals(dg.get("e"), "f"); Assert.assertEquals(dg.get("g"), "h"); } } testng-testng-6.9.5/src/main/java/org/testng/xml/dom/Wrapper.java0000644000175000017500000000370512551235562024247 0ustar eugeneeugenepackage org.testng.xml.dom; import org.testng.collections.Lists; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import java.lang.annotation.Annotation; import java.util.List; public class Wrapper { private OnElement m_onElement; private OnElementList m_onElementList; private Tag m_tag; private TagContent m_tagContent; private Object m_bean; public Wrapper(Annotation a, Object bean) { m_bean = bean; if (a instanceof OnElement) m_onElement = (OnElement) a; else if (a instanceof OnElementList) m_onElementList = (OnElementList) a; else if (a instanceof Tag) m_tag = (Tag) a; else if (a instanceof TagContent) m_tagContent = (TagContent) a; else throw new RuntimeException("Illegal annotation " + a); } public String getTagName() { if (m_onElement != null) return m_onElement.tag(); else if (m_onElementList != null) return m_onElementList.tag(); else return m_tag.name(); } public List getParameters(Element element) { List allParameters = Lists.newArrayList(); if (m_onElement != null) { List result = Lists.newArrayList(); for (String attributeName : m_onElement.attributes()) { result.add(element.getAttribute(attributeName)); } allParameters.add(result.toArray()); } else if (m_tag != null) { List result = Lists.newArrayList(); result.add(m_bean); allParameters.add(result.toArray()); } else { NodeList childNodes = element.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { if (childNodes.item(i).hasAttributes()) { Element item = (Element) childNodes.item(i); List result = Lists.newArrayList(); for (String attributeName : m_onElementList.attributes()) { result.add(item.getAttribute(attributeName)); } allParameters.add(result.toArray()); } } } return allParameters; } } testng-testng-6.9.5/src/main/java/org/testng/xml/dom/TestNGTagFactory.java0000644000175000017500000000134412551235562025754 0ustar eugeneeugenepackage org.testng.xml.dom; import java.util.Map; import org.testng.collections.Maps; public class TestNGTagFactory implements ITagFactory { private Map> m_map = Maps.newHashMap(); public TestNGTagFactory() { // m_map.put("suite-files", XDom.ChildSuite.class); } @Override public Class getClassForTag(String tag) { Class result = m_map.get(tag); if (result != null) { return result; } else { String className = "org.testng.xml.Xml" + Reflect.toCapitalizedCamelCase(tag); try { result = Class.forName(className); } catch (ClassNotFoundException e) { System.out.println("Couldn't find class " + className); } } return result; } } testng-testng-6.9.5/src/main/java/org/testng/xml/dom/TagContent.java0000644000175000017500000000044012551235562024666 0ustar eugeneeugenepackage org.testng.xml.dom; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({METHOD}) public @interface TagContent { String name(); } testng-testng-6.9.5/src/main/java/org/testng/xml/dom/Tag.java0000644000175000017500000000043112551235562023333 0ustar eugeneeugenepackage org.testng.xml.dom; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({METHOD}) public @interface Tag { String name(); } testng-testng-6.9.5/src/main/java/org/testng/xml/dom/Reflect.java0000644000175000017500000000410012551235562024201 0ustar eugeneeugenepackage org.testng.xml.dom; import org.testng.collections.Lists; import org.testng.internal.collections.Pair; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; public class Reflect { public static List> findMethodsWithAnnotation( Class c, Class ac, Object bean) { List> result = Lists.newArrayList(); for (Method m : c.getMethods()) { Annotation a = m.getAnnotation(ac); if (a != null) { result.add(Pair.of(m, new Wrapper(a, bean))); } } return result; } public static Pair findSetterForTag( Class c, String tagName, Object bean) { // Try to find an annotation List> annotations = Arrays.asList(OnElement.class, OnElementList.class, Tag.class); for (Class annotationClass : annotations) { List> methods = findMethodsWithAnnotation(c, annotationClass, bean); for (Pair pair : methods) { if (pair.second().getTagName().equals(tagName)) { return pair; } } } // try fo find an adder or a setter for (String prefix : new String[] { "add", "set" }) { for (Method m : c.getDeclaredMethods()) { String methodName = toCamelCase(tagName, prefix); if (m.getName().equals(methodName)) { return Pair.of(m, null); } } } return null; } private static String toCamelCase(String name, String prefix) { return prefix + toCapitalizedCamelCase(name); } public static String toCapitalizedCamelCase(String name) { StringBuilder result = new StringBuilder(name.substring(0, 1).toUpperCase()); for (int i = 1; i < name.length(); i++) { if (name.charAt(i) == '-') { result.append(Character.toUpperCase(name.charAt(i + 1))); i++; } else { result.append(name.charAt(i)); } } return result.toString(); } } testng-testng-6.9.5/src/main/java/org/testng/xml/dom/ParentSetter.java0000644000175000017500000000041712551235562025244 0ustar eugeneeugenepackage org.testng.xml.dom; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({METHOD}) public @interface ParentSetter { } testng-testng-6.9.5/src/main/java/org/testng/xml/dom/OnElementList.java0000644000175000017500000000047412551235562025351 0ustar eugeneeugenepackage org.testng.xml.dom; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({METHOD}) public @interface OnElementList { String tag(); String[] attributes(); } testng-testng-6.9.5/src/main/java/org/testng/xml/dom/OnElement.java0000644000175000017500000000047012551235562024511 0ustar eugeneeugenepackage org.testng.xml.dom; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({METHOD}) public @interface OnElement { String tag(); String[] attributes(); } testng-testng-6.9.5/src/main/java/org/testng/xml/dom/ITagSetter.java0000644000175000017500000000022012551235562024627 0ustar eugeneeugenepackage org.testng.xml.dom; import org.w3c.dom.Node; public interface ITagSetter { void setProperty(String name, T parent, Node node); } testng-testng-6.9.5/src/main/java/org/testng/xml/dom/ITagFactory.java0000644000175000017500000000014612551235562024777 0ustar eugeneeugenepackage org.testng.xml.dom; public interface ITagFactory { Class getClassForTag(String tag); } testng-testng-6.9.5/src/main/java/org/testng/xml/dom/DomXmlParser.java0000644000175000017500000000431112551235562025176 0ustar eugeneeugenepackage org.testng.xml.dom; import org.testng.xml.ISuiteParser; import org.testng.xml.XMLParser; import org.testng.xml.XmlSuite; import org.w3c.dom.Document; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathExpressionException; import java.io.IOException; import java.io.InputStream; public class DomXmlParser extends XMLParser implements ISuiteParser { @Override public XmlSuite parse(String currentFile, InputStream inputStream, boolean loadClasses) { XmlSuite result = null; try { result = parse2(currentFile, inputStream, loadClasses); } catch (Exception e) { e.printStackTrace(); } return result; } @Override public boolean accept(String fileName) { return fileName.endsWith(".xml"); } public XmlSuite parse2(String currentFile, InputStream inputStream, boolean loadClasses) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); // never forget this! DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(inputStream); DomUtil xpu = new DomUtil(doc); XmlSuite result = new XmlSuite(); xpu.populate(result); // XPathFactory xpathFactory = XPathFactory.newInstance(); // XPath xpath = xpathFactory.newXPath(); // // { // XPathExpression expr = xpath.compile("//suite"); // Object result = expr.evaluate(doc, XPathConstants.NODESET); // NodeList nodes = (NodeList) result; // for (int i = 0; i < nodes.getLength(); i++) { // Node node = nodes.item(i); // for (int j = 0; j < node.getAttributes().getLength(); j++) { // System.out.println(node.getAttributes().item(j)); // } // } // } // { // XPathExpression expr = xpath.compile("//suite/@name"); // Object result = expr.evaluate(doc, XPathConstants.STRING); // System.out.println("NAME:" + result); // } System.out.println(result.toXml()); return result; } } testng-testng-6.9.5/src/main/java/org/testng/xml/dom/DomUtil.java0000644000175000017500000002410512551235562024201 0ustar eugeneeugenepackage org.testng.xml.dom; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.xml.XmlClass; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Iterator; import java.util.List; import java.util.Map; public class DomUtil { private XPath m_xpath; private Document m_document; public DomUtil(Document doc) { XPathFactory xpathFactory = XPathFactory.newInstance(); m_xpath = xpathFactory.newXPath(); m_document = doc; } public void populate(final XmlSuite xmlSuite) throws XPathExpressionException { NodeList nodes = m_document.getChildNodes(); final Map parameters = Maps.newHashMap(); for (int i = 0; i < nodes.getLength(); i++) { Node item1 = nodes.item(i); Map map = Maps.newHashMap(); map.put("parameter", new NodeProcessor() { @Override public void process(Node node) { Element e = (Element) node; parameters.put(e.getAttribute("name"), e.getAttribute("value")); } }); map.put("test", new NodeProcessor() { @Override public void process(Node node) { XmlTest xmlTest = new XmlTest(xmlSuite); populateTest(xmlTest, node); } }); map.put("suite-files", new NodeProcessor() { @Override public void process(Node node) { NodeList item2Children = node.getChildNodes(); List suiteFiles = Lists.newArrayList(); for (int k = 0; k < item2Children.getLength(); k++) { Node item3 = item2Children.item(k); if (item3 instanceof Element) { Element e = (Element) item3; if ("suite-file".equals(item3.getNodeName())) { suiteFiles.add(e.getAttribute("path")); } } } xmlSuite.setSuiteFiles(suiteFiles); } }); parseNodeAndChildren("suite", item1, xmlSuite, map); // if ("suite".equals(item1.getNodeName()) && item1.getAttributes() != null) { // populateAttributes(item1, xmlSuite); // NodeList item1Children = item1.getChildNodes(); // for (int j = 0; j < item1Children.getLength(); j++) { // Node item2 = item1Children.item(j); // if ("parameter".equals(item2.getNodeName())) { // Element e = (Element) item2; // parameters.put(e.getAttribute("name"), e.getAttribute("value")); // } else if ("test".equals(item2.getNodeName())) { // XmlTest xmlTest = new XmlTest(xmlSuite); // populateTest(xmlTest, item2); // } else if ("suite-files".equals(item2.getNodeName())) { // NodeList item2Children = item2.getChildNodes(); // List suiteFiles = Lists.newArrayList(); // for (int k = 0; k < item2Children.getLength(); k++) { // Node item3 = item2Children.item(k); // if (item3 instanceof Element) { // Element e = (Element) item3; // if ("suite-file".equals(item3.getNodeName())) { // suiteFiles.add(e.getAttribute("path")); // } // } // } // xmlSuite.setSuiteFiles(suiteFiles); // } // } // } } xmlSuite.setParameters(parameters); // XPathExpression expr = m_xpath.compile("//suite/test"); // NodeList tests = (NodeList) expr.evaluate(m_document, XPathConstants.NODESET); // for (int i = 0; i < tests.getLength(); i++) { // Node node = tests.item(i); // System.out.println(":" + node); // } } public static interface NodeProcessor { void process(Node node); } private void parseNodeAndChildren(String name, Node root, Object object, Map processors) throws XPathExpressionException { if (name.equals(root.getNodeName()) && root.getAttributes() != null) { populateAttributes(root, object); NodeList children = root.getChildNodes(); for (int j = 0; j < children.getLength(); j++) { Node item2 = children.item(j); String nodeName = item2.getNodeName(); NodeProcessor proc = processors.get(nodeName); if (proc != null) { proc.process(item2); } else if (! nodeName.startsWith("#")){ throw new RuntimeException("No processor found for " + nodeName); } // if ("parameter".equals(item2.getNodeName())) { // Element e = (Element) item2; // parameters.put(e.getAttribute("name"), e.getAttribute("value")); // } } } } public static Iterator findChildren(Node node, String name) { List result = Lists.newArrayList(); NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node n = children.item(i); if (name.equals(n.getNodeName())) { result.add(n); } } return result.iterator(); } private void populateTest(XmlTest xmlTest, Node item) { Map testParameters = Maps.newHashMap(); populateAttributes(item, xmlTest); NodeList itemChildren = item.getChildNodes(); for (int k = 0; k < itemChildren.getLength(); k++) { Node item2 = itemChildren.item(k); if ("parameter".equals(item2.getNodeName())) { Element e = (Element) item2; testParameters.put(e.getAttribute("name"), e.getAttribute("value")); } else if ("classes".equals(item2.getNodeName())) { NodeList item2Children = item2.getChildNodes(); for (int l = 0; l < item2Children.getLength(); l++) { Node item4 = item2Children.item(l); if ("class".equals(item4.getNodeName())) { XmlClass xmlClass = new XmlClass(); populateAttributes(item4, xmlClass); xmlTest.getClasses().add(xmlClass); // TODO: excluded/included methods } } } else if ("groups".equals(item2.getNodeName())) { NodeList item2Children = item2.getChildNodes(); List includes = Lists.newArrayList(); List excludes = Lists.newArrayList(); for (int l = 0; l < item2Children.getLength(); l++) { Node item3 = item2Children.item(l); if ("run".equals(item3.getNodeName())) { NodeList item3Children = item3.getChildNodes(); for (int m = 0; m < item3Children.getLength(); m++) { Node item4 = item3Children.item(m); if ("include".equals(item4.getNodeName())) { includes.add(((Element) item4).getAttribute("name")); } else if ("exclude".equals(item4.getNodeName())) { excludes.add(((Element) item4).getAttribute("name")); } } } else if ("dependencies".equals(item3.getNodeName())) { NodeList item3Children = item3.getChildNodes(); for (int m = 0; m < item3Children.getLength(); m++) { Node item4 = item3Children.item(m); if ("group".equals(item4.getNodeName())) { Element e = (Element) item4; xmlTest.addXmlDependencyGroup(e.getAttribute("name"), e.getAttribute("depends-on")); } } } else if ("define".equals(item3.getNodeName())) { xmlDefine(xmlTest, item3); } } xmlTest.setIncludedGroups(includes); xmlTest.setExcludedGroups(excludes); } // TODO: (method-selectors?,packages?) > } xmlTest.setParameters(testParameters); } /** * Parse the tag. */ private void xmlDefine(XmlTest xmlTest, Node item) { NodeList item3Children = item.getChildNodes(); List groups = Lists.newArrayList(); for (int m = 0; m < item3Children.getLength(); m++) { Node item4 = item3Children.item(m); if ("include".equals(item4.getNodeName())) { Element e = (Element) item4; groups.add(e.getAttribute("name")); } } xmlTest.addMetaGroup(((Element) item).getAttribute("name"), groups); } private void populateAttributes(Node node, Object object) { for (int j = 0; j < node.getAttributes().getLength(); j++) { Node item = node.getAttributes().item(j); p(node.getAttributes().item(j).toString()); setProperty(object, item.getLocalName(), item.getNodeValue()); } } private void setProperty(Object object, String name, Object value) { String methodName = toCamelCaseSetter(name); Method foundMethod = null; for (Method m : object.getClass().getDeclaredMethods()) { if (m.getName().equals(methodName)) { foundMethod = m; break; } } if (foundMethod == null) { p("Warning: couldn't find setter method " + methodName); } else { try { p("Invoking " + methodName + " with " + value); Class type = foundMethod.getParameterTypes()[0]; if (type == Boolean.class || type == boolean.class) { foundMethod.invoke(object, Boolean.parseBoolean(value.toString())); } else if (type == Integer.class || type == int.class) { foundMethod.invoke(object, Integer.parseInt(value.toString())); } else { foundMethod.invoke(object, value.toString()); } } catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } } private void p(String string) { // System.out.println("[XPathUtil] " + string); } private String toCamelCaseSetter(String name) { StringBuilder result = new StringBuilder("set" + name.substring(0, 1).toUpperCase()); for (int i = 1; i < name.length(); i++) { if (name.charAt(i) == '-') { result.append(Character.toUpperCase(name.charAt(i + 1))); i++; } else { result.append(name.charAt(i)); } } return result.toString(); } } testng-testng-6.9.5/src/main/java/org/testng/xml/XmlUtils.java0000644000175000017500000000160512551235562023626 0ustar eugeneeugenepackage org.testng.xml; import org.testng.reporters.XMLStringBuffer; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; public class XmlUtils { /** * Don't add this property if it's equal to its default value. */ public static void setProperty(Properties p, String name, String value, String def) { if (! def.equals(value) && value != null) { p.setProperty(name, value); } } public static void dumpParameters(XMLStringBuffer xsb, Map parameters) { // parameters if (!parameters.isEmpty()) { for(Map.Entry para: parameters.entrySet()) { Properties paramProps= new Properties(); paramProps.setProperty("name", para.getKey()); paramProps.setProperty("value", para.getValue()); xsb.addEmptyElement("parameter", paramProps); // BUGFIX: TESTNG-27 } } } } testng-testng-6.9.5/src/main/java/org/testng/xml/XmlTest.java0000755000175000017500000006104412551235562023453 0ustar eugeneeugenepackage org.testng.xml; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.UUID; import org.testng.TestNG; import org.testng.TestNGException; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.reporters.XMLStringBuffer; import org.testng.xml.dom.ParentSetter; /** * This class describes the tag <test> in testng.xml. * * @author Cedric Beust * @author Alexandru Popescu */ public class XmlTest implements Serializable, Cloneable { private static final long serialVersionUID = 6533504325942417606L; public static int DEFAULT_TIMEOUT_MS = Integer.MAX_VALUE; private XmlSuite m_suite; private String m_name; private Integer m_verbose = XmlSuite.DEFAULT_VERBOSE; private Boolean m_isJUnit = XmlSuite.DEFAULT_JUNIT; private int m_threadCount= -1; private List m_xmlClasses = Lists.newArrayList(); private List m_includedGroups = Lists.newArrayList(); private List m_excludedGroups = Lists.newArrayList(); private Map> m_metaGroups = Maps.newHashMap(); private Map m_parameters = Maps.newHashMap(); private String m_parallel; private List m_methodSelectors = Lists.newArrayList(); // test level packages private List m_xmlPackages = Lists.newArrayList(); private String m_timeOut; private Boolean m_skipFailedInvocationCounts = XmlSuite.DEFAULT_SKIP_FAILED_INVOCATION_COUNTS; private Map> m_failedInvocationNumbers = null; // lazily initialized private String m_preserveOrder = XmlSuite.DEFAULT_PRESERVE_ORDER; private int m_index; private Boolean m_groupByInstances; private Boolean m_allowReturnValues = null; private Map m_xmlDependencyGroups = Maps.newHashMap(); /** * Constructs a XmlTest and adds it to suite's list of tests. * * @param suite the parent suite. * @param index the index of this test tag in testng.xml */ public XmlTest(XmlSuite suite, int index) { init(suite, index); } public XmlTest(XmlSuite suite) { init(suite, 0); } private void init(XmlSuite suite, int index) { m_suite = suite; m_suite.getTests().add(this); m_index = index; //no two tests in the same suite should have the same name. //so, make the default test name unique m_name = TestNG.DEFAULT_COMMAND_LINE_TEST_NAME + " " + UUID.randomUUID().toString(); } // For YAML public XmlTest() { } public void setXmlPackages(List packages) { m_xmlPackages = Lists.newArrayList(packages); } public List getXmlPackages() { return m_xmlPackages; } // For YAML public List getPackages() { return getXmlPackages(); } // For YAML public void setPackages(List p) { setXmlPackages(p); } public List getMethodSelectors() { return m_methodSelectors; } public void setMethodSelectors(List methodSelectors) { m_methodSelectors = Lists.newArrayList(methodSelectors); } /** * Returns the suite this test is part of. * @return the suite this test is part of. */ public XmlSuite getSuite() { return m_suite; } /** * @return the includedGroups. * Note: do not modify the returned value, use {@link #addIncludedGroup(String)}. */ public List getIncludedGroups() { List result; if (m_xmlGroups != null) { result = m_xmlGroups.getRun().getIncludes(); result.addAll(m_suite.getIncludedGroups()); } else { // deprecated result = Lists.newArrayList(m_includedGroups); result.addAll(m_suite.getIncludedGroups()); } return result; } /** * Sets the XML Classes. * @param classes The classes to set. * @deprecated use setXmlClasses */ @Deprecated public void setClassNames(List classes) { m_xmlClasses = classes; } /** * @return Returns the classes. */ public List getXmlClasses() { return m_xmlClasses; } // For YAML public List getClasses() { return getXmlClasses(); } // For YAML public void setClasses(List c) { setXmlClasses(c); } /** * Sets the XML Classes. * @param classes The classes to set. */ public void setXmlClasses(List classes) { m_xmlClasses = classes; } /** * @return Returns the name. */ public String getName() { return m_name; } /** * @param name The name to set. */ public void setName(String name) { m_name = name; } /** * @param v */ public void setVerbose(int v) { m_verbose = v; } public int getThreadCount() { return m_threadCount > 0 ? m_threadCount : getSuite().getThreadCount(); } public void setThreadCount(int threadCount) { m_threadCount = threadCount; } /** * @param g */ public void setIncludedGroups(List g) { m_includedGroups = g; } /** * @param g The excludedGrousps to set. */ public void setExcludedGroups(List g) { m_excludedGroups = g; } /** * @return Returns the excludedGroups. * Note: do not modify the returned value, use {@link #addExcludedGroup(String)}. */ public List getExcludedGroups() { List result = new ArrayList(m_excludedGroups); result.addAll(m_suite.getExcludedGroups()); return result; } public void addIncludedGroup(String g) { m_includedGroups.add(g); } public void addExcludedGroup(String g) { m_excludedGroups.add(g); } /** * @return Returns the verbose. */ public int getVerbose() { Integer result = m_verbose; if (null == result || XmlSuite.DEFAULT_VERBOSE.equals(m_verbose)) { result = m_suite.getVerbose(); } if (null != result) { return result; } else { return 1; } } public boolean getGroupByInstances() { Boolean result = m_groupByInstances; if (result == null || XmlSuite.DEFAULT_GROUP_BY_INSTANCES.equals(m_groupByInstances)) { result = m_suite.getGroupByInstances(); } if (result != null) { return result; } else { return XmlSuite.DEFAULT_GROUP_BY_INSTANCES; } } public void setGroupByInstances(boolean f) { m_groupByInstances = f; } /** * @return Returns the isJUnit. */ public boolean isJUnit() { Boolean result = m_isJUnit; if (null == result || XmlSuite.DEFAULT_JUNIT.equals(result)) { result = m_suite.isJUnit(); } return result; } /** * @param isJUnit The isJUnit to set. */ public void setJUnit(boolean isJUnit) { m_isJUnit = isJUnit; } // For YAML public void setJunit(boolean isJUnit) { setJUnit(isJUnit); } public void setSkipFailedInvocationCounts(boolean skip) { m_skipFailedInvocationCounts = skip; } /** * @return Returns the isJUnit. */ public boolean skipFailedInvocationCounts() { Boolean result = m_skipFailedInvocationCounts; if (null == result) { result = m_suite.skipFailedInvocationCounts(); } return result; } public void addMetaGroup(String name, List metaGroup) { m_metaGroups.put(name, metaGroup); } // For YAML public void setMetaGroups(Map> metaGroups) { m_metaGroups = metaGroups; } /** * @return Returns the metaGroups. */ public Map> getMetaGroups() { if (m_xmlGroups != null) { Map> result = Maps.newHashMap(); List defines = m_xmlGroups.getDefines(); for (XmlDefine xd : defines) { result.put(xd.getName(), xd.getIncludes()); } return result; } else { // deprecated return m_metaGroups; } } /** * @param parameters */ public void setParameters(Map parameters) { m_parameters = parameters; } public void addParameter(String key, String value) { m_parameters.put(key, value); } public String getParameter(String name) { String result = m_parameters.get(name); if (null == result) { result = m_suite.getParameter(name); } return result; } /** * @return the parameters defined in this test tag and the tags above it. */ public Map getAllParameters() { Map result = Maps.newHashMap(); Map parameters = getSuite().getParameters(); for (Map.Entry parameter : parameters.entrySet()) { result.put(parameter.getKey(), parameter.getValue()); } for (String key : m_parameters.keySet()) { result.put(key, m_parameters.get(key)); } return result; } /** * @return the parameters defined in this tag, and only this test tag. To retrieve * the inherited parameters as well, call {@code getAllParameters()}. */ public Map getLocalParameters() { return m_parameters; } /** * @deprecated Use {@code getLocalParameters()} or {@code getAllParameters()} */ @Deprecated public Map getParameters() { return getAllParameters(); } /** * @return the parameters defined on this tag only */ public Map getTestParameters() { return m_parameters; } public void setParallel(String parallel) { m_parallel = parallel; } public String getParallel() { String result = null; if (null != m_parallel || XmlSuite.DEFAULT_PARALLEL.equals(m_parallel)) { result = m_parallel; } else { result = m_suite.getParallel(); } return result; } public String getTimeOut() { String result = null; if (null != m_timeOut) { result = m_timeOut; } else { result = m_suite.getTimeOut(); } return result; } public long getTimeOut(long def) { long result = def; if (getTimeOut() != null) { result = new Long(getTimeOut()); } return result; } public void setTimeOut(long timeOut) { m_timeOut = Long.toString(timeOut); } private void setTimeOut(String timeOut) { m_timeOut = timeOut; } public void setExpression(String expression) { setBeanShellExpression(expression); } public void setBeanShellExpression(String expression) { List selectors = getMethodSelectors(); if (selectors.size() > 0) { selectors.get(0).setExpression(expression); } else if (expression != null) { XmlMethodSelector xms = new XmlMethodSelector(); xms.setExpression(expression); xms.setLanguage("BeanShell"); getMethodSelectors().add(xms); } } public String getExpression() { List selectors = getMethodSelectors(); if (selectors.size() > 0) { return selectors.get(0).getExpression(); } else { return null; } } public String toXml(String indent) { XMLStringBuffer xsb = new XMLStringBuffer(indent); Properties p = new Properties(); p.setProperty("name", getName()); if (m_isJUnit != null) { XmlUtils.setProperty(p, "junit", m_isJUnit.toString(), XmlSuite.DEFAULT_JUNIT.toString()); } if (m_parallel != null) { XmlUtils.setProperty(p, "parallel", m_parallel, XmlSuite.DEFAULT_PARALLEL); } if (m_verbose != null) { XmlUtils.setProperty(p, "verbose", m_verbose.toString(), XmlSuite.DEFAULT_VERBOSE.toString()); } if (null != m_timeOut) { p.setProperty("time-out", m_timeOut.toString()); } if (m_preserveOrder != null && ! XmlSuite.DEFAULT_PRESERVE_ORDER.equals(m_preserveOrder)) { p.setProperty("preserve-order", m_preserveOrder.toString()); } if (m_threadCount != -1) { p.setProperty("thread-count", Integer.toString(m_threadCount)); } if (m_groupByInstances != null) { XmlUtils.setProperty(p, "group-by-instances", String.valueOf(getGroupByInstances()), XmlSuite.DEFAULT_GROUP_BY_INSTANCES.toString()); } xsb.push("test", p); if (null != getMethodSelectors() && !getMethodSelectors().isEmpty()) { xsb.push("method-selectors"); for (XmlMethodSelector selector: getMethodSelectors()) { xsb.getStringBuffer().append(selector.toXml(indent + " ")); } xsb.pop("method-selectors"); } XmlUtils.dumpParameters(xsb, m_parameters); // groups if (!m_metaGroups.isEmpty() || !m_includedGroups.isEmpty() || !m_excludedGroups.isEmpty() || !m_xmlDependencyGroups.isEmpty()) { xsb.push("groups"); // define for (String metaGroupName: m_metaGroups.keySet()) { Properties metaGroupProp= new Properties(); metaGroupProp.setProperty("name", metaGroupName); xsb.push("define", metaGroupProp); for (String groupName: m_metaGroups.get(metaGroupName)) { Properties includeProps = new Properties(); includeProps.setProperty("name", groupName); xsb.addEmptyElement("include", includeProps); } xsb.pop("define"); } // run if (!m_includedGroups.isEmpty() || !m_excludedGroups.isEmpty()) { xsb.push("run"); for (String includeGroupName: m_includedGroups) { Properties includeProps = new Properties(); includeProps.setProperty("name", includeGroupName); xsb.addEmptyElement("include", includeProps); } for (String excludeGroupName: m_excludedGroups) { Properties excludeProps = new Properties(); excludeProps.setProperty("name", excludeGroupName); xsb.addEmptyElement("exclude", excludeProps); } xsb.pop("run"); } // group dependencies if (m_xmlDependencyGroups != null && ! m_xmlDependencyGroups.isEmpty()) { xsb.push("dependencies"); for (Map.Entry entry : m_xmlDependencyGroups.entrySet()) { xsb.addEmptyElement("group", "name", entry.getKey(), "depends-on", entry.getValue()); } xsb.pop("dependencies"); } xsb.pop("groups"); } if (null != m_xmlPackages && !m_xmlPackages.isEmpty()) { xsb.push("packages"); for (XmlPackage pack: m_xmlPackages) { xsb.getStringBuffer().append(pack.toXml(" ")); } xsb.pop("packages"); } // classes if (null != getXmlClasses() && !getXmlClasses().isEmpty()) { xsb.push("classes"); for (XmlClass cls : getXmlClasses()) { xsb.getStringBuffer().append(cls.toXml(indent + " ")); } xsb.pop("classes"); } xsb.pop("test"); return xsb.toXML(); } @Override public String toString() { // return toXml(""); StringBuffer result = new StringBuffer("[Test: \"" + m_name + "\"") .append(" verbose:" + m_verbose); result.append("[parameters:"); for (String k : m_parameters.keySet()) { String v = m_parameters.get(k); result.append(k + "=>" + v); } result.append("]"); result.append("[metagroups:"); for (String g : m_metaGroups.keySet()) { List mg = m_metaGroups.get(g); result.append(g).append("="); for (String n : mg) { result.append(n).append(","); } } result.append("] "); result.append("[included: "); for (String g : m_includedGroups) { result.append(g).append(" "); } result.append("]"); result.append("[excluded: "); for (String g : m_excludedGroups) { result.append(g).append(""); } result.append("] "); result.append(" classes:"); for (XmlClass cl : m_xmlClasses) { result.append(cl).append(" "); } result.append(" packages:"); for (XmlPackage p : m_xmlPackages) { result.append(p).append(" "); } result.append("] "); return result.toString(); } static void ppp(String s) { System.out.println("[XmlTest] " + s); } /** * Clone the source XmlTest by including: * - test attributes * - groups definitions * - parameters * * The <classes> sub element is ignored for the moment. * * @return a clone of the current XmlTest */ @Override public Object clone() { XmlTest result = new XmlTest(getSuite()); result.setName(getName()); result.setIncludedGroups(getIncludedGroups()); result.setExcludedGroups(getExcludedGroups()); result.setJUnit(isJUnit()); result.setParallel(getParallel()); result.setVerbose(getVerbose()); result.setParameters(getLocalParameters()); result.setXmlPackages(getXmlPackages()); result.setTimeOut(getTimeOut()); Map> metagroups = getMetaGroups(); for (Map.Entry> group: metagroups.entrySet()) { result.addMetaGroup(group.getKey(), group.getValue()); } return result; } /** * Convenience method to cache the ordering numbers for methods. */ public List getInvocationNumbers(String method) { if (m_failedInvocationNumbers == null) { m_failedInvocationNumbers = Maps.newHashMap(); for (XmlClass c : getXmlClasses()) { for (XmlInclude xi : c.getIncludedMethods()) { List invocationNumbers = xi.getInvocationNumbers(); if (invocationNumbers.size() > 0) { String methodName = c.getName() + "." + xi.getName(); m_failedInvocationNumbers.put(methodName, invocationNumbers); } } } } List result = m_failedInvocationNumbers.get(method); if (result == null) { // Don't use emptyList here since this list might end up receiving values if // the test run fails. return Lists.newArrayList(); } else { return result; } } public void setPreserveOrder(String preserveOrder) { m_preserveOrder = preserveOrder; } public String getPreserveOrder() { String result = m_preserveOrder; if (result == null || XmlSuite.DEFAULT_PRESERVE_ORDER.equals(m_preserveOrder)) { result = m_suite.getPreserveOrder(); } return result; } public void setSuite(XmlSuite result) { m_suite = result; } public Boolean getAllowReturnValues() { if (m_allowReturnValues != null) return m_allowReturnValues; else return getSuite().getAllowReturnValues(); } public void setAllowReturnValues(Boolean allowReturnValues) { m_allowReturnValues = allowReturnValues; } /** * Note that this attribute does not come from the XML file, it's calculated * internally and represents the order in which this test tag was found in its * <suite> tag. It's used to calculate the ordering of the tests * when preserve-test-order is true. */ public int getIndex() { return m_index; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((m_excludedGroups == null) ? 0 : m_excludedGroups.hashCode()); result = prime * result + ((m_failedInvocationNumbers == null) ? 0 : m_failedInvocationNumbers .hashCode()); result = prime * result + ((m_includedGroups == null) ? 0 : m_includedGroups.hashCode()); result = prime * result + ((m_isJUnit == null) ? 0 : m_isJUnit.hashCode()); result = prime * result + ((m_metaGroups == null) ? 0 : m_metaGroups.hashCode()); result = prime * result + ((m_methodSelectors == null) ? 0 : m_methodSelectors.hashCode()); result = prime * result + ((m_name == null) ? 0 : m_name.hashCode()); result = prime * result + ((m_parallel == null) ? 0 : m_parallel.hashCode()); result = prime * result + ((m_parameters == null) ? 0 : m_parameters.hashCode()); result = prime * result + ((m_preserveOrder == null) ? 0 : m_preserveOrder.hashCode()); result = prime * result + ((m_skipFailedInvocationCounts == null) ? 0 : m_skipFailedInvocationCounts.hashCode()); result = prime * result + m_threadCount; result = prime * result + ((m_timeOut == null) ? 0 : m_timeOut.hashCode()); result = prime * result + ((m_verbose == null) ? 0 : m_verbose.hashCode()); result = prime * result + ((m_xmlClasses == null) ? 0 : m_xmlClasses.hashCode()); result = prime * result + ((m_xmlPackages == null) ? 0 : m_xmlPackages.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) return XmlSuite.f(); if (getClass() != obj.getClass()) return XmlSuite.f(); XmlTest other = (XmlTest) obj; if (m_excludedGroups == null) { if (other.m_excludedGroups != null) return XmlSuite.f(); } else if (!m_excludedGroups.equals(other.m_excludedGroups)) return XmlSuite.f(); // if (m_expression == null) { // if (other.m_expression != null) // return XmlSuite.f(); // } else if (!m_expression.equals(other.m_expression)) // return XmlSuite.f(); if (m_failedInvocationNumbers == null) { if (other.m_failedInvocationNumbers != null) return XmlSuite.f(); } else if (!m_failedInvocationNumbers .equals(other.m_failedInvocationNumbers)) return XmlSuite.f(); if (m_includedGroups == null) { if (other.m_includedGroups != null) return XmlSuite.f(); } else if (!m_includedGroups.equals(other.m_includedGroups)) return XmlSuite.f(); if (m_isJUnit == null) { if (other.m_isJUnit != null && ! other.m_isJUnit.equals(XmlSuite.DEFAULT_JUNIT)) return XmlSuite.f(); } else if (!m_isJUnit.equals(other.m_isJUnit)) return XmlSuite.f(); if (m_metaGroups == null) { if (other.m_metaGroups != null) return XmlSuite.f(); } else if (!m_metaGroups.equals(other.m_metaGroups)) return XmlSuite.f(); if (m_methodSelectors == null) { if (other.m_methodSelectors != null) return XmlSuite.f(); } else if (!m_methodSelectors.equals(other.m_methodSelectors)) return XmlSuite.f(); if (m_name == null) { if (other.m_name != null) return XmlSuite.f(); } else if (!m_name.equals(other.m_name)) return XmlSuite.f(); if (m_parallel == null) { if (other.m_parallel != null) return XmlSuite.f(); } else if (!m_parallel.equals(other.m_parallel)) return XmlSuite.f(); if (m_parameters == null) { if (other.m_parameters != null) return XmlSuite.f(); } else if (!m_parameters.equals(other.m_parameters)) return XmlSuite.f(); if (m_preserveOrder == null) { if (other.m_preserveOrder != null) return XmlSuite.f(); } else if (!m_preserveOrder.equals(other.m_preserveOrder)) return XmlSuite.f(); if (m_skipFailedInvocationCounts == null) { if (other.m_skipFailedInvocationCounts != null) return XmlSuite.f(); } else if (!m_skipFailedInvocationCounts .equals(other.m_skipFailedInvocationCounts)) return XmlSuite.f(); if (m_threadCount != other.m_threadCount) return XmlSuite.f(); if (m_timeOut == null) { if (other.m_timeOut != null) return XmlSuite.f(); } else if (!m_timeOut.equals(other.m_timeOut)) return XmlSuite.f(); if (m_verbose == null) { if (other.m_verbose != null) return XmlSuite.f(); } else if (!m_verbose.equals(other.m_verbose)) return XmlSuite.f(); if (m_xmlClasses == null) { if (other.m_xmlClasses != null) return XmlSuite.f(); } else if (!m_xmlClasses.equals(other.m_xmlClasses)) return XmlSuite.f(); if (m_xmlPackages == null) { if (other.m_xmlPackages != null) return XmlSuite.f(); } else if (!m_xmlPackages.equals(other.m_xmlPackages)) return XmlSuite.f(); return true; } public void addXmlDependencyGroup(String group, String dependsOn) { if (! m_xmlDependencyGroups.containsKey(group)) { m_xmlDependencyGroups.put(group, dependsOn); } else { throw new TestNGException("Duplicate group dependency found for group \"" + group + "\"" + ", use a space-separated list of groups in the \"depends-on\" attribute"); } } public Map getXmlDependencyGroups() { if (m_xmlGroups != null) { Map result = Maps.newHashMap(); List deps = m_xmlGroups.getDependencies(); for (XmlDependencies d : deps) { result.putAll(d.getDependencies()); } return result; } else { // deprecated return m_xmlDependencyGroups; } } @ParentSetter public void setXmlSuite(XmlSuite suite) { m_suite = suite; } private XmlGroups m_xmlGroups; public void setGroups(XmlGroups xmlGroups) { m_xmlGroups = xmlGroups; } } testng-testng-6.9.5/src/main/java/org/testng/xml/XmlSuite.java0000755000175000017500000007053712551235562023634 0ustar eugeneeugenepackage org.testng.xml; import java.io.Serializable; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import org.testng.ITestObjectFactory; import org.testng.TestNG; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.reporters.XMLStringBuffer; import org.testng.xml.dom.OnElement; import org.testng.xml.dom.OnElementList; import org.testng.xml.dom.Tag; import static org.testng.collections.CollectionUtils.hasElements; import static org.testng.internal.Utils.isStringNotEmpty; /** * This class describes the tag <suite> in testng.xml. * * @author Cedric Beust * @author Alexandru Popescu */ public class XmlSuite implements Serializable, Cloneable { /** Parallel modes */ public static final String PARALLEL_TESTS = "tests"; public static final String PARALLEL_METHODS = "methods"; public static final String PARALLEL_CLASSES = "classes"; public static final String PARALLEL_INSTANCES = "instances"; public static final String PARALLEL_NONE = "none"; public static Set PARALLEL_MODES = new HashSet() {{ add(PARALLEL_TESTS); add(PARALLEL_METHODS); add(PARALLEL_CLASSES); add(PARALLEL_INSTANCES); add(PARALLEL_NONE); add("true"); add("false"); }}; /** Configuration failure policy options */ public static final String SKIP = "skip"; public static final String CONTINUE = "continue"; private String m_test; /** The default suite name TODO CQ is this OK as a default name. */ private static final String DEFAULT_SUITE_NAME = "Default Suite"; /** The suite name (defaults to DEFAULT_SUITE_NAME) */ private String m_name = DEFAULT_SUITE_NAME; /** The suite verbose flag. (0 to 10)*/ public static Integer DEFAULT_VERBOSE = 1; private Integer m_verbose = null; public static String DEFAULT_PARALLEL = "false"; 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; private String m_configFailurePolicy = DEFAULT_CONFIG_FAILURE_POLICY; /** JUnit compatibility flag. */ public static Boolean DEFAULT_JUNIT = Boolean.FALSE; private Boolean m_isJUnit = DEFAULT_JUNIT; /** mixed mode flag. */ public static Boolean DEFAULT_MIXED = Boolean.FALSE; private Boolean m_isMixed = DEFAULT_MIXED; public static Boolean DEFAULT_SKIP_FAILED_INVOCATION_COUNTS = Boolean.FALSE; private Boolean m_skipFailedInvocationCounts = DEFAULT_SKIP_FAILED_INVOCATION_COUNTS; /** The thread count. */ public static Integer DEFAULT_THREAD_COUNT = 5; private int m_threadCount = DEFAULT_THREAD_COUNT; /** Thread count for the data provider pool */ public static final Integer DEFAULT_DATA_PROVIDER_THREAD_COUNT = 10; private int m_dataProviderThreadCount = DEFAULT_DATA_PROVIDER_THREAD_COUNT; /** By default, a method failing will cause all instances of that class to skip */ public static final Boolean DEFAULT_GROUP_BY_INSTANCES = false; private Boolean m_groupByInstances = DEFAULT_GROUP_BY_INSTANCES; public static Boolean DEFAULT_ALLOW_RETURN_VALUES = Boolean.FALSE; private Boolean m_allowReturnValues = DEFAULT_ALLOW_RETURN_VALUES; /** The packages containing test classes. */ private List m_xmlPackages = Lists.newArrayList(); /** BeanShell expression. */ private String m_expression = null; /** Suite level method selectors. */ private List m_methodSelectors = Lists.newArrayList(); /** Tests in suite. */ private List m_tests = Lists.newArrayList(); /** Suite level parameters. */ private Map m_parameters = Maps.newHashMap(); /** Name of the XML file */ private String m_fileName; /** Time out for methods/tests */ private String m_timeOut; /** List of child XML suite specified using tags */ private List m_childSuites = Lists.newArrayList(); /** Parent XML Suite if this suite was specified in another suite using tag */ private XmlSuite m_parentSuite; private List m_suiteFiles = Lists.newArrayList(); private ITestObjectFactory m_objectFactory; private List m_listeners = Lists.newArrayList(); private static final long serialVersionUID = 4999962288272750226L; public static String DEFAULT_PRESERVE_ORDER = "true"; private String m_preserveOrder = DEFAULT_PRESERVE_ORDER; private List m_includedGroups = Lists.newArrayList(); private List m_excludedGroups = Lists.newArrayList(); private XmlMethodSelectors m_xmlMethodSelectors; /** * @return the fileName */ public String getFileName() { return m_fileName; } /** * @param fileName the fileName to set */ public void setFileName(String fileName) { m_fileName = fileName; } /** * Returns the parallel mode. * @return the parallel mode. */ public String getParallel() { return m_parallel; } public String getParentModule() { return m_parentModule; } public String getGuiceStage() { return m_guiceStage; } public ITestObjectFactory getObjectFactory() { return m_objectFactory; } public void setObjectFactory(ITestObjectFactory objectFactory) { m_objectFactory = objectFactory; } /** * Sets the parallel mode * @param parallel the parallel mode */ public void setParallel(String parallel) { m_parallel = parallel; } public void setParentModule(String parentModule) { m_parentModule = parentModule; } public void setGuiceStage(String guiceStage) { m_guiceStage = guiceStage; } /** * Sets the configuration failure policy. * @param configFailurePolicy the config failure policy */ public void setConfigFailurePolicy(String configFailurePolicy) { m_configFailurePolicy = configFailurePolicy; } /** * Returns the configuration failure policy. * @return the configuration failure policy */ public String getConfigFailurePolicy() { return m_configFailurePolicy; } /** * Returns the verbose. * @return the verbose. */ public Integer getVerbose() { return m_verbose != null ? m_verbose : TestNG.DEFAULT_VERBOSE; } /** * Set the verbose. * @param verbose The verbose to set. */ public void setVerbose(Integer verbose) { m_verbose = verbose; } /** * Returns the name. * @return the name. */ public String getName() { return m_name; } /** * Sets the name. * @param name The name to set. */ public void setName(String name) { m_name = name; } /** * Returns the test. * @return the test. */ public String getTest() { return m_test; } /** * Returns the tests. * @return the tests. */ public List getTests() { return m_tests; } // For YAML public void setTests(List tests) { m_tests = tests; } /** * Returns the method selectors. * * @return the method selectors. */ public List getMethodSelectors() { if (m_xmlMethodSelectors != null) { return m_xmlMethodSelectors.getMethodSelectors(); } else { // deprecated return m_methodSelectors; } } /** * Sets the method selectors. * * @param methodSelectors the method selectors. */ public void setMethodSelectors(List methodSelectors) { m_methodSelectors = Lists.newArrayList(methodSelectors); } /** * Updates the list of parameters that apply to this XML suite. This method * should be invoked any time there is a change in the state of this suite that * would affect the parameter list.
* NOTE: Currently being invoked after a parent suite is added or if parameters * for this suite are updated. */ private void updateParameters() { /* * Whatever parameters are set by user or via XML, should be updated * using parameters from parent suite, if it exists. Parameters from this * suite override the same named parameters from parent suite. */ if (m_parentSuite != null) { Set keySet = m_parentSuite.getParameters().keySet(); for (String name : keySet) { if (!m_parameters.containsKey(name)) { m_parameters.put(name, m_parentSuite.getParameter(name)); } } } } /** * Sets parameters. * @param parameters the parameters. */ public void setParameters(Map parameters) { m_parameters = parameters; updateParameters(); } /** * Gets the parameters that apply to tests in this suite.
* Set of parameters for a suite is appended with parameters from parent suite. * Also, parameters from this suite override the same named parameters from * parent suite. */ public Map getParameters() { return m_parameters; } /** * @return The parameters defined in this suite and all its XmlTests. */ public Map getAllParameters() { Map result = Maps.newHashMap(); for (Map.Entry entry : m_parameters.entrySet()) { result.put(entry.getKey(), entry.getValue()); } for (XmlTest test : getTests()) { Map tp = test.getLocalParameters(); for (Map.Entry entry : tp.entrySet()) { result.put(entry.getKey(), entry.getValue()); } } return result; } /** * Returns the parameter defined in this suite only. * @param name the parameter name. * @return The parameter defined in this suite only. */ public String getParameter(String name) { return m_parameters.get(name); } /** * @return The threadCount. */ public int getThreadCount() { return m_threadCount; } /** * Set the thread count. * @param threadCount The thread count to set. */ public void setThreadCount(int threadCount) { m_threadCount = threadCount; } /** * @return The JUnit compatibility flag. */ public Boolean isJUnit() { return m_isJUnit; } /** * Sets the JUnit compatibility flag. * * @param isJUnit the JUnit compatibility flag. */ public void setJUnit(Boolean isJUnit) { m_isJUnit = isJUnit; } // For YAML public void setJunit(Boolean j) { setJUnit(j); } public Boolean skipFailedInvocationCounts() { return m_skipFailedInvocationCounts; } public void setSkipFailedInvocationCounts(boolean skip) { m_skipFailedInvocationCounts = skip; } /** * Sets the XML packages. * * @param packages the XML packages. */ public void setXmlPackages(List packages) { m_xmlPackages = Lists.newArrayList(packages); } /** * Returns the XML packages. * * @return the XML packages. */ public List getXmlPackages() { return m_xmlPackages; } // For YAML public List getPackages() { return getXmlPackages(); } @Tag(name = "method-selectors") public void setMethodSelectors(XmlMethodSelectors xms) { m_xmlMethodSelectors = xms; } // For YAML public void setPackages(List packages) { setXmlPackages(packages); } /** * @return A String representation of this XML suite. */ public String toXml() { XMLStringBuffer xsb = new XMLStringBuffer(); xsb.setDocType("suite SYSTEM \"" + Parser.TESTNG_DTD_URL + '\"'); Properties p = new Properties(); p.setProperty("name", getName()); if (getVerbose() != null) { XmlUtils.setProperty(p, "verbose", getVerbose().toString(), DEFAULT_VERBOSE.toString()); } final String parallel= getParallel(); if(isStringNotEmpty(parallel) && !DEFAULT_PARALLEL.equals(parallel)) { p.setProperty("parallel", parallel); } XmlUtils.setProperty(p, "group-by-instances", String.valueOf(getGroupByInstances()), DEFAULT_GROUP_BY_INSTANCES.toString()); XmlUtils.setProperty(p, "configfailurepolicy", getConfigFailurePolicy(), DEFAULT_CONFIG_FAILURE_POLICY); XmlUtils.setProperty(p, "thread-count", String.valueOf(getThreadCount()), DEFAULT_THREAD_COUNT.toString()); XmlUtils.setProperty(p, "data-provider-thread-count", String.valueOf(getDataProviderThreadCount()), DEFAULT_DATA_PROVIDER_THREAD_COUNT.toString()); if (! DEFAULT_JUNIT.equals(m_isJUnit)) { p.setProperty("junit", m_isJUnit != null ? m_isJUnit.toString() : "false"); // TESTNG-141 } XmlUtils.setProperty(p, "skipfailedinvocationcounts", m_skipFailedInvocationCounts.toString(), DEFAULT_SKIP_FAILED_INVOCATION_COUNTS.toString()); if(null != m_objectFactory) { p.setProperty("object-factory", m_objectFactory.getClass().getName()); } 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); XmlUtils.dumpParameters(xsb, m_parameters); if (hasElements(m_listeners)) { xsb.push("listeners"); for (String listenerName: m_listeners) { Properties listenerProps = new Properties(); listenerProps.setProperty("class-name", listenerName); xsb.addEmptyElement("listener", listenerProps); } xsb.pop("listeners"); } if (hasElements(getXmlPackages())) { xsb.push("packages"); for (XmlPackage pack : getXmlPackages()) { xsb.getStringBuffer().append(pack.toXml(" ")); } xsb.pop("packages"); } if (getXmlMethodSelectors() != null) { xsb.getStringBuffer().append(getXmlMethodSelectors().toXml(" ")); } else { // deprecated if (hasElements(getMethodSelectors())) { xsb.push("method-selectors"); for (XmlMethodSelector selector : getMethodSelectors()) { xsb.getStringBuffer().append(selector.toXml(" ")); } xsb.pop("method-selectors"); } } List suiteFiles = getSuiteFiles(); if (suiteFiles.size() > 0) { xsb.push("suite-files"); for (String sf : suiteFiles) { Properties prop = new Properties(); prop.setProperty("path", sf); xsb.addEmptyElement("suite-file", prop); } xsb.pop("suite-files"); } List included = getIncludedGroups(); List excluded = getExcludedGroups(); if (hasElements(included) || hasElements(excluded)) { xsb.push("groups"); xsb.push("run"); for (String g : included) { xsb.addEmptyElement("include", "name", g); } for (String g : excluded) { xsb.addEmptyElement("exclude", "name", g); } xsb.pop("run"); xsb.pop("groups"); } if (m_xmlGroups != null) { xsb.getStringBuffer().append(m_xmlGroups.toXml(" ")); } for (XmlTest test : getTests()) { xsb.getStringBuffer().append(test.toXml(" ")); } xsb.pop("suite"); return xsb.toXML(); } @Tag(name = "method-selectors") public void setXmlMethodSelectors(XmlMethodSelectors xms) { m_xmlMethodSelectors = xms; } private XmlMethodSelectors getXmlMethodSelectors() { return m_xmlMethodSelectors; } /** * {@inheritDoc} */ @Override public String toString() { StringBuffer result = new StringBuffer("[Suite: \"").append( m_name).append( "\" "); for (XmlTest t : m_tests) { result.append(" ").append( t.toString()).append(' '); } for (XmlMethodSelector ms : m_methodSelectors) { result.append(" methodSelector:" + ms); } result.append(']'); return result.toString(); } /** * Logs to System.out. * @param s the message to log. */ private static void ppp(String s) { System.out.println("[XmlSuite] " + s); } /** * {@inheritDoc} * Note that this is not a full clone: XmlTest children are not cloned by this * method. */ @Override public Object clone() { XmlSuite result = new XmlSuite(); result.setName(getName()); result.setListeners(getListeners()); result.setParallel(getParallel()); result.setParentModule(getParentModule()); result.setGuiceStage(getGuiceStage()); result.setConfigFailurePolicy(getConfigFailurePolicy()); result.setThreadCount(getThreadCount()); result.setDataProviderThreadCount(getDataProviderThreadCount()); result.setParameters(getAllParameters()); result.setVerbose(getVerbose()); result.setXmlPackages(getXmlPackages()); // result.setBeanShellExpression(getExpression()); result.setMethodSelectors(getMethodSelectors()); result.setJUnit(isJUnit()); // TESTNG-141 result.setSkipFailedInvocationCounts(skipFailedInvocationCounts()); result.setObjectFactory(getObjectFactory()); result.setAllowReturnValues(getAllowReturnValues()); result.setTimeOut(getTimeOut()); return result; } /** * Sets the timeout. * * @param timeOut the timeout. */ public void setTimeOut(String timeOut) { m_timeOut = timeOut; } /** * Returns the timeout. * @return the timeout. */ public String getTimeOut() { return m_timeOut; } /** * Returns the timeout as a long value specifying the default value to be used if * no timeout was specified. * * @param def the the default value to be used if no timeout was specified. * @return the timeout as a long value specifying the default value to be used if * no timeout was specified. */ public long getTimeOut(long def) { long result = def; if (m_timeOut != null) { result = new Long(m_timeOut); } return result; } /** * Sets the suite files. * * @param files the suite files. */ public void setSuiteFiles(List files) { m_suiteFiles = files; } /** * Returns the suite files. * @return the suite files. */ public List getSuiteFiles() { return m_suiteFiles; } public void setListeners(List listeners) { m_listeners = listeners; } public List getListeners() { if (m_parentSuite != null) { List listeners = m_parentSuite.getListeners(); for (String listener : listeners) { if (!m_listeners.contains(listener)) { m_listeners.add(listener); } } } return m_listeners; } public void setDataProviderThreadCount(int count) { m_dataProviderThreadCount = count; } public int getDataProviderThreadCount() { // org.testng.CommandLineArgs.DATA_PROVIDER_THREAD_COUNT String s = System.getProperty("dataproviderthreadcount"); if (s != null) { try { int nthreads = Integer.parseInt(s); return nthreads; } catch(NumberFormatException nfe) { System.err.println("Parsing System property 'dataproviderthreadcount': " + nfe); } } return m_dataProviderThreadCount; } public void setParentSuite(XmlSuite parentSuite) { m_parentSuite = parentSuite; updateParameters(); } public XmlSuite getParentSuite() { return m_parentSuite; } public List getChildSuites() { return m_childSuites; } @Override public int hashCode() { final int prime = 31; int result = 1; // result = prime * result // + ((m_childSuites == null) ? 0 : m_childSuites.hashCode()); result = prime * result + ((m_configFailurePolicy == null) ? 0 : m_configFailurePolicy .hashCode()); result = prime * result + m_dataProviderThreadCount; result = prime * result + ((m_expression == null) ? 0 : m_expression.hashCode()); result = prime * result + ((m_fileName == null) ? 0 : m_fileName.hashCode()); result = prime * result + ((m_isJUnit == null) ? 0 : m_isJUnit.hashCode()); result = prime * result + ((m_listeners == null) ? 0 : m_listeners.hashCode()); result = prime * result + ((m_methodSelectors == null) ? 0 : m_methodSelectors.hashCode()); result = prime * result + ((m_name == null) ? 0 : m_name.hashCode()); result = prime * result + ((m_objectFactory == null) ? 0 : m_objectFactory.hashCode()); result = prime * result + ((m_parallel == null) ? 0 : m_parallel.hashCode()); // result = prime * result // + ((m_parameters == null) ? 0 : m_parameters.hashCode()); // result = prime * result // + ((m_parentSuite == null) ? 0 : m_parentSuite.hashCode()); result = prime * result + ((m_skipFailedInvocationCounts == null) ? 0 : m_skipFailedInvocationCounts.hashCode()); result = prime * result + ((m_suiteFiles == null) ? 0 : m_suiteFiles.hashCode()); result = prime * result + ((m_test == null) ? 0 : m_test.hashCode()); result = prime * result + ((m_tests == null) ? 0 : m_tests.hashCode()); result = prime * result + m_threadCount; result = prime * result + ((m_timeOut == null) ? 0 : m_timeOut.hashCode()); result = prime * result + ((m_verbose == null) ? 0 : m_verbose.hashCode()); result = prime * result + ((m_xmlPackages == null) ? 0 : m_xmlPackages.hashCode()); return result; } /** * Used to debug equals() bugs. */ static boolean f() { return false; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return f(); } if (getClass() != obj.getClass()) { return f(); } XmlSuite other = (XmlSuite) obj; // if (m_childSuites == null) { // if (other.m_childSuites != null) // return f(); // } else if (!m_childSuites.equals(other.m_childSuites)) // return f(); if (m_configFailurePolicy == null) { if (other.m_configFailurePolicy != null) { return f(); } } else if (!m_configFailurePolicy.equals(other.m_configFailurePolicy)) { return f(); } if (m_dataProviderThreadCount != other.m_dataProviderThreadCount) { return f(); } if (m_expression == null) { if (other.m_expression != null) { return f(); } } else if (!m_expression.equals(other.m_expression)) { return f(); } if (m_isJUnit == null) { if (other.m_isJUnit != null) { return f(); } } else if (!m_isJUnit.equals(other.m_isJUnit)) { return f(); } if (m_listeners == null) { if (other.m_listeners != null) { return f(); } } else if (!m_listeners.equals(other.m_listeners)) { return f(); } if (m_methodSelectors == null) { if (other.m_methodSelectors != null) { return f(); } } else if (!m_methodSelectors.equals(other.m_methodSelectors)) { return f(); } if (m_name == null) { if (other.m_name != null) { return f(); } } else if (!m_name.equals(other.m_name)) { return f(); } if (m_objectFactory == null) { if (other.m_objectFactory != null) { return f(); } } else if (!m_objectFactory.equals(other.m_objectFactory)) { return f(); } if (m_parallel == null) { if (other.m_parallel != null) { return f(); } } else if (!m_parallel.equals(other.m_parallel)) { return f(); } // if (m_parameters == null) { // if (other.m_parameters != null) { // return f(); // } // } else if (!m_parameters.equals(other.m_parameters)) { // return f(); // } // if (m_parentSuite == null) { // if (other.m_parentSuite != null) // return f(); // } else if (!m_parentSuite.equals(other.m_parentSuite)) // return f(); if (m_skipFailedInvocationCounts == null) { if (other.m_skipFailedInvocationCounts != null) return f(); } else if (!m_skipFailedInvocationCounts .equals(other.m_skipFailedInvocationCounts)) return f(); if (m_suiteFiles == null) { if (other.m_suiteFiles != null) return f(); } else if (!m_suiteFiles.equals(other.m_suiteFiles)) return f(); if (m_test == null) { if (other.m_test != null) return f(); } else if (!m_test.equals(other.m_test)) return f(); if (m_tests == null) { if (other.m_tests != null) return f(); } else if (!m_tests.equals(other.m_tests)) return f(); if (m_threadCount != other.m_threadCount) return f(); if (m_timeOut == null) { if (other.m_timeOut != null) return f(); } else if (!m_timeOut.equals(other.m_timeOut)) return f(); if (m_verbose == null) { if (other.m_verbose != null) return f(); } else if (!m_verbose.equals(other.m_verbose)) return f(); if (m_xmlPackages == null) { if (other.m_xmlPackages != null) return f(); } else if (!m_xmlPackages.equals(other.m_xmlPackages)) return f(); return true; } /** * The DTD sometimes forces certain attributes to receive a default value. Such * a value is considered equal to another one if that other one is null. */ private boolean eq(String o1, String o2, String def) { boolean result = false; if (o1 == null && o2 == null) result = true; else if (o1 != null) { result = o1.equals(o2) || (def.equals(o1) && o2 == null); } else if (o2 != null) { result = o2.equals(o1) || (def.equals(o2) && o1 == null); } return result; } public void setPreserveOrder(String f) { m_preserveOrder = f; } public String getPreserveOrder() { return m_preserveOrder; } /** * @return Returns the includedGroups. * Note: do not modify the returned value, use {@link #addIncludedGroup(String)}. */ public List getIncludedGroups() { if (m_xmlGroups != null) { return m_xmlGroups.getRun().getIncludes(); } else { // deprecated return m_includedGroups; } } public void addIncludedGroup(String g) { m_includedGroups.add(g); } /** * @param g */ public void setIncludedGroups(List g) { m_includedGroups = g; } /** * @param g The excludedGrousps to set. */ public void setExcludedGroups(List g) { m_excludedGroups = g; } /** * @return Returns the excludedGroups. * Note: do not modify the returned value, use {@link #addExcludedGroup(String)}. */ public List getExcludedGroups() { if (m_xmlGroups != null) { return m_xmlGroups.getRun().getExcludes(); } else { return m_excludedGroups; } } public void addExcludedGroup(String g) { m_excludedGroups.add(g); } public Boolean getGroupByInstances() { return m_groupByInstances; } public void setGroupByInstances(boolean f) { m_groupByInstances = f; } public void addListener(String listener) { m_listeners.add(listener); } public Boolean getAllowReturnValues() { return m_allowReturnValues; } public void setAllowReturnValues(Boolean allowReturnValues) { m_allowReturnValues = allowReturnValues; } private XmlGroups m_xmlGroups; public void setGroups(XmlGroups xmlGroups) { m_xmlGroups = xmlGroups; } @OnElement(tag = "parameter", attributes = { "name", "value" }) public void onParameterElement(String name, String value) { getParameters().put(name, value); } @OnElementList(tag = "listeners", attributes = { "class-name" }) public void onListenerElement(String className) { addListener(className); } @OnElementList(tag = "suite-files", attributes = { "path" }) public void onSuiteFilesElement(String path) { getSuiteFiles().add(path); } @OnElementList(tag = "packages", attributes = { "name" }) public void onPackagesElement(String name) { getPackages().add(new XmlPackage(name)); } // @OnElementList(tag = "method-selectors", attributes = { "language", "name", "priority" }) public void onMethodSelectorElement(String language, String name, String priority) { System.out.println("Language:" + language); } public XmlGroups getGroups() { return m_xmlGroups; } public void addTest(XmlTest test) { getTests().add(test); } public Collection getPackageNames() { List result = Lists.newArrayList(); for (XmlPackage p : getPackages()) { result.add(p.getName()); } return result; } public static boolean isParallel(String parallel) { return PARALLEL_MODES.contains(parallel) && ! "false".equals(parallel); } } testng-testng-6.9.5/src/main/java/org/testng/xml/XmlScript.java0000644000175000017500000000067212551235562023775 0ustar eugeneeugenepackage org.testng.xml; import org.testng.xml.dom.TagContent; public class XmlScript { private String m_language; private String m_script; public void setLanguage(String language) { m_language = language; } @TagContent(name = "script") public void setScript(String script) { m_script = script; } public String getScript() { return m_script; } public String getLanguage() { return m_language; } } testng-testng-6.9.5/src/main/java/org/testng/xml/XmlRun.java0000644000175000017500000000232312551235562023270 0ustar eugeneeugenepackage org.testng.xml; import static org.testng.collections.CollectionUtils.hasElements; import org.testng.collections.Lists; import org.testng.reporters.XMLStringBuffer; import org.testng.xml.dom.OnElement; import java.util.List; public class XmlRun { public String toXml(String indent) { XMLStringBuffer xsb = new XMLStringBuffer(indent); boolean hasElements = hasElements(m_excludes) || hasElements(m_includes); if (hasElements) { xsb.push("run"); } for (String s : m_includes) { xsb.addEmptyElement("include", "name", s); } for (String s : m_excludes) { xsb.addEmptyElement("exclude", "name", s); } if (hasElements) { xsb.pop("run"); } return xsb.toXML(); } private List m_excludes = Lists.newArrayList(); public List getExcludes() { return m_excludes; } @OnElement(tag = "exclude", attributes = "name") public void onExclude(String name) { m_excludes.add(name); } private List m_includes = Lists.newArrayList(); public List getIncludes() { return m_includes; } @OnElement(tag = "include", attributes = "name") public void onInclude(String name) { m_includes.add(name); } } testng-testng-6.9.5/src/main/java/org/testng/xml/XmlPackage.java0000755000175000017500000001033512551235562024064 0ustar eugeneeugenepackage org.testng.xml; import java.io.IOException; import java.io.Serializable; import java.util.List; import java.util.Properties; import org.testng.collections.Lists; import org.testng.internal.PackageUtils; import org.testng.internal.Utils; import org.testng.reporters.XMLStringBuffer; /** * This class describes the tag in testng.xml. * * @author Cedric * @author Alexandru Popescu */ public class XmlPackage implements Serializable { /** * */ private static final long serialVersionUID = 1996341670354923204L; private String m_name; private List m_include = Lists.newArrayList(); private List m_exclude = Lists.newArrayList(); private List m_xmlClasses= null; public XmlPackage() { } // For YAML public XmlPackage(String name) { m_name = name; } /** * @return the exclude */ public List getExclude() { return m_exclude; } /** * @param exclude the exclude to set */ public void setExclude(List exclude) { m_exclude = exclude; } /** * @return the include */ public List getInclude() { return m_include; } /** * @param include the include to set */ public void setInclude(List include) { m_include = include; } /** * @return the name */ public String getName() { return m_name; } /** * @param name the name to set */ public void setName(String name) { m_name = name; } public List getXmlClasses() { if(null == m_xmlClasses) { m_xmlClasses= initializeXmlClasses(); } return m_xmlClasses; } private List initializeXmlClasses() { List result= Lists.newArrayList(); try { String[] classes = PackageUtils.findClassesInPackage(m_name, m_include, m_exclude); int index = 0; for(String className: classes) { result.add(new XmlClass(className, index++, false /* don't load classes */)); } } catch(IOException ioex) { Utils.log("XmlPackage", 1, ioex.getMessage()); } return result; } public String toXml(String indent) { XMLStringBuffer xsb = new XMLStringBuffer(indent); Properties p = new Properties(); p.setProperty("name", getName()); if (getInclude().isEmpty() && getExclude().isEmpty()) { xsb.addEmptyElement("package", p); } else { xsb.push("package", p); for (String m : getInclude()) { Properties includeProp= new Properties(); includeProp.setProperty("name", m); xsb.addEmptyElement("include", includeProp); } for (String m: getExclude()) { Properties excludeProp= new Properties(); excludeProp.setProperty("name", m); xsb.addEmptyElement("exclude", excludeProp); } xsb.pop("package"); } return xsb.toXML(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((m_exclude == null) ? 0 : m_exclude.hashCode()); result = prime * result + ((m_include == null) ? 0 : m_include.hashCode()); result = prime * result + ((m_name == null) ? 0 : m_name.hashCode()); result = prime * result + ((m_xmlClasses == null) ? 0 : m_xmlClasses.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return XmlSuite.f(); if (getClass() != obj.getClass()) return XmlSuite.f(); XmlPackage other = (XmlPackage) obj; if (m_exclude == null) { if (other.m_exclude != null) return XmlSuite.f(); } else if (!m_exclude.equals(other.m_exclude)) return XmlSuite.f(); if (m_include == null) { if (other.m_include != null) return XmlSuite.f(); } else if (!m_include.equals(other.m_include)) return XmlSuite.f(); if (m_name == null) { if (other.m_name != null) return XmlSuite.f(); } else if (!m_name.equals(other.m_name)) return XmlSuite.f(); if (m_xmlClasses == null) { if (other.m_xmlClasses != null) return XmlSuite.f(); } else if (!m_xmlClasses.equals(other.m_xmlClasses)) return XmlSuite.f(); return true; } } testng-testng-6.9.5/src/main/java/org/testng/xml/XmlMethodSelectors.java0000644000175000017500000000162512551235562025634 0ustar eugeneeugenepackage org.testng.xml; import static org.testng.collections.CollectionUtils.hasElements; import org.testng.collections.Lists; import org.testng.reporters.XMLStringBuffer; import java.util.List; public class XmlMethodSelectors { private List m_methodSelectors = Lists.newArrayList(); public XmlMethodSelectors() { } public List getMethodSelectors() { return m_methodSelectors; } public void setMethodSelector(XmlMethodSelector xms) { m_methodSelectors.add(xms); } public String toXml(String indent) { XMLStringBuffer xsb = new XMLStringBuffer(indent); if (hasElements(m_methodSelectors)) { xsb.push("method-selectors"); for (XmlMethodSelector selector : m_methodSelectors) { xsb.getStringBuffer().append(selector.toXml(indent + " ")); } xsb.pop("method-selectors"); } return xsb.toXML(); } } testng-testng-6.9.5/src/main/java/org/testng/xml/XmlMethodSelector.java0000755000175000017500000000775412551235562025465 0ustar eugeneeugenepackage org.testng.xml; import org.testng.TestNGException; import org.testng.reporters.XMLStringBuffer; import org.testng.xml.dom.OnElement; import java.util.Properties; /** * This class describes the tag in testng.xml. * * Created on Sep 26, 2005 * @author cbeust * @author Alexandru Popescu */ public class XmlMethodSelector { // Either this: private String m_className; private int m_priority; // Or that: private XmlScript m_script = new XmlScript(); // For YAML public void setClassName(String s) { m_className = s; } public String getClassName() { return m_className; } // For YAML @OnElement(tag = "selector-class", attributes = { "name", "priority" }) public void setElement(String name, String priority) { setName(name); setPriority(Integer.parseInt(priority)); } public void setName(String name) { m_className = name; } public void setScript(XmlScript script) { m_script = script; } /** * @return Returns the expression. */ public String getExpression() { return m_script.getScript(); } /** * @param expression The expression to set. */ public void setExpression(String expression) { m_script.setScript(expression); } /** * @return Returns the language. */ public String getLanguage() { return m_script.getLanguage(); } /** * @param language The language to set. */ // @OnElement(tag = "script", attributes = "language") public void setLanguage(String language) { m_script.setLanguage(language); // m_language = language; } public int getPriority() { return m_priority; } public void setPriority(int priority) { m_priority = priority; } private void ppp(String s) { System.out.println("[XmlMethodSelector] " + s); } public String toXml(String indent) { XMLStringBuffer xsb = new XMLStringBuffer(indent); xsb.push("method-selector"); if (null != m_className) { Properties clsProp = new Properties(); clsProp.setProperty("name", getClassName()); if(getPriority() != -1) { clsProp.setProperty("priority", String.valueOf(getPriority())); } xsb.addEmptyElement("selector-class", clsProp); } else if (getLanguage() != null) { Properties scriptProp = new Properties(); scriptProp.setProperty("language", getLanguage()); xsb.push("script", scriptProp); xsb.addCDATA(getExpression()); xsb.pop("script"); } else { throw new TestNGException("Invalid Method Selector: found neither class name nor language"); } xsb.pop("method-selector"); return xsb.toXML(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((m_className == null) ? 0 : m_className.hashCode()); result = prime * result + ((getExpression() == null) ? 0 : getExpression().hashCode()); result = prime * result + ((getLanguage() == null) ? 0 : getLanguage().hashCode()); result = prime * result + m_priority; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return XmlSuite.f(); if (getClass() != obj.getClass()) return XmlSuite.f(); XmlMethodSelector other = (XmlMethodSelector) obj; if (m_className == null) { if (other.m_className != null) return XmlSuite.f(); } else if (!m_className.equals(other.m_className)) return XmlSuite.f(); if (getExpression() == null) { if (other.getExpression() != null) return XmlSuite.f(); } else if (!getExpression().equals(other.getExpression())) return XmlSuite.f(); if (getLanguage() == null) { if (other.getLanguage() != null) return XmlSuite.f(); } else if (!getLanguage().equals(other.getLanguage())) return XmlSuite.f(); if (m_priority != other.m_priority) return XmlSuite.f(); return true; } } testng-testng-6.9.5/src/main/java/org/testng/xml/XmlInclude.java0000644000175000017500000001022212551235562024104 0ustar eugeneeugenepackage org.testng.xml; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.reporters.XMLStringBuffer; import java.io.Serializable; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Properties; public class XmlInclude implements Serializable { private static final long serialVersionUID = 1L; private String m_name; private List m_invocationNumbers = Lists.newArrayList(); private int m_index; private String m_description; private Map m_parameters = Maps.newHashMap(); private XmlClass m_xmlClass; public XmlInclude() { } public XmlInclude(String n) { this(n, Collections. emptyList(), 0); } public XmlInclude(String n, int index) { this(n, Collections. emptyList(), index); } public XmlInclude(String n, List list, int index) { m_name = n; m_invocationNumbers = list; m_index = index; } public void setDescription(String description) { m_description = description; } public String getDescription() { return m_description; } public String getName() { return m_name; } public List getInvocationNumbers() { return m_invocationNumbers; } public int getIndex() { return m_index; } public String toXml(String indent) { XMLStringBuffer xsb = new XMLStringBuffer(indent); Properties p = new Properties(); p.setProperty("name", getName()); List invocationNumbers = getInvocationNumbers(); if (invocationNumbers != null && invocationNumbers.size() > 0) { p.setProperty("invocation-numbers", XmlClass.listToString(invocationNumbers).toString()); } if (!m_parameters.isEmpty()){ xsb.push("include", p); XmlUtils.dumpParameters(xsb, m_parameters); xsb.pop("include"); } else { xsb.addEmptyElement("include", p); } return xsb.toXML(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + m_index; result = prime * result + ((m_invocationNumbers == null) ? 0 : m_invocationNumbers.hashCode()); result = prime * result + (m_parameters == null ? 0 : m_parameters.hashCode()); result = prime * result + ((m_name == null) ? 0 : m_name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return XmlSuite.f(); if (getClass() != obj.getClass()) return XmlSuite.f(); XmlInclude other = (XmlInclude) obj; // if (m_index != other.m_index) // return XmlSuite.f(); if (m_invocationNumbers == null) { if (other.m_invocationNumbers != null) return XmlSuite.f(); } else if (!m_invocationNumbers.equals(other.m_invocationNumbers)) return XmlSuite.f(); if (m_name == null) { if (other.m_name != null) return XmlSuite.f(); } else if (!m_name.equals(other.m_name)) return XmlSuite.f(); if (m_parameters == null) { if (other.m_parameters != null) { return XmlSuite.f(); } } else if (!m_parameters.equals(other.m_parameters)) { return XmlSuite.f(); } return true; } public void addParameter(String name, String value) { m_parameters.put(name, value); } /** * @deprecated Use {@code getLocalParameters()} or {@code getAllParameters()} */ @Deprecated public Map getParameters() { return getAllParameters(); } /** * @return the parameters defined in this test tag, and only this test tag. To retrieve * the inherited parameters as well, call {@code getAllParameters()}. */ public Map getLocalParameters() { return m_parameters; } /** * @return the parameters defined in this tag and the tags above it. */ public Map getAllParameters() { Map result = Maps.newHashMap(); if (m_xmlClass != null) { result.putAll(m_xmlClass.getAllParameters()); } result.putAll(m_parameters); return result; } public void setXmlClass(XmlClass xmlClass) { m_xmlClass = xmlClass; } } testng-testng-6.9.5/src/main/java/org/testng/xml/XmlGroups.java0000644000175000017500000000331512551235562024005 0ustar eugeneeugenepackage org.testng.xml; import java.util.List; import org.testng.collections.Lists; import org.testng.reporters.XMLStringBuffer; import org.testng.xml.dom.Tag; import static org.testng.collections.CollectionUtils.hasElements; public class XmlGroups { private List m_defines = Lists.newArrayList(); private XmlRun m_run; private List m_dependencies = Lists.newArrayList(); public List getDefines() { return m_defines; } @Tag(name = "define") public void addDefine(XmlDefine define) { getDefines().add(define); } public void setDefines(List defines) { m_defines = defines; } public XmlRun getRun() { return m_run; } public void setRun(XmlRun run) { m_run = run; } public List getDependencies() { return m_dependencies; } // public void setDependencies(List dependencies) { // m_dependencies = dependencies; // } @Tag(name = "dependencies") public void setXmlDependencies(XmlDependencies dependencies) { m_dependencies.add(dependencies); } public String toXml(String indent) { XMLStringBuffer xsb = new XMLStringBuffer(indent); String indent2 = indent + " "; boolean hasGroups = hasElements(m_defines) || m_run != null || hasElements(m_dependencies); if (hasGroups) { xsb.push("groups"); } for (XmlDefine d : m_defines) { xsb.getStringBuffer().append(d.toXml(indent2)); } xsb.getStringBuffer().append(m_run.toXml(indent2)); for (XmlDependencies d : m_dependencies) { xsb.getStringBuffer().append(d.toXml(indent2)); } if (hasGroups) { xsb.pop("groups"); } return xsb.toXML(); } } testng-testng-6.9.5/src/main/java/org/testng/xml/XmlDependencies.java0000644000175000017500000000210312551235562025106 0ustar eugeneeugenepackage org.testng.xml; import java.util.Map; import org.testng.collections.Maps; import org.testng.reporters.XMLStringBuffer; import org.testng.xml.dom.OnElement; import static org.testng.collections.CollectionUtils.hasElements; public class XmlDependencies { private Map m_xmlDependencyGroups = Maps.newHashMap(); @OnElement(tag = "group", attributes = { "name", "depends-on" }) public void onGroup(String name, String dependsOn) { m_xmlDependencyGroups.put(name, dependsOn); } public Map getDependencies() { return m_xmlDependencyGroups; } public String toXml(String indent) { XMLStringBuffer xsb = new XMLStringBuffer(indent); boolean hasElements = hasElements(m_xmlDependencyGroups); if (hasElements) { xsb.push("dependencies"); } for (Map.Entry entry : m_xmlDependencyGroups.entrySet()) { xsb.addEmptyElement("include", "name", entry.getKey(), "depends-on", entry.getValue()); } if (hasElements) { xsb.pop("dependencies"); } return xsb.toXML(); } } testng-testng-6.9.5/src/main/java/org/testng/xml/XmlDefine.java0000644000175000017500000000201512551235562023714 0ustar eugeneeugenepackage org.testng.xml; import static org.testng.collections.CollectionUtils.hasElements; import org.testng.collections.Lists; import org.testng.reporters.XMLStringBuffer; import org.testng.xml.dom.OnElement; import java.util.List; public class XmlDefine { private String m_name; public void setName(String name) { m_name = name; } public String getName() { return m_name; } public String toXml(String indent) { XMLStringBuffer xsb = new XMLStringBuffer(indent); boolean hasElements = hasElements(m_includes); if (hasElements) { xsb.push("define", "name", m_name); } for (String s : m_includes) { xsb.addEmptyElement("include", "name", s); } if (hasElements) { xsb.pop("define"); } return xsb.toXML(); } private List m_includes = Lists.newArrayList(); @OnElement(tag = "include", attributes = "name") public void onElement(String name) { m_includes.add(name); } public List getIncludes() { return m_includes; } } testng-testng-6.9.5/src/main/java/org/testng/xml/XmlClass.java0000755000175000017500000002001012551235562023565 0ustar eugeneeugenepackage org.testng.xml; import org.testng.TestNGException; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.collections.Objects; import org.testng.internal.ClassHelper; import org.testng.reporters.XMLStringBuffer; import java.io.Serializable; import java.util.List; import java.util.Map; import java.util.Properties; /** * This class describes the tag in testng.xml. * * @author Cedric Beust */ public class XmlClass implements Serializable, Cloneable { private static final long serialVersionUID = 8885360896966149897L; private List m_includedMethods = Lists.newArrayList(); private List m_excludedMethods = Lists.newArrayList(); private String m_name = null; private Class m_class = null; /** The index of this class in the tag */ private int m_index; /** True if the classes need to be loaded */ private boolean m_loadClasses = true; private Map m_parameters = Maps.newHashMap(); private XmlTest m_xmlTest; public XmlClass() { init("", null, 0, false /* load classes */); } public XmlClass(String name) { init(name, null, 0); } public XmlClass(String name, boolean loadClasses) { init(name, null, 0, loadClasses); } public XmlClass(Class cls) { init(cls.getName(), cls, 0, true); } public XmlClass(Class cls, boolean loadClasses) { init(cls.getName(), cls, 0, loadClasses); } public XmlClass(String className, int index) { init(className, null, index, true /* load classes */); } public XmlClass(String className, int index, boolean loadClasses) { init(className, null, index, loadClasses); } private void init(String className, Class cls, int index) { init(className, cls, index, true /* load classes */); } private void init(String className, Class cls, int index, boolean resolveClass) { m_name = className; m_class = cls; m_index = index; if (null == m_class && resolveClass) { loadClass(); } } private void loadClass() { m_class = ClassHelper.forName(m_name); if (null == m_class) { throw new TestNGException("Cannot find class in classpath: " + m_name); } } /** * @return Returns the className. */ public Class getSupportClass() { if (m_class == null) loadClass(); return m_class; } /** * @param className The className to set. */ public void setClass(Class className) { m_class = className; } /** * @return Returns the excludedMethods. */ public List getExcludedMethods() { return m_excludedMethods; } /** * @param excludedMethods The excludedMethods to set. */ public void setExcludedMethods(List excludedMethods) { m_excludedMethods = excludedMethods; } /** * @return Returns the includedMethods. */ public List getIncludedMethods() { return m_includedMethods; } /** * @param includedMethods The includedMethods to set. */ public void setIncludedMethods(List includedMethods) { m_includedMethods = includedMethods; } /** * @return Returns the name. */ public String getName() { return m_name; } /** * @param name The name to set. */ public void setName(String name) { m_name = name; } /** * @return true if the classes need to be loaded. */ public boolean loadClasses() { return m_loadClasses; } @Override public String toString() { return Objects.toStringHelper(getClass()) .add("class", m_name) .toString(); } public String toXml(String indent) { XMLStringBuffer xsb = new XMLStringBuffer(indent); Properties prop = new Properties(); prop.setProperty("name", getName()); boolean hasMethods = !m_includedMethods.isEmpty() || !m_excludedMethods.isEmpty(); boolean hasParameters = !m_parameters.isEmpty(); if (hasParameters || hasMethods) { xsb.push("class", prop); XmlUtils.dumpParameters(xsb, m_parameters); if (hasMethods) { xsb.push("methods"); for (XmlInclude m : getIncludedMethods()) { xsb.getStringBuffer().append(m.toXml(indent + " ")); } for (String m: getExcludedMethods()) { Properties p= new Properties(); p.setProperty("name", m); xsb.addEmptyElement("exclude", p); } xsb.pop("methods"); } xsb.pop("class"); } else { xsb.addEmptyElement("class", prop); } return xsb.toXML(); } public static String listToString(List invocationNumbers) { StringBuilder result = new StringBuilder(); int i = 0; for (Integer n : invocationNumbers) { if (i++ > 0) { result.append(" "); } result.append(n); } return result.toString(); } /** * Clone an XmlClass by copying all its components. */ @Override public Object clone() { XmlClass result = new XmlClass(getName(), getIndex(), loadClasses()); result.setExcludedMethods(getExcludedMethods()); result.setIncludedMethods(getIncludedMethods()); return result; } /** * Note that this attribute does not come from the XML file, it's calculated * internally and represents the order in which this class was found in its * <test> tag. It's used to calculate the ordering of the classes * when preserve-order is true. */ public int getIndex() { return m_index; } public void setIndex(int index) { m_index = index; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((m_class == null) ? 0 : m_class.hashCode()); result = prime * result + (m_loadClasses ? 1 : 0); result = prime * result + ((m_excludedMethods == null) ? 0 : m_excludedMethods.hashCode()); result = prime * result + ((m_includedMethods == null) ? 0 : m_includedMethods.hashCode()); result = prime * result + m_index; result = prime * result + ((m_name == null) ? 0 : m_name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) return XmlSuite.f(); if (getClass() != obj.getClass()) return XmlSuite.f(); XmlClass other = (XmlClass) obj; if (other.m_loadClasses != m_loadClasses) { return XmlSuite.f(); } else if (!m_excludedMethods.equals(other.m_excludedMethods)) { return XmlSuite.f(); } if (m_includedMethods == null) { if (other.m_includedMethods != null) return XmlSuite.f(); } else if (!m_includedMethods.equals(other.m_includedMethods)) return XmlSuite.f(); // if (m_index != other.m_index) // return XmlSuite.f(); if (m_name == null) { if (other.m_name != null) return XmlSuite.f(); } else if (!m_name.equals(other.m_name)) return XmlSuite.f(); return true; } public void setParameters(Map parameters) { m_parameters.clear(); m_parameters.putAll(parameters); } /** * @return The parameters defined in this test tag and the tags above it. */ public Map getAllParameters() { Map result = Maps.newHashMap(); Map parameters = m_xmlTest.getLocalParameters(); for (Map.Entry parameter : parameters.entrySet()) { result.put(parameter.getKey(), parameter.getValue()); } for (String key : m_parameters.keySet()) { result.put(key, m_parameters.get(key)); } return result; } /** * @return The parameters defined in this tag, and only this test tag. To retrieve * the inherited parameters as well, call {@code getAllParameters()}. */ public Map getLocalParameters() { return m_parameters; } /** * @deprecated Use {@code getLocalParameters()} or {@code getAllParameters()} */ @Deprecated public Map getParameters() { return getAllParameters(); } public void setXmlTest(XmlTest test) { m_xmlTest = test; } } testng-testng-6.9.5/src/main/java/org/testng/xml/XMLParser.java0000644000175000017500000000675612551235562023676 0ustar eugeneeugenepackage org.testng.xml; import java.io.IOException; import java.io.InputStream; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.testng.TestNGException; import org.testng.internal.ClassHelper; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; abstract public class XMLParser implements IFileParser { private final static SAXParser m_saxParser; static { SAXParserFactory spf = loadSAXParserFactory(); if (supportsValidation(spf)) { spf.setValidating(true); } SAXParser parser = null; try { parser = spf.newSAXParser(); } catch (ParserConfigurationException | SAXException e) { e.printStackTrace(); } m_saxParser = parser; } public void parse(InputStream is, DefaultHandler dh) throws SAXException, IOException { synchronized (m_saxParser) { m_saxParser.parse(is, dh); } } /** * Tries to load a SAXParserFactory by trying in order the following: * com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl (SUN JDK5) * org.apache.crimson.jaxp.SAXParserFactoryImpl (SUN JDK1.4) and * last SAXParserFactory.newInstance(). * * @return a SAXParserFactory implementation * @throws TestNGException thrown if no SAXParserFactory can be loaded */ private static SAXParserFactory loadSAXParserFactory() { SAXParserFactory spf = null; StringBuffer errorLog= new StringBuffer(); try { Class factoryClass= ClassHelper.forName("com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"); spf = (SAXParserFactory) factoryClass.newInstance(); } catch(Exception ex) { errorLog.append("JDK5 SAXParserFactory cannot be loaded: " + ex.getMessage()); } if(null == spf) { // If running with JDK 1.4 try { Class factoryClass = ClassHelper.forName("org.apache.crimson.jaxp.SAXParserFactoryImpl"); spf = (SAXParserFactory) factoryClass.newInstance(); } catch(Exception ex) { errorLog.append("\n").append("JDK1.4 SAXParserFactory cannot be loaded: " + ex.getMessage()); } } Throwable cause= null; if(null == spf) { try { spf= SAXParserFactory.newInstance(); } catch(FactoryConfigurationError fcerr) { cause= fcerr; } } if(null == spf) { throw new TestNGException("Cannot initialize a SAXParserFactory\n" + errorLog.toString(), cause); } return spf; } /** * Tests if the current SAXParserFactory supports DTD validation. */ private static boolean supportsValidation(SAXParserFactory spf) { try { return spf.getFeature("http://xml.org/sax/features/validation"); } catch(Exception ex) { ; } return false; } // private static void ppp(String s) { // System.out.println("[Parser] " + s); // } // /** // * // * @param argv ignored // * @throws FileNotFoundException if the // * @throws ParserConfigurationException // * @throws SAXException // * @throws IOException // * @since 1.0 // */ // public static void main(String[] argv) // throws FileNotFoundException, ParserConfigurationException, SAXException, IOException // { // XmlSuite l = // new Parser("c:/eclipse-workspace/testng/test/testng.xml").parse(); // // System.out.println(l); // } @Override } testng-testng-6.9.5/src/main/java/org/testng/xml/TestNGContentHandler.java0000755000175000017500000006044612551235562026055 0ustar eugeneeugenepackage org.testng.xml; import static org.testng.internal.Utils.isStringBlank; import org.testng.ITestObjectFactory; import org.testng.TestNGException; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.internal.Utils; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.DefaultHandler; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Stack; /** * Suite definition parser utility. * * @author Cedric Beust * @author Alexandru Popescu */ public class TestNGContentHandler extends DefaultHandler { private XmlSuite m_currentSuite = null; private XmlTest m_currentTest = null; private List m_currentDefines = null; private List m_currentRuns = null; private List m_currentClasses = null; private int m_currentTestIndex = 0; private int m_currentClassIndex = 0; private int m_currentIncludeIndex = 0; private List m_currentPackages = null; private XmlPackage m_currentPackage = null; private List m_suites = Lists.newArrayList(); private List m_currentIncludedGroups = null; private List m_currentExcludedGroups = null; private Map m_currentTestParameters = null; private Map m_currentSuiteParameters = null; private Map m_currentClassParameters = null; private Include m_currentInclude; private List m_currentMetaGroup = null; private String m_currentMetaGroupName; enum Location { SUITE, TEST, CLASS, INCLUDE, EXCLUDE } private Stack m_locations = new Stack<>(); private XmlClass m_currentClass = null; private ArrayList m_currentIncludedMethods = null; private List m_currentExcludedMethods = null; private ArrayList m_currentSelectors = null; private XmlMethodSelector m_currentSelector = null; private String m_currentLanguage = null; private String m_currentExpression = null; private List m_suiteFiles = Lists.newArrayList(); private boolean m_enabledTest; private List m_listeners; private String m_fileName; private boolean m_loadClasses; public TestNGContentHandler(String fileName, boolean loadClasses) { m_fileName = fileName; m_loadClasses = loadClasses; } static private void ppp(String s) { System.out.println("[TestNGContentHandler] " + s); } /* * (non-Javadoc) * * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String, * java.lang.String) */ @Override public InputSource resolveEntity(String systemId, String publicId) throws IOException, SAXException { InputSource result = null; if (Parser.DEPRECATED_TESTNG_DTD_URL.equals(publicId) || Parser.TESTNG_DTD_URL.equals(publicId)) { InputStream is = getClass().getClassLoader().getResourceAsStream(Parser.TESTNG_DTD); if (null == is) { is = Thread.currentThread().getContextClassLoader().getResourceAsStream(Parser.TESTNG_DTD); if (null == is) { System.out.println("WARNING: couldn't find in classpath " + publicId + "\n" + "Fetching it from the Web site."); result = super.resolveEntity(systemId, publicId); } else { result = new InputSource(is); } } else { result = new InputSource(is); } } else { result = super.resolveEntity(systemId, publicId); } return result; } /** * Parse */ private void xmlSuiteFile(boolean start, Attributes attributes) { if (start) { String path = attributes.getValue("path"); pushLocation(Location.SUITE); m_suiteFiles.add(path); } else { m_currentSuite.setSuiteFiles(m_suiteFiles); popLocation(Location.SUITE); } } /** * Parse */ private void xmlSuite(boolean start, Attributes attributes) { if (start) { pushLocation(Location.SUITE); String name = attributes.getValue("name"); if (isStringBlank(name)) { throw new TestNGException("The tag must define the name attribute"); } m_currentSuite = new XmlSuite(); m_currentSuite.setFileName(m_fileName); m_currentSuite.setName(name); m_currentSuiteParameters = Maps.newHashMap(); String verbose = attributes.getValue("verbose"); if (null != verbose) { m_currentSuite.setVerbose(new Integer(verbose)); } String jUnit = attributes.getValue("junit"); if (null != jUnit) { m_currentSuite.setJUnit(Boolean.valueOf(jUnit)); } String parallel = attributes.getValue("parallel"); if (parallel != null) { if (isValidParallel(parallel)) { m_currentSuite.setParallel(parallel); } else { Utils.log("Parser", 1, "[WARN] Unknown value of attribute 'parallel' at suite level: '" + parallel + "'."); } } String parentModule = attributes.getValue("parent-module"); 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)) { m_currentSuite.setConfigFailurePolicy(configFailurePolicy); } } String groupByInstances = attributes.getValue("group-by-instances"); if (groupByInstances!= null) { m_currentSuite.setGroupByInstances(Boolean.valueOf(groupByInstances)); } String skip = attributes.getValue("skipfailedinvocationcounts"); if (skip != null) { m_currentSuite.setSkipFailedInvocationCounts(Boolean.valueOf(skip)); } String threadCount = attributes.getValue("thread-count"); if (null != threadCount) { m_currentSuite.setThreadCount(Integer.parseInt(threadCount)); } String dataProviderThreadCount = attributes.getValue("data-provider-thread-count"); if (null != dataProviderThreadCount) { m_currentSuite.setDataProviderThreadCount(Integer.parseInt(dataProviderThreadCount)); } String timeOut = attributes.getValue("time-out"); if (null != timeOut) { m_currentSuite.setTimeOut(timeOut); } String objectFactory = attributes.getValue("object-factory"); if (null != objectFactory && m_loadClasses) { try { m_currentSuite.setObjectFactory((ITestObjectFactory)Class.forName(objectFactory).newInstance()); } catch(Exception e) { Utils.log("Parser", 1, "[ERROR] Unable to create custom object factory '" + objectFactory + "' :" + e); } } String preserveOrder = attributes.getValue("preserve-order"); if (preserveOrder != null) { m_currentSuite.setPreserveOrder(preserveOrder); } String allowReturnValues = attributes.getValue("allow-return-values"); if (allowReturnValues != null) { m_currentSuite.setAllowReturnValues(Boolean.valueOf(allowReturnValues)); } } else { m_currentSuite.setParameters(m_currentSuiteParameters); m_suites.add(m_currentSuite); m_currentSuiteParameters = null; popLocation(Location.SUITE); } } /** * Parse */ private void xmlDefine(boolean start, Attributes attributes) { if (start) { String name = attributes.getValue("name"); m_currentDefines = Lists.newArrayList(); m_currentMetaGroup = Lists.newArrayList(); m_currentMetaGroupName = name; } else { m_currentTest.addMetaGroup(m_currentMetaGroupName, m_currentMetaGroup); m_currentDefines = null; } } /** * Parse \n" + "\n"; public static void generateLog(ITestContext testContext, String host, String outputDirectory, Collection failedConfs, Collection skippedConfs, Collection passedTests, Collection failedTests, Collection skippedTests, Collection percentageTests) { StringBuffer sb = new StringBuffer(); sb.append("\n\n") .append("TestNG: ").append(testContext.getName()).append("\n") .append(HtmlHelper.getCssString()) .append(HEAD) .append("\n") .append("\n"); Date startDate = testContext.getStartDate(); Date endDate = testContext.getEndDate(); long duration = (endDate.getTime() - startDate.getTime()) / 1000; int passed = testContext.getPassedTests().size() + testContext.getFailedButWithinSuccessPercentageTests().size(); int failed = testContext.getFailedTests().size(); int skipped = testContext.getSkippedTests().size(); String hostLine = Utils.isStringEmpty(host) ? "" : "
\n"; sb .append("

").append(testContext.getName()).append("

") .append("
Remote host:" + host + "
\n") .append("\n") // .append("\n") // .append("\n") .append("\n") .append("\n") .append("\n") .append("\n") .append(hostLine) .append("\n") .append("\n") .append("\n") .append("\n") .append("\n") .append("\n") .append("
Property file:").append(m_testRunner.getPropertyFileName()).append("
Tests passed/Failed/Skipped:").append(passed).append("/").append(failed).append("/").append(skipped).append("
Started on:").append(testContext.getStartDate().toString()).append("
Total time:").append(duration).append(" seconds (").append(endDate.getTime() - startDate.getTime()) .append(" ms)
Included groups:").append(arrayToString(testContext.getIncludedGroups())).append("
Excluded groups:").append(arrayToString(testContext.getExcludedGroups())).append("

\n") ; sb.append("(Hover the method name to see the test class name)

\n"); if (failedConfs.size() > 0) { generateTable(sb, "FAILED CONFIGURATIONS", failedConfs, "failed", CONFIGURATION_COMPARATOR); } if (skippedConfs.size() > 0) { generateTable(sb, "SKIPPED CONFIGURATIONS", skippedConfs, "skipped", CONFIGURATION_COMPARATOR); } if (failedTests.size() > 0) { generateTable(sb, "FAILED TESTS", failedTests, "failed", NAME_COMPARATOR); } if (percentageTests.size() > 0) { generateTable(sb, "FAILED TESTS BUT WITHIN SUCCESS PERCENTAGE", percentageTests, "percent", NAME_COMPARATOR); } if (passedTests.size() > 0) { generateTable(sb, "PASSED TESTS", passedTests, "passed", NAME_COMPARATOR); } if (skippedTests.size() > 0) { generateTable(sb, "SKIPPED TESTS", skippedTests, "skipped", NAME_COMPARATOR); } sb.append("\n"); Utils.writeFile(outputDirectory, getOutputFile(testContext), sb.toString()); } private static void ppp(String s) { System.out.println("[TestHTMLReporter] " + s); } private static class NameComparator implements Comparator, Serializable { private static final long serialVersionUID = 381775815838366907L; public int compare(ITestResult o1, ITestResult o2) { String c1 = o1.getMethod().getMethodName(); String c2 = o2.getMethod().getMethodName(); return c1.compareTo(c2); } } private static class ConfigurationComparator implements Comparator, Serializable { private static final long serialVersionUID = 5558550850685483455L; public int compare(ITestResult o1, ITestResult o2) { ITestNGMethod tm1= o1.getMethod(); ITestNGMethod tm2= o2.getMethod(); return annotationValue(tm2) - annotationValue(tm1); } private static int annotationValue(ITestNGMethod method) { if(method.isBeforeSuiteConfiguration()) { return 10; } if(method.isBeforeTestConfiguration()) { return 9; } if(method.isBeforeClassConfiguration()) { return 8; } if(method.isBeforeGroupsConfiguration()) { return 7; } if(method.isBeforeMethodConfiguration()) { return 6; } if(method.isAfterMethodConfiguration()) { return 5; } if(method.isAfterGroupsConfiguration()) { return 4; } if(method.isAfterClassConfiguration()) { return 3; } if(method.isAfterTestConfiguration()) { return 2; } if(method.isAfterSuiteConfiguration()) { return 1; } return 0; } } } testng-testng-6.9.5/src/main/java/org/testng/reporters/SuiteHTMLReporter.java0000755000175000017500000006455012551235562026606 0ustar eugeneeugenepackage org.testng.reporters; import static org.testng.internal.Utils.isStringNotEmpty; import org.testng.IInvokedMethod; import org.testng.IReporter; import org.testng.ISuite; import org.testng.ISuiteResult; import org.testng.ITestClass; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.Reporter; import org.testng.collections.Maps; import org.testng.internal.Utils; import org.testng.xml.XmlSuite; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; /** * This class implements an HTML reporter for suites. * * @author cbeust * @author Alexandru Popescu */ public class SuiteHTMLReporter implements IReporter { public static final String METHODS_CHRONOLOGICAL = "methods.html"; public static final String METHODS_ALPHABETICAL = "methods-alphabetical.html"; public static final String GROUPS = "groups.html"; public static final String CLASSES = "classes.html"; public static final String REPORTER_OUTPUT = "reporter-output.html"; public static final String METHODS_NOT_RUN = "methods-not-run.html"; public static final String TESTNG_XML = "testng.xml.html"; private Map m_classes = Maps.newHashMap(); private String m_outputDirectory; @Override public void generateReport(List xmlSuites, List suites, String outputDirectory) { m_outputDirectory = generateOutputDirectoryName(outputDirectory + File.separator + "old"); try { HtmlHelper.generateStylesheet(outputDirectory); } catch (IOException e) { // TODO Propagate the exception properly. e.printStackTrace(); } for (ISuite suite : suites) { // // Generate the various reports // XmlSuite xmlSuite = suite.getXmlSuite(); if (xmlSuite.getTests().size() == 0) { continue; } generateTableOfContents(xmlSuite, suite); generateSuites(xmlSuite, suite); generateIndex(xmlSuite, suite); generateMain(xmlSuite, suite); generateMethodsAndGroups(xmlSuite, suite); generateMethodsChronologically(xmlSuite, suite, METHODS_CHRONOLOGICAL, false); generateMethodsChronologically(xmlSuite, suite, METHODS_ALPHABETICAL, true); generateClasses(xmlSuite, suite); generateReporterOutput(xmlSuite, suite); generateExcludedMethodsReport(xmlSuite, suite); generateXmlFile(xmlSuite, suite); } generateIndex(suites); } /** * Overridable by subclasses to create different directory names (e.g. with timestamps). * @param outputDirectory the output directory specified by the user */ protected String generateOutputDirectoryName(String outputDirectory) { return outputDirectory; } private void generateXmlFile(XmlSuite xmlSuite, ISuite suite) { String content = xmlSuite.toXml().replaceAll("<", "<").replaceAll(">", ">") .replaceAll(" ", " ").replaceAll("\n", "
"); StringBuffer sb = new StringBuffer(""); sb.append("").append("testng.xml for ") .append(xmlSuite.getName()).append("") .append(content) .append(""); Utils.writeFile(getOutputDirectory(xmlSuite), TESTNG_XML, sb.toString()); } /** * Generate the main index.html file that lists all the suites * and their result */ private void generateIndex(List suites) { StringBuffer sb = new StringBuffer(); String title = "Test results"; sb.append("\n" + title + "") .append(HtmlHelper.getCssString(".")) .append("\n") .append("

").append(title).append("

\n") .append("") .append("\n"); int totalFailedTests = 0; int totalPassedTests = 0; int totalSkippedTests = 0; StringBuffer suiteBuf= new StringBuffer(); for (ISuite suite : suites) { if (suite.getResults().size() == 0) { continue; } String name = suite.getName(); int failedTests= 0; int passedTests= 0; int skippedTests= 0; Map results = suite.getResults(); for (ISuiteResult result : results.values()) { ITestContext context = result.getTestContext(); failedTests += context.getFailedTests().size(); totalFailedTests += context.getFailedTests().size(); passedTests += context.getPassedTests().size(); totalPassedTests += context.getPassedTests().size(); skippedTests += context.getSkippedTests().size(); totalSkippedTests += context.getSkippedTests().size(); } String cls = failedTests > 0 ? "invocation-failed" : (passedTests > 0 ? "invocation-passed" : "invocation-failed"); suiteBuf.append("") .append("\n"); suiteBuf.append("") .append("") .append("") .append("") .append(""); } String cls= totalFailedTests > 0 ? "invocation-failed" : (totalPassedTests > 0 ? "invocation-passed" : "invocation-failed"); sb.append("") .append("") .append("") .append("") .append("") .append("") .append("\n"); sb.append(suiteBuf); sb.append("
SuitePassedFailedSkippedtestng.xml
") .append(name).append("" + passedTests + "" + failedTests + "" + skippedTests + "Link").append("
Total").append(totalPassedTests).append("").append(totalFailedTests).append("").append(totalSkippedTests).append(" 
").append("\n"); Utils.writeFile(m_outputDirectory, "index.html", sb.toString()); } private void generateExcludedMethodsReport(XmlSuite xmlSuite, ISuite suite) { Collection excluded = suite.getExcludedMethods(); StringBuffer sb2 = new StringBuffer("

Methods that were not run

\n"); for (ITestNGMethod method : excluded) { Method m = method.getMethod(); if (m != null) { sb2.append("\n"); } } sb2.append("
") .append(m.getDeclaringClass().getName() + "." + m.getName()); String description = method.getDescription(); if(isStringNotEmpty(description)) { sb2.append("
").append(SP2).append("").append(description).append(""); } sb2.append("
"); Utils.writeFile(getOutputDirectory(xmlSuite), METHODS_NOT_RUN, sb2.toString()); } private void generateReporterOutput(XmlSuite xmlSuite, ISuite suite) { StringBuffer sb = new StringBuffer(); // // Reporter output // sb.append("

Reporter output

") .append(""); List output = Reporter.getOutput(); for (String line : output) { sb.append("\n"); } sb.append("
").append(line).append("
"); Utils.writeFile(getOutputDirectory(xmlSuite), REPORTER_OUTPUT, sb.toString()); } private void generateClasses(XmlSuite xmlSuite, ISuite suite) { StringBuffer sb = new StringBuffer(); sb.append("\n") .append("\n") .append("\n") .append("\n") .append("\n") .append("") ; for (ITestClass tc : m_classes.values()) { sb.append(generateClass(tc)); } sb.append("
Class nameMethod nameGroups
\n"); Utils.writeFile(getOutputDirectory(xmlSuite), CLASSES, sb.toString()); } private final static String SP = " "; private final static String SP2 = SP + SP + SP + SP; private final static String SP3 = SP2 + SP2; private final static String SP4 = SP3 + SP3; private String generateClass(ITestClass cls) { StringBuffer sb = new StringBuffer(); sb.append("\n") .append("").append(cls.getRealClass().getName()).append("\n") .append(" ") .append(" ") .append("\n") ; String[] tags = new String[] { "@Test", "@BeforeClass", "@BeforeMethod", "@AfterMethod", "@AfterClass" }; ITestNGMethod[][] methods = new ITestNGMethod[][] { cls.getTestMethods(), cls.getBeforeClassMethods(), cls.getBeforeTestMethods(), cls.getAfterTestMethods(), cls.getAfterClassMethods() }; for (int i = 0; i < tags.length; i++) { sb.append("\n") .append("").append(tags[i]).append("\n") .append("\n") .append(dumpMethods(methods[i])) ; } // sb.append("
") // .append("

").append(cls.getRealClass().getName()).append("

\n"); // // sb.append("
").append(SP3).append("Test methods\n") // .append(dumpMethods(cls.getTestMethods())).append("
\n") // .append("
").append(SP3).append("@BeforeClass\n") // .append(dumpMethods(cls.getBeforeClassMethods())).append("
\n") // .append("
").append(SP3).append("@BeforeMethod\n") // .append(dumpMethods(cls.getBeforeTestMethods())).append("
\n") // .append("
").append(SP3).append("@AfterMethod\n") // .append(dumpMethods(cls.getAfterTestMethods())).append("
\n") // .append("
").append(SP3).append("@AfterClass\n") // .append(dumpMethods(cls.getAfterClassMethods())).append("
\n") // ; String result = sb.toString(); return result; } private String dumpMethods(ITestNGMethod[] testMethods) { StringBuffer sb = new StringBuffer(); if(null == testMethods || testMethods.length == 0) { return ""; } for (ITestNGMethod m : testMethods) { sb.append("\n"); sb.append(" \n") .append("").append(m.getMethodName()).append("\n") ; String[] groups = m.getGroups(); if (groups != null && groups.length > 0) { sb.append(""); for (String g : groups) { sb.append(g).append(" "); } sb.append("\n"); } else { sb.append(" "); } sb.append("\n"); } // StringBuffer sb = new StringBuffer("
"); //""); // for (ITestNGMethod tm : testMethods) { // sb // .append(SP4).append(tm.getMethodName()).append("()\n") // .append(dumpGroups(tm.getGroups())) // .append("
"); // ; // } String result = sb.toString(); return result; } private String dumpGroups(String[] groups) { StringBuffer sb = new StringBuffer(); if (null != groups && groups.length > 0) { sb.append(SP4).append("["); for (String g : groups) { sb.append(g).append(" "); } sb.append("]
\n"); } String result = sb.toString(); return result; } /** * Generate information about the methods that were run */ public static final String AFTER= "<<"; public static final String BEFORE = ">>"; private void generateMethodsChronologically(XmlSuite xmlSuite, ISuite suite, String outputFileName, boolean alphabetical) { StringBuffer sb = new StringBuffer(); sb.append("

Methods run, sorted chronologically

"); sb.append("

" + BEFORE + " means before, " + AFTER + " means after

"); long startDate = -1; sb.append("
").append(suite.getName()).append("

"); sb.append("(Hover the method name to see the test class name)

\n"); Utils.writeFile(getOutputDirectory(xmlSuite), outputFileName, sb.toString()); sb = null; //not needed anymore Collection invokedMethods = suite.getAllInvokedMethods(); if (alphabetical) { @SuppressWarnings({"unchecked"}) Comparator alphabeticalComparator = new Comparator(){ @Override public int compare(Object o1, Object o2) { IInvokedMethod m1 = (IInvokedMethod) o1; IInvokedMethod m2 = (IInvokedMethod) o2; return m1.getTestMethod().getMethodName().compareTo(m2.getTestMethod().getMethodName()); } }; Collections.sort((List) invokedMethods, alphabeticalComparator); } SimpleDateFormat format = new SimpleDateFormat("yy/MM/dd HH:mm:ss"); StringBuffer table = new StringBuffer(); boolean addedHeader = false; for (IInvokedMethod iim : invokedMethods) { ITestNGMethod tm = iim.getTestMethod(); table.setLength(0); if (!addedHeader) { table.append("

\n") .append("") .append("") .append("") .append("") .append("") .append("") .append("") .append("") .append("") .append("") .append("") .append("\n"); addedHeader = true; } String methodName = tm.toString(); boolean bc = tm.isBeforeClassConfiguration(); boolean ac = tm.isAfterClassConfiguration(); boolean bt = tm.isBeforeTestConfiguration(); boolean at = tm.isAfterTestConfiguration(); boolean bs = tm.isBeforeSuiteConfiguration(); boolean as = tm.isAfterSuiteConfiguration(); boolean bg = tm.isBeforeGroupsConfiguration(); boolean ag = tm.isAfterGroupsConfiguration(); boolean setUp = tm.isBeforeMethodConfiguration(); boolean tearDown = tm.isAfterMethodConfiguration(); boolean isClassConfiguration = bc || ac; boolean isGroupsConfiguration = bg || ag; boolean isTestConfiguration = bt || at; boolean isSuiteConfiguration = bs || as; boolean isSetupOrTearDown = setUp || tearDown; String configurationClassMethod = isClassConfiguration ? (bc ? BEFORE : AFTER) + methodName : SP; String configurationTestMethod = isTestConfiguration ? (bt ? BEFORE : AFTER) + methodName : SP; String configurationGroupsMethod = isGroupsConfiguration ? (bg ? BEFORE : AFTER) + methodName : SP; String configurationSuiteMethod = isSuiteConfiguration ? (bs ? BEFORE : AFTER) + methodName : SP; String setUpOrTearDownMethod = isSetupOrTearDown ? (setUp ? BEFORE : AFTER) + methodName : SP; String testMethod = tm.isTest() ? methodName : SP; StringBuffer instances = new StringBuffer(); for (long o : tm.getInstanceHashCodes()) { instances.append(o).append(" "); } if (startDate == -1) { startDate = iim.getDate(); } String date = format.format(iim.getDate()); table.append("") .append(" ") .append(" ") .append(td(configurationSuiteMethod)) .append(td(configurationTestMethod)) .append(td(configurationClassMethod)) .append(td(configurationGroupsMethod)) .append(td(setUpOrTearDownMethod)) .append(td(testMethod)) .append(" ") .append(" ") .append("\n") ; Utils.appendToFile(getOutputDirectory(xmlSuite), outputFileName, table.toString()); } Utils.appendToFile(getOutputDirectory(xmlSuite), outputFileName, "
TimeDelta (ms)Suite
configuration
Test
configuration
Class
configuration
Groups
configuration
Method
configuration
Test
method
ThreadInstances
").append(date).append("").append(iim.getDate() - startDate).append("").append(tm.getId()).append("").append(instances).append("
\n"); } /** * Generate a HTML color based on the class of the method */ private String createColor(ITestNGMethod tm) { // real class can be null if this client is remote (not serializable) long color = tm.getRealClass() != null ? tm.getRealClass().hashCode() & 0xffffff: 0xffffff; long[] rgb = { ((color & 0xff0000) >> 16) & 0xff, ((color & 0x00ff00) >> 8) & 0xff, color & 0xff }; // Not too dark for (int i = 0; i < rgb.length; i++) { if (rgb[i] < 0x60) { rgb[i] += 0x60; } } long adjustedColor = (rgb[0] << 16) | (rgb[1] << 8) | rgb[2]; String result = Long.toHexString(adjustedColor); return result; } private String td(String s) { StringBuffer result = new StringBuffer(); String prefix = ""; if (s.startsWith(BEFORE)) { prefix = BEFORE; } else if (s.startsWith(AFTER)) { prefix = AFTER; } if (! s.equals(SP)) { result.append(""); int open = s.lastIndexOf("("); int start = s.substring(0, open).lastIndexOf("."); // int end = s.lastIndexOf(")"); if (start >= 0) { result.append(prefix + s.substring(start + 1, open)); } else { result.append(prefix + s); } result.append(" \n"); } else { result.append("").append(SP).append(""); } return result.toString(); } private void ppp(String s) { System.out.println("[SuiteHTMLReporter] " + s); } /** * Generate information about methods and groups */ private void generateMethodsAndGroups(XmlSuite xmlSuite, ISuite suite) { StringBuffer sb = new StringBuffer(); Map> groups = suite.getMethodsByGroups(); sb.append("

Groups used for this test run

"); if (groups.size() > 0) { sb.append("\n") .append("") .append(""); String[] groupNames = groups.keySet().toArray(new String[groups.size()]); Arrays.sort(groupNames); for (String group : groupNames) { Collection methods = groups.get(group); sb.append(""); StringBuffer methodNames = new StringBuffer(); Map uniqueMethods = Maps.newHashMap(); for (ITestNGMethod tm : methods) { uniqueMethods.put(tm, tm); } for (ITestNGMethod tm : uniqueMethods.values()) { methodNames.append(tm.toString()).append("
"); } sb.append("
\n"); } sb.append("
Group nameMethods
").append(group).append("" + methodNames.toString() + "
\n"); } Utils.writeFile(getOutputDirectory(xmlSuite), GROUPS, sb.toString()); } private void generateIndex(XmlSuite xmlSuite, ISuite sr) { StringBuffer index = new StringBuffer() .append("Results for " + sr.getName() + "\n") .append("\n") .append("\n") .append("\n") .append("\n") .append("\n") ; Utils.writeFile(getOutputDirectory(xmlSuite), "index.html", index.toString()); } private String makeTitle(ISuite suite) { return "Results for
" + suite.getName() + ""; } private void generateMain(XmlSuite xmlSuite, ISuite sr) { StringBuffer index = new StringBuffer() .append("Results for " + sr.getName() + "\n") .append("Select a result on the left-hand pane.") .append("\n") ; Utils.writeFile(getOutputDirectory(xmlSuite), "main.html", index.toString()); } /** * */ private void generateTableOfContents(XmlSuite xmlSuite, ISuite suite) { StringBuffer tableOfContents = new StringBuffer(); // // Generate methods and groups hyperlinks // Map suiteResults = suite.getResults(); int groupCount = suite.getMethodsByGroups().size(); int methodCount = 0; for (ISuiteResult sr : suiteResults.values()) { ITestNGMethod[] methods = sr.getTestContext().getAllTestMethods(); methodCount += Utils.calculateInvokedMethodCount(methods); // Collect testClasses for (ITestNGMethod tm : methods) { ITestClass tc = tm.getTestClass(); m_classes.put(tc.getRealClass().getName(), tc); } } String name = "Results for " + suite.getName(); tableOfContents .append("\n") .append("\n") .append("" + name + "\n") .append(HtmlHelper.getCssString()) .append("\n") ; tableOfContents .append("\n") .append("

" + makeTitle(suite) + "

\n") .append("\n") .append("\n") .append("\n") .append("\n") .append("\n") .append("\n") .append("\n") .append("\n") .append("\n") .append("\n") .append("") .append("
") .append(suiteResults.size()).append(" ").append(pluralize(suiteResults.size(), "test")) .append("") .append("") .append(m_classes.size() + " " + pluralize(m_classes.size(), "class")) .append("") .append("" + methodCount + " " + pluralize(methodCount, "method") + ":
\n") .append("  ").append("chronological
\n") .append("  ").append("alphabetical
\n") .append("  not run (" + suite.getExcludedMethods().size() + ")") .append("
").append(groupCount + pluralize(groupCount, " group") + "reporter outputtestng.xml
"); // // Generate results for individual tests // // Order the results so we can show the failures first, then the skip and // finally the successes Map redResults = Maps.newHashMap(); Map yellowResults = Maps.newHashMap(); Map greenResults = Maps.newHashMap(); for (Map.Entry entry : suiteResults.entrySet()) { String suiteName = entry.getKey(); ISuiteResult sr = entry.getValue(); ITestContext tc = sr.getTestContext(); int failed = tc.getFailedTests().size(); int skipped = tc.getSkippedTests().size(); int passed = tc.getPassedTests().size(); if (failed > 0) { redResults.put(suiteName, sr); } else if (skipped > 0) { yellowResults.put(suiteName, sr); } else if (passed > 0) { greenResults.put(suiteName, sr); } else { redResults.put(suiteName, sr); } } ISuiteResult[][] results = new ISuiteResult[][] { sortResults(redResults.values()), sortResults(yellowResults.values()), sortResults(greenResults.values()) }; String[] colors = {"failed", "skipped", "passed"}; for (int i = 0; i < colors.length; i++) { ISuiteResult[] r = results[i]; for (ISuiteResult sr: r) { String suiteName = sr.getTestContext().getName(); generateSuiteResult(suiteName, sr, colors[i], tableOfContents, m_outputDirectory); } } tableOfContents.append(""); Utils.writeFile(getOutputDirectory(xmlSuite), "toc.html", tableOfContents.toString()); } private String pluralize(int count, String singular) { return count > 1 ? (singular.endsWith("s") ? singular + "es" : singular + "s") : singular; } private String getOutputDirectory(XmlSuite xmlSuite) { return m_outputDirectory + File.separatorChar + xmlSuite.getName(); } private ISuiteResult[] sortResults(Collection r) { ISuiteResult[] result = r.toArray(new ISuiteResult[r.size()]); Arrays.sort(result); return result; } private void generateSuiteResult(String suiteName, ISuiteResult sr, String cssClass, StringBuffer tableOfContents, String outputDirectory) { ITestContext tc = sr.getTestContext(); int passed = tc.getPassedTests().size(); int failed = tc.getFailedTests().size(); int skipped = tc.getSkippedTests().size(); String baseFile = tc.getName(); tableOfContents .append("\n\n") .append("

\n") ; tableOfContents.append("

\n") .append("") .append("") .append("") .append("
") .append(suiteName).append(" (").append(passed).append("/").append(failed).append("/").append(skipped).append(")") .append("\n") .append(" Results\n") // .append(" Output\n") // .append("  Property file
\n") .append("
\n") .append("
\n"); } /** * Writes a property file for each suite result. * * @param xmlSuite * @param suite */ private void generateSuites(XmlSuite xmlSuite, ISuite suite) { Map suiteResults = suite.getResults(); for (ISuiteResult sr : suiteResults.values()) { ITestContext testContext = sr.getTestContext(); StringBuffer sb = new StringBuffer(); for (ISuiteResult suiteResult : suiteResults.values()) { sb.append(suiteResult.toString()); } Utils.writeFile(getOutputDirectory(xmlSuite), testContext.getName() + ".properties", sb.toString()); } } } testng-testng-6.9.5/src/main/java/org/testng/reporters/JqReporter.java0000644000175000017500000001647212551235562025377 0ustar eugeneeugenepackage org.testng.reporters; import org.testng.IReporter; import org.testng.IResultMap; import org.testng.ISuite; import org.testng.ISuiteResult; import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.collections.ListMultiMap; import org.testng.collections.Maps; import org.testng.internal.Utils; import org.testng.xml.XmlSuite; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; public class JqReporter implements IReporter { private static final String C = "class"; private static final String D = "div"; private static final String S = "span"; private int m_testCount = 0; private String m_outputDirectory; private Map m_testMap = Maps.newHashMap(); @Override public void generateReport(List xmlSuites, List suites, String outputDirectory) { m_outputDirectory = "/Users/cedric/java/misc/jquery"; XMLStringBuffer xsb = new XMLStringBuffer(" "); xsb.push(D, "id", "suites"); generateSuites(xmlSuites, suites, xsb); xsb.pop(D); String all; try { all = Files.readFile(new File("/Users/cedric/java/misc/jquery/head")); Utils.writeFile(m_outputDirectory, "index2.html", all + xsb.toXML()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private XMLStringBuffer generateSuites(List xmlSuites, List suites, XMLStringBuffer main) { for (ISuite suite : suites) { if (suite.getResults().size() == 0) { continue; } XMLStringBuffer xsb = new XMLStringBuffer(main.getCurrentIndent()); XMLStringBuffer header = new XMLStringBuffer(main.getCurrentIndent()); xsb.push(D, C, "suite-content"); Map results = suite.getResults(); XMLStringBuffer xs1 = new XMLStringBuffer(xsb.getCurrentIndent()); XMLStringBuffer xs2 = new XMLStringBuffer(xsb.getCurrentIndent()); XMLStringBuffer xs3 = new XMLStringBuffer(xsb.getCurrentIndent()); int failed = 0; int skipped = 0; int passed = 0; for (ISuiteResult result : results.values()) { ITestContext context = result.getTestContext(); failed += context.getFailedTests().size(); generateTests("failed", context.getFailedTests(), context, xs1); skipped += context.getSkippedTests().size(); generateTests("skipped", context.getSkippedTests(), context, xs2); passed += context.getPassedTests().size(); generateTests("passed", context.getPassedTests(), context, xs3); } xsb.addOptional(D, "Failed" + " tests", C, "result-banner " + "failed"); xsb.addString(xs1.toXML()); xsb.addOptional(D, "Skipped" + " tests", C, "result-banner " + "skipped"); xsb.addString(xs2.toXML()); xsb.addOptional(D, "Passed" + " tests", C, "result-banner " + "passed"); xsb.addString(xs3.toXML()); header.push(D, C, "suite"); header.push(D, C, "suite-header"); header.addOptional(S, suite.getName(), C, "suite-name"); header.push(D, C, "stats"); int total = failed + skipped + passed; String stats = String.format("%s, %d failed, %d skipped, %d passed", pluralize(total, "method"), failed, skipped, passed); header.push("ul"); // Method stats header.push("li"); header.addOptional(S, stats, C, "method-stats"); header.pop("li"); // Tests header.push("li"); header.addOptional(S, String.format("%s ", pluralize(results.values().size(), "test"), C, "test-stats")); header.pop("li"); // List of tests header.push("ul"); for (ISuiteResult tr : results.values()) { String testName = tr.getTestContext().getName(); header.push("li"); header.addOptional("a", testName, "href", "#" + m_testMap.get(testName)); header.pop("li"); } header.pop("ul"); header.pop("ul"); header.pop(D); header.pop(D); main.addString(header.toXML()); main.addString(xsb.toXML()); } return main; } private String capitalize(String s) { return Character.toUpperCase(s.charAt(0)) + s.substring(1); } private void generateTests(String tagClass, IResultMap tests, ITestContext context, XMLStringBuffer xsb) { if (tests.getAllMethods().isEmpty()) return; xsb.push(D, C, "test" + (tagClass != null ? " " + tagClass : "")); ListMultiMap, ITestResult> map = Maps.newListMultiMap(); for (ITestResult m : tests.getAllResults()) { map.put(m.getTestClass().getRealClass(), m); } String testName = "test-" + (m_testCount++); m_testMap.put(context.getName(), testName); xsb.push(D, C, "test-name"); xsb.push("a", "name", testName); xsb.addString(context.getName()); xsb.pop("a"); // Expand icon xsb.push("a", C, "expand", "href", "#"); xsb.addEmptyElement("img", "src", getStatusImage(tagClass)); xsb.pop("a"); xsb.pop(D); xsb.push(D, C, "test-content"); for (Class c : map.keySet()) { xsb.push(D, C, C); xsb.push(D, C, "class-header"); // Passed/failed icon xsb.addEmptyElement("img", "src", getImage(tagClass)); xsb.addOptional(S, c.getName(), C, "class-name"); xsb.pop(D); xsb.push(D, C, "class-content"); List l = map.get(c); for (ITestResult m : l) { generateMethod(tagClass, m, context, xsb); } xsb.pop(D); xsb.pop(D); } xsb.pop(D); xsb.pop(D); } private static String getStatusImage(String status) { return "up.png"; // if ("passed".equals(status)) return "down.png"; // else return "up.png"; } private static String getImage(String tagClass) { return tagClass + ".png"; } private void generateMethod(String tagClass, ITestResult tr, ITestContext context, XMLStringBuffer xsb) { long time = tr.getEndMillis() - tr.getStartMillis(); xsb.push(D, C, "method"); xsb.push(D, C, "method-content"); xsb.addOptional(S, tr.getMethod().getMethodName(), C, "method-name"); // Parameters? if (tr.getParameters().length > 0) { StringBuilder sb = new StringBuilder(); boolean first = true; for (Object p : tr.getParameters()) { if (!first) sb.append(", "); first = false; sb.append(Utils.toString(p)); } xsb.addOptional(S, "(" + sb.toString() + ")", C, "parameters"); } // Exception? if (tr.getThrowable() != null) { StringBuilder stackTrace = new StringBuilder(); for (StackTraceElement str : tr.getThrowable().getStackTrace()) { stackTrace.append(str.toString()).append("
"); } xsb.addOptional(D, stackTrace.toString() + "\n", C, "stack-trace"); } xsb.addOptional(S, " " + Long.toString(time) + " ms", C, "method-time"); xsb.pop(D); xsb.pop(D); } /** * Overridable by subclasses to create different directory names (e.g. with timestamps). * @param outputDirectory the output directory specified by the user */ protected String generateOutputDirectoryName(String outputDirectory) { return outputDirectory; } private String pluralize(int count, String singular) { return Integer.toString(count) + " " + (count > 1 ? (singular.endsWith("s") ? singular + "es" : singular + "s") : singular); } } testng-testng-6.9.5/src/main/java/org/testng/reporters/JUnitXMLReporter.java0000755000175000017500000002213612551235562026434 0ustar eugeneeugenepackage org.testng.reporters; import org.testng.ITestContext; 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 java.net.InetAddress; import java.net.UnknownHostException; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.regex.Pattern; /** * A JUnit XML report generator (replacing the original JUnitXMLReporter that was * based on XML APIs). * * @author Alex Popescu */ public class JUnitXMLReporter implements IResultListener2 { private static final Pattern ENTITY= Pattern.compile("&[a-zA-Z]+;.*"); private static final Pattern LESS= Pattern.compile("<"); private static final Pattern GREATER= Pattern.compile(">"); private static final Pattern SINGLE_QUOTE = Pattern.compile("'"); private static final Pattern QUOTE = Pattern.compile("\""); private static final Map ATTR_ESCAPES= Maps.newHashMap(); static { ATTR_ESCAPES.put("<", LESS); ATTR_ESCAPES.put(">", GREATER); ATTR_ESCAPES.put("'", SINGLE_QUOTE); ATTR_ESCAPES.put(""", QUOTE); } /** * keep lists of all the results */ private int m_numPassed= 0; private int m_numFailed= 0; private int m_numSkipped= 0; private int m_numFailedButIgnored= 0; private List m_allTests = Collections.synchronizedList(Lists.newArrayList()); private List m_configIssues = Collections.synchronizedList(Lists.newArrayList()); private Map m_fileNameMap = Maps.newHashMap(); private int m_fileNameIncrementer = 0; @Override public void onTestStart(ITestResult result) { } @Override public void beforeConfiguration(ITestResult tr) { } /** * Invoked each time a test succeeds. */ @Override public void onTestSuccess(ITestResult tr) { m_allTests.add(tr); m_numPassed++; } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult tr) { m_allTests.add(tr); m_numFailedButIgnored++; } /** * Invoked each time a test fails. */ @Override public void onTestFailure(ITestResult tr) { m_allTests.add(tr); m_numFailed++; } /** * Invoked each time a test is skipped. */ @Override public void onTestSkipped(ITestResult tr) { m_allTests.add(tr); m_numSkipped++; } /** * Invoked after the test class is instantiated and before * any configuration method is called. * */ @Override public void onStart(ITestContext context) { } /** * Invoked after all the tests have run and all their * Configuration methods have been called. * */ @Override public void onFinish(ITestContext context) { generateReport(context); resetAll(); } /** * @see org.testng.IConfigurationListener#onConfigurationFailure(org.testng.ITestResult) */ @Override public void onConfigurationFailure(ITestResult itr) { m_configIssues.add(itr); } /** * @see org.testng.IConfigurationListener#onConfigurationSkip(org.testng.ITestResult) */ @Override public void onConfigurationSkip(ITestResult itr) { m_configIssues.add(itr); } /** * @see org.testng.IConfigurationListener#onConfigurationSuccess(org.testng.ITestResult) */ @Override public void onConfigurationSuccess(ITestResult itr) { } /** * generate the XML report given what we know from all the test results */ protected void generateReport(ITestContext context) { XMLStringBuffer document= new XMLStringBuffer(); document.addComment("Generated by " + getClass().getName()); Properties attrs= new Properties(); attrs.setProperty(XMLConstants.ATTR_ERRORS, "0"); attrs.setProperty(XMLConstants.ATTR_FAILURES, "" + m_numFailed); try { attrs.setProperty(XMLConstants.ATTR_HOSTNAME, InetAddress.getLocalHost().getHostName()); } catch (UnknownHostException e) { // ignore } Set packages = getPackages(context); if (packages.size() > 0) { attrs.setProperty(XMLConstants.ATTR_NAME, context.getCurrentXmlTest().getName()); // attrs.setProperty(XMLConstants.ATTR_PACKAGE, packages.iterator().next()); } attrs.setProperty(XMLConstants.ATTR_TESTS, "" + m_allTests.size()); attrs.setProperty(XMLConstants.ATTR_TIME, "" + ((context.getEndDate().getTime() - context.getStartDate().getTime()) / 1000.0)); Date timeStamp = Calendar.getInstance().getTime(); attrs.setProperty(XMLConstants.ATTR_TIMESTAMP, timeStamp.toGMTString()); document.push(XMLConstants.TESTSUITE, attrs); // document.addEmptyElement(XMLConstants.PROPERTIES); for(ITestResult tr : m_configIssues) { createElement(document, tr); } for(ITestResult tr : m_allTests) { createElement(document, tr); } document.pop(); Utils.writeUtf8File(context.getOutputDirectory(),generateFileName(context) + ".xml", document.toXML()); } private Set getPackages(ITestContext context) { Set result = Sets.newHashSet(); for (ITestNGMethod m : context.getAllTestMethods()) { Package pkg = m.getMethod().getDeclaringClass().getPackage(); if (pkg != null) { result.add(pkg.getName()); } } return result; } private void createElement(XMLStringBuffer doc, ITestResult tr) { Properties attrs= new Properties(); long elapsedTimeMillis= tr.getEndMillis() - tr.getStartMillis(); String name= tr.getMethod().isTest() ? tr.getName() : Utils.detailedMethodName(tr.getMethod(), false); attrs.setProperty(XMLConstants.ATTR_NAME, name); attrs.setProperty(XMLConstants.ATTR_CLASSNAME, tr.getTestClass().getRealClass().getName()); attrs.setProperty(XMLConstants.ATTR_TIME, "" + (((double) elapsedTimeMillis) / 1000)); if((ITestResult.FAILURE == tr.getStatus()) || (ITestResult.SKIP == tr.getStatus())) { doc.push(XMLConstants.TESTCASE, attrs); if(ITestResult.FAILURE == tr.getStatus()) { createFailureElement(doc, tr); } else if(ITestResult.SKIP == tr.getStatus()) { createSkipElement(doc, tr); } doc.pop(); } else { doc.addEmptyElement(XMLConstants.TESTCASE, attrs); } } private void createFailureElement(XMLStringBuffer doc, ITestResult tr) { Properties attrs= new Properties(); Throwable t= tr.getThrowable(); if(t != null) { attrs.setProperty(XMLConstants.ATTR_TYPE, t.getClass().getName()); String message= t.getMessage(); if((message != null) && (message.length() > 0)) { attrs.setProperty(XMLConstants.ATTR_MESSAGE, encodeAttr(message)); // ENCODE } doc.push(XMLConstants.FAILURE, attrs); doc.addCDATA(Utils.stackTrace(t, false)[0]); doc.pop(); } else { doc.addEmptyElement(XMLConstants.FAILURE); // THIS IS AN ERROR } } private void createSkipElement(XMLStringBuffer doc, ITestResult tr) { doc.addEmptyElement("skipped"); } private String encodeAttr(String attr) { String result= replaceAmpersand(attr, ENTITY); for(Map.Entry e: ATTR_ESCAPES.entrySet()) { result= e.getValue().matcher(result).replaceAll(e.getKey()); } return result; } private String replaceAmpersand(String str, Pattern pattern) { int start = 0; int idx = str.indexOf('&', start); if(idx == -1) { return str; } StringBuffer result= new StringBuffer(); while(idx != -1) { result.append(str.substring(start, idx)); if(pattern.matcher(str.substring(idx)).matches()) { // do nothing it is an entity; result.append("&"); } else { result.append("&"); } start= idx + 1; idx= str.indexOf('&', start); } result.append(str.substring(start)); return result.toString(); } /** * Reset all member variables for next test. * */ private void resetAll() { m_allTests = Collections.synchronizedList(Lists.newArrayList()); m_configIssues = Collections.synchronizedList(Lists.newArrayList()); m_numFailed = 0; m_numFailedButIgnored = 0; m_numPassed = 0; m_numSkipped = 0; } /** * @author Borojevic Created this method to guarantee unique file names for * reports.
* Also, this will guarantee that the old reports are overwritten * when tests are run again. * @param context * test context * @return unique name for the file associated with this test context. * */ private String generateFileName(ITestContext context) { String fileName = null; String keyToSearch = context.getSuite().getName() + context.getName(); if (m_fileNameMap.get(keyToSearch) == null) { fileName = context.getName(); } else { fileName = context.getName() + m_fileNameIncrementer++; } m_fileNameMap.put(keyToSearch, fileName); return fileName; } } testng-testng-6.9.5/src/main/java/org/testng/reporters/JUnitReportReporter.java0000644000175000017500000002240712551235562027245 0ustar eugeneeugenepackage org.testng.reporters; import org.testng.IReporter; import org.testng.ISuite; import org.testng.ISuiteResult; import org.testng.ITestContext; import org.testng.ITestNGMethod; 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.xml.XmlSuite; import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.net.InetAddress; import java.net.UnknownHostException; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; public class JUnitReportReporter implements IReporter { @Override public void generateReport(List xmlSuites, List suites, String defaultOutputDirectory) { Map, Set> results = Maps.newHashMap(); Map, Set> failedConfigurations = Maps.newHashMap(); ListMultiMap befores = Maps.newListMultiMap(); ListMultiMap afters = Maps.newListMultiMap(); for (ISuite suite : suites) { Map suiteResults = suite.getResults(); for (ISuiteResult sr : suiteResults.values()) { ITestContext tc = sr.getTestContext(); addResults(tc.getPassedTests().getAllResults(), results); addResults(tc.getFailedTests().getAllResults(), results); addResults(tc.getSkippedTests().getAllResults(), results); addResults(tc.getFailedConfigurations().getAllResults(), failedConfigurations); for (ITestResult tr : tc.getPassedConfigurations().getAllResults()) { if (tr.getMethod().isBeforeMethodConfiguration()) { befores.put(tr.getInstance(), tr); } if (tr.getMethod().isAfterMethodConfiguration()) { afters.put(tr.getInstance(), tr); } } } } // A list of iterators for all the passed configuration, explanation below // ListMultiMap, ITestResult> beforeConfigurations = Maps.newListMultiMap(); // ListMultiMap, ITestResult> afterConfigurations = Maps.newListMultiMap(); // for (Map.Entry, Set> es : passedConfigurations.entrySet()) { // for (ITestResult tr : es.getValue()) { // ITestNGMethod method = tr.getMethod(); // if (method.isBeforeMethodConfiguration()) { // beforeConfigurations.put(method.getRealClass(), tr); // } // if (method.isAfterMethodConfiguration()) { // afterConfigurations.put(method.getRealClass(), tr); // } // } // } // Map> befores = Maps.newHashMap(); // for (Map.Entry, List> es : beforeConfigurations.getEntrySet()) { // List tr = es.getValue(); // for (ITestResult itr : es.getValue()) { // } // } // Map, Iterator> afters = Maps.newHashMap(); // for (Map.Entry, List> es : afterConfigurations.getEntrySet()) { // afters.put(es.getKey(), es.getValue().iterator()); // } for (Map.Entry, Set> entry : results.entrySet()) { Class cls = entry.getKey(); Properties p1 = new Properties(); p1.setProperty("name", cls.getName()); Date timeStamp = Calendar.getInstance().getTime(); p1.setProperty(XMLConstants.ATTR_TIMESTAMP, timeStamp.toGMTString()); List testCases = Lists.newArrayList(); int failures = 0; int errors = 0; int testCount = 0; float totalTime = 0; for (ITestResult tr: entry.getValue()) { TestTag testTag = new TestTag(); boolean isSuccess = tr.getStatus() == ITestResult.SUCCESS; if (! isSuccess) { if (tr.getThrowable() instanceof AssertionError) { failures++; } else { errors++; } } Properties p2 = new Properties(); p2.setProperty("classname", cls.getName()); p2.setProperty("name", getTestName(tr)); long time = tr.getEndMillis() - tr.getStartMillis(); time += getNextConfiguration(befores, tr); time += getNextConfiguration(afters, tr); p2.setProperty("time", "" + formatTime(time)); Throwable t = getThrowable(tr, failedConfigurations); if (! isSuccess && t != null) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); t.printStackTrace(pw); testTag.message = t.getMessage(); testTag.type = t.getClass().getName(); testTag.stackTrace = sw.toString(); testTag.errorTag = tr.getThrowable() instanceof AssertionError ? "failure" : "error"; } totalTime += time; testCount++; testTag.properties = p2; testCases.add(testTag); } p1.setProperty("failures", "" + failures); p1.setProperty("errors", "" + errors); p1.setProperty("name", cls.getName()); p1.setProperty("tests", "" + testCount); p1.setProperty("time", "" + formatTime(totalTime)); try { p1.setProperty(XMLConstants.ATTR_HOSTNAME, InetAddress.getLocalHost().getHostName()); } catch (UnknownHostException e) { // ignore } // // Now that we have all the information we need, generate the file // XMLStringBuffer xsb = new XMLStringBuffer(); xsb.addComment("Generated by " + getClass().getName()); xsb.push("testsuite", p1); for (TestTag testTag : testCases) { if (testTag.stackTrace == null) { xsb.addEmptyElement("testcase", testTag.properties); } else { xsb.push("testcase", testTag.properties); Properties p = new Properties(); if (testTag.message != null) { p.setProperty("message", testTag.message); } p.setProperty("type", testTag.type); xsb.push(testTag.errorTag, p); xsb.addCDATA(testTag.stackTrace); xsb.pop(testTag.errorTag); xsb.pop("testcase"); } } xsb.pop("testsuite"); String outputDirectory = defaultOutputDirectory + File.separator + "junitreports"; Utils.writeUtf8File(outputDirectory, getFileName(cls), xsb.toXML()); } // System.out.println(xsb.toXML()); // System.out.println(""); } /** * Add the time of the configuration method to this test method. * * The only problem with this method is that the timing of a test method * might not be added to the time of the same configuration method that ran before * it but since they should all be equivalent, this should never be an issue. */ private long getNextConfiguration(ListMultiMap configurations, ITestResult tr) { long result = 0; List confResults = configurations.get(tr.getInstance()); Map seen = Maps.newHashMap(); if (confResults != null) { for (ITestResult r : confResults) { if (! seen.containsKey(r.getMethod())) { result += r.getEndMillis() - r.getStartMillis(); seen.put(r.getMethod(), r); } } confResults.removeAll(seen.values()); } return result; } protected String getFileName(Class cls) { return "TEST-" + cls.getName() + ".xml"; } protected String getTestName(ITestResult tr) { return tr.getMethod().getMethodName(); } private String formatTime(float time) { DecimalFormatSymbols symbols = new DecimalFormatSymbols(); // JUnitReports wants points here, regardless of the locale symbols.setDecimalSeparator('.'); DecimalFormat format = new DecimalFormat("#.###", symbols); format.setMinimumFractionDigits(3); return format.format(time / 1000.0f); } private Throwable getThrowable(ITestResult tr, Map, Set> failedConfigurations) { Throwable result = tr.getThrowable(); if (result == null && tr.getStatus() == ITestResult.SKIP) { // Attempt to grab the stack trace from the configuration failure for (Set failures : failedConfigurations.values()) { for (ITestResult failure : failures) { // Naive implementation for now, eventually, we need to try to find // out if it's this failure that caused the skip since (maybe by // seeing if the class of the configuration method is assignable to // the class of the test method, although that's not 100% fool proof if (failure.getThrowable() != null) { return failure.getThrowable(); } } } } return result; } class TestTag { public Properties properties; public String message; public String type; public String stackTrace; public String errorTag; } private void addResults(Set allResults, Map, Set> out) { for (ITestResult tr : allResults) { Class cls = tr.getMethod().getTestClass().getRealClass(); Set l = out.get(cls); if (l == null) { l = Sets.newHashSet(); out.put(cls, l); } l.add(tr); } } } testng-testng-6.9.5/src/main/java/org/testng/reporters/IBuffer.java0000644000175000017500000000022712551235562024613 0ustar eugeneeugenepackage org.testng.reporters; import java.io.Writer; public interface IBuffer { IBuffer append(CharSequence string); void toWriter(Writer fw); } testng-testng-6.9.5/src/main/java/org/testng/reporters/HtmlHelper.java0000755000175000017500000000166412551235562025346 0ustar eugeneeugenepackage org.testng.reporters; import org.testng.internal.Utils; import java.io.File; import java.io.IOException; public class HtmlHelper { private static final String CSS_FILE_NAME = "testng.css"; private static final String MY_CSS_FILE_NAME = "my-testng.css"; static public String getCssString() { return getCssString(".."); } static public String getCssString(String directory) { return "\n" + "\n"; } public static File generateStylesheet(String outputDirectory) throws IOException { File stylesheetFile = new File(outputDirectory, CSS_FILE_NAME); if (!stylesheetFile.exists()) { Utils.writeResourceToFile(stylesheetFile, CSS_FILE_NAME, TestHTMLReporter.class); } return stylesheetFile; } } testng-testng-6.9.5/src/main/java/org/testng/reporters/Files.java0000644000175000017500000000410312551235562024330 0ustar eugeneeugenepackage 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; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; import java.io.StringWriter; import java.io.Writer; public class Files { public static String readFile(File f) throws IOException { try (InputStream is = new FileInputStream(f)) { return readFile(is); } } public static String readFile(InputStream is) throws IOException { StringBuilder result = new StringBuilder(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String line = br.readLine(); while (line != null) { result.append(line + "\n"); line = br.readLine(); } return result.toString(); } public static void writeFile(String string, File f) throws IOException { f.getParentFile().mkdirs(); FileWriter fw = new FileWriter(f); BufferedWriter bw = new BufferedWriter(fw); bw.write(string); bw.close(); fw.close(); } public static void copyFile(InputStream from, File to) throws IOException { if (! to.getParentFile().exists()) { to.getParentFile().mkdirs(); } 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); } } } public static String streamToString(InputStream is) throws IOException { if (is != null) { Writer writer = new StringWriter(); char[] buffer = new char[1024]; try { Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); int n; while ((n = reader.read(buffer)) != -1) { writer.write(buffer, 0, n); } } finally { is.close(); } return writer.toString(); } else { return ""; } } } testng-testng-6.9.5/src/main/java/org/testng/reporters/FileStringBuffer.java0000644000175000017500000001167712551235562026504 0ustar eugeneeugenepackage org.testng.reporters; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.io.Writer; import java.util.Random; /** * A string buffer that flushes its content to a temporary file whenever the internal * string buffer becomes larger than MAX. If the buffer never reaches that size, no file * is ever created and everything happens in memory, so the overhead compared to * StringBuffer/StringBuilder is minimal. * * Note: calling toString() will force the entire string to be loaded in memory, use * toWriter() if you need to avoid this. * * This class is not multi thread safe. * * @author Cedric Beust * * @since Nov 9, 2012 */ public class FileStringBuffer implements IBuffer { private static int MAX = 100000; private static final boolean VERBOSE = System.getProperty("fileStringBuffer") != null; private File m_file; private StringBuilder m_sb = new StringBuilder(); private final int m_maxCharacters; public FileStringBuffer() { this(MAX); } public FileStringBuffer(int maxCharacters) { m_maxCharacters = maxCharacters; } @Override public FileStringBuffer append(CharSequence s) { if (s == null) { throw new IllegalArgumentException("CharSequence (Argument 0 of FileStringBuffer#append) should not be null"); } // m_sb.append(s); if (m_sb.length() > m_maxCharacters) { flushToFile(); } if (s.length() < MAX) { // Small string, add it to our internal buffer m_sb.append(s); } else { // Big string, add it to the temporary file directly flushToFile(); try { copy(new StringReader(s.toString()), new FileWriter(m_file, true /* append */)); } catch (IOException e) { e.printStackTrace(); } } return this; } @Override public void toWriter(Writer fw) { if (fw == null) { throw new IllegalArgumentException("Writer (Argument 0 of FileStringBuffer#toWriter) should not be null"); } try { BufferedWriter bw = new BufferedWriter(fw); if (m_file == null) { bw.write(m_sb.toString()); bw.close(); } else { flushToFile(); copy(new FileReader(m_file), bw); } } catch(IOException ex) { ex.printStackTrace(); } } private static void copy(Reader input, Writer output) throws IOException { char[] buf = new char[MAX]; while (true) { int length = input.read(buf); if (length < 0) break; output.write(buf, 0, length); } try { input.close(); } catch (IOException ignore) { } try { output.close(); } catch (IOException ignore) { } } private void flushToFile() { if (m_sb.length() == 0) return; if (m_file == null) { try { m_file = File.createTempFile("testng", "fileStringBuffer"); m_file.deleteOnExit(); p("Created temp file " + m_file); } catch (IOException e) { e.printStackTrace(); } } FileWriter fw; try { p("Size " + m_sb.length() + ", flushing to " + m_file); fw = new FileWriter(m_file, true /* append */); fw.append(m_sb); fw.close(); } catch (IOException e) { e.printStackTrace(); } m_sb = new StringBuilder(); } private static void p(String s) { if (VERBOSE) { System.out.println("[FileStringBuffer] " + s); } } @Override public String toString() { String result = null; if (m_file != null) { flushToFile(); try { result = Files.readFile(m_file); } catch (IOException e) { e.printStackTrace(); } } else { result = m_sb.toString(); } return result; } private static void save(File expected, String s) throws IOException { expected.delete(); FileWriter expectedWriter = new FileWriter(expected); expectedWriter.append(s); expectedWriter.close(); } public static void main(String[] args) throws IOException { String s = "abcdefghijklmnopqrstuvwxyz"; FileStringBuffer fsb = new FileStringBuffer(10); StringBuilder control = new StringBuilder(); Random r = new Random(); for (int i = 0; i < 1000; i++) { int start = Math.abs(r.nextInt() % 26); int length = Math.abs(r.nextInt() % (26 - start)); String fragment = s.substring(start, start + length); p("... Appending " + fragment); fsb.append(fragment); control.append(fragment); } File expected = new File("/tmp/expected"); expected.delete(); FileWriter expectedWriter = new FileWriter(expected); expectedWriter.append(control); expectedWriter.close(); File actual = new File("/tmp/actual"); actual.delete(); FileWriter actualWriter = new FileWriter(actual); fsb.toWriter(actualWriter); actualWriter.close(); // Assert.assertEquals(fsb.toString(), control.toString()); } } testng-testng-6.9.5/src/main/java/org/testng/reporters/FailedReporter.java0000755000175000017500000002031412551235562026202 0ustar eugeneeugenepackage org.testng.reporters; import org.testng.IReporter; import org.testng.ISuite; import org.testng.ISuiteResult; import org.testng.ITestContext; import org.testng.ITestNGMethod; 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.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * This reporter is responsible for creating testng-failed.xml * * @author Cedric Beust * @author Alexandru Popescu */ public class FailedReporter extends TestListenerAdapter implements IReporter { public static final String TESTNG_FAILED_XML = "testng-failed.xml"; private XmlSuite m_xmlSuite; public FailedReporter() { } public FailedReporter(XmlSuite xmlSuite) { m_xmlSuite = xmlSuite; } @Override public void generateReport(List xmlSuites, List suites, String outputDirectory) { for (ISuite suite : suites) { generateFailureSuite(suite.getXmlSuite(), suite, outputDirectory); } } protected void generateFailureSuite(XmlSuite xmlSuite, ISuite suite, String outputDir) { XmlSuite failedSuite = (XmlSuite) xmlSuite.clone(); failedSuite.setName("Failed suite [" + xmlSuite.getName() + "]"); m_xmlSuite= failedSuite; Map xmlTests= Maps.newHashMap(); for(XmlTest xmlT: xmlSuite.getTests()) { xmlTests.put(xmlT.getName(), xmlT); } Map results = suite.getResults(); for(Map.Entry entry : results.entrySet()) { ISuiteResult suiteResult = entry.getValue(); ITestContext testContext = suiteResult.getTestContext(); generateXmlTest(suite, xmlTests.get(testContext.getName()), testContext, testContext.getFailedTests().getAllResults(), testContext.getSkippedTests().getAllResults()); } if(null != failedSuite.getTests() && failedSuite.getTests().size() > 0) { Utils.writeUtf8File(outputDir, TESTNG_FAILED_XML, failedSuite.toXml()); Utils.writeUtf8File(suite.getOutputDirectory(), TESTNG_FAILED_XML, failedSuite.toXml()); } } /** * Do not rely on this method. The class is used as IReporter. * * @see org.testng.TestListenerAdapter#onFinish(org.testng.ITestContext) * @deprecated this class is used now as IReporter */ @Deprecated @Override public void onFinish(ITestContext context) { // Delete the previous file // File f = new File(context.getOutputDirectory(), getFileName(context)); // f.delete(); // Calculate the methods we need to rerun : failed tests and // their dependents // List failedTests = getFailedTests(); // List skippedTests = getSkippedTests(); } private void generateXmlTest(ISuite suite, XmlTest xmlTest, ITestContext context, Collection failedTests, Collection skippedTests) { // Note: we can have skipped tests and no failed tests // if a method depends on nonexistent groups if (skippedTests.size() > 0 || failedTests.size() > 0) { Set methodsToReRun = Sets.newHashSet(); // Get the transitive closure of all the failed methods and the methods // they depend on Collection[] allTests = new Collection[] { failedTests, skippedTests }; for (Collection tests : allTests) { for (ITestResult failedTest : tests) { ITestNGMethod current = failedTest.getMethod(); if (current.isTest()) { methodsToReRun.add(current); ITestNGMethod method = failedTest.getMethod(); // Don't count configuration methods if (method.isTest()) { List methodsDependedUpon = MethodHelper.getMethodsDependedUpon(method, context.getAllTestMethods()); for (ITestNGMethod m : methodsDependedUpon) { if (m.isTest()) { methodsToReRun.add(m); } } } } } } // // Now we have all the right methods. Go through the list of // all the methods that were run and only pick those that are // in the methodToReRun map. Since the methods are already // sorted, we don't need to sort them again. // List result = Lists.newArrayList(); for (ITestNGMethod m : context.getAllTestMethods()) { if (methodsToReRun.contains(m)) { result.add(m); } } methodsToReRun.clear(); Collection invoked= suite.getInvokedMethods(); for(ITestNGMethod tm: invoked) { if(!tm.isTest()) { methodsToReRun.add(tm); } } result.addAll(methodsToReRun); createXmlTest(context, result, xmlTest); } } /** * Generate testng-failed.xml */ private void createXmlTest(ITestContext context, List methods, XmlTest srcXmlTest) { XmlTest xmlTest = new XmlTest(m_xmlSuite); xmlTest.setName(context.getName() + "(failed)"); xmlTest.setBeanShellExpression(srcXmlTest.getExpression()); xmlTest.setIncludedGroups(srcXmlTest.getIncludedGroups()); xmlTest.setExcludedGroups(srcXmlTest.getExcludedGroups()); xmlTest.setParallel(srcXmlTest.getParallel()); xmlTest.setParameters(srcXmlTest.getLocalParameters()); xmlTest.setJUnit(srcXmlTest.isJUnit()); List xmlClasses = createXmlClasses(methods, srcXmlTest); xmlTest.setXmlClasses(xmlClasses); } /** * @param methods The methods we want to represent * @param srcXmlTest * @return A list of XmlClass objects (each representing a tag) based * on the parameter methods */ private List createXmlClasses(List methods, XmlTest srcXmlTest) { List result = Lists.newArrayList(); Map> methodsMap= Maps.newHashMap(); for (ITestNGMethod m : methods) { Object[] instances= m.getInstances(); Class clazz= instances == null || instances.length == 0 || instances[0] == null ? m.getRealClass() : instances[0].getClass(); Set methodList= methodsMap.get(clazz); if(null == methodList) { methodList= new HashSet<>(); methodsMap.put(clazz, methodList); } methodList.add(m); } // Ideally, we should preserve each parameter in each class but putting them // all in the same bag for now Map parameters = Maps.newHashMap(); for (XmlClass c : srcXmlTest.getClasses()) { parameters.putAll(c.getLocalParameters()); } int index = 0; for(Map.Entry> entry: methodsMap.entrySet()) { Class clazz= entry.getKey(); Set methodList= entry.getValue(); // @author Borojevic // Need to check all the methods, not just @Test ones. XmlClass xmlClass= new XmlClass(clazz.getName(), index++, false /* don't load classes */); List methodNames= Lists.newArrayList(methodList.size()); int ind = 0; for(ITestNGMethod m: methodList) { methodNames.add(new XmlInclude(m.getMethod().getName(), m.getFailedInvocationNumbers(), ind++)); } xmlClass.setIncludedMethods(methodNames); xmlClass.setParameters(parameters); result.add(xmlClass); } return result; } /** * TODO: we might want to make that more flexible in the future, but for * now, hardcode the file name */ private String getFileName(ITestContext context) { return TESTNG_FAILED_XML; } private static void ppp(String s) { System.out.println("[FailedReporter] " + s); } } testng-testng-6.9.5/src/main/java/org/testng/reporters/ExitCodeListener.java0000755000175000017500000000065612551235562026514 0ustar eugeneeugenepackage org.testng.reporters; import org.testng.TestNG; /** * A very simple ITestListener used by the TestNG runner to * find out the exit code. * * @author Alexandru Popescu */ public class ExitCodeListener extends TestNG.ExitCodeListener { public ExitCodeListener() { super(); } public ExitCodeListener(TestNG runner) { super(runner); } } testng-testng-6.9.5/src/main/java/org/testng/reporters/EmailableReporter2.java0000644000175000017500000007360612551235562026764 0ustar eugeneeugenepackage org.testng.reporters; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.text.NumberFormat; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Set; import org.testng.IReporter; import org.testng.ISuite; import org.testng.ISuiteResult; import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.Reporter; import org.testng.collections.Lists; import org.testng.internal.Utils; import org.testng.log4testng.Logger; import org.testng.xml.XmlSuite; /** * Reporter that generates a single-page HTML report of the test results. *

* Based on an earlier implementation by Paul Mendelson. *

* * @author Abraham Lin */ public class EmailableReporter2 implements IReporter { private static final Logger LOG = Logger.getLogger(EmailableReporter.class); protected PrintWriter writer; protected List suiteResults = Lists.newArrayList(); // Reusable buffer private StringBuilder buffer = new StringBuilder(); @Override public void generateReport(List xmlSuites, List suites, String outputDirectory) { try { writer = createWriter(outputDirectory); } catch (IOException e) { LOG.error("Unable to create output file", e); return; } for (ISuite suite : suites) { suiteResults.add(new SuiteResult(suite)); } writeDocumentStart(); writeHead(); writeBody(); writeDocumentEnd(); writer.close(); } protected PrintWriter createWriter(String outdir) throws IOException { new File(outdir).mkdirs(); return new PrintWriter(new BufferedWriter(new FileWriter(new File( outdir, "emailable-report.html")))); } protected void writeDocumentStart() { writer.println(""); writer.print(""); } protected void writeHead() { writer.print(""); writer.print("TestNG Report"); writeStylesheet(); writer.print(""); } protected void writeStylesheet() { writer.print(""); } protected void writeBody() { writer.print(""); writeSuiteSummary(); writeScenarioSummary(); writeScenarioDetails(); writer.print(""); } protected void writeDocumentEnd() { writer.print(""); } protected void writeSuiteSummary() { NumberFormat integerFormat = NumberFormat.getIntegerInstance(); NumberFormat decimalFormat = NumberFormat.getNumberInstance(); int totalPassedTests = 0; int totalSkippedTests = 0; int totalFailedTests = 0; long totalDuration = 0; writer.print(""); writer.print(""); writer.print(""); writer.print(""); writer.print(""); writer.print(""); writer.print(""); writer.print(""); writer.print(""); writer.print(""); int testIndex = 0; for (SuiteResult suiteResult : suiteResults) { writer.print(""); for (TestResult testResult : suiteResult.getTestResults()) { int passedTests = testResult.getPassedTestCount(); int skippedTests = testResult.getSkippedTestCount(); int failedTests = testResult.getFailedTestCount(); long duration = testResult.getDuration(); writer.print(""); buffer.setLength(0); writeTableData(buffer.append("") .append(Utils.escapeHtml(testResult.getTestName())) .append("").toString()); writeTableData(integerFormat.format(passedTests), "num"); writeTableData(integerFormat.format(skippedTests), (skippedTests > 0 ? "num attn" : "num")); writeTableData(integerFormat.format(failedTests), (failedTests > 0 ? "num attn" : "num")); writeTableData(decimalFormat.format(duration), "num"); writeTableData(testResult.getIncludedGroups()); writeTableData(testResult.getExcludedGroups()); writer.print(""); totalPassedTests += passedTests; totalSkippedTests += skippedTests; totalFailedTests += failedTests; totalDuration += duration; testIndex++; } } // Print totals if there was more than one test if (testIndex > 1) { writer.print(""); writer.print(""); writeTableHeader(integerFormat.format(totalPassedTests), "num"); writeTableHeader(integerFormat.format(totalSkippedTests), (totalSkippedTests > 0 ? "num attn" : "num")); writeTableHeader(integerFormat.format(totalFailedTests), (totalFailedTests > 0 ? "num attn" : "num")); writeTableHeader(decimalFormat.format(totalDuration), "num"); writer.print(""); writer.print(""); } writer.print("
Test# Passed# Skipped# FailedTime (ms)Included GroupsExcluded Groups
"); writer.print(Utils.escapeHtml(suiteResult.getSuiteName())); writer.print("
Total
"); } /** * Writes a summary of all the test scenarios. */ protected void writeScenarioSummary() { writer.print(""); writer.print(""); writer.print(""); writer.print(""); writer.print(""); writer.print(""); writer.print(""); writer.print(""); writer.print(""); int testIndex = 0; int scenarioIndex = 0; for (SuiteResult suiteResult : suiteResults) { writer.print(""); for (TestResult testResult : suiteResult.getTestResults()) { writer.print(""); String testName = Utils.escapeHtml(testResult.getTestName()); scenarioIndex += writeScenarioSummary(testName + " — failed (configuration methods)", testResult.getFailedConfigurationResults(), "failed", scenarioIndex); scenarioIndex += writeScenarioSummary(testName + " — failed", testResult.getFailedTestResults(), "failed", scenarioIndex); scenarioIndex += writeScenarioSummary(testName + " — skipped (configuration methods)", testResult.getSkippedConfigurationResults(), "skipped", scenarioIndex); scenarioIndex += writeScenarioSummary(testName + " — skipped", testResult.getSkippedTestResults(), "skipped", scenarioIndex); scenarioIndex += writeScenarioSummary(testName + " — passed", testResult.getPassedTestResults(), "passed", scenarioIndex); writer.print(""); testIndex++; } } writer.print("
ClassMethodStartTime (ms)
"); writer.print(Utils.escapeHtml(suiteResult.getSuiteName())); writer.print("
"); } /** * Writes the scenario summary for the results of a given state for a single * test. */ private int writeScenarioSummary(String description, List classResults, String cssClassPrefix, int startingScenarioIndex) { int scenarioCount = 0; if (!classResults.isEmpty()) { writer.print(""); writer.print(description); writer.print(""); int scenarioIndex = startingScenarioIndex; int classIndex = 0; for (ClassResult classResult : classResults) { String cssClass = cssClassPrefix + ((classIndex % 2) == 0 ? "even" : "odd"); buffer.setLength(0); int scenariosPerClass = 0; int methodIndex = 0; for (MethodResult methodResult : classResult.getMethodResults()) { List results = methodResult.getResults(); int resultsCount = results.size(); assert resultsCount > 0; ITestResult firstResult = results.iterator().next(); String methodName = Utils.escapeHtml(firstResult .getMethod().getMethodName()); long start = firstResult.getStartMillis(); long duration = firstResult.getEndMillis() - start; // The first method per class shares a row with the class // header if (methodIndex > 0) { buffer.append(""); } // Write the timing information with the first scenario per // method buffer.append("").append(methodName) .append("").append("").append(start) .append("").append("") .append(duration).append(""); scenarioIndex++; // Write the remaining scenarios for the method for (int i = 1; i < resultsCount; i++) { buffer.append("").append("") .append(methodName).append(""); scenarioIndex++; } scenariosPerClass += resultsCount; methodIndex++; } // Write the test results for the class writer.print(""); writer.print(""); writer.print(Utils.escapeHtml(classResult.getClassName())); writer.print(""); writer.print(buffer); classIndex++; } scenarioCount = scenarioIndex - startingScenarioIndex; } return scenarioCount; } /** * Writes the details for all test scenarios. */ protected void writeScenarioDetails() { int scenarioIndex = 0; for (SuiteResult suiteResult : suiteResults) { for (TestResult testResult : suiteResult.getTestResults()) { writer.print("

"); writer.print(Utils.escapeHtml(testResult.getTestName())); writer.print("

"); scenarioIndex += writeScenarioDetails( testResult.getFailedConfigurationResults(), scenarioIndex); scenarioIndex += writeScenarioDetails( testResult.getFailedTestResults(), scenarioIndex); scenarioIndex += writeScenarioDetails( testResult.getSkippedConfigurationResults(), scenarioIndex); scenarioIndex += writeScenarioDetails( testResult.getSkippedTestResults(), scenarioIndex); scenarioIndex += writeScenarioDetails( testResult.getPassedTestResults(), scenarioIndex); } } } /** * Writes the scenario details for the results of a given state for a single * test. */ private int writeScenarioDetails(List classResults, int startingScenarioIndex) { int scenarioIndex = startingScenarioIndex; for (ClassResult classResult : classResults) { String className = classResult.getClassName(); for (MethodResult methodResult : classResult.getMethodResults()) { List results = methodResult.getResults(); assert !results.isEmpty(); String label = Utils .escapeHtml(className + "#" + results.iterator().next().getMethod() .getMethodName()); for (ITestResult result : results) { writeScenario(scenarioIndex, label, result); scenarioIndex++; } } } return scenarioIndex - startingScenarioIndex; } /** * Writes the details for an individual test scenario. */ private void writeScenario(int scenarioIndex, String label, ITestResult result) { writer.print("

"); writer.print(label); writer.print("

"); writer.print(""); // Write test parameters (if any) Object[] parameters = result.getParameters(); int parameterCount = (parameters == null ? 0 : parameters.length); if (parameterCount > 0) { writer.print(""); for (int i = 1; i <= parameterCount; i++) { writer.print(""); } writer.print(""); for (Object parameter : parameters) { writer.print(""); } writer.print(""); } // Write reporter messages (if any) List reporterMessages = Reporter.getOutput(result); if (!reporterMessages.isEmpty()) { writer.print(" 1) { writer.print(" colspan=\""); writer.print(parameterCount); writer.print("\""); } writer.print(">Messages"); writer.print(" 1) { writer.print(" colspan=\""); writer.print(parameterCount); writer.print("\""); } writer.print(">"); writeReporterMessages(reporterMessages); writer.print(""); } // Write exception (if any) Throwable throwable = result.getThrowable(); if (throwable != null) { writer.print(" 1) { writer.print(" colspan=\""); writer.print(parameterCount); writer.print("\""); } writer.print(">"); writer.print((result.getStatus() == ITestResult.SUCCESS ? "Expected Exception" : "Exception")); writer.print(""); writer.print(" 1) { writer.print(" colspan=\""); writer.print(parameterCount); writer.print("\""); } writer.print(">"); writeStackTrace(throwable); writer.print(""); } writer.print("
Parameter #"); writer.print(i); writer.print("
"); writer.print(Utils.escapeHtml(Utils.toString(parameter))); writer.print("
"); writer.print("

back to summary

"); } protected void writeReporterMessages(List reporterMessages) { writer.print("
"); Iterator iterator = reporterMessages.iterator(); assert iterator.hasNext(); writer.print(Utils.escapeHtml(iterator.next())); while (iterator.hasNext()) { writer.print("
"); writer.print(Utils.escapeHtml(iterator.next())); } writer.print("
"); } protected void writeStackTrace(Throwable throwable) { writer.print("
"); writer.print(Utils.stackTrace(throwable, true)[0]); writer.print("
"); } /** * Writes a TH element with the specified contents and CSS class names. * * @param html * the HTML contents * @param cssClasses * the space-delimited CSS classes or null if there are no * classes to apply */ protected void writeTableHeader(String html, String cssClasses) { writeTag("th", html, cssClasses); } /** * Writes a TD element with the specified contents. * * @param html * the HTML contents */ protected void writeTableData(String html) { writeTableData(html, null); } /** * Writes a TD element with the specified contents and CSS class names. * * @param html * the HTML contents * @param cssClasses * the space-delimited CSS classes or null if there are no * classes to apply */ protected void writeTableData(String html, String cssClasses) { writeTag("td", html, cssClasses); } /** * Writes an arbitrary HTML element with the specified contents and CSS * class names. * * @param tag * the tag name * @param html * the HTML contents * @param cssClasses * the space-delimited CSS classes or null if there are no * classes to apply */ protected void writeTag(String tag, String html, String cssClasses) { writer.print("<"); writer.print(tag); if (cssClasses != null) { writer.print(" class=\""); writer.print(cssClasses); writer.print("\""); } writer.print(">"); writer.print(html); writer.print(""); } /** * Groups {@link TestResult}s by suite. */ protected static class SuiteResult { private final String suiteName; private final List testResults = Lists.newArrayList(); public SuiteResult(ISuite suite) { suiteName = suite.getName(); for (ISuiteResult suiteResult : suite.getResults().values()) { testResults.add(new TestResult(suiteResult.getTestContext())); } } public String getSuiteName() { return suiteName; } /** * @return the test results (possibly empty) */ public List getTestResults() { return testResults; } } /** * Groups {@link ClassResult}s by test, type (configuration or test), and * status. */ protected static class TestResult { /** * Orders test results by class name and then by method name (in * lexicographic order). */ protected static final Comparator RESULT_COMPARATOR = new Comparator() { @Override public int compare(ITestResult o1, ITestResult o2) { int result = o1.getTestClass().getName() .compareTo(o2.getTestClass().getName()); if (result == 0) { result = o1.getMethod().getMethodName() .compareTo(o2.getMethod().getMethodName()); } return result; } }; private final String testName; private final List failedConfigurationResults; private final List failedTestResults; private final List skippedConfigurationResults; private final List skippedTestResults; private final List passedTestResults; private final int failedTestCount; private final int skippedTestCount; private final int passedTestCount; private final long duration; private final String includedGroups; private final String excludedGroups; public TestResult(ITestContext context) { testName = context.getName(); Set failedConfigurations = context .getFailedConfigurations().getAllResults(); Set failedTests = context.getFailedTests() .getAllResults(); Set skippedConfigurations = context .getSkippedConfigurations().getAllResults(); Set skippedTests = context.getSkippedTests() .getAllResults(); Set passedTests = context.getPassedTests() .getAllResults(); failedConfigurationResults = groupResults(failedConfigurations); failedTestResults = groupResults(failedTests); skippedConfigurationResults = groupResults(skippedConfigurations); skippedTestResults = groupResults(skippedTests); passedTestResults = groupResults(passedTests); failedTestCount = failedTests.size(); skippedTestCount = skippedTests.size(); passedTestCount = passedTests.size(); duration = context.getEndDate().getTime() - context.getStartDate().getTime(); includedGroups = formatGroups(context.getIncludedGroups()); excludedGroups = formatGroups(context.getExcludedGroups()); } /** * Groups test results by method and then by class. */ protected List groupResults(Set results) { List classResults = Lists.newArrayList(); if (!results.isEmpty()) { List resultsPerClass = Lists.newArrayList(); List resultsPerMethod = Lists.newArrayList(); List resultsList = Lists.newArrayList(results); Collections.sort(resultsList, RESULT_COMPARATOR); Iterator resultsIterator = resultsList.iterator(); assert resultsIterator.hasNext(); ITestResult result = resultsIterator.next(); resultsPerMethod.add(result); String previousClassName = result.getTestClass().getName(); String previousMethodName = result.getMethod().getMethodName(); while (resultsIterator.hasNext()) { result = resultsIterator.next(); String className = result.getTestClass().getName(); if (!previousClassName.equals(className)) { // Different class implies different method assert !resultsPerMethod.isEmpty(); resultsPerClass.add(new MethodResult(resultsPerMethod)); resultsPerMethod = Lists.newArrayList(); assert !resultsPerClass.isEmpty(); classResults.add(new ClassResult(previousClassName, resultsPerClass)); resultsPerClass = Lists.newArrayList(); previousClassName = className; previousMethodName = result.getMethod().getMethodName(); } else { String methodName = result.getMethod().getMethodName(); if (!previousMethodName.equals(methodName)) { assert !resultsPerMethod.isEmpty(); resultsPerClass.add(new MethodResult(resultsPerMethod)); resultsPerMethod = Lists.newArrayList(); previousMethodName = methodName; } } resultsPerMethod.add(result); } assert !resultsPerMethod.isEmpty(); resultsPerClass.add(new MethodResult(resultsPerMethod)); assert !resultsPerClass.isEmpty(); classResults.add(new ClassResult(previousClassName, resultsPerClass)); } return classResults; } public String getTestName() { return testName; } /** * @return the results for failed configurations (possibly empty) */ public List getFailedConfigurationResults() { return failedConfigurationResults; } /** * @return the results for failed tests (possibly empty) */ public List getFailedTestResults() { return failedTestResults; } /** * @return the results for skipped configurations (possibly empty) */ public List getSkippedConfigurationResults() { return skippedConfigurationResults; } /** * @return the results for skipped tests (possibly empty) */ public List getSkippedTestResults() { return skippedTestResults; } /** * @return the results for passed tests (possibly empty) */ public List getPassedTestResults() { return passedTestResults; } public int getFailedTestCount() { return failedTestCount; } public int getSkippedTestCount() { return skippedTestCount; } public int getPassedTestCount() { return passedTestCount; } public long getDuration() { return duration; } public String getIncludedGroups() { return includedGroups; } public String getExcludedGroups() { return excludedGroups; } /** * Formats an array of groups for display. */ protected String formatGroups(String[] groups) { if (groups.length == 0) { return ""; } StringBuilder builder = new StringBuilder(); builder.append(groups[0]); for (int i = 1; i < groups.length; i++) { builder.append(", ").append(groups[i]); } return builder.toString(); } } /** * Groups {@link MethodResult}s by class. */ protected static class ClassResult { private final String className; private final List methodResults; /** * @param className * the class name * @param methodResults * the non-null, non-empty {@link MethodResult} list */ public ClassResult(String className, List methodResults) { this.className = className; this.methodResults = methodResults; } public String getClassName() { return className; } /** * @return the non-null, non-empty {@link MethodResult} list */ public List getMethodResults() { return methodResults; } } /** * Groups test results by method. */ protected static class MethodResult { private final List results; /** * @param results * the non-null, non-empty result list */ public MethodResult(List results) { this.results = results; } /** * @return the non-null, non-empty result list */ public List getResults() { return results; } } } testng-testng-6.9.5/src/main/java/org/testng/reporters/EmailableReporter.java0000755000175000017500000004262112551235562026676 0ustar eugeneeugenepackage org.testng.reporters; import org.testng.IInvokedMethod; import org.testng.IReporter; import org.testng.IResultMap; import org.testng.ISuite; import org.testng.ISuiteResult; import org.testng.ITestClass; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.ITestResult; import org.testng.Reporter; import org.testng.collections.Lists; import org.testng.internal.Utils; import org.testng.log4testng.Logger; import org.testng.xml.XmlSuite; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Set; /** * Reported designed to render self-contained HTML top down view of a testing * suite. * * @author Paul Mendelson * @since 5.2 * @version $Revision: 719 $ */ public class EmailableReporter implements IReporter { private static final Logger L = Logger.getLogger(EmailableReporter.class); // ~ Instance fields ------------------------------------------------------ private PrintWriter m_out; private int m_row; private Integer m_testIndex; private int m_methodIndex; // ~ Methods -------------------------------------------------------------- /** Creates summary of the run */ @Override public void generateReport(List xml, List suites, String outdir) { try { m_out = createWriter(outdir); } catch (IOException e) { L.error("output file", e); return; } startHtml(m_out); generateSuiteSummaryReport(suites); generateMethodSummaryReport(suites); generateMethodDetailReport(suites); endHtml(m_out); m_out.flush(); m_out.close(); } protected PrintWriter createWriter(String outdir) throws IOException { new File(outdir).mkdirs(); return new PrintWriter(new BufferedWriter(new FileWriter(new File(outdir, "emailable-report.html")))); } /** Creates a table showing the highlights of each test method with links to the method details */ protected void generateMethodSummaryReport(List suites) { m_methodIndex = 0; startResultSummaryTable("methodOverview"); int testIndex = 1; for (ISuite suite : suites) { if(suites.size()>1) { titleRow(suite.getName(), 5); } Map r = suite.getResults(); for (ISuiteResult r2 : r.values()) { ITestContext testContext = r2.getTestContext(); String testName = testContext.getName(); m_testIndex = testIndex; resultSummary(suite, testContext.getFailedConfigurations(), testName, "failed", " (configuration methods)"); resultSummary(suite, testContext.getFailedTests(), testName, "failed", ""); resultSummary(suite, testContext.getSkippedConfigurations(), testName, "skipped", " (configuration methods)"); resultSummary(suite, testContext.getSkippedTests(), testName, "skipped", ""); resultSummary(suite, testContext.getPassedTests(), testName, "passed", ""); testIndex++; } } m_out.println(""); } /** Creates a section showing known results for each method */ protected void generateMethodDetailReport(List suites) { m_methodIndex = 0; for (ISuite suite : suites) { Map r = suite.getResults(); for (ISuiteResult r2 : r.values()) { ITestContext testContext = r2.getTestContext(); if (r.values().size() > 0) { m_out.println("

" + testContext.getName() + "

"); } resultDetail(testContext.getFailedConfigurations()); resultDetail(testContext.getFailedTests()); resultDetail(testContext.getSkippedConfigurations()); resultDetail(testContext.getSkippedTests()); resultDetail(testContext.getPassedTests()); } } } /** * @param tests */ private void resultSummary(ISuite suite, IResultMap tests, String testname, String style, String details) { if (tests.getAllResults().size() > 0) { StringBuffer buff = new StringBuffer(); String lastClassName = ""; int mq = 0; int cq = 0; for (ITestNGMethod method : getMethodSet(tests, suite)) { m_row += 1; m_methodIndex += 1; ITestClass testClass = method.getTestClass(); String className = testClass.getName(); if (mq == 0) { String id = (m_testIndex == null ? null : "t" + Integer.toString(m_testIndex)); titleRow(testname + " — " + style + details, 5, id); m_testIndex = null; } if (!className.equalsIgnoreCase(lastClassName)) { if (mq > 0) { cq += 1; m_out.print("" + " 1) { m_out.print(" rowspan=\"" + mq + "\""); } m_out.println(">" + lastClassName + "" + buff); } mq = 0; buff.setLength(0); lastClassName = className; } Set resultSet = tests.getResults(method); long end = Long.MIN_VALUE; long start = Long.MAX_VALUE; for (ITestResult testResult : tests.getResults(method)) { if (testResult.getEndMillis() > end) { end = testResult.getEndMillis(); } if (testResult.getStartMillis() < start) { start = testResult.getStartMillis(); } } mq += 1; if (mq > 1) { buff.append(""); } String description = method.getDescription(); String testInstanceName = resultSet.toArray(new ITestResult[]{})[0].getTestName(); buff.append("" + qualifiedName(method) + " " + (description != null && description.length() > 0 ? "(\"" + description + "\")" : "") + "" + (null == testInstanceName ? "" : "
(" + testInstanceName + ")") + "" + "" + resultSet.size() + "" + "" + start + "" + "" + (end - start) + "" + ""); } if (mq > 0) { cq += 1; m_out.print("" + " 1) { m_out.print(" rowspan=\"" + mq + "\""); } m_out.println(">" + lastClassName + "" + buff); } } } /** Starts and defines columns result summary table */ private void startResultSummaryTable(String style) { tableStart(style, "summary"); m_out.println("Class" + "Method# of
ScenariosStartTime
(ms)"); m_row = 0; } private String qualifiedName(ITestNGMethod method) { StringBuilder addon = new StringBuilder(); String[] groups = method.getGroups(); int length = groups.length; if (length > 0 && !"basic".equalsIgnoreCase(groups[0])) { addon.append("("); for (int i = 0; i < length; i++) { if (i > 0) { addon.append(", "); } addon.append(groups[i]); } addon.append(")"); } return "" + method.getMethodName() + " " + addon; } private void resultDetail(IResultMap tests) { for (ITestResult result : tests.getAllResults()) { ITestNGMethod method = result.getMethod(); m_methodIndex++; String cname = method.getTestClass().getName(); m_out.println("

" + cname + ":" + method.getMethodName() + "

"); Set resultSet = tests.getResults(method); generateForResult(result, method, resultSet.size()); m_out.println("

back to summary

"); } } private void generateForResult(ITestResult ans, ITestNGMethod method, int resultSetSize) { Object[] parameters = ans.getParameters(); boolean hasParameters = parameters != null && parameters.length > 0; if (hasParameters) { tableStart("result", null); m_out.print(""); for (int x = 1; x <= parameters.length; x++) { m_out.print("Parameter #" + x + ""); } m_out.println(""); m_out.print(""); for (Object p : parameters) { m_out.println("" + Utils.escapeHtml(Utils.toString(p)) + ""); } m_out.println(""); } List msgs = Reporter.getOutput(ans); boolean hasReporterOutput = msgs.size() > 0; Throwable exception=ans.getThrowable(); boolean hasThrowable = exception!=null; if (hasReporterOutput||hasThrowable) { if (hasParameters) { m_out.print(" 1) { m_out.print(" colspan=\"" + parameters.length + "\""); } m_out.println(">"); } else { m_out.println("
"); } if (hasReporterOutput) { if(hasThrowable) { m_out.println("

Test Messages

"); } for (String line : msgs) { m_out.println(line + "
"); } } if(hasThrowable) { boolean wantsMinimalOutput = ans.getStatus()==ITestResult.SUCCESS; if(hasReporterOutput) { m_out.println("

" +(wantsMinimalOutput?"Expected Exception":"Failure") +"

"); } generateExceptionReport(exception,method); } if (hasParameters) { m_out.println(""); } else { m_out.println("
"); } } if (hasParameters) { m_out.println(""); } } protected void generateExceptionReport(Throwable exception,ITestNGMethod method) { m_out.print("
"); m_out.print(Utils.stackTrace(exception, true)[0]); m_out.println("
"); } /** * Since the methods will be sorted chronologically, we want to return * the ITestNGMethod from the invoked methods. */ private Collection getMethodSet(IResultMap tests, ISuite suite) { List r = Lists.newArrayList(); List invokedMethods = suite.getAllInvokedMethods(); for (IInvokedMethod im : invokedMethods) { if (tests.getAllMethods().contains(im.getTestMethod())) { r.add(im); } } Arrays.sort(r.toArray(new IInvokedMethod[r.size()]), new TestSorter()); List result = Lists.newArrayList(); // Add all the invoked methods for (IInvokedMethod m : r) { result.add(m.getTestMethod()); } // Add all the methods that weren't invoked (e.g. skipped) that we // haven't added yet for (ITestNGMethod m : tests.getAllMethods()) { if (!result.contains(m)) { result.add(m); } } return result; } public void generateSuiteSummaryReport(List suites) { tableStart("testOverview", null); m_out.print(""); tableColumnStart("Test"); tableColumnStart("Methods
Passed"); tableColumnStart("Scenarios
Passed"); tableColumnStart("# skipped"); tableColumnStart("# failed"); tableColumnStart("Total
Time"); tableColumnStart("Included
Groups"); tableColumnStart("Excluded
Groups"); m_out.println(""); NumberFormat formatter = new DecimalFormat("#,##0.0"); int qty_tests = 0; int qty_pass_m = 0; int qty_pass_s = 0; int qty_skip = 0; int qty_fail = 0; long time_start = Long.MAX_VALUE; long time_end = Long.MIN_VALUE; m_testIndex = 1; for (ISuite suite : suites) { if (suites.size() > 1) { titleRow(suite.getName(), 8); } Map tests = suite.getResults(); for (ISuiteResult r : tests.values()) { qty_tests += 1; ITestContext overview = r.getTestContext(); startSummaryRow(overview.getName()); int q = getMethodSet(overview.getPassedTests(), suite).size(); qty_pass_m += q; summaryCell(q,Integer.MAX_VALUE); q = overview.getPassedTests().size(); qty_pass_s += q; summaryCell(q,Integer.MAX_VALUE); q = getMethodSet(overview.getSkippedTests(), suite).size(); qty_skip += q; summaryCell(q,0); q = getMethodSet(overview.getFailedTests(), suite).size(); qty_fail += q; summaryCell(q,0); time_start = Math.min(overview.getStartDate().getTime(), time_start); time_end = Math.max(overview.getEndDate().getTime(), time_end); summaryCell(formatter.format( (overview.getEndDate().getTime() - overview.getStartDate().getTime()) / 1000.) + " seconds", true); summaryCell(overview.getIncludedGroups()); summaryCell(overview.getExcludedGroups()); m_out.println(""); m_testIndex++; } } if (qty_tests > 1) { m_out.println("Total"); summaryCell(qty_pass_m,Integer.MAX_VALUE); summaryCell(qty_pass_s,Integer.MAX_VALUE); summaryCell(qty_skip,0); summaryCell(qty_fail,0); summaryCell(formatter.format((time_end - time_start) / 1000.) + " seconds", true); m_out.println(" "); } m_out.println(""); } private void summaryCell(String[] val) { StringBuffer b = new StringBuffer(); for (String v : val) { b.append(v + " "); } summaryCell(b.toString(),true); } private void summaryCell(String v,boolean isgood) { m_out.print("" + v + ""); } private void startSummaryRow(String label) { m_row += 1; m_out.print("" + label + "" + ""); } private void summaryCell(int v,int maxexpected) { summaryCell(String.valueOf(v),v<=maxexpected); } private void tableStart(String cssclass, String id) { m_out.println(""); m_row = 0; } private void tableColumnStart(String label) { m_out.print(""); } private void titleRow(String label, int cq) { titleRow(label, cq, null); } private void titleRow(String label, int cq, String id) { m_out.print(""); m_row = 0; } /** Starts HTML stream */ protected void startHtml(PrintWriter out) { out.println(""); out.println(""); out.println(""); out.println("TestNG Report"); out.println(""); out.println(""); out.println(""); } /** Finishes HTML stream */ protected void endHtml(PrintWriter out) { out.println(""); } // ~ Inner Classes -------------------------------------------------------- /** Arranges methods by classname and method name */ private class TestSorter implements Comparator { // ~ Methods ------------------------------------------------------------- /** Arranges methods by classname and method name */ @Override public int compare(IInvokedMethod o1, IInvokedMethod o2) { // System.out.println("Comparing " + o1.getMethodName() + " " + o1.getDate() // + " and " + o2.getMethodName() + " " + o2.getDate()); return (int) (o1.getDate() - o2.getDate()); // int r = ((T) o1).getTestClass().getName().compareTo(((T) o2).getTestClass().getName()); // if (r == 0) { // r = ((T) o1).getMethodName().compareTo(((T) o2).getMethodName()); // } // return r; } } } testng-testng-6.9.5/src/main/java/org/testng/reporters/DotTestListener.java0000755000175000017500000000106012551235562026364 0ustar eugeneeugenepackage org.testng.reporters; import org.testng.ITestResult; import org.testng.TestListenerAdapter; public class DotTestListener extends TestListenerAdapter { private int m_count = 0; @Override public void onTestFailure(ITestResult tr) { log("F"); } @Override public void onTestSkipped(ITestResult tr) { log("S"); } @Override public void onTestSuccess(ITestResult tr) { log("."); } private void log(String string) { System.out.print(string); if (m_count++ % 40 == 0) { System.out.println(""); } } } testng-testng-6.9.5/src/main/java/org/testng/reporters/Buffer.java0000644000175000017500000000020112551235562024472 0ustar eugeneeugenepackage org.testng.reporters; public class Buffer { public static IBuffer create() { return new FileStringBuffer(); } } testng-testng-6.9.5/src/main/java/org/testng/remote/0000755000175000017500000000000012551235562021673 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/0000755000175000017500000000000012551235562024265 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/TestResultMessage.java0000755000175000017500000003165612551235562030571 0ustar eugeneeugenepackage org.testng.remote.strprotocol; import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.SkipException; import org.testng.collections.Lists; import static org.testng.internal.Utils.isStringEmpty; /** * An IStringMessage implementation for test results events. * * @author Alexandru Popescu */ public class TestResultMessage implements IStringMessage { protected int m_messageType; protected String m_suiteName; protected String m_testName; protected String m_testClassName; protected String m_testMethodName; protected String m_stackTrace; protected long m_startMillis; protected long m_endMillis; protected String[] m_parameters= new String[0]; protected String[] m_paramTypes= new String[0]; private String m_testDescription; private int m_invocationCount; private int m_currentInvocationCount; private String m_instanceName; /** * This constructor is used by the Eclipse client to initialize a result message based * on what was received over the network. */ public TestResultMessage(final int resultType, final String suiteName, final String testName, final String className, final String methodName, final String testDescriptor, String instanceName, final String[] params, final long startMillis, final long endMillis, final String stackTrace, int invocationCount, int currentInvocationCount) { init(resultType, suiteName, testName, className, methodName, stackTrace, startMillis, endMillis, extractParams(params), extractParamTypes(params), testDescriptor, instanceName, invocationCount, currentInvocationCount ); } /** * This constructor is used by RemoteTestNG to initialize a result message * from an ITestResult. */ public TestResultMessage(final String suiteName, final String testName, final ITestResult result) { Throwable throwable = result.getThrowable(); String stackTrace = null; if((ITestResult.FAILURE == result.getStatus()) || (ITestResult.SUCCESS_PERCENTAGE_FAILURE == result.getStatus())) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); Throwable cause= throwable; if (null != cause) { cause.printStackTrace(pw); stackTrace = sw.getBuffer().toString(); } else { stackTrace= "unknown stack trace"; } } else if(ITestResult.SKIP == result.getStatus() && (throwable != null && SkipException.class.isAssignableFrom(throwable.getClass()))) { stackTrace= throwable.getMessage(); } else if (throwable != null) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); throwable.printStackTrace(pw); stackTrace = sw.toString(); } init(MessageHelper.TEST_RESULT + result.getStatus(), suiteName, testName, result.getTestClass().getName(), result.getMethod().getMethod().getName(), MessageHelper.replaceUnicodeCharactersWithAscii(stackTrace), result.getStartMillis(), result.getEndMillis(), toString(result.getParameters(), result.getMethod().getMethod().getParameterTypes()), toString(result.getMethod().getMethod().getParameterTypes()), MessageHelper.replaceUnicodeCharactersWithAscii(result.getName()), MessageHelper.replaceUnicodeCharactersWithAscii(result.getInstanceName()), result.getMethod().getInvocationCount(), result.getMethod().getCurrentInvocationCount() ); } public TestResultMessage(final ITestContext testCtx, final ITestResult result) { this(testCtx.getSuite().getName(), testCtx.getCurrentXmlTest().getName(), result); // this(testCtx.getSuite().getName(), // result.getTestName() != null ? result.getTestName() : result.getName(), result); } private void init(final int resultType, final String suiteName, final String testName, final String className, final String methodName, final String stackTrace, final long startMillis, final long endMillis, final String[] parameters, final String[] types, final String testDescription, String instanceName, int invocationCount, int currentInvocationCount) { m_messageType = resultType; m_suiteName = suiteName; m_testName = testName; m_testClassName = className; m_testMethodName = methodName; m_stackTrace = stackTrace; m_startMillis= startMillis; m_endMillis= endMillis; m_parameters= parameters; m_paramTypes= types; m_testDescription= testDescription; m_invocationCount = invocationCount; m_currentInvocationCount = currentInvocationCount; m_instanceName = instanceName; } public int getResult() { return m_messageType; } @Override public String getMessageAsString() { StringBuffer buf = new StringBuffer(); StringBuffer parambuf = new StringBuffer(); if(null != m_parameters && m_parameters.length > 0) { for (int j = 0; j < m_parameters.length; j++) { if (j > 0) { parambuf.append(MessageHelper.PARAM_DELIMITER); } parambuf.append(m_paramTypes[j] + ":" + m_parameters[j]); } } buf.append(m_messageType) .append(MessageHelper.DELIMITER) .append(m_suiteName) .append(MessageHelper.DELIMITER) .append(m_testName) .append(MessageHelper.DELIMITER) .append(m_testClassName) .append(MessageHelper.DELIMITER) .append(m_testMethodName) .append(MessageHelper.DELIMITER) .append(parambuf) .append(MessageHelper.DELIMITER) .append(m_startMillis) .append(MessageHelper.DELIMITER) .append(m_endMillis) .append(MessageHelper.DELIMITER) .append(MessageHelper.replaceNewLine(m_stackTrace)) .append(MessageHelper.DELIMITER) .append(MessageHelper.replaceNewLine(m_testDescription)) ; return buf.toString(); } public String getSuiteName() { return m_suiteName; } public String getTestClass() { return m_testClassName; } public String getMethod() { return m_testMethodName; } public String getName() { return m_testName; } public String getStackTrace() { return m_stackTrace; } public long getEndMillis() { return m_endMillis; } public long getStartMillis() { return m_startMillis; } public String[] getParameters() { return m_parameters; } public String[] getParameterTypes() { return m_paramTypes; } public String getTestDescription() { return m_testDescription; } public String toDisplayString() { StringBuffer buf= new StringBuffer(m_testName != null ? m_testName : m_testMethodName); if(null != m_parameters && m_parameters.length > 0) { buf.append("("); for(int i= 0; i < m_parameters.length; i++) { if(i > 0) { buf.append(", "); } if("java.lang.String".equals(m_paramTypes[i]) && !("null".equals(m_parameters[i]) || "\"\"".equals(m_parameters[i]))) { buf.append("\"").append(m_parameters[i]).append("\""); } else { buf.append(m_parameters[i]); } } buf.append(")"); } return buf.toString(); } @Override public boolean equals(Object o) { if(this == o) { return true; } if(o == null || getClass() != o.getClass()) { return false; } final TestResultMessage that = (TestResultMessage) o; if(m_suiteName != null ? !m_suiteName.equals(that.m_suiteName) : that.m_suiteName != null) { return false; } if(m_testName != null ? !m_testName.equals(that.m_testName) : that.m_testName != null) { return false; } if(m_testClassName != null ? !m_testClassName.equals(that.m_testClassName) : that.m_testClassName != null) { return false; } String toDisplayString= toDisplayString(); if(toDisplayString != null ? !toDisplayString.equals(that.toDisplayString()) : that.toDisplayString() != null) { return false; } return true; } @Override public int hashCode() { int result = (m_suiteName != null ? m_suiteName.hashCode() : 0); result = 29 * result + (m_testName != null ? m_testName.hashCode() : 0); result = 29 * result + m_testClassName.hashCode(); result = 29 * result + toDisplayString().hashCode(); return result; } String[] toString(Object[] objects, Class[] objectClasses) { if(null == objects) { return new String[0]; } List result= Lists.newArrayList(objects.length); for(Object o: objects) { if(null == o) { result.add("null"); } else if (o.getClass().isArray()) { String[] strArray; if (o.getClass().getComponentType().isPrimitive()){ strArray = primitiveArrayToString(o); } else { strArray = toString((Object[]) o, null); } StringBuilder sb = new StringBuilder("["); for (int i = 0; i < strArray.length; i++) { sb.append(strArray[i]); if (i + 1 < strArray.length) { sb.append(","); } } sb.append("]"); result.add(sb.toString()); } else { String tostring= o.toString(); if(isStringEmpty(tostring)) { result.add("\"\""); } else { result.add(MessageHelper.replaceNewLine(tostring)); } } } return result.toArray(new String[result.size()]); } private String[] primitiveArrayToString(Object o) { List results = Lists.newArrayList(); if (o instanceof byte[]) { byte[] array = (byte[]) o; for (byte anArray : array) { results.add(String.valueOf(anArray)); } } else if (o instanceof boolean[]) { boolean[] array = (boolean[]) o; for (boolean anArray : array) { results.add(String.valueOf(anArray)); } } else if (o instanceof char[]) { char[] array = (char[]) o; for (char anArray : array) { results.add(String.valueOf(anArray)); } } else if (o instanceof double[]) { double[] array = (double[]) o; for (double anArray : array) { results.add(String.valueOf(anArray)); } } else if (o instanceof float[]) { float[] array = (float[]) o; for (float anArray : array) { results.add(String.valueOf(anArray)); } } else if (o instanceof short[]) { short[] array = (short[]) o; for (short anArray : array) { results.add(String.valueOf(anArray)); } } else if (o instanceof int[]) { int[] array = (int[]) o; for (int anArray : array) { results.add(String.valueOf(anArray)); } } else if (o instanceof long[]) { long[] array = (long[]) o; for (long anArray : array) { results.add(String.valueOf(anArray)); } } return results.toArray(new String[results.size()]); } private String[] toString(Class[] classes) { if(null == classes) { return new String[0]; } List result= Lists.newArrayList(classes.length); for(Class cls: classes) { result.add(cls.getName()); } return result.toArray(new String[result.size()]); } private String[] extractParamTypes(String[] params) { List result= Lists.newArrayList(params.length); for(String s: params) { result.add(s.substring(0, s.indexOf(':'))); } return result.toArray(new String[result.size()]); } private String[] extractParams(String[] params) { List result= Lists.newArrayList(params.length); for(String s: params) { result.add(MessageHelper.replaceNewLineReplacer(s.substring(s.indexOf(':') + 1))); } return result.toArray(new String[result.size()]); } public int getInvocationCount() { return m_invocationCount; } public int getCurrentInvocationCount() { return m_currentInvocationCount; } @Override public String toString() { return "[TestResultMessage suite:" + m_suiteName + " test:" + m_testName + " method:" + m_testMethodName + "]"; } public void setParameters(String[] params) { m_parameters = extractParams(params); m_paramTypes = extractParamTypes(params); } public String getInstanceName() { return m_instanceName; } } testng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/TestMessage.java0000755000175000017500000000635612551235562027371 0ustar eugeneeugenepackage org.testng.remote.strprotocol; import org.testng.ITestContext; /** * An IStringMessage implementation for test events. * * @author Alexandru Popescu */ public class TestMessage implements IStringMessage { protected final boolean m_testStart; protected final String m_suiteName; protected final String m_testName; protected final int m_testMethodCount; protected final int m_passedTestCount; protected final int m_failedTestCount; protected final int m_skippedTestCount; protected final int m_successPercentageFailedTestCount; public TestMessage(final boolean isTestStart, final String suiteName, final String testName, final int methodCount, final int passedCount, final int failedCount, final int skippedCount, final int percentageCount) { m_testStart = isTestStart; m_suiteName = suiteName; m_testName = testName; m_testMethodCount = methodCount; m_passedTestCount = passedCount; m_failedTestCount = failedCount; m_skippedTestCount = skippedCount; m_successPercentageFailedTestCount = percentageCount; } public TestMessage(final ITestContext testContext, final boolean isTestStart) { this(isTestStart, testContext.getSuite().getName(), testContext.getCurrentXmlTest().getName(), testContext.getAllTestMethods().length, testContext.getPassedTests().size(), testContext.getFailedTests().size(), testContext.getSkippedTests().size(), testContext.getFailedButWithinSuccessPercentageTests().size()); } public boolean isMessageOnStart() { return m_testStart; } @Override public String getMessageAsString() { StringBuffer buf = new StringBuffer(); buf.append(m_testStart ? MessageHelper.TEST_START : MessageHelper.TEST_FINISH) .append(MessageHelper.DELIMITER) .append(m_suiteName) .append(MessageHelper.DELIMITER) .append(m_testName) .append(MessageHelper.DELIMITER) .append(m_testMethodCount) .append(MessageHelper.DELIMITER) .append(m_passedTestCount) .append(MessageHelper.DELIMITER) .append(m_failedTestCount) .append(MessageHelper.DELIMITER) .append(m_skippedTestCount) .append(MessageHelper.DELIMITER) .append(m_successPercentageFailedTestCount) ; return buf.toString(); } public String getSuiteName() { return m_suiteName; } public String getTestName() { return m_testName; } public boolean isTestStart() { return m_testStart; } public int getTestMethodCount() { return m_testMethodCount; } public int getSuccessPercentageFailedTestCount() { return m_successPercentageFailedTestCount; } public int getFailedTestCount() { return m_failedTestCount; } public int getPassedTestCount() { return m_passedTestCount; } public int getSkippedTestCount() { return m_skippedTestCount; } @Override public String toString() { return "[TestMessage suite:" + m_suiteName + " testName:" + m_testName + " passed:" + m_passedTestCount + " failed:" + m_failedTestCount + "]"; } } testng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/SuiteMessage.java0000755000175000017500000000572112551235562027536 0ustar eugeneeugenepackage org.testng.remote.strprotocol; import java.util.Collection; import java.util.List; import java.util.Map; import org.testng.ISuite; import org.testng.ITestNGMethod; import org.testng.collections.Lists; import org.testng.collections.Maps; /** * A IStringMessage implementation for suite running events. * * @author Alexandru Popescu */ public class SuiteMessage implements IStringMessage { protected final String m_suiteName; protected final int m_testMethodCount; protected final boolean m_startSuite; private List m_excludedMethods = Lists.newArrayList(); private Map m_descriptions; public SuiteMessage(final String suiteName, final boolean startSuiteRun, final int methodCount) { m_suiteName = suiteName; m_startSuite = startSuiteRun; m_testMethodCount = methodCount; } public SuiteMessage(final ISuite suite, final boolean startSuiteRun) { m_suiteName = suite.getName(); m_testMethodCount =suite.getInvokedMethods().size(); m_startSuite = startSuiteRun; Collection excludedMethods = suite.getExcludedMethods(); if (excludedMethods != null && excludedMethods.size() > 0) { m_excludedMethods = Lists.newArrayList(); m_descriptions = Maps.newHashMap(); for (ITestNGMethod m : excludedMethods) { String methodName = m.getTestClass().getName() + "." + m.getMethodName(); m_excludedMethods.add(methodName); if (m.getDescription() != null) m_descriptions.put(methodName, m.getDescription()); } } } public void setExcludedMethods(List methods) { m_excludedMethods = Lists.newArrayList(); m_excludedMethods.addAll(methods); } public List getExcludedMethods() { return m_excludedMethods; } public String getDescriptionForMethod(String methodName) { return m_descriptions.get(methodName); } public boolean isMessageOnStart() { return m_startSuite; } public String getSuiteName() { return m_suiteName; } public int getTestMethodCount() { return m_testMethodCount; } @Override public String getMessageAsString() { StringBuffer buf = new StringBuffer(); buf.append(m_startSuite ? MessageHelper.SUITE_START : MessageHelper.SUITE_FINISH) .append(MessageHelper.DELIMITER) .append(m_suiteName) .append(MessageHelper.DELIMITER) .append(m_testMethodCount) ; if (m_excludedMethods != null && m_excludedMethods.size() > 0) { buf.append(MessageHelper.DELIMITER); buf.append(m_excludedMethods.size()); for (String method : m_excludedMethods) { buf.append(MessageHelper.DELIMITER); buf.append(method); } } return buf.toString(); } @Override public String toString() { return "[SuiteMessage suite:" + m_suiteName + (m_startSuite ? " starting" : " ending") + " methodCount:" + m_testMethodCount + "]"; } } testng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/StringMessageSender.java0000644000175000017500000001007512551235562031047 0ustar eugeneeugenepackage org.testng.remote.strprotocol; import org.testng.remote.RemoteTestNG; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.SocketException; public class StringMessageSender extends BaseMessageSender { private PrintWriter writer; public StringMessageSender(String host, int port) { super(host, port, false /* no ack */); } public StringMessageSender(String host, int port, boolean ack) { super(host, port, ack); } @Override public void sendMessage(IMessage message) { if (m_outStream == null) { throw new IllegalStateException("Trying to send a message on a shutdown sender"); } if (writer == null) { try { writer = new PrintWriter(new BufferedWriter( new OutputStreamWriter(m_outStream, "UTF-8")), //$NON-NLS-1$ false /* autoflush */); } catch (UnsupportedEncodingException e1) { writer = new PrintWriter(new BufferedWriter( new OutputStreamWriter(m_outStream)), false /* autoflush */); } } String msg = ((IStringMessage) message).getMessageAsString(); if (RemoteTestNG.isVerbose()) { p("Sending message:" + message); p(" String version:" + msg); StringBuffer buf = new StringBuffer(); for(int i = 0; i < msg.length(); i++) { if('\u0001' == msg.charAt(i)) { p(" word:[" + buf.toString() + "]"); buf.delete(0, buf.length()); } else { buf.append(msg.charAt(i)); } } p(" word:[" + buf.toString() + "]"); } synchronized(m_ackLock) { writer.println(msg); writer.flush(); waitForAck(); } } private static void p(String msg) { if (RemoteTestNG.isVerbose()) { System.out.println("[StringMessageSender] " + msg); //$NON-NLS-1$ } } @Override public IMessage receiveMessage() { IMessage result = null; if (m_inReader == null) { try { m_inReader = new BufferedReader(new InputStreamReader(m_inStream, "UTF-8")); } catch (UnsupportedEncodingException e) { m_inReader = new BufferedReader(new InputStreamReader(m_inStream)); } } try { // try { // m_outputWriter = new PrintWriter(new OutputStreamWriter(fSocket.getOutputStream(), "UTF-8"), // true); // } // catch(UnsupportedEncodingException e1) { // m_outputWriter = new PrintWriter(new OutputStreamWriter(fSocket.getOutputStream()), true); // } result = receiveMessage(m_inReader.readLine()); } catch(IOException e) { handleThrowable(e); } return result; // finally { // shutDown(); // return null; // } } protected void handleThrowable(Throwable cause) { if (RemoteTestNG.isVerbose()) { cause.printStackTrace(); } } // private String readMessage(BufferedReader in) throws IOException { // return in.readLine(); // } private IMessage receiveMessage(String message) { if (message == null) return null; IMessage result = null; int messageType = MessageHelper.getMessageType(message); // try { if(messageType < MessageHelper.SUITE) { // Generic message result = MessageHelper.unmarshallGenericMessage(message); } else if(messageType < MessageHelper.TEST) { // Suite message result = MessageHelper.createSuiteMessage(message); } else if(messageType < MessageHelper.TEST_RESULT) { // Test message result = MessageHelper.createTestMessage(message); } else { // TestResult message result = MessageHelper.unmarshallTestResultMessage(message); } // } // finally { // if(isRunning() && (null != m_outputWriter)) { // m_outputWriter.println(MessageHelper.ACK_MSG); // m_outputWriter.flush(); // } // } p("receiveMessage() received:" + result); return result; } } testng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/SerializedMessageSender.java0000644000175000017500000000253612551235562031677 0ustar eugeneeugenepackage org.testng.remote.strprotocol; import org.testng.remote.RemoteTestNG; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerializedMessageSender extends BaseMessageSender { public SerializedMessageSender(String host, int port) { super(host, port, false /* no ack */); } public SerializedMessageSender(String host, int port, boolean ack) { super(host, port, ack); } @Override public void sendMessage(IMessage message) throws IOException { synchronized(m_outStream) { p("Sending message " + message); ObjectOutputStream oos = new ObjectOutputStream(m_outStream); oos.writeObject(message); oos.flush(); waitForAck(); } } @Override public IMessage receiveMessage() throws IOException, ClassNotFoundException { IMessage result = null; try { ObjectInputStream ios = new ObjectInputStream(m_inStream); // synchronized(m_input) { result = (IMessage) ios.readObject(); p("Received message " + result); // sendAck(); // } } catch(Exception ex) { if (RemoteTestNG.isVerbose()) { ex.printStackTrace(); } } return result; } static void p(String s) { if (RemoteTestNG.isVerbose()) { System.out.println("[SerializedMessageSender] " + s); } } } testng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/RemoteTestListener.java0000755000175000017500000000651712551235562030745 0ustar eugeneeugenepackage org.testng.remote.strprotocol; import org.testng.ISuite; import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.internal.IResultListener2; import org.testng.xml.XmlTest; /** * A special listener that remote the event with string protocol. * * @author Alexandru Popescu */ public class RemoteTestListener implements IResultListener2 { private final MessageHub m_sender; private ISuite m_suite; private XmlTest m_xmlTest; private ITestContext m_currentTestContext; public RemoteTestListener(ISuite suite, XmlTest test, MessageHub msh) { m_sender = msh; m_suite= suite; m_xmlTest= test; } @Override public void onStart(ITestContext testCtx) { m_currentTestContext = testCtx; m_sender.sendMessage(new TestMessage(testCtx, true /*start*/)); } @Override public void onFinish(ITestContext testCtx) { m_sender.sendMessage(new TestMessage(testCtx, false /*end*/)); m_currentTestContext = null; } @Override public void onTestStart(ITestResult testResult) { TestResultMessage trm= null; if (null == m_currentTestContext) { trm= new TestResultMessage(m_suite.getName(), m_xmlTest.getName(), testResult); } else { trm= new TestResultMessage(m_currentTestContext, testResult); } m_sender.sendMessage(trm); } @Override public void beforeConfiguration(ITestResult tr) { } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult testResult) { if (null == m_currentTestContext) { m_sender.sendMessage(new TestResultMessage(m_suite.getName(), m_xmlTest.getName(), testResult)); } else { m_sender.sendMessage(new TestResultMessage(m_currentTestContext, testResult)); } } @Override public void onTestFailure(ITestResult testResult) { if (null == m_currentTestContext) { m_sender.sendMessage(new TestResultMessage(m_suite.getName(), m_xmlTest.getName(), testResult)); } else { m_sender.sendMessage(new TestResultMessage(m_currentTestContext, testResult)); } } @Override public void onTestSkipped(ITestResult testResult) { if (null == m_currentTestContext) { m_sender.sendMessage(new TestResultMessage(m_suite.getName(), m_xmlTest.getName(), testResult)); } else { m_sender.sendMessage(new TestResultMessage(m_currentTestContext, testResult)); } } @Override public void onTestSuccess(ITestResult testResult) { if (null == m_currentTestContext) { m_sender.sendMessage(new TestResultMessage(m_suite.getName(), m_xmlTest.getName(), testResult)); } else { m_sender.sendMessage(new TestResultMessage(m_currentTestContext, testResult)); } } /** * @see org.testng.IConfigurationListener#onConfigurationFailure(org.testng.ITestResult) */ @Override public void onConfigurationFailure(ITestResult itr) { // Show configuration failures in the main view for convenience onTestFailure(itr); } /** * @see org.testng.IConfigurationListener#onConfigurationSkip(org.testng.ITestResult) */ @Override public void onConfigurationSkip(ITestResult itr) { onTestSkipped(itr); } /** * @see org.testng.IConfigurationListener#onConfigurationSuccess(org.testng.ITestResult) */ @Override public void onConfigurationSuccess(ITestResult itr) { } }testng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/MessageHub.java0000755000175000017500000000325212551235562027160 0ustar eugeneeugenepackage org.testng.remote.strprotocol; import java.io.IOException; import java.net.SocketTimeoutException; import org.testng.TestNGException; import org.testng.remote.RemoteTestNG; /** * Central class to connect to the host and send message. * * @author Cedric Beust */ public class MessageHub { private boolean m_debug = false; private IMessageSender m_messageSender; public MessageHub(IMessageSender messageSender) { m_messageSender = messageSender; } /** * Starts the connection. * * @throws TestNGException if an exception occurred while establishing the connection */ public void connect() throws IOException { m_messageSender.connect(); } /** * Shutsdown the connection to the remote test listener. */ public void shutDown() { m_messageSender.shutDown(); } public void sendMessage(IMessage message) { try { m_messageSender.sendMessage(message); } catch (Exception e) { e.printStackTrace(); } } public IMessage receiveMessage() { IMessage result = null; try { result = m_messageSender.receiveMessage(); m_messageSender.sendAck(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; } private static void p(String msg) { if (RemoteTestNG.isVerbose()) { System.out.println("[StringMessageSenderHelper] " + msg); //$NON-NLS-1$ } } public void setDebug(boolean debug) { m_debug = debug; } public void initReceiver() throws SocketTimeoutException { m_messageSender.initReceiver(); } public IMessageSender getMessageSender() { return m_messageSender; } } testng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/MessageHelper.java0000755000175000017500000002070412551235562027662 0ustar eugeneeugenepackage org.testng.remote.strprotocol; import org.testng.ITestResult; import org.testng.collections.Lists; import java.util.List; import java.util.regex.Pattern; /** * Marshal/unmarshal tool for IStringMessages. * * @author Alexandru Popescu */ public class MessageHelper { public static final char DELIMITER = '\u0001'; public static final char PARAM_DELIMITER = '\u0004'; private static final char LINE_SEP_DELIMITER_1 = '\u0002'; private static final char LINE_SEP_DELIMITER_2 = '\u0003'; public static final int GENERIC_SUITE_COUNT = 1; public static final int SUITE = 10; public static final int SUITE_START = 11; public static final int SUITE_FINISH = 12; public static final int TEST = 100; public static final int TEST_START = 101; public static final int TEST_FINISH = 102; public static final int TEST_RESULT = 1000; public static final int PASSED_TEST = TEST_RESULT + ITestResult.SUCCESS; public static final int FAILED_TEST = TEST_RESULT + ITestResult.FAILURE; public static final int SKIPPED_TEST = TEST_RESULT + ITestResult.SKIP; public static final int FAILED_ON_PERCENTAGE_TEST = TEST_RESULT + ITestResult.SUCCESS_PERCENTAGE_FAILURE; public static final int TEST_STARTED = TEST_RESULT + ITestResult.STARTED; public static final String STOP_MSG = ">STOP"; public static final String ACK_MSG = ">ACK"; public static int getMessageType(final String message) { int idx = message.indexOf(DELIMITER); return idx == -1 ? Integer.parseInt(message) : Integer.parseInt(message.substring(0, idx)); } public static GenericMessage unmarshallGenericMessage(final String message) { String[] messageParts = parseMessage(message); if(messageParts.length == 1) { return new GenericMessage(Integer.parseInt(messageParts[0])); } else { GenericMessage result = new GenericMessage(Integer.parseInt(messageParts[0])); for(int i = 1; i < messageParts.length; i+=2) { if ("testCount".equals(messageParts[i])) { result.setTestCount(Integer.parseInt(messageParts[i + 1])); } else if ("suiteCount".equals(messageParts[i])) { result.setSuiteCount(Integer.parseInt(messageParts[i + 1])); } } return result; } } public static SuiteMessage createSuiteMessage(final String message) { int type = getMessageType(message); String[] messageParts = parseMessage(message); SuiteMessage result = new SuiteMessage(messageParts[1], MessageHelper.SUITE_START == type, Integer.parseInt(messageParts[2])); // Any excluded methods? if (messageParts.length > 3) { int count = Integer.parseInt(messageParts[3]); if (count > 0) { List methods = Lists.newArrayList(); int i = 4; while (count-- > 0) { methods.add(messageParts[i++]); } result.setExcludedMethods(methods); } } return result; } public static TestMessage createTestMessage(final String message) { int type = getMessageType(message); String[] messageParts = parseMessage(message); return new TestMessage(MessageHelper.TEST_START == type, messageParts[1], messageParts[2], Integer.parseInt(messageParts[3]), Integer.parseInt(messageParts[4]), Integer.parseInt(messageParts[5]), Integer.parseInt(messageParts[6]), Integer.parseInt(messageParts[7])); } public static TestResultMessage unmarshallTestResultMessage(final String message) { String[] messageParts = parseMessage(message); String parametersFragment= null; String startTimestampFragment= null; String stopTimestampFragment= null; String stackTraceFragment= null; String testDescriptor= null; switch(messageParts.length) { case 10: { parametersFragment= messageParts[5]; startTimestampFragment= messageParts[6]; stopTimestampFragment= messageParts[7]; stackTraceFragment= messageParts[8]; testDescriptor= messageParts[9]; } break; case 9: { parametersFragment= messageParts[5]; startTimestampFragment= messageParts[6]; stopTimestampFragment= messageParts[7]; stackTraceFragment= messageParts[8]; } break; default: { // HINT: old protocol without parameters parametersFragment= null; startTimestampFragment= messageParts[5]; stopTimestampFragment= messageParts[6]; stackTraceFragment= messageParts[7]; } } return new TestResultMessage(Integer.parseInt(messageParts[0]), messageParts[1], messageParts[2], messageParts[3], messageParts[4], replaceAsciiCharactersWithUnicode(replaceNewLineReplacer(testDescriptor)), replaceAsciiCharactersWithUnicode(replaceNewLineReplacer(testDescriptor)), parseParameters(parametersFragment), Long.parseLong(startTimestampFragment), Long.parseLong(stopTimestampFragment), replaceAsciiCharactersWithUnicode(replaceNewLineReplacer(stackTraceFragment)), 0, 0 /* invocation counts not supported by this protocol */ ); } public static String replaceNewLine(String message) { if(null == message) { return message; } return message.replace('\n', LINE_SEP_DELIMITER_1).replace('\r', LINE_SEP_DELIMITER_2); } public static String replaceUnicodeCharactersWithAscii(String message) { if(null == message) { return message; } return replace( replace( replace( replace(message, "\u0004", "\\u0004"), "\u0003", "\\u0003"), "\u0002", "\\u0002"), "\u0001", "\\u0001"); } public static String replaceAsciiCharactersWithUnicode(String message) { if(null == message) { return message; } return replace( replace( replace( replace(message, "\\u0004", "\u0004"), "\\u0003", "\u0003"), "\\u0002", "\u0002"), "\\u0001", "\u0001"); } public static String replaceNewLineReplacer(String message) { if(null == message) { return message; } return message.replace(LINE_SEP_DELIMITER_1, '\n').replace(LINE_SEP_DELIMITER_2, '\r'); } private static String[] parseParameters(final String messagePart) { return tokenize(messagePart, PARAM_DELIMITER); } private static String[] parseMessage(final String message) { return tokenize(message, DELIMITER); } private static String[] tokenize(final String message, final char separator) { if(null == message) { return new String[0]; } List tokens = Lists.newArrayList(); int start = 0; for(int i = 0; i < message.length(); i++) { if(separator == message.charAt(i)) { tokens.add(message.substring(start, i)); start = i + 1; } } if(start < message.length()) { tokens.add(message.substring(start, message.length())); } return tokens.toArray(new String[tokens.size()]); } /** * Implementation according to JDK5 String.replace(CharSequence,CharSequence) */ private static final String replace(String original, CharSequence target, CharSequence replacement) { return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(original) .replaceAll(quoteReplacement(replacement.toString())); } /** * Implementation according to JDK5 String.replace(CharSequence,CharSequence) */ private static String quoteReplacement(String s) { if ((s.indexOf('\\') == -1) && (s.indexOf('$') == -1)) { return s; } StringBuffer sb = new StringBuffer(); for (int i=0; iAlexandru Popescu */ public interface IStringMessage extends IMessage { String getMessageAsString(); } testng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/IRemoteTestListener.java0000755000175000017500000000113112551235562031041 0ustar eugeneeugenepackage org.testng.remote.strprotocol; /** * Interface replicating ITestListener for remote listeners. * * @author Alexandru Popescu * @see org.testng.ITestListener */ public interface IRemoteTestListener { void onStart(TestMessage tm); void onFinish(TestMessage tm); void onTestStart(TestResultMessage trm); void onTestSuccess(TestResultMessage trm); void onTestFailure(TestResultMessage trm); void onTestSkipped(TestResultMessage trm); void onTestFailedButWithinSuccessPercentage(TestResultMessage trm); } testng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/IRemoteSuiteListener.java0000755000175000017500000000173612551235562031226 0ustar eugeneeugenepackage org.testng.remote.strprotocol; /** * Interface replicating the ISuiteListener used for remote listeners. * * @author Alexandru Popescu * @see org.testng.ISuiteListener */ public interface IRemoteSuiteListener { /** * General information about the number of suites to be run. * This is called once before all suites. * * @param genericMessage a message containing the number of suites that will be run */ void onInitialization(GenericMessage genericMessage); /** * @see org.testng.ISuiteListener#onStart(org.testng.ISuite) * * @param suiteMessage the suite message containing the description of the suite to be run. */ void onStart(SuiteMessage suiteMessage); /** * @see org.testng.ISuiteListener#onFinish(org.testng.ISuite) * * @param suiteMessage the suite message containing infos about the finished suite. */ void onFinish(SuiteMessage suiteMessage); } testng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/IMessageSender.java0000644000175000017500000000154512551235562027773 0ustar eugeneeugenepackage org.testng.remote.strprotocol; import java.io.IOException; import java.net.SocketException; import java.net.SocketTimeoutException; public interface IMessageSender { void connect() throws IOException; /** * Initialize the receiver. * * @throws SocketException This exception will be thrown if a connection * to the remote TestNG instance could not be established after ten * seconds. */ void initReceiver() throws SocketTimeoutException; void sendMessage(IMessage message) throws Exception; /** * Will return null or throw EOFException when the connection has been severed. */ IMessage receiveMessage() throws Exception; void shutDown(); // These two methods should probably be in a separate class since they should all be // the same for implementers of this interface. void sendAck(); void sendStop(); } testng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/IMessage.java0000755000175000017500000000037612551235562026636 0ustar eugeneeugenepackage org.testng.remote.strprotocol; import java.io.Serializable; /** * Marker interface for messages exchanged between RemoteTestNG and a client. * * @author Cedric Beust */ public interface IMessage extends Serializable { } testng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/GenericMessage.java0000755000175000017500000000416212551235562030017 0ustar eugeneeugenepackage org.testng.remote.strprotocol; /** * A generic message to be used with remote listeners. * It is described by a {@link #m_messageType} and can contain a Map * or values. * * @author Alexandru Popescu */ public class GenericMessage implements IStringMessage { // protected Map m_properties; protected final int m_messageType; private int m_suiteCount; private int m_testCount; public GenericMessage(final int type) { m_messageType = type; } public int getSuiteCount() { return m_suiteCount; } public void setSuiteCount(int suiteCount) { m_suiteCount = suiteCount; } public int getTestCount() { return m_testCount; } public void setTestCount(int testCount) { m_testCount = testCount; } // public GenericMessage(final int type, Map props) { // m_messageType = type; // m_properties = props; // } // public GenericMessage addProperty(final String propName, final Object propValue) { // m_properties.put(propName, propValue); // // return this; // } public GenericMessage addProperty(final String propName, final int propValue) { return addProperty(propName, propValue); } // public String getProperty(final String propName) { // return (String) m_properties.get(propName); // } @Override public String getMessageAsString() { StringBuffer buf = new StringBuffer(); buf.append(m_messageType); buf.append(MessageHelper.DELIMITER).append("testCount").append(getTestCount()) .append(MessageHelper.DELIMITER).append("suiteCount").append(getSuiteCount()); // for(Iterator it = m_properties.entrySet().iterator(); it.hasNext(); ) { // Map.Entry entry = (Map.Entry) it.next(); // // buf.append(MessageHelper.DELIMITER) // .append(entry.getKey()) // .append(MessageHelper.DELIMITER) // .append(entry.getValue()) // ; // } return buf.toString(); } @Override public String toString() { return "[GenericMessage suiteCount:" + m_suiteCount + " testCount:" + m_testCount + "]"; } } testng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/BaseMessageSender.java0000644000175000017500000001635312551235562030460 0ustar eugeneeugenepackage org.testng.remote.strprotocol; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.ConnectException; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; import org.testng.TestNGException; import org.testng.remote.RemoteTestNG; abstract public class BaseMessageSender implements IMessageSender { private boolean m_debug = false; protected Socket m_clientSocket; private String m_host; private int m_port; protected Object m_ackLock = new Object(); /** Outgoing message stream. */ protected OutputStream m_outStream; /** Used to send ACK and STOP */ private PrintWriter m_outWriter; /** Incoming message stream. */ protected volatile InputStream m_inStream; /** Used to receive ACK and STOP */ protected volatile BufferedReader m_inReader; private ReaderThread m_readerThread; private boolean m_ack; // protected InputStream m_receiverInputStream; public BaseMessageSender(String host, int port, boolean ack) { m_host = host; m_port = port; m_ack = ack; } /** * Starts the connection. * * @throws TestNGException if an exception occurred while establishing the connection */ @Override public void connect() throws IOException { p("Waiting for Eclipse client on " + m_host + ":" + m_port); while (true) { try { m_clientSocket = new Socket(m_host, m_port); p("Received a connection from Eclipse on " + m_host + ":" + m_port); // Output streams m_outStream = m_clientSocket.getOutputStream(); m_outWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(m_outStream))); // Input streams m_inStream = m_clientSocket.getInputStream(); try { m_inReader = new BufferedReader(new InputStreamReader(m_inStream, "UTF-8")); //$NON-NLS-1$ } catch(UnsupportedEncodingException ueex) { // Should never happen m_inReader = new BufferedReader(new InputStreamReader(m_inStream)); } p("Connection established, starting reader thread"); m_readerThread = new ReaderThread(); m_readerThread.start(); return; } catch(ConnectException ex) { // ignore and retry try { Thread.sleep(4000); } catch(InterruptedException handled) { Thread.currentThread().interrupt(); } } } } private void sendAdminMessage(String message) { m_outWriter.println(message); m_outWriter.flush(); } private int m_serial = 0; @Override public void sendAck() { p("Sending ACK " + m_serial); // Note: adding the serial at the end of this message causes a lock up if interacting // with TestNG 5.14 and older (reported by JetBrains). The following git commit: // 5730bdfb33ec7a8bf4104852cd4a5f2875ba8267 // changed equals() to startsWith(). // It's ok to add this serial back for debugging, but don't commit it until JetBrains // confirms they no longer need backward compatibility with 5.14. sendAdminMessage(MessageHelper.ACK_MSG); // + m_serial++); } @Override public void sendStop() { sendAdminMessage(MessageHelper.STOP_MSG); } @Override public void initReceiver() throws SocketTimeoutException { if (m_inStream != null) { p("Receiver already initialized"); } ServerSocket serverSocket = null; try { p("initReceiver on port " + m_port); serverSocket = new ServerSocket(m_port); serverSocket.setSoTimeout(5000); Socket socket = serverSocket.accept(); m_inStream = socket.getInputStream(); m_inReader = new BufferedReader(new InputStreamReader(m_inStream)); m_outStream = socket.getOutputStream(); m_outWriter = new PrintWriter(new OutputStreamWriter(m_outStream)); } catch(SocketTimeoutException ste) { try { serverSocket.close(); } catch (IOException e) { // ignore } throw ste; } catch (IOException ioe) { // TODO Auto-generated catch block ioe.printStackTrace(); } } @Override public void shutDown() { if(null != m_outStream) { try { m_outStream.close(); } catch(IOException ex) { // ignore } m_outStream = null; } try { if(null != m_readerThread) { m_readerThread.interrupt(); } if(null != m_inReader) { m_inReader.close(); m_inReader = null; } } catch(IOException e) { e.printStackTrace(); } try { if(null != m_clientSocket) { m_clientSocket.close(); m_clientSocket = null; } } catch(IOException e) { if(m_debug) { e.printStackTrace(); } } } private String m_latestAck; protected void waitForAck() { if (m_ack) { try { p("Message sent, waiting for ACK..."); synchronized(m_ackLock) { m_ackLock.wait(); } p("... ACK received:" + m_latestAck); } catch(InterruptedException handled) { Thread.currentThread().interrupt(); } } } private static void p(String msg) { if (RemoteTestNG.isVerbose()) { System.out.println("[BaseMessageSender] " + msg); //$NON-NLS-1$ } } /** * Reader thread that processes messages from the client. */ private class ReaderThread extends Thread { public ReaderThread() { super("ReaderThread"); //$NON-NLS-1$ } @Override public void run() { try { p("ReaderThread waiting for an admin message"); String message = m_inReader.readLine(); p("ReaderThread received admin message:" + message); while (message != null) { if (m_debug) { p("Admin message:" + message); //$NON-NLS-1$ } boolean acknowledge = message.startsWith(MessageHelper.ACK_MSG); boolean stop = MessageHelper.STOP_MSG.equals(message); if(acknowledge || stop) { if (acknowledge) { p("Received ACK:" + message); m_latestAck = message; } synchronized(m_ackLock) { m_ackLock.notifyAll(); } if (stop) { break; } } else { p("Received unknown message: '" + message + "'"); } message = m_inReader != null ? m_inReader.readLine() : null; } // while((m_reader != null) && (message = m_reader.readLine()) != null) { // if (m_debug) { // p("Admin message:" + message); //$NON-NLS-1$ // } // boolean acknowledge = MessageHelper.ACK_MSG.equals(message); // boolean stop = MessageHelper.STOP_MSG.equals(message); // if(acknowledge || stop) { // synchronized(m_lock) { // m_lock.notifyAll(); // } // if (stop) { // break; // } // } // } } catch(IOException ioe) { if (RemoteTestNG.isVerbose()) { ioe.printStackTrace(); } } } } } testng-testng-6.9.5/src/main/java/org/testng/remote/strprotocol/AbstractRemoteTestRunnerClient.java0000755000175000017500000001630112551235562033244 0ustar eugeneeugene/******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Julien Ruaux: jruaux@octo.com * Vincent Massol: vmassol@octo.com * * Adapted by: * Alexandru Popescu: the_mindstorm@evolva.ro ******************************************************************************/ package org.testng.remote.strprotocol; import org.testng.TestNGException; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * The client side of the RemoteTestRunner. Handles the * marshaling of the different messages. */ public abstract class AbstractRemoteTestRunnerClient { /** * An array of listeners that are informed about test events. */ protected IRemoteSuiteListener[] m_suiteListeners; protected IRemoteTestListener[] m_testListeners; /** * The server socket */ private ServerSocket fServerSocket; private Socket fSocket; private ServerConnection m_serverConnection; // private PrintWriter m_outputWriter; // private BufferedReader m_inputReader; /** * Start listening to a test run. Start a server connection that * the RemoteTestRunner can connect to. */ public synchronized void startListening(IRemoteSuiteListener[] suiteListeners, IRemoteTestListener[] testListeners, ServerConnection serverConnection) { m_suiteListeners= suiteListeners; m_testListeners= testListeners; m_serverConnection = serverConnection; serverConnection.start(); } public IRemoteSuiteListener[] getSuiteListeners() { return m_suiteListeners; } public IRemoteTestListener[] getTestListeners() { return m_testListeners; } private synchronized void shutdown() { // if(m_outputWriter != null) { // m_outputWriter.close(); // m_outputWriter = null; // } // try { // if(m_inputReader != null) { // m_inputReader.close(); // m_inputReader = null; // } // } // catch(IOException e) { // e.printStackTrace(); // } try { if(fSocket != null) { fSocket.close(); fSocket = null; } } catch(IOException e) { e.printStackTrace(); } try { if(fServerSocket != null) { fServerSocket.close(); fServerSocket = null; } } catch(IOException e) { e.printStackTrace(); } } public boolean isRunning() { return m_serverConnection.getMessageSender() != null; } /** * Requests to stop the remote test run. */ public synchronized void stopTest() { if(isRunning()) { m_serverConnection.getMessageSender().sendStop(); shutdown(); } } // private String readMessage(BufferedReader in) throws IOException { // return in.readLine(); // } // // private void receiveMessage(String message) { // int messageType = MessageHelper.getMessageType(message); // // try { // if(messageType < MessageHelper.SUITE) { // // Generic message // GenericMessage gm = MessageHelper.unmarshallGenericMessage(message); // notifyStart(gm); // } // else if(messageType < MessageHelper.TEST) { // // Suite message // SuiteMessage sm = MessageHelper.createSuiteMessage(message); // notifySuiteEvents(sm); // } // else if(messageType < MessageHelper.TEST_RESULT) { // // Test message // TestMessage tm = MessageHelper.createTestMessage(message); // notifyTestEvents(tm); // } // else { // // TestResult message // TestResultMessage trm = MessageHelper.unmarshallTestResultMessage(message); // notifyResultEvents(trm); // } // } // finally { // if(isRunning() && (null != m_outputWriter)) { // m_outputWriter.println(MessageHelper.ACK_MSG); // m_outputWriter.flush(); // } // } // } protected abstract void notifyStart(final GenericMessage genericMessage); protected abstract void notifySuiteEvents(final SuiteMessage suiteMessage); protected abstract void notifyTestEvents(final TestMessage testMessage); protected abstract void notifyResultEvents(final TestResultMessage testResultMessage); /** * Reads the message stream from the RemoteTestRunner */ public abstract class ServerConnection extends Thread { private MessageHub m_messageHub; public ServerConnection(IMessageSender messageMarshaller) { super("TestNG - ServerConnection"); //$NON-NLS-1$ m_messageHub = new MessageHub(messageMarshaller); } IMessageSender getMessageSender() { return m_messageHub != null ? m_messageHub.getMessageSender() : null; } @Override public void run() { try { IMessage message = m_messageHub.receiveMessage(); while (message != null) { if (message instanceof GenericMessage) { notifyStart((GenericMessage) message); } else if (message instanceof SuiteMessage) { notifySuiteEvents((SuiteMessage) message); } else if (message instanceof TestMessage) { notifyTestEvents((TestMessage) message); } else if (message instanceof TestResultMessage) { notifyResultEvents((TestResultMessage) message); } else { throw new TestNGException("Unknown message type:" + message); } // if (isRunning()) { // m_messageMarshaller.sendAck(); // } message = m_messageHub.receiveMessage(); } } finally { m_messageHub.shutDown(); m_messageHub = null; } // try { // fServerSocket = new ServerSocket(fServerPort); // fSocket = fServerSocket.accept(); // try { // m_inputReader = new BufferedReader(new InputStreamReader(fSocket.getInputStream(), // "UTF-8")); //$NON-NLS-1$ // } // catch(UnsupportedEncodingException e) { // m_inputReader = new BufferedReader(new InputStreamReader(fSocket.getInputStream())); // } // try { // m_outputWriter = new PrintWriter(new OutputStreamWriter(fSocket.getOutputStream(), "UTF-8"), // true); // } // catch(UnsupportedEncodingException e1) { // m_outputWriter = new PrintWriter(new OutputStreamWriter(fSocket.getOutputStream()), true); // } // String message; // while((m_inputReader != null) && ((message = readMessage(m_inputReader)) != null)) { // receiveMessage(message); // } // } // catch(SocketException e) { // handleThrowable(e); // } // catch(IOException e) { // handleThrowable(e); // } // finally { // shutdown(); // } } protected abstract void handleThrowable(Throwable cause); } } testng-testng-6.9.5/src/main/java/org/testng/remote/adapter/0000755000175000017500000000000012551235562023313 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/remote/adapter/RemoteResultListener.java0000644000175000017500000000421512551235562030320 0ustar eugeneeugene/* * @(#)ResultListener.java Apr 9, 2007 * * Copyright 2007 GigaSpaces Technologies Inc. */ package org.testng.remote.adapter; import java.util.Map; import org.testng.ISuite; import org.testng.ISuiteResult; import org.testng.ITestContext; import org.testng.SuiteRunner; import org.testng.reporters.TestHTMLReporter; /** * This listener is called by the {@link IWorkerAdapter} implementation when a remote test result is ready. * * @author Guy Korland * @since April 9, 2007 * @see IWorkerAdapter */ public class RemoteResultListener { /** * Holds the corresponded {@link SuiteRunner} for the processed {@link org.testng.xml.XmlSuite}. */ final private SuiteRunner m_runner; /** * Creates a listener for an {@link org.testng.xml.XmlSuite} result. * @param runner the corresponded {@link SuiteRunner} */ public RemoteResultListener( SuiteRunner runner) { m_runner = runner; } /** * Should called by the {@link IWorkerAdapter} implementation when a remote suite result is ready. * @param remoteSuiteRunner remote result. */ public void onResult( ISuite remoteSuiteRunner) { m_runner.setHost(remoteSuiteRunner.getHost()); Map tmpResults = remoteSuiteRunner.getResults(); Map suiteResults = m_runner.getResults(); for (Map.Entry entry : tmpResults.entrySet()) { ISuiteResult suiteResult = entry.getValue(); suiteResults.put(entry.getKey(), suiteResult); ITestContext tc = suiteResult.getTestContext(); TestHTMLReporter.generateLog(tc, remoteSuiteRunner.getHost(), m_runner.getOutputDirectory(), tc.getFailedConfigurations().getAllResults(), tc.getSkippedConfigurations().getAllResults(), tc.getPassedTests().getAllResults(), tc.getFailedTests().getAllResults(), tc.getSkippedTests().getAllResults(), tc.getFailedButWithinSuccessPercentageTests().getAllResults()); } } } testng-testng-6.9.5/src/main/java/org/testng/remote/adapter/IWorkerAdapter.java0000644000175000017500000000247512551235562027051 0ustar eugeneeugenepackage org.testng.remote.adapter; import java.io.IOException; import java.util.Properties; import org.testng.ISuite; import org.testng.xml.XmlSuite; /** * This interface should be implemented by the Master-Slave transport adapter. * This interface is used by the Slave to pull suites and return results. * * @author Guy Korland * @since April 9, 2007 * @see IMasterAdapter */ public interface IWorkerAdapter { /** * Initializes the worker adapter. * @param properties holds the properties loaded from the remote.properties file. * @throws Exception adapter might throw any exception on initialization, which will abort this adapter. */ void init( Properties properties) throws Exception; /** * A blocking call to get the next Suite to test. * @param timeout the maximum time to wait for the next suite. * @return the next suite avaliable or null if the timeout has reached. * @throws IOException might be thrown on IO error. * @throws InterruptedException if interrupted while waiting. */ XmlSuite getSuite( long timeout) throws InterruptedException, IOException; /** * Return a suite result. * @param result the result to return * @throws IOException might be thrown on IO error. */ void returnResult( ISuite result) throws IOException; } testng-testng-6.9.5/src/main/java/org/testng/remote/adapter/IMasterAdapter.java0000644000175000017500000000236712551235562027033 0ustar eugeneeugenepackage org.testng.remote.adapter; import java.io.IOException; import java.util.Properties; import org.testng.xml.XmlSuite; /** * This interface should be implemented by the Master-Slave transport adapter. * This interface is used by the Master to push suites and get results. * * @author Guy Korland * @since April 9, 2007 * @see IWorkerAdapter */ public interface IMasterAdapter { /** * Initializes the Master adapter. * @param prop holds the properties loaded from the remote.properties file. * @throws Exception adapter might throw any exception on initialization, which will abort this adapter. */ void init( Properties prop) throws Exception; /** * Run a suite remotely. * @param suite the suite to send. * @param listener the corresponded listener, should be called when result is ready. * @throws IOException might be thrown on IO error. */ void runSuitesRemotely( XmlSuite suite, RemoteResultListener listener) throws IOException; /** * A blocking wait for the remote results to return. * * @param timeout the maximum time to wait for all the suites to return a result. * @throws InterruptedException */ public void awaitTermination(long timeout) throws InterruptedException; }testng-testng-6.9.5/src/main/java/org/testng/remote/adapter/DefaultWorkerAdapter.java0000644000175000017500000000442112551235562030236 0ustar eugeneeugenepackage org.testng.remote.adapter; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.Properties; import org.testng.ISuite; import org.testng.internal.Utils; import org.testng.remote.ConnectionInfo; import org.testng.xml.XmlSuite; /** * Default Slave adapter, provides an adapter based on static port. * * * @author Guy Korland * @since April 20, 2007 */ public class DefaultWorkerAdapter implements IWorkerAdapter { public static final String SLAVE_PORT = "slave.port"; private ConnectionInfo m_connectionInfo; private int m_clientPort; @Override public void init( Properties prop) throws Exception { m_clientPort = Integer.parseInt( prop.getProperty(SLAVE_PORT, "0")); m_connectionInfo = resetSocket( m_clientPort, null); } /* * @see org.testng.remote.adapter.IWorkerApadter#getSuite(long) */ @Override public XmlSuite getSuite(long timeout) throws InterruptedException, IOException { try { return (XmlSuite) m_connectionInfo.getOis().readObject(); } catch (ClassNotFoundException e) { e.printStackTrace(System.out); throw new RuntimeException( e); } catch(IOException ex) { log("Connection closed " + ex.getMessage()); m_connectionInfo = resetSocket(m_clientPort, m_connectionInfo); throw ex; } } /* * @see org.testng.remote.adapter.IWorkerApadter#returnResult(org.testng.ISuite) */ @Override public void returnResult(ISuite result) throws IOException { try { m_connectionInfo.getOos().writeObject(result); } catch(IOException ex) { log("Connection closed " + ex.getMessage()); m_connectionInfo = resetSocket(m_clientPort, m_connectionInfo); throw ex; } } private static ConnectionInfo resetSocket(int clientPort, ConnectionInfo oldCi) throws IOException { ConnectionInfo result = new ConnectionInfo(); ServerSocket serverSocket = new ServerSocket(clientPort); serverSocket.setReuseAddress(true); log("Waiting for connections on port " + clientPort); Socket socket = serverSocket.accept(); result.setSocket(socket); return result; } private static void log(String string) { Utils.log("", 2, string); } } testng-testng-6.9.5/src/main/java/org/testng/remote/adapter/DefaultMastertAdapter.java0000755000175000017500000000437312551235562030415 0ustar eugeneeugenepackage org.testng.remote.adapter; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import java.util.List; import java.util.Properties; import org.testng.collections.Lists; import org.testng.internal.Utils; import org.testng.internal.remote.SlavePool; import org.testng.internal.thread.ThreadUtil; import org.testng.remote.RemoteSuiteWorker; import org.testng.xml.XmlSuite; /** * Default Master adapter, provides an adapter based on hosts file. * * * @author Guy Korland * @since April 20, 2007 */ public class DefaultMastertAdapter implements IMasterAdapter { public static final String HOSTS = "testng.hosts"; private String[] m_hosts; final private SlavePool m_slavePool = new SlavePool(); final private List m_workers = Lists.newArrayList(); /* * @see org.testng.remote.adapter.IMasterAdapter#init(java.util.Properties) */ @Override public void init(Properties properties) { String hostLine = properties.getProperty(HOSTS); m_hosts = hostLine.split(" "); // // Create one socket per host found // Socket[] sockets = new Socket[m_hosts.length]; for (int i = 0; i < m_hosts.length; i++) { String host = m_hosts[i]; String[] s = host.split(":"); try { sockets[i] = new Socket(s[0], Integer.parseInt(s[1])); } catch (NumberFormatException | UnknownHostException e) { e.printStackTrace(System.out); } catch (IOException e) { Utils.error("Couldn't connect to " + host + ": " + e.getMessage()); } } // // Add these hosts to the pool // try { m_slavePool.addSlaves(sockets); } catch (IOException e1) { e1.printStackTrace(System.out); } } /* * @see org.testng.remote.adapter.IMasterAdapter#runSuitesRemotely(java.util.List, org.testng.internal.annotations.IAnnotationFinder, org.testng.internal.annotations.IAnnotationFinder) */ @Override public void runSuitesRemotely( XmlSuite suite, RemoteResultListener listener) throws IOException { m_workers.add(new RemoteSuiteWorker(suite, m_slavePool, listener)); } @Override public void awaitTermination(long timeout) throws InterruptedException { ThreadUtil.execute(m_workers, 1, 10 * 1000L, false); } } testng-testng-6.9.5/src/main/java/org/testng/remote/SuiteSlave.java0000644000175000017500000000473012551235562024626 0ustar eugeneeugenepackage org.testng.remote; import java.util.List; import java.util.Properties; import org.testng.ISuite; import org.testng.TestNG; import org.testng.TestNGException; import org.testng.collections.Lists; import org.testng.internal.PropertiesFile; import org.testng.internal.Utils; import org.testng.remote.adapter.DefaultWorkerAdapter; import org.testng.remote.adapter.IWorkerAdapter; import org.testng.xml.XmlSuite; /** * Run test suits sent by the dispatcher. * * * @author Guy Korland * @since April 20, 2007 */ public class SuiteSlave { /** * Properties allowed in remote.properties */ public static final String VERBOSE = "testng.verbose"; public static final String SLAVE_ADPATER = "testng.slave.adpter"; final private int m_verbose; final private IWorkerAdapter m_slaveAdpter; final private TestNG m_testng; /** * Creates a new suite dispatcher. */ public SuiteSlave( String propertiesFile, TestNG testng) throws TestNGException { try { m_testng = testng; PropertiesFile file = new PropertiesFile( propertiesFile); Properties properties = file.getProperties(); m_verbose = Integer.parseInt( properties.getProperty(VERBOSE, "1")); String adapter = properties.getProperty(SLAVE_ADPATER); if( adapter == null) { m_slaveAdpter = new DefaultWorkerAdapter(); } else { Class clazz = Class.forName(adapter); m_slaveAdpter = (IWorkerAdapter)clazz.newInstance(); } m_slaveAdpter.init(properties); } catch( Exception e) { throw new TestNGException( "Fail to initialize slave mode", e); } } /** * Invoked in client mode. In this case, wait for a connection * on the given port, run the XmlSuite we received and return the SuiteRunner * created to run it. */ public void waitForSuites() { try { while (true) { //TODO set timeout XmlSuite s = m_slaveAdpter.getSuite(Long.MAX_VALUE); if( s== null) { continue; } log("Processing " + s.getName()); List suites = Lists.newArrayList(); suites.add(s); m_testng.setXmlSuites(suites); List suiteRunners = m_testng.runSuitesLocally(); ISuite sr = suiteRunners.get(0); log("Done processing " + s.getName()); m_slaveAdpter.returnResult(sr); } } catch(Exception ex) { ex.printStackTrace(System.out); } } private static void log(String string) { Utils.log("", 2, string); } } testng-testng-6.9.5/src/main/java/org/testng/remote/SuiteDispatcher.java0000644000175000017500000001245212551235562025642 0ustar eugeneeugenepackage org.testng.remote; import java.util.Collection; import java.util.List; import java.util.Properties; import org.testng.ISuite; import org.testng.ISuiteResult; import org.testng.ITestListener; import org.testng.ITestResult; import org.testng.SuiteRunner; import org.testng.TestNGException; import org.testng.collections.Lists; import org.testng.internal.IConfiguration; import org.testng.internal.Invoker; import org.testng.internal.PropertiesFile; import org.testng.remote.adapter.DefaultMastertAdapter; import org.testng.remote.adapter.IMasterAdapter; import org.testng.remote.adapter.RemoteResultListener; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; /** * Dispatches test suits according to the strategy defined. * * * @author Guy Korland * @since April 20, 2007 */ public class SuiteDispatcher { /** * Properties allowed in remote.properties */ public static final String MASTER_STRATEGY = "testng.master.strategy"; public static final String VERBOSE = "testng.verbose"; public static final String MASTER_ADPATER = "testng.master.adpter"; /** * Values allowed for STRATEGY */ public static final String STRATEGY_TEST = "test"; public static final String STRATEGY_SUITE = "suite"; final private int m_verbose; final private boolean m_isStrategyTest; final private IMasterAdapter m_masterAdpter; /** * Creates a new suite dispatcher. */ public SuiteDispatcher( String propertiesFile) throws TestNGException { try { PropertiesFile file = new PropertiesFile( propertiesFile); Properties properties = file.getProperties(); m_verbose = Integer.parseInt( properties.getProperty(VERBOSE, "1")); String strategy = properties.getProperty(MASTER_STRATEGY, STRATEGY_SUITE); m_isStrategyTest = STRATEGY_TEST.equalsIgnoreCase(strategy); String adapter = properties.getProperty(MASTER_ADPATER); if( adapter == null) { m_masterAdpter = new DefaultMastertAdapter(); } else { Class clazz = Class.forName(adapter); m_masterAdpter = (IMasterAdapter)clazz.newInstance(); } m_masterAdpter.init(properties); } catch( Exception e) { throw new TestNGException( "Fail to initialize master mode", e); } } /** * Dispatch test suites * @return suites result */ public List dispatch(IConfiguration configuration, List suites, String outputDir, List testListeners){ List result = Lists.newArrayList(); try { // // Dispatch the suites/tests // for (XmlSuite suite : suites) { suite.setVerbose(m_verbose); SuiteRunner suiteRunner = new SuiteRunner(configuration, suite, outputDir); RemoteResultListener listener = new RemoteResultListener( suiteRunner); if (m_isStrategyTest) { for (XmlTest test : suite.getTests()) { XmlSuite tmpSuite = new XmlSuite(); tmpSuite.setXmlPackages(suite.getXmlPackages()); tmpSuite.setJUnit(suite.isJUnit()); tmpSuite.setSkipFailedInvocationCounts(suite.skipFailedInvocationCounts()); 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()); tmpSuite.setVerbose(suite.getVerbose()); tmpSuite.setObjectFactory(suite.getObjectFactory()); XmlTest tmpTest = new XmlTest(tmpSuite); tmpTest.setBeanShellExpression(test.getExpression()); tmpTest.setXmlClasses(test.getXmlClasses()); tmpTest.setExcludedGroups(test.getExcludedGroups()); tmpTest.setIncludedGroups(test.getIncludedGroups()); tmpTest.setJUnit(test.isJUnit()); tmpTest.setMethodSelectors(test.getMethodSelectors()); tmpTest.setName(test.getName()); tmpTest.setParallel(test.getParallel()); tmpTest.setParameters(test.getLocalParameters()); tmpTest.setVerbose(test.getVerbose()); tmpTest.setXmlClasses(test.getXmlClasses()); tmpTest.setXmlPackages(test.getXmlPackages()); m_masterAdpter.runSuitesRemotely(tmpSuite, listener); } } else { m_masterAdpter.runSuitesRemotely(suite, listener); } result.add(suiteRunner); } m_masterAdpter.awaitTermination(100000); // // Run test listeners // for (ISuite suite : result) { for (ISuiteResult suiteResult : suite.getResults().values()) { Collection allTests[] = new Collection[] { suiteResult.getTestContext().getPassedTests().getAllResults(), suiteResult.getTestContext().getFailedTests().getAllResults(), suiteResult.getTestContext().getSkippedTests().getAllResults(), suiteResult.getTestContext().getFailedButWithinSuccessPercentageTests().getAllResults(), }; for (Collection all : allTests) { for (ITestResult tr : all) { Invoker.runTestListeners(tr, testListeners); } } } } } catch( Exception ex) { //TODO add to logs ex.printStackTrace(); } return result; } } testng-testng-6.9.5/src/main/java/org/testng/remote/RemoteWorker.java0000755000175000017500000000215512551235562025171 0ustar eugeneeugenepackage org.testng.remote; import org.testng.SuiteRunner; import org.testng.internal.Utils; import org.testng.internal.remote.SlavePool; import org.testng.remote.adapter.RemoteResultListener; import org.testng.xml.XmlSuite; import java.io.IOException; public class RemoteWorker { protected RemoteResultListener m_listener; private SlavePool m_slavePool; public RemoteWorker(RemoteResultListener listener, SlavePool slavePool) { m_listener = listener; m_slavePool = slavePool; } protected SlavePool getSlavePool() { return m_slavePool; } protected SuiteRunner sendSuite(ConnectionInfo ci, XmlSuite suite) throws IOException, ClassNotFoundException { log("Sending " + suite.getName() + " to " + ci.getSocket().getInetAddress().getCanonicalHostName() + ":" + ci.getSocket().getRemoteSocketAddress()); ci.getOos().writeObject(suite); ci.getOos().flush(); SuiteRunner result = (SuiteRunner) ci.getOis().readObject(); log("Received results for " + result.getName()); return result; } private void log(String string) { Utils.log("", 2, string); } } testng-testng-6.9.5/src/main/java/org/testng/remote/RemoteTestNG.java0000644000175000017500000002165612551235562025070 0ustar eugeneeugenepackage org.testng.remote; import static org.testng.internal.Utils.defaultIfStringEmpty; import com.beust.jcommander.JCommander; import com.beust.jcommander.ParameterException; import org.testng.CommandLineArgs; import org.testng.IInvokedMethodListener; import org.testng.ISuite; import org.testng.ISuiteListener; import org.testng.ITestRunnerFactory; import org.testng.TestNG; import org.testng.TestNGException; import org.testng.TestRunner; import org.testng.collections.Lists; import org.testng.remote.strprotocol.GenericMessage; import org.testng.remote.strprotocol.IMessageSender; import org.testng.remote.strprotocol.MessageHelper; import org.testng.remote.strprotocol.MessageHub; import org.testng.remote.strprotocol.RemoteTestListener; import org.testng.remote.strprotocol.SerializedMessageSender; import org.testng.remote.strprotocol.StringMessageSender; import org.testng.remote.strprotocol.SuiteMessage; import org.testng.reporters.JUnitXMLReporter; import org.testng.reporters.TestHTMLReporter; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import java.util.Arrays; import java.util.List; /** * Extension of TestNG registering a remote TestListener. * * @author Cedric Beust */ public class RemoteTestNG extends TestNG { private static final String LOCALHOST = "localhost"; // The following constants are referenced by the Eclipse plug-in, make sure you // modify the plug-in as well if you change any of them. public static final String DEBUG_PORT = "12345"; public static final String DEBUG_SUITE_FILE = "testng-customsuite.xml"; public static final String DEBUG_SUITE_DIRECTORY = System.getProperty("java.io.tmpdir"); public static final String PROPERTY_DEBUG = "testng.eclipse.debug"; public static final String PROPERTY_VERBOSE = "testng.eclipse.verbose"; // End of Eclipse constants. private ITestRunnerFactory m_customTestRunnerFactory; private String m_host; /** Port used for the string protocol */ private Integer m_port = null; /** Port used for the serialized protocol */ private static Integer m_serPort = null; private static boolean m_debug; private static boolean m_dontExit; private static boolean m_ack; public void setHost(String host) { m_host = defaultIfStringEmpty(host, LOCALHOST); } private void calculateAllSuites(List suites, List outSuites) { for (XmlSuite s : suites) { outSuites.add(s); // calculateAllSuites(s.getChildSuites(), outSuites); } } @Override public void run() { IMessageSender sender = m_serPort != null ? new SerializedMessageSender(m_host, m_serPort, m_ack) : new StringMessageSender(m_host, m_port); final MessageHub msh = new MessageHub(sender); msh.setDebug(isDebug()); try { msh.connect(); // We couldn't do this until now in debug mode since the .xml file didn't exist yet. // Now that we have connected with the Eclipse client, we know that it created the .xml // file so we can proceed with the initialization initializeSuitesAndJarFile(); List suites = Lists.newArrayList(); calculateAllSuites(m_suites, suites); // System.out.println("Suites: " + m_suites.get(0).getChildSuites().size() // + " and:" + suites.get(0).getChildSuites().size()); if(suites.size() > 0) { int testCount= 0; for (XmlSuite suite : suites) { testCount += suite.getTests().size(); } GenericMessage gm= new GenericMessage(MessageHelper.GENERIC_SUITE_COUNT); gm.setSuiteCount(suites.size()); gm.setTestCount(testCount); msh.sendMessage(gm); addListener(new RemoteSuiteListener(msh)); setTestRunnerFactory(new DelegatingTestRunnerFactory(buildTestRunnerFactory(), msh)); // System.out.println("RemoteTestNG starting"); super.run(); } else { System.err.println("No test suite found. Nothing to run"); } } catch(Throwable cause) { cause.printStackTrace(System.err); } finally { // System.out.println("RemoteTestNG finishing: " + (getEnd() - getStart()) + " ms"); msh.shutDown(); if (! m_debug && ! m_dontExit) { System.exit(0); } } } /** * Override by the plugin if you need to configure differently the TestRunner * (usually this is needed if different listeners/reporters are needed). * Note: you don't need to worry about the wiring listener, because it is added * automatically. */ protected ITestRunnerFactory buildTestRunnerFactory() { if(null == m_customTestRunnerFactory) { m_customTestRunnerFactory= new ITestRunnerFactory() { @Override public TestRunner newTestRunner(ISuite suite, XmlTest xmlTest, List listeners) { TestRunner runner = new TestRunner(getConfiguration(), suite, xmlTest, false /*skipFailedInvocationCounts */, listeners); if (m_useDefaultListeners) { runner.addListener(new TestHTMLReporter()); runner.addListener(new JUnitXMLReporter()); } return runner; } }; } return m_customTestRunnerFactory; } public static void main(String[] args) throws ParameterException { CommandLineArgs cla = new CommandLineArgs(); RemoteArgs ra = new RemoteArgs(); new JCommander(Arrays.asList(cla, ra), args); m_dontExit = ra.dontExit; if (cla.port != null && ra.serPort != null) { throw new TestNGException("Can only specify one of " + CommandLineArgs.PORT + " and " + RemoteArgs.PORT); } m_debug = cla.debug; m_ack = ra.ack; if (m_debug) { // while (true) { initAndRun(args, cla, ra); // } } else { initAndRun(args, cla, ra); } } private static void initAndRun(String[] args, CommandLineArgs cla, RemoteArgs ra) { RemoteTestNG remoteTestNg = new RemoteTestNG(); if (m_debug) { // In debug mode, override the port and the XML file to a fixed location cla.port = Integer.parseInt(DEBUG_PORT); ra.serPort = cla.port; cla.suiteFiles = Arrays.asList(new String[] { DEBUG_SUITE_DIRECTORY + DEBUG_SUITE_FILE }); } remoteTestNg.configure(cla); remoteTestNg.setHost(cla.host); m_serPort = ra.serPort; remoteTestNg.m_port = cla.port; if (isVerbose()) { StringBuilder sb = new StringBuilder("Invoked with "); for (String s : args) { sb.append(s).append(" "); } p(sb.toString()); // remoteTestNg.setVerbose(1); // } else { // remoteTestNg.setVerbose(0); } validateCommandLineParameters(cla); remoteTestNg.run(); // if (m_debug) { // // Run in a loop if in debug mode so it is possible to run several launches // // without having to relauch RemoteTestNG. // while (true) { // remoteTestNg.run(); // remoteTestNg.configure(cla); // } // } else { // remoteTestNg.run(); // } } private static void p(String s) { if (isVerbose()) { System.out.println("[RemoteTestNG] " + s); } } public static boolean isVerbose() { boolean result = System.getProperty(PROPERTY_VERBOSE) != null || isDebug(); return result; } public static boolean isDebug() { return m_debug || System.getProperty(PROPERTY_DEBUG) != null; } private String getHost() { return m_host; } private int getPort() { return m_port; } /** A ISuiteListener wiring the results using the internal string-based protocol. */ private static class RemoteSuiteListener implements ISuiteListener { private final MessageHub m_messageSender; RemoteSuiteListener(MessageHub smsh) { m_messageSender= smsh; } @Override public void onFinish(ISuite suite) { m_messageSender.sendMessage(new SuiteMessage(suite, false /*start*/)); } @Override public void onStart(ISuite suite) { m_messageSender.sendMessage(new SuiteMessage(suite, true /*start*/)); } } private static class DelegatingTestRunnerFactory implements ITestRunnerFactory { private final ITestRunnerFactory m_delegateFactory; private final MessageHub m_messageSender; DelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { m_delegateFactory= trf; m_messageSender= smsh; } @Override public TestRunner newTestRunner(ISuite suite, XmlTest test, List listeners) { TestRunner tr = m_delegateFactory.newTestRunner(suite, test, listeners); tr.addListener(new RemoteTestListener(suite, test, m_messageSender)); return tr; } } } testng-testng-6.9.5/src/main/java/org/testng/remote/RemoteSuiteWorker.java0000755000175000017500000000142412551235562026201 0ustar eugeneeugenepackage org.testng.remote; import org.testng.SuiteRunner; import org.testng.internal.remote.SlavePool; import org.testng.remote.adapter.RemoteResultListener; import org.testng.xml.XmlSuite; /** * A worker that will be put into an Executor and that sends a suite * This class * * @author cbeust */ public class RemoteSuiteWorker extends RemoteWorker implements Runnable { private XmlSuite m_suite; public RemoteSuiteWorker(XmlSuite suite, SlavePool slavePool, RemoteResultListener listener) { super(listener, slavePool); m_suite = suite; } @Override public void run() { try { SuiteRunner result = sendSuite(getSlavePool().getSlave(), m_suite); m_listener.onResult(result); } catch (Exception e) { e.printStackTrace(); } } } testng-testng-6.9.5/src/main/java/org/testng/remote/RemoteArgs.java0000644000175000017500000000104512551235562024606 0ustar eugeneeugenepackage org.testng.remote; import com.beust.jcommander.Parameter; public class RemoteArgs { public static final String PORT = "-serport"; @Parameter(names = PORT, description = "The port for the serialization protocol") public Integer serPort; public static final String DONT_EXIT= "-dontexit"; @Parameter(names = DONT_EXIT, description = "Do not exit the JVM once done") public boolean dontExit = false; public static final String ACK = "-ack"; @Parameter(names = ACK, description = "Use ACK's") public boolean ack = false; } testng-testng-6.9.5/src/main/java/org/testng/remote/ConnectionInfo.java0000755000175000017500000000135512551235562025460 0ustar eugeneeugenepackage org.testng.remote; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.Socket; public class ConnectionInfo { private Socket m_socket; private ObjectInputStream m_ois; private ObjectOutputStream m_oos; public ObjectInputStream getOis() throws IOException { if (m_ois == null) { m_ois = new ObjectInputStream(m_socket.getInputStream()); } return m_ois; } public ObjectOutputStream getOos() throws IOException { if (m_oos == null) { m_oos = new ObjectOutputStream(m_socket.getOutputStream()); } return m_oos; } public void setSocket(Socket s) { m_socket = s; } public Socket getSocket() { return m_socket; } } testng-testng-6.9.5/src/main/java/org/testng/mustache/0000755000175000017500000000000012551235562022211 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/mustache/VariableChunk.java0000644000175000017500000000076612551235562025603 0ustar eugeneeugenepackage org.testng.mustache; public class VariableChunk extends BaseChunk { private String m_variable; public VariableChunk(Model model, String variable) { super(model); m_variable = variable; } @Override public String compose() { String result = m_model.resolveValueToString(m_variable); p("VariableChunk returning: " + result); return result; } @Override public String toString() { return "[VariableChunk " + m_variable + " model:" + m_model + "]"; } } testng-testng-6.9.5/src/main/java/org/testng/mustache/Value.java0000644000175000017500000000027712551235562024136 0ustar eugeneeugenepackage org.testng.mustache; public class Value { private Object m_object; public Value(Object object) { m_object = object; } public Object get() { return m_object; } } testng-testng-6.9.5/src/main/java/org/testng/mustache/StringChunk.java0000644000175000017500000000054712551235562025321 0ustar eugeneeugenepackage org.testng.mustache; public class StringChunk extends BaseChunk { private String m_string; public StringChunk(Model model, String string) { super(model); m_string = string; } @Override public String compose() { return m_string; } @Override public String toString() { return "[StringChunk " + m_string + "]"; } } testng-testng-6.9.5/src/main/java/org/testng/mustache/Mustache.java0000644000175000017500000000723112551235562024630 0ustar eugeneeugenepackage org.testng.mustache; import org.testng.collections.Lists; import java.io.IOException; import java.util.List; import java.util.Map; public class Mustache { public String run(String template, Map m) throws IOException { return run(template, new Model(m)); } String run(String template, Model model) throws IOException { int lineNumber = 0; List chunks = Lists.newArrayList(); int ti = 0; while (ti < template.length()) { int start; int end; if (template.charAt(ti) == '\n') lineNumber++; if (template.charAt(ti) == '{' && ti + 1 < template.length() && template.charAt(ti + 1) == '{') { int index = ti + 2; start = index; boolean foundEnd = false; while (index < template.length() && ! foundEnd) { index++; foundEnd = template.charAt(index) == '}' && index + 1 < template.length() && template.charAt(index + 1) == '}'; } if (foundEnd) { end = index; String variable = template.substring(start, end); p("Found variable:" + variable); if (variable.startsWith("#")) { // Complex variable {{#foo}}. String conditionalVariable = variable.substring(1); Value value = model.resolveValue(conditionalVariable); int endIndex = findClosingIndex(template, ti, conditionalVariable); Object v = value.get(); if (v == null) { // Null condition, do nothing } else if (v instanceof Iterable) { // Iterable, call a sub Mustache to process this chunk in a loop // after pushing a new submodel Iterable it = (Iterable) v; String subTemplate = template.substring(ti + variable.length() + 4, endIndex); for (Object o : it) { model.push(conditionalVariable, o); String r = new Mustache().run(subTemplate, model); model.popSubModel(); chunks.add(new StringChunk(model, r)); } } else { // Scope, call a sub Mustache to process this chunk // after pushing a new submodel String subTemplate = template.substring(ti + variable.length() + 4, endIndex); model.push(conditionalVariable, v); String r = new Mustache().run(subTemplate, model); model.popSubModel(); chunks.add(new StringChunk(model, r)); } ti = endIndex + variable.length() + 4; } else { // Regular variable {{foo}} chunks.add(new VariableChunk(model, variable)); ti += variable.length() + 4; } } else { throw new RuntimeException("Unclosed variable at line " + lineNumber); } } else { chunks.add(new StringChunk(model, "" + template.charAt(ti))); ti++; } } // while p("******************** Final composition, chunks:"); StringBuilder result = new StringBuilder(); p("*** Template:" + template); for (BaseChunk bc : chunks) { p("*** " + bc); } for (BaseChunk bc : chunks) { String c = bc.compose(); result.append(c); } p("*** Final result:" + result); return result.toString(); } private int findClosingIndex(String template, int ti, String conditionalVariable) { int result = template.lastIndexOf("{{/" + conditionalVariable); return result; } private void p(String string) { if (false) { System.out.println(string); } } public static void main(String[] args) throws IOException { } } testng-testng-6.9.5/src/main/java/org/testng/mustache/Model.java0000644000175000017500000000400512551235562024113 0ustar eugeneeugenepackage org.testng.mustache; import java.lang.reflect.Field; import java.util.Map; import java.util.Stack; public class Model { private Map m_model; private Stack m_subModels = new Stack<>(); private static class SubModel { String variable; Object subModel; } public Model(Map model) { m_model = model; } public void push(String variable, Object subModel) { SubModel sl = new SubModel(); sl.variable = variable; sl.subModel = subModel; m_subModels.push(sl); } public Value resolveValue(String variable) { if (! m_subModels.isEmpty()) { for (SubModel object : m_subModels) { Value value = resolveOnClass(object.subModel, variable); if (value != null) { return value; } } } return new Value(m_model.get(variable)); } private Value resolveOnClass(Object object, String variable) { // if (object instanceof Iterable) { // Iterable it = (Iterable) object; // List result = Lists.newArrayList(); // for (Object o : it) { // List values = resolveOnClass(o, variable); // result.addAll(values); // } // return result; // } else { Class cls = object.getClass(); try { Field f = cls.getField(variable); return new Value(f.get(object)); } catch (IllegalAccessException | NoSuchFieldException | SecurityException e) { // e.printStackTrace(); } // } return null; } public Object getTopSubModel() { return m_subModels.peek().variable; } public void popSubModel() { m_subModels.pop(); } public String resolveValueToString(String variable) { StringBuilder result = new StringBuilder(); Value value = resolveValue(variable); if (value.get() != null) { return value.get().toString(); } else { return ""; } } @Override public String toString() { return "[Model " + m_model + " subModel:" + m_subModels + "]"; } } testng-testng-6.9.5/src/main/java/org/testng/mustache/BaseChunk.java0000644000175000017500000000043212551235562024716 0ustar eugeneeugenepackage org.testng.mustache; abstract public class BaseChunk { protected Model m_model; public BaseChunk(Model model) { m_model = model; } protected void p(String string) { if (false) { System.out.println(string); } } abstract String compose(); } testng-testng-6.9.5/src/main/java/org/testng/log4testng/0000755000175000017500000000000012551235562022472 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/log4testng/Logger.java0000755000175000017500000006171412551235562024570 0ustar eugeneeugenepackage org.testng.log4testng; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import org.testng.Assert; import org.testng.collections.Maps; /** * TestNG support logging via a custom logging framework similar to * Log4j. To control logging, add a * resource named "log4testng.properties" to your classpath. The logging levels are * TRACE, DEBUG, INFO, WARN, ERROR and FATAL. * The Logging framework has the following characteristics: * *
    *
  • All logging is done using System.out (for levels < ERROR) or System.err. There * is no way to specify Appenders.
  • *
  • There is no way to control logging programmatically.
  • *
  • The log4testng.properties resource is searched in the classpath on the first * call to the logging API. If it is not present, logging defaults to the WARN * level.
  • *
* * The property file contains lines in the following format: * *

 * # log4testng will log its own behavior (generally used for debugging this package only).
 * log4testng.debug=true
 *
 * # Specifies the root Loggers logging level. Will log DEBUG level and above
 * log4testng.rootLogger=DEBUG
 *
 * # The org.testng.reporters.EmailableReporter Logger will log TRACE level and above
 * log4testng.logger.org.testng.reporters.EmailableReporter=TRACE
 *
 * # All Logger in packages below org.testng will log WARN level and above
 * log4testng.logger.org.testng=WARN
 * 
* * In your source files you will typically instantiate and use loggers this ways: *

 * import org.testng.log4testng.Logger;
 *
 * class ThisClass {
 *     private static final Logger LOGGER = Logger.getLogger(ThisClass.class);
 *
 *     ...
 *     LOGGER.debug("entering myMethod()");
 *     ...
 *     LOGGER.warn("unknown file: " + filename);
 *     ...
 *     LOGGER.error("Unexpected error", exception);
 * 
*/ public class Logger { // Attribute an hierarchical integer value to all levels. private static int i= 0; private static final int TRACE= i++; private static final int DEBUG= i++; private static final int INFO= i++; private static final int WARN= i++; private static final int ERROR= i++; private static final int FATAL= i++; private static final int LEVEL_COUNT= i; /** Standard prefix of all property names in log4testng.properties. */ private static final String PREFIX= "log4testng."; /** Standard prefix of all logger names in log4testng.properties. */ private static final String LOGGER_PREFIX= PREFIX + "logger."; /** Root logger name in log4testng.properties. */ private static final String ROOT_LOGGER= PREFIX + "rootLogger"; /** Debug property name in log4testng.properties. */ private static final String DEBUG_PROPERTY= PREFIX + "debug"; /** The standard error stream (this is allways System.err except for unit tests) */ private static PrintStream err= System.err; /** The standard output stream (this is allways System.out except for unit tests) */ private static PrintStream out= System.out; /** An ordered list of level names. */ private static final String[] levelNames= new String[LEVEL_COUNT]; static { levelNames[TRACE]= "TRACE"; levelNames[DEBUG]= "DEBUG"; levelNames[INFO] = "INFO"; levelNames[WARN] = "WARN"; levelNames[ERROR] = "ERROR"; levelNames[FATAL] = "FATAL"; } /** A map from level name to level integer index (TRACE->0, DEBUG->1 ...) */ private static final Map levelMap= Maps.newHashMap(); static { for(i= 0; i < LEVEL_COUNT; ++i) { levelMap.put(levelNames[i], i); } } /** true if the Logging system has been initialized. */ private static boolean initialized; /** Map from Logger names to level index (as specified in log4testng.properties) */ private static final Map loggerLevels = Maps.newHashMap(); /** Map of all known loggers. */ private static final Map loggers = Maps.newHashMap(); /** The logging level of the root logger (defaults to warn). */ private static int rootLoggerLevel= WARN; /** Should log4testng log what it is doing (defaults to false). */ private static boolean debug= false; /** The logger's level */ private final int level; /** The logger's name. */ private final Class klass; private final String m_className; /** * Retrieve a logger named according to the value of the pClass.getName() * parameter. If the named logger already exists, then the existing instance * will be returned. Otherwise, a new instance is created. By default, loggers * do not have a set level but inherit it from their nearest ancestor with * a set level. * * @param pClass The class' logger to retrieve. * @return a logger named according to the value of the pClass.getName(). */ public static synchronized Logger getLogger(Class pClass) { initialize(); Logger logger= loggers.get(pClass); if(logger != null) { return logger; } int level= getLevel(pClass); logger= new Logger(pClass, level); loggers.put(pClass, logger); return logger; } /** * Check whether this logger is enabled for the TRACE Level. * @return true if this logger is enabled for level TRACE, false otherwise. */ public boolean isTraceEnabled() { return isLevelEnabled(TRACE); } /** * Log a message object with the TRACE level. This method first checks if this * logger is TRACE enabled. If this logger is TRACE enabled, then it converts * the message object (passed as parameter) to a string by invoking toString(). * WARNING Note that passing a Throwable to this method will print the name of * the Throwable but no stack trace. To print a stack trace use the * trace(Object, Throwable) form instead. * @param message the message object to log. */ public void trace(Object message) { log(TRACE, message, null); } /** * Log a message object with the TRACE level including the stack trace of the * Throwable t passed as parameter. * See Logger.trace(Object) form for more detailed information. * @param message the message object to log. * @param t the exception to log, including its stack trace. */ public void trace(Object message, Throwable t) { log(TRACE, message, t); } /** * Check whether this logger is enabled for the DEBUG Level. * @return true if this logger is enabled for level DEBUG, false otherwise. */ public boolean isDebugEnabled() { return isLevelEnabled(DEBUG); } /** * Log a message object with the DEBUG level. * See Logger.trace(Object) form for more detailed information. * @param message the message object to log. */ public void debug(Object message) { log(DEBUG, message, null); } /** * Log a message object with the DEBUG level including the stack trace of the * Throwable t passed as parameter. * See Logger.trace(Object, Throwable) form for more detailed information. * @param message the message object to log. * @param t the exception to log, including its stack trace. */ public void debug(Object message, Throwable t) { log(DEBUG, message, t); } /** * Check whether this logger is enabled for the INFO Level. * @return true if this logger is enabled for level INFO, false otherwise. */ public boolean isInfoEnabled() { return isLevelEnabled(INFO); } /** * Log a message object with the INFO level. * See Logger.trace(Object) form for more detailed information. * @param message the message object to log. */ public void info(Object message) { log(INFO, message, null); } /** * Log a message object with the WARN level including the stack trace of the * Throwable t passed as parameter. * See Logger.trace(Object, Throwable) form for more detailed information. * @param message the message object to log. * @param t the exception to log, including its stack trace. */ public void info(Object message, Throwable t) { log(INFO, message, t); } /** * Log a message object with the WARN level. * See Logger.trace(Object) form for more detailed information. * @param message the message object to log. */ public void warn(Object message) { log(WARN, message, null); } /** * Log a message object with the ERROR level including the stack trace of the * Throwable t passed as parameter. * See Logger.trace(Object, Throwable) form for more detailed information. * @param message the message object to log. * @param t the exception to log, including its stack trace. */ public void warn(Object message, Throwable t) { log(WARN, message, t); } /** * Log a message object with the ERROR level. * See Logger.trace(Object) form for more detailed information. * @param message the message object to log. */ public void error(Object message) { log(ERROR, message, null); } /** * Log a message object with the DEBUG level including the stack trace of the * Throwable t passed as parameter. * See Logger.trace(Object, Throwable) form for more detailed information. * @param message the message object to log. * @param t the exception to log, including its stack trace. */ public void error(Object message, Throwable t) { log(ERROR, message, t); } /** * Log a message object with the FATAL level. * See Logger.trace(Object) form for more detailed information. * @param message the message object to log. */ public void fatal(Object message) { log(FATAL, message, null); } /** * Log a message object with the FATAL level including the stack trace of the * Throwable t passed as parameter. * See Logger.trace(Object, Throwable) form for more detailed information. * @param message the message object to log. * @param t the exception to log, including its stack trace. */ public void fatal(Object message, Throwable t) { log(FATAL, message, t); } private Logger(Class pClass, int pLevel) { level= pLevel; klass= pClass; m_className= pClass.getName().substring(pClass.getName().lastIndexOf('.') + 1); } private static synchronized void initialize() { if(initialized) { return; } // We flag as initialized right away because if anything goes wrong // We still consider it initialized. TODO Is this OK? initialized= true; InputStream is= Thread.currentThread().getContextClassLoader().getResourceAsStream("log4testng.properties"); if(is == null) { return; } Properties properties= new Properties(); try { properties.load(is); } catch(IOException e) { throw new RuntimeException(e); } checkProperties(properties); } private static void checkProperties(Properties pProperties) { { // See if we want to debug log4testng String debugStr= pProperties.getProperty(DEBUG_PROPERTY); if(debugStr != null) { if(debugStr.equalsIgnoreCase("true")) { debug= true; } else if(debugStr.equalsIgnoreCase("false")) { debug= false; } else { throw new IllegalArgumentException("Unknown " + DEBUG_PROPERTY + " value " + debugStr); } } loglog4testng("log4testng.debug set to " + debug); } { // Set the value of the root logger (if any). String rootLevelStr= pProperties.getProperty(ROOT_LOGGER); if(rootLevelStr != null) { Integer ilevel= levelMap.get(rootLevelStr.toUpperCase()); if(ilevel == null) { throw new IllegalArgumentException("Unknown level for log4testng.rootLogger " + rootLevelStr + " in log4testng.properties"); } rootLoggerLevel= ilevel; loglog4testng("Root level logger set to " + rootLevelStr + " level."); } } Iterator it= pProperties.entrySet().iterator(); while(it.hasNext()) { Map.Entry entry= (Entry) it.next(); String logger= (String) entry.getKey(); String level= (String) entry.getValue(); if(!logger.startsWith(PREFIX)) { throw new IllegalArgumentException("Illegal property value: " + logger); } if(logger.equals(DEBUG_PROPERTY)) { // Already handled } else if(logger.equals(ROOT_LOGGER)) { // Already handled } else { if(!logger.startsWith(LOGGER_PREFIX)) { throw new IllegalArgumentException("Illegal property value: " + logger); } Integer ilevel= levelMap.get(level.toUpperCase()); if(ilevel == null) { throw new IllegalArgumentException("Unknown level " + level + " for logger " + logger + " in log4testng.properties"); } loggerLevels.put(logger.substring(LOGGER_PREFIX.length()), ilevel); loglog4testng("logger " + logger + " set to " + ilevel + " level."); } } } /** * Returns the level associated to the current class. The level is obtain by searching * for a logger in the "testng-logging.properties" resource. For example, if class is * "org.testng.TestNG" the the following loggers are searched in this order: *
    *
  1. "org.testng.TestNG"
  2. *
  3. "org.testng"
  4. *
  5. "org"
  6. *
  7. The root level
  8. *
* * @param pClass the class name used for logger name. * @return the level associated to the current class. */ private static int getLevel(Class pClass) { String name= pClass.getName(); loglog4testng("Getting level for logger " + name); while(true) { Integer level= loggerLevels.get(name); if(level != null) { loglog4testng("Found level " + level + " for logger " + name); return level; } int dot= name.lastIndexOf('.'); if(dot == -1) { loglog4testng("Found level " + rootLoggerLevel + " for root logger"); // Logger name not found. Defaults to root logger level. return rootLoggerLevel; } name= name.substring(0, dot); } } private boolean isLevelEnabled(int pLevel) { return level <= pLevel; } private void log(int pLevel, Object pMessage, Throwable pT) { if(isLevelEnabled(pLevel)) { PrintStream ps= (pLevel >= ERROR) ? err : out; if(null != pT) { synchronized(ps) { ps.println("[" + m_className + "] [" + levelNames[pLevel] + "] " + pMessage); pT.printStackTrace(ps); } } else { ps.println("[" + m_className + "] [" + levelNames[pLevel] + "] " + pMessage); } } } /** * Logs the message to System.out of debug is on. * @param pmessage the message to log to the console */ private static void loglog4testng(String pmessage) { if(debug) { out.println("[log4testng] [debug] " + pmessage); } } /** * This method is for debugging purpose only. * * @param pProperties a properties bundle initialised as log4testng * property file would be. * @param pOut the standard output stream to be used for logging. * @param pErr the standard error stream to be used for logging. */ private static synchronized void testInitialize(Properties pProperties, PrintStream pOut, PrintStream pErr) { initialized= true; loggers.clear(); rootLoggerLevel= WARN; debug= false; out= pOut; err= pErr; checkProperties(pProperties); } /** * Makes sure the default debug value is false. */ private static void testDebugDefault() { Properties props= new Properties(); ByteArrayOutputStream out1= new ByteArrayOutputStream(); ByteArrayOutputStream err1= new ByteArrayOutputStream(); PrintStream out2= new PrintStream(out1); PrintStream err2= new PrintStream(err1); props.put("log4testng.rootLogger", "WARN"); testInitialize(props, out2, err2); Assert.assertEquals(out1.toString(), ""); Assert.assertEquals(err1.toString(), ""); } /** * Makes sure the debug value can be turned on and actualls logs something. */ private static void testDebugOn() { Properties props= new Properties(); ByteArrayOutputStream out1= new ByteArrayOutputStream(); ByteArrayOutputStream err1= new ByteArrayOutputStream(); PrintStream out2= new PrintStream(out1); PrintStream err2= new PrintStream(err1); props.put("log4testng.debug", "true"); props.put("log4testng.rootLogger", "WARN"); testInitialize(props, out2, err2); Assert.assertTrue(out1.toString().startsWith("[log4testng][debug]")); Assert.assertEquals(err1.toString(), ""); } /** * Makes sure the debug value can be turned off and logs nothing. */ private static void testDebugOff() { Properties props= new Properties(); ByteArrayOutputStream out1= new ByteArrayOutputStream(); ByteArrayOutputStream err1= new ByteArrayOutputStream(); PrintStream out2= new PrintStream(out1); PrintStream err2= new PrintStream(err1); props.put("log4testng.debug", "false"); props.put("log4testng.rootLogger", "WARN"); testInitialize(props, out2, err2); Assert.assertEquals(out1.toString(), ""); Assert.assertEquals(err1.toString(), ""); } /** * Makes sure an illegal debug value throws an exception. */ private static void testDebugError() { Properties props= new Properties(); ByteArrayOutputStream out1= new ByteArrayOutputStream(); ByteArrayOutputStream err1= new ByteArrayOutputStream(); PrintStream out2= new PrintStream(out1); PrintStream err2= new PrintStream(err1); props.put("log4testng.debug", "unknown"); props.put("log4testng.rootLogger", "WARN"); try { testInitialize(props, out2, err2); throw new RuntimeException("failure"); } catch(IllegalArgumentException pEx) { // Normal case Assert.assertEquals(out1.toString(), ""); Assert.assertEquals(err1.toString(), ""); } } /** * Tests that the root logger's default level is WARN and that loggers do not * log bellow this level and do log in the correct stream for levels equal to * and above WARN. */ private static void testRootLoggerDefault() { Properties props= new Properties(); ByteArrayOutputStream out1= new ByteArrayOutputStream(); ByteArrayOutputStream err1= new ByteArrayOutputStream(); PrintStream out2= new PrintStream(out1); PrintStream err2= new PrintStream(err1); testInitialize(props, out2, err2); Logger strLogger= Logger.getLogger(String.class); strLogger.trace("trace should not appear"); Assert.assertEquals(out1.toString(), ""); Assert.assertEquals(err1.toString(), ""); strLogger.debug("debug should not appear"); Assert.assertEquals(out1.toString(), ""); Assert.assertEquals(err1.toString(), ""); strLogger.info("info should not appear"); Assert.assertEquals(out1.toString(), ""); Assert.assertEquals(err1.toString(), ""); strLogger.warn("warn should appear"); int outlength= out1.toString().length(); Assert.assertTrue(out1.toString().startsWith("[java.lang.String] [WARN] warn should appear")); Assert.assertEquals(err1.toString(), ""); strLogger.error("error should appear"); Assert.assertEquals(out1.toString().length(), outlength); Assert.assertTrue(err1.toString().startsWith("[java.lang.String] [ERROR] error should appear")); strLogger.fatal("fatal should appear"); Assert.assertEquals(out1.toString().length(), outlength); Assert.assertTrue(err1.toString().contains("[java.lang.String] [FATAL] fatal should appear")); } /** * Test setting the root logger level */ private static void testRootLoggerSet() { Properties props= new Properties(); ByteArrayOutputStream out1= new ByteArrayOutputStream(); ByteArrayOutputStream err1= new ByteArrayOutputStream(); PrintStream out2= new PrintStream(out1); PrintStream err2= new PrintStream(err1); props.put("log4testng.rootLogger", "DEBUG"); testInitialize(props, out2, err2); Logger strLogger= Logger.getLogger(String.class); strLogger.trace("trace should appear"); Assert.assertEquals(out1.toString(), ""); Assert.assertEquals(err1.toString(), ""); strLogger.debug("debug should appear"); Assert.assertTrue(out1.toString().startsWith("[java.lang.String] [DEBUG] debug should appear")); Assert.assertEquals(err1.toString(), ""); } /** * Test setting the root logger to an illegal level value throws an exception. */ private static void testRootLoggerSetError() { Properties props= new Properties(); ByteArrayOutputStream out1= new ByteArrayOutputStream(); ByteArrayOutputStream err1= new ByteArrayOutputStream(); PrintStream out2= new PrintStream(out1); PrintStream err2= new PrintStream(err1); props.put("log4testng.rootLogger", "unknown"); try { testInitialize(props, out2, err2); throw new RuntimeException("failure"); } catch(IllegalArgumentException pEx) { // Normal case Assert.assertEquals(out1.toString(), ""); Assert.assertEquals(err1.toString(), ""); } } /** * Test setting a user logger level */ private static void testUserLoggerSet() { Properties props= new Properties(); ByteArrayOutputStream out1= new ByteArrayOutputStream(); ByteArrayOutputStream err1= new ByteArrayOutputStream(); PrintStream out2= new PrintStream(out1); PrintStream err2= new PrintStream(err1); props.put("log4testng.logger.java.lang.String", "DEBUG"); testInitialize(props, out2, err2); Logger strLogger= Logger.getLogger(String.class); strLogger.trace("trace should not appear"); Assert.assertEquals(out1.toString(), ""); Assert.assertEquals(err1.toString(), ""); strLogger.debug("debug should appear"); int outLength= out1.toString().length(); Assert.assertTrue(out1.toString().startsWith("[java.lang.String] [DEBUG] debug should appear")); Assert.assertEquals(err1.toString(), ""); Logger classLogger= Logger.getLogger(Class.class); classLogger.debug("debug should not appear"); Assert.assertEquals(out1.toString().length(), outLength); Assert.assertEquals(err1.toString(), ""); classLogger.warn("warn should appear"); Assert.assertTrue(out1.toString().contains("[java.lang.Class] [WARN] warn should appear")); Assert.assertEquals(err1.toString(), ""); } /** * Test setting a user logger to an illegal level value throws an exception */ private static void testUserLoggerSetError() { Properties props= new Properties(); ByteArrayOutputStream out1= new ByteArrayOutputStream(); ByteArrayOutputStream err1= new ByteArrayOutputStream(); PrintStream out2= new PrintStream(out1); PrintStream err2= new PrintStream(err1); props.put("log4testng.logger.java.lang.String", "unknown"); try { testInitialize(props, out2, err2); throw new RuntimeException("failure"); } catch(IllegalArgumentException pEx) { // Normal case Assert.assertEquals(out1.toString(), ""); Assert.assertEquals(err1.toString(), ""); } } /** * Tests setting a partial logger name (a hierarchy scope) */ private static void testUserLoggerSetHierarchy() { Properties props= new Properties(); ByteArrayOutputStream out1= new ByteArrayOutputStream(); ByteArrayOutputStream err1= new ByteArrayOutputStream(); PrintStream out2= new PrintStream(out1); PrintStream err2= new PrintStream(err1); props.put("log4testng.logger.java.lang", "DEBUG"); testInitialize(props, out2, err2); Logger strLogger= Logger.getLogger(String.class); strLogger.trace("trace should not appear"); Assert.assertEquals(out1.toString(), ""); Assert.assertEquals(err1.toString(), ""); strLogger.debug("debug should appear"); Assert.assertTrue(out1.toString().startsWith("[java.lang.String] [DEBUG] debug should appear")); Assert.assertEquals(err1.toString(), ""); } /** * Run all tests. (very crusty ...) * @param pArgs not used */ public static void main(String[] pArgs) { testDebugDefault(); testDebugOn(); testDebugOff(); testDebugError(); testRootLoggerDefault(); testRootLoggerSet(); testRootLoggerSetError(); testUserLoggerSet(); testUserLoggerSetError(); testUserLoggerSetHierarchy(); } } testng-testng-6.9.5/src/main/java/org/testng/log/0000755000175000017500000000000012551235562021161 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/log/TextFormatter.java0000755000175000017500000000111012551235562024630 0ustar eugeneeugenepackage org.testng.log; import java.util.logging.LogRecord; import java.util.logging.SimpleFormatter; /** * This class implements a simple TextFormatter because the brainded * default formatter of java.util.logging outputs everything on two * lines and it's ugly as butt. * * @author Cedric Beust, May 2, 2004 * */ public class TextFormatter extends SimpleFormatter { @Override public synchronized String format(LogRecord record) { StringBuffer result = new StringBuffer(); result.append(record.getMessage()).append("\n"); return result.toString(); } } testng-testng-6.9.5/src/main/java/org/testng/junit/0000755000175000017500000000000012551235562021531 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/junit/JUnitTestRunner.java0000755000175000017500000002174112551235562025467 0ustar eugeneeugenepackage org.testng.junit; import java.lang.reflect.Constructor; import org.testng.ITestListener; import org.testng.ITestNGMethod; import org.testng.ITestResult; import org.testng.TestNGException; import org.testng.collections.Lists; import org.testng.internal.ITestResultNotifier; import org.testng.internal.InvokedMethod; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Calendar; import java.util.List; import java.util.Map; import java.util.WeakHashMap; import junit.framework.AssertionFailedError; import junit.framework.Test; import junit.framework.TestListener; import junit.framework.TestResult; import junit.framework.TestSuite; import org.testng.*; /** * A JUnit TestRunner that records/triggers all information/events necessary to TestNG. * * @author Alexandru Popescu */ public class JUnitTestRunner implements TestListener, IJUnitTestRunner { public static final String SUITE_METHODNAME = "suite"; private ITestResultNotifier m_parentRunner; private Map m_tests= new WeakHashMap<>(); private List m_methods= Lists.newArrayList(); private List m_invokedMethodListeners = Lists.newArrayList(); public JUnitTestRunner() { } public JUnitTestRunner(ITestResultNotifier tr) { m_parentRunner= tr; } /** * Needed from TestRunner in order to figure out what JUnit test methods were run. * * @return the list of all JUnit test methods run */ @Override public List getTestMethods() { return m_methods; } @Override public void setTestResultNotifier(ITestResultNotifier notifier) { m_parentRunner= notifier; } /** * @see junit.framework.TestListener#startTest(junit.framework.Test) */ @Override public void startTest(Test test) { m_tests.put(test, new TestRunInfo(Calendar.getInstance().getTimeInMillis())); } /** * @see junit.framework.TestListener#addError(junit.framework.Test, java.lang.Throwable) */ @Override public void addError(Test test, Throwable t) { recordFailure(test, t); } /** * @see junit.framework.TestListener#addFailure(junit.framework.Test, junit.framework.AssertionFailedError) */ @Override public void addFailure(Test test, AssertionFailedError t) { recordFailure(test, t); } private void recordFailure(Test test, Throwable t) { TestRunInfo tri= m_tests.get(test); if(null != tri) { tri.setThrowable(t); } } /** * @see junit.framework.TestListener#endTest(junit.framework.Test) */ @Override public void endTest(Test test) { TestRunInfo tri= m_tests.get(test); if(null == tri) { return; // HINT: this should never happen. How do I protect myself? } org.testng.internal.TestResult tr= recordResults(test, tri); runTestListeners(tr, m_parentRunner.getTestListeners()); } public void setInvokedMethodListeners(List listeners) { m_invokedMethodListeners = listeners; } private org.testng.internal.TestResult recordResults(Test test, TestRunInfo tri) { JUnitTestClass tc= new JUnit3TestClass(test); JUnitTestMethod tm= new JUnit3TestMethod(tc, test); org.testng.internal.TestResult tr= new org.testng.internal.TestResult(tc, test, tm, tri.m_failure, tri.m_start, Calendar.getInstance().getTimeInMillis(), null); if(tri.isFailure()) { tr.setStatus(ITestResult.FAILURE); m_parentRunner.addFailedTest(tm, tr); } else { m_parentRunner.addPassedTest(tm, 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) { l.beforeInvocation(im, tr); } return tr; } private static void runTestListeners(ITestResult tr, List listeners) { for (ITestListener itl : listeners) { switch(tr.getStatus()) { case ITestResult.SKIP: { itl.onTestSkipped(tr); break; } case ITestResult.SUCCESS_PERCENTAGE_FAILURE: { itl.onTestFailedButWithinSuccessPercentage(tr); break; } case ITestResult.FAILURE: { itl.onTestFailure(tr); break; } case ITestResult.SUCCESS: { itl.onTestSuccess(tr); break; } case ITestResult.STARTED: { itl.onTestStart(tr); break; } default: { assert false : "UNKNOWN STATUS:" + tr; } } } } /** * Returns the Test corresponding to the given suite. This is * a template method, subclasses override runFailed(), clearStatus(). */ protected Test getTest(Class testClass, String... methods) { if (methods.length > 0) { TestSuite ts = new TestSuite(); try { Constructor c = testClass.getConstructor(String.class); for (String m: methods) { try { ts.addTest((Test) c.newInstance(m)); } catch (InstantiationException ex) { runFailed(testClass, "abstract class " + ex); } catch (IllegalAccessException ex) { runFailed(testClass, "constructor is not public " + ex); } catch (IllegalArgumentException ex) { runFailed(testClass, "actual and formal parameters differ " + ex); } catch (InvocationTargetException ex) { runFailed(testClass, "exception while instatiating test for method '" + m + "' " + ex); } } } catch (NoSuchMethodException ex) { runFailed(testClass, "no constructor accepting String argument found " + ex); } catch (SecurityException ex) { runFailed(testClass, "security exception " + ex); } return ts; } Method suiteMethod = null; try { suiteMethod = testClass.getMethod(SUITE_METHODNAME, new Class[0]); } catch (Exception e) { // try to extract a test suite automatically return new TestSuite(testClass); } if (!Modifier.isStatic(suiteMethod.getModifiers())) { runFailed(testClass, "suite() method must be static"); return null; } Test test = null; try { test = (Test) suiteMethod.invoke(null, (Object[]) new Class[0]); // static method if (test == null) { return test; } } catch (InvocationTargetException e) { runFailed(testClass, "failed to invoke method suite():" + e.getTargetException().toString()); return null; } catch (IllegalAccessException e) { runFailed(testClass, "failed to invoke method suite():" + e.toString()); return null; } return test; } /** * A start implementation that ignores the TestResult * @param testClass the JUnit test class */ @Override public void run(Class testClass, String... methods) { start(testClass, methods); } /** * Starts a test run. Analyzes the command line arguments and runs the given * test suite. */ public TestResult start(Class testCase, String... methods) { try { Test suite = getTest(testCase, methods); if(null != suite) { return doRun(suite); } else { runFailed(testCase, "could not create/run JUnit test suite"); } } catch (Exception e) { runFailed(testCase, "could not create/run JUnit test suite: " + e.getMessage()); } return null; } protected void runFailed(Class clazz, String message) { throw new TestNGException("Failure in JUnit mode for class " + clazz.getName() + ": " + message); } /** * Creates the TestResult to be used for the test run. */ protected TestResult createTestResult() { return new TestResult(); } protected TestResult doRun(Test suite) { TestResult result = createTestResult(); result.addListener(this); suite.run(result); return result; } private static class TestRunInfo { private final long m_start; private Throwable m_failure; public TestRunInfo(long start) { m_start= start; } public boolean isFailure() { return null != m_failure; } public void setThrowable(Throwable t) { m_failure= t; } } } testng-testng-6.9.5/src/main/java/org/testng/junit/JUnitTestRecognizer.java0000644000175000017500000000016712551235562026321 0ustar eugeneeugenepackage org.testng.junit; /** * * @author lukas */ interface JUnitTestRecognizer { boolean isTest(Class c); } testng-testng-6.9.5/src/main/java/org/testng/junit/JUnitTestMethod.java0000644000175000017500000000155512551235562025434 0ustar eugeneeugenepackage org.testng.junit; import java.lang.reflect.Method; import org.testng.ITestNGMethod; import org.testng.internal.BaseTestMethod; /** * * @author lukas */ //NO JUnit specific code here to avoid runtime errors public abstract class JUnitTestMethod extends BaseTestMethod { protected JUnitTestMethod(JUnitTestClass owner, Method method, Object 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); } @Override public boolean isTest() { return true; } @Override public ITestNGMethod clone() { throw new IllegalStateException("clone is not supported for JUnit"); } } testng-testng-6.9.5/src/main/java/org/testng/junit/JUnitTestFinder.java0000644000175000017500000000352712551235562025424 0ustar eugeneeugenepackage org.testng.junit; import java.lang.reflect.Modifier; import org.testng.internal.Utils; /** * * @author ljungman */ public final class JUnitTestFinder { private static final String JUNIT3_TEST = "junit.framework.Test"; private static final String JUNIT3_FINDER = "org.testng.junit.JUnit3TestRecognizer"; private static final String JUNIT4_TEST = "org.junit.Test"; private static final String JUNIT4_FINDER = "org.testng.junit.JUnit4TestRecognizer"; private static final JUnitTestRecognizer junit3; private static final JUnitTestRecognizer junit4; static { junit3 = getJUnitTestRecognizer(JUNIT3_TEST, JUNIT3_FINDER); junit4 = getJUnitTestRecognizer(JUNIT4_TEST, JUNIT4_FINDER); if (junit3 == null) { Utils.log("JUnitTestFinder", 2, "JUnit3 was not found on the classpath"); } if (junit4 == null) { Utils.log("JUnitTestFinder", 2, "JUnit4 was not found on the classpath"); } } public static boolean isJUnitTest(Class c) { if (!haveJUnit()) { return false; } //only public classes are interesting, so filter out the rest if (!Modifier.isPublic(c.getModifiers()) || c.isInterface() || c.isAnnotation() || c.isEnum()) { return false; } return (junit3 != null && junit3.isTest(c)) || (junit4 != null && junit4.isTest(c)); } private static boolean haveJUnit() { return junit3 != null || junit4 != null; } private static JUnitTestRecognizer getJUnitTestRecognizer(String test, String name) { try { Class.forName(test); Class c = (Class) Class.forName(name); return c.newInstance(); } catch (Throwable t) { //ignore return null; } } } testng-testng-6.9.5/src/main/java/org/testng/junit/JUnitTestClass.java0000644000175000017500000001141212551235562025252 0ustar eugeneeugenepackage org.testng.junit; import java.util.List; import org.testng.ITestClass; import org.testng.ITestNGMethod; import org.testng.collections.Lists; import org.testng.xml.XmlClass; import org.testng.xml.XmlTest; /** * * @author lukas */ //NO JUnit specific code here to avoid runtime errors public abstract class JUnitTestClass implements ITestClass { private static final long serialVersionUID = 405598615794850925L; private List m_testMethods = Lists.newArrayList(); private List m_beforeClass = Lists.newArrayList(); private List m_afterClass = Lists.newArrayList(); private List m_beforeTest = Lists.newArrayList(); private List m_afterTest = Lists.newArrayList(); private Class m_realClass; private Object[] m_instances; private long[] m_instanceHashes; private XmlTest m_xmlTest; private XmlClass m_xmlClass; public JUnitTestClass(Class test) { m_realClass = test; m_instances = new Object[]{test}; m_instanceHashes = new long[]{test.hashCode()}; } List getTestMethodList() { return m_testMethods; } /** * @see org.testng.IClass#addInstance(java.lang.Object) */ @Override public void addInstance(Object instance) { throw new IllegalStateException("addInstance is not supported for JUnit"); } /** * @see org.testng.IClass#getName() */ @Override public String getName() { return m_realClass.getName(); } /** * @see org.testng.IClass#getRealClass() */ @Override public Class getRealClass() { return m_realClass; } @Override public String getTestName() { return m_xmlTest.getName(); } @Override public XmlTest getXmlTest() { return m_xmlTest; } @Override public XmlClass getXmlClass() { return m_xmlClass; } /** * @see org.testng.ITestClass#getInstanceCount() */ @Override public int getInstanceCount() { return 1; } /** * @see org.testng.ITestClass#getInstanceHashCodes() */ @Override public long[] getInstanceHashCodes() { return m_instanceHashes; } /** * @see org.testng.ITestClass#getInstances(boolean) */ @Override public Object[] getInstances(boolean reuse) { return m_instances; } /** * @see org.testng.ITestClass#getTestMethods() */ @Override public ITestNGMethod[] getTestMethods() { return m_testMethods.toArray(new ITestNGMethod[m_testMethods.size()]); } /** * @see org.testng.ITestClass#getBeforeTestMethods() */ @Override public ITestNGMethod[] getBeforeTestMethods() { return m_beforeTest.toArray(new ITestNGMethod[m_beforeTest.size()]); } /** * @see org.testng.ITestClass#getAfterTestMethods() */ @Override public ITestNGMethod[] getAfterTestMethods() { return m_afterTest.toArray(new ITestNGMethod[m_afterTest.size()]); } /** * @see org.testng.ITestClass#getBeforeClassMethods() */ @Override public ITestNGMethod[] getBeforeClassMethods() { return m_beforeClass.toArray(new ITestNGMethod[m_beforeClass.size()]); } /** * @see org.testng.ITestClass#getAfterClassMethods() */ @Override public ITestNGMethod[] getAfterClassMethods() { return m_afterClass.toArray(new ITestNGMethod[m_afterClass.size()]); } //features not supported by JUnit private static final ITestNGMethod[] EMPTY_METHODARRAY = new ITestNGMethod[0]; /** * @see org.testng.ITestClass#getBeforeSuiteMethods() */ @Override public ITestNGMethod[] getBeforeSuiteMethods() { return EMPTY_METHODARRAY; } /** * @see org.testng.ITestClass#getAfterSuiteMethods() */ @Override public ITestNGMethod[] getAfterSuiteMethods() { return EMPTY_METHODARRAY; } /** * @see org.testng.ITestClass#getBeforeGroupsMethods() */ @Override public ITestNGMethod[] getBeforeGroupsMethods() { return EMPTY_METHODARRAY; } /** * @see org.testng.ITestClass#getAfterGroupsMethods() */ @Override public ITestNGMethod[] getAfterGroupsMethods() { return EMPTY_METHODARRAY; } //already deprecated stuff, not usable in junit /** * @see org.testng.ITestClass#getBeforeTestConfigurationMethods() */ @Override public ITestNGMethod[] getBeforeTestConfigurationMethods() { return EMPTY_METHODARRAY; } /** * @see org.testng.ITestClass#getAfterTestConfigurationMethods() */ @Override public ITestNGMethod[] getAfterTestConfigurationMethods() { return EMPTY_METHODARRAY; } } testng-testng-6.9.5/src/main/java/org/testng/junit/JUnitMethodFinder.java0000755000175000017500000001277612551235562025736 0ustar eugeneeugenepackage org.testng.junit; import org.testng.ITestMethodFinder; import org.testng.ITestNGMethod; import org.testng.collections.Lists; import org.testng.internal.TestNGMethod; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.xml.XmlTest; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashSet; import java.util.List; import java.util.Set; /** * This class locates all test and configuration methods according to JUnit. * It is used to change the strategy used by TestRunner to locate its test * methods. * * @author Cedric Beust, May 3, 2004 * */ public class JUnitMethodFinder implements ITestMethodFinder { private String m_testName = null; private IAnnotationFinder m_annotationFinder = null; public JUnitMethodFinder(String testName, IAnnotationFinder finder) { m_testName = testName; m_annotationFinder = finder; } private Constructor findConstructor(Class cls, Class[] parameters) { Constructor result = null; try { result = cls.getConstructor(parameters); } catch (SecurityException | NoSuchMethodException ex) { // ignore } return result; } @Override public ITestNGMethod[] getTestMethods(Class cls, XmlTest xmlTest) { ITestNGMethod[] result = privateFindTestMethods(new INameFilter() { @Override public boolean accept(Method method) { return method.getName().startsWith("test") && method.getParameterTypes().length == 0; } }, cls); // ppp("====="); // ppp("FIND TEST METHOD RETURNING "); // for (ITestMethod m : result) { // ppp(" " + m); // } // ppp("====="); return result; } private ITestNGMethod[] privateFindTestMethods(INameFilter filter, Class cls) { List vResult = Lists.newArrayList(); // We do not want to walk up the class hierarchy and accept the // same method twice (e.g. setUp) which would lead to double-invocation. // All relevant JUnit methods are parameter-less so we store accepted // method names in a Set to filter out duplicates. Set acceptedMethodNames = new HashSet<>(); // // Collect all methods that start with test // Class current = cls; while(!(current == Object.class)) { Method[] allMethods = current.getDeclaredMethods(); for(Method allMethod : allMethods) { ITestNGMethod m = new TestNGMethod(/* allMethods[i].getDeclaringClass(), */ allMethod, m_annotationFinder, null, null); /* @@@ */ Method method = m.getMethod(); String methodName = method.getName(); if(filter.accept(method) && !acceptedMethodNames.contains(methodName)) { // if (m.getName().startsWith("test")) { // ppp("Found JUnit test method: " + tm); vResult.add(m); acceptedMethodNames.add(methodName); } } current = current.getSuperclass(); } return vResult.toArray(new ITestNGMethod[vResult.size()]); } private static void ppp(String s) { System.out.println("[JUnitMethodFinder] " + s); } private Object instantiate(Class cls) { Object result = null; Constructor ctor = findConstructor(cls, new Class[] { String.class }); try { if (null != ctor) { result = ctor.newInstance(new Object[] { m_testName }); } else { ctor = cls.getConstructor(new Class[0]); result = ctor.newInstance(new Object[0]); } } catch (IllegalArgumentException | NoSuchMethodException | InvocationTargetException | IllegalAccessException | SecurityException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { System.err.println("Couldn't find a constructor with a String parameter on your JUnit test class."); ex.printStackTrace(); } return result; } @Override public ITestNGMethod[] getBeforeTestMethods(Class cls) { ITestNGMethod[] result = privateFindTestMethods(new INameFilter() { @Override public boolean accept(Method method) { return "setUp".equals(method.getName()); } }, cls); return result; } @Override public ITestNGMethod[] getAfterTestMethods(Class cls) { ITestNGMethod[] result = privateFindTestMethods(new INameFilter() { @Override public boolean accept(Method method) { return "tearDown".equals(method.getName()); } }, cls); return result; } @Override public ITestNGMethod[] getAfterClassMethods(Class cls) { return new ITestNGMethod[0]; } @Override public ITestNGMethod[] getBeforeClassMethods(Class cls) { return new ITestNGMethod[0]; } @Override public ITestNGMethod[] getBeforeSuiteMethods(Class cls) { return new ITestNGMethod[0]; } @Override public ITestNGMethod[] getAfterSuiteMethods(Class cls) { return new ITestNGMethod[0]; } @Override public ITestNGMethod[] getBeforeTestConfigurationMethods(Class testClass) { return new ITestNGMethod[0]; } @Override public ITestNGMethod[] getAfterTestConfigurationMethods(Class testClass) { return new ITestNGMethod[0]; } @Override public ITestNGMethod[] getBeforeGroupsConfigurationMethods(Class testClass) { return new ITestNGMethod[0]; } @Override public ITestNGMethod[] getAfterGroupsConfigurationMethods(Class testClass) { return new ITestNGMethod[0]; } } ///////////// interface INameFilter { public boolean accept(Method method); } testng-testng-6.9.5/src/main/java/org/testng/junit/JUnit4TestRunner.java0000644000175000017500000001670412551235562025553 0ustar eugeneeugenepackage org.testng.junit; import java.util.*; import java.util.regex.Pattern; import org.junit.runner.Description; import org.junit.runner.JUnitCore; import org.junit.runner.Request; import org.junit.runner.Result; import org.junit.runner.manipulation.Filter; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunListener; import org.testng.*; import org.testng.collections.Lists; import org.testng.internal.ITestResultNotifier; import org.testng.internal.InvokedMethod; import org.testng.internal.TestResult; /** * A JUnit TestRunner that records/triggers all information/events necessary to * TestNG. * * @author Lukas Jungmann */ public class JUnit4TestRunner implements IJUnitTestRunner { private ITestResultNotifier m_parentRunner; private List m_methods = Lists.newArrayList(); private List m_listeners = Lists.newArrayList(); private List m_invokeListeners = Lists.newArrayList(); public JUnit4TestRunner() { } public JUnit4TestRunner(ITestResultNotifier tr) { m_parentRunner = tr; m_listeners = m_parentRunner.getTestListeners(); } /** * Needed from TestRunner in order to figure out what JUnit test methods * were run. * * @return the list of all JUnit test methods run */ @Override public List getTestMethods() { return m_methods; } @Override public void setTestResultNotifier(ITestResultNotifier notifier) { m_parentRunner = notifier; m_listeners = m_parentRunner.getTestListeners(); } public void setInvokedMethodListeners(List listeners) { m_invokeListeners = listeners; } /** * A * start implementation that ignores the * TestResult * * @param testClass the JUnit test class */ @Override public void run(Class testClass, String... methods) { start(testClass, methods); } /** * Starts a test run. Analyzes the command line arguments and runs the given * test suite. */ public Result start(final Class testCase, final String... methods) { try { JUnitCore core = new JUnitCore(); core.addListener(new RL()); Request r = Request.aClass(testCase); return core.run(r.filterWith(new Filter() { @Override public boolean shouldRun(Description description) { if (description == null) { return false; } if (methods.length == 0) { //run everything return true; } for (String m: methods) { Pattern p = Pattern.compile(m); if (p.matcher(description.getMethodName()).matches()) { return true; } } return false; } @Override public String describe() { return "TestNG method filter"; } })); } catch (Throwable t) { throw new TestNGException("Failure in JUnit mode for class " + testCase.getName(), t); } } private class RL extends RunListener { private Map runs = new WeakHashMap<>(); private List notified = new LinkedList<>(); @Override public void testAssumptionFailure(Failure failure) { notified.add(failure.getDescription()); ITestResult tr = runs.get(failure.getDescription()); tr.setStatus(TestResult.SKIP); tr.setEndMillis(Calendar.getInstance().getTimeInMillis()); tr.setThrowable(failure.getException()); m_parentRunner.addSkippedTest(tr.getMethod(), tr); for (ITestListener l : m_listeners) { l.onTestSkipped(tr); } } @Override public void testFailure(Failure failure) throws Exception { if (isAssumptionFailed(failure)) { this.testAssumptionFailure(failure); return; } notified.add(failure.getDescription()); ITestResult tr = runs.get(failure.getDescription()); tr.setStatus(TestResult.FAILURE); tr.setEndMillis(Calendar.getInstance().getTimeInMillis()); tr.setThrowable(failure.getException()); m_parentRunner.addFailedTest(tr.getMethod(), tr); for (ITestListener l : m_listeners) { l.onTestFailure(tr); } } @Override public void testFinished(Description description) throws Exception { ITestResult tr = runs.get(description); if (!notified.contains(description)) { tr.setStatus(TestResult.SUCCESS); tr.setEndMillis(Calendar.getInstance().getTimeInMillis()); m_parentRunner.addPassedTest(tr.getMethod(), tr); for (ITestListener l : m_listeners) { l.onTestSuccess(tr); } } m_methods.add(tr.getMethod()); } @Override public void testIgnored(Description description) throws Exception { ITestResult tr = createTestResult(description); tr.setStatus(TestResult.SKIP); tr.setEndMillis(tr.getStartMillis()); m_parentRunner.addSkippedTest(tr.getMethod(), tr); m_methods.add(tr.getMethod()); for (ITestListener l : m_listeners) { l.onTestSkipped(tr); } } @Override public void testRunFinished(Result result) throws Exception { } @Override public void testRunStarted(Description description) throws Exception { } @Override public void testStarted(Description description) throws Exception { ITestResult tr = createTestResult(description); runs.put(description, tr); for (ITestListener l : m_listeners) { l.onTestStart(tr); } } private ITestResult createTestResult(Description test) { JUnit4TestClass tc = new JUnit4TestClass(test); JUnitTestMethod tm = new JUnit4TestMethod(tc, test); TestResult tr = new TestResult(tc, test, tm, null, Calendar.getInstance().getTimeInMillis(), 0, null); 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); } return tr; } } private static boolean isAssumptionFailed(Failure failure) { if (failure == null) { return false; } //noinspection ThrowableResultOfMethodCallIgnored final Throwable exception = failure.getException(); //noinspection SimplifiableIfStatement if (exception == null) { return false; } return "org.junit.internal.AssumptionViolatedException".equals(exception.getClass().getCanonicalName()); } } testng-testng-6.9.5/src/main/java/org/testng/junit/JUnit4TestRecognizer.java0000644000175000017500000000152012551235562026377 0ustar eugeneeugenepackage org.testng.junit; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import org.junit.runner.RunWith; /** * * @author lukas */ public final class JUnit4TestRecognizer implements JUnitTestRecognizer { public JUnit4TestRecognizer() { } public boolean isTest(Class c) { for (Annotation an: c.getAnnotations()) { if (RunWith.class.isAssignableFrom(an.annotationType())) { return true; } } boolean haveTest = false; for (Method m : c.getMethods()) { for (Annotation a : m.getDeclaredAnnotations()) { if (org.junit.Test.class.isAssignableFrom(a.annotationType())) { haveTest = true; break; } } } return haveTest; } } testng-testng-6.9.5/src/main/java/org/testng/junit/JUnit4TestMethod.java0000644000175000017500000000205512551235562025514 0ustar eugeneeugenepackage org.testng.junit; import java.lang.reflect.Method; import org.junit.runner.Description; import org.testng.internal.Utils; /** * * @author lukas */ public class JUnit4TestMethod extends JUnitTestMethod { public JUnit4TestMethod(JUnitTestClass owner, Description desc) { super(owner, desc.getMethodName(), getMethod(desc), desc); } @Override public Object[] getInstances() { return new Object[0]; } 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) { Utils.log("JUnit4TestMethod", 2, "Method '" + method + "' not found in class '" + c.getName() + "': " + t.getMessage()); return null; } } } testng-testng-6.9.5/src/main/java/org/testng/junit/JUnit4TestClass.java0000644000175000017500000000035712551235562025344 0ustar eugeneeugenepackage org.testng.junit; import org.junit.runner.Description; /** * * @author lukas */ public class JUnit4TestClass extends JUnitTestClass { public JUnit4TestClass(Description test) { super(test.getTestClass()); } } testng-testng-6.9.5/src/main/java/org/testng/junit/JUnit3TestRecognizer.java0000644000175000017500000000217712551235562026407 0ustar eugeneeugenepackage org.testng.junit; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import junit.framework.Test; /** * * @author lukas */ public class JUnit3TestRecognizer implements JUnitTestRecognizer { public JUnit3TestRecognizer() { } public boolean isTest(Class c) { //class implementing junit.framework.Test with at least one test* method if (Test.class.isAssignableFrom(c)) { boolean haveTest = false; for (Method m : c.getMethods()) { if (m.getName().startsWith("test")) { haveTest = true; break; } } if (haveTest) { return true; } } try { //or a class with public static Test suite() method Method m = c.getDeclaredMethod("suite"); if (Modifier.isPublic(m.getModifiers()) && Modifier.isStatic(m.getModifiers())) { return m.getReturnType().isAssignableFrom(Test.class); } } catch (Throwable t) { return false; } return false; } } testng-testng-6.9.5/src/main/java/org/testng/junit/JUnit3TestMethod.java0000644000175000017500000000143412551235562025513 0ustar eugeneeugenepackage org.testng.junit; import java.lang.reflect.Method; import junit.framework.Test; import org.testng.internal.Utils; /** * * @author lukas */ public class JUnit3TestMethod extends JUnitTestMethod { public JUnit3TestMethod(JUnitTestClass owner, Test test) { super(owner, getMethod(test), test); } private static Method getMethod(Test t) { String name = null; try { Method nameMethod = t.getClass().getMethod("getName"); name = (String) nameMethod.invoke(t); return t.getClass().getMethod(name); } catch (Throwable th) { Utils.log("JUnit3TestMethod", 2, "Method '" + name + "' not found in class '" + t + "': " + th.getMessage()); return null; } } } testng-testng-6.9.5/src/main/java/org/testng/junit/JUnit3TestClass.java0000644000175000017500000000033412551235562025336 0ustar eugeneeugenepackage org.testng.junit; import junit.framework.Test; /** * * @author lukas */ public class JUnit3TestClass extends JUnitTestClass { public JUnit3TestClass(Test test) { super(test.getClass()); } } testng-testng-6.9.5/src/main/java/org/testng/junit/IJUnitTestRunner.java0000755000175000017500000000113612551235562025574 0ustar eugeneeugenepackage org.testng.junit; import java.util.List; import org.testng.IInvokedMethodListener; import org.testng.ITestNGMethod; import org.testng.internal.ITestResultNotifier; /** * An abstraction interface over JUnit test runners. * * @author Alexandru Popescu */ public interface IJUnitTestRunner { void setInvokedMethodListeners(List listener); void setTestResultNotifier(ITestResultNotifier notifier); void run(Class junitTestClass, String... methods); List getTestMethods(); } testng-testng-6.9.5/src/main/java/org/testng/internal/0000755000175000017500000000000012551235562022214 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/internal/thread/0000755000175000017500000000000012551235562023463 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/internal/thread/graph/0000755000175000017500000000000012551235562024564 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/internal/thread/graph/SuiteWorkerFactory.java0000644000175000017500000000233012551235562031240 0ustar eugeneeugenepackage org.testng.internal.thread.graph; import org.testng.ISuite; import org.testng.SuiteRunnerWorker; import org.testng.collections.Lists; import org.testng.internal.SuiteRunnerMap; import java.util.List; /** * An {@code IThreadWorkerFactory} for {@code SuiteRunner}s * * @author nullin * */ public class SuiteWorkerFactory implements IThreadWorkerFactory { private Integer m_verbose; private String m_defaultSuiteName; private SuiteRunnerMap m_suiteRunnerMap; public SuiteWorkerFactory(SuiteRunnerMap suiteRunnerMap, Integer verbose, String defaultSuiteName) { m_suiteRunnerMap = suiteRunnerMap; m_verbose = verbose; m_defaultSuiteName = defaultSuiteName; } /** * For each suite, creates a {@code SuiteRunnerWorker} * @param suites set of suite runners * @return list of suite runner workers */ @Override public List> createWorkers(List suites) { List> suiteWorkers = Lists.newArrayList(); for (ISuite suiteRunner : suites) { SuiteRunnerWorker worker = new SuiteRunnerWorker(suiteRunner, m_suiteRunnerMap, m_verbose, m_defaultSuiteName); suiteWorkers.add(worker); } return suiteWorkers; } } testng-testng-6.9.5/src/main/java/org/testng/internal/thread/graph/IWorker.java0000644000175000017500000000102612551235562027010 0ustar eugeneeugenepackage org.testng.internal.thread.graph; import java.util.List; /** * A runnable object that is used by {@code GraphThreadPoolExecutor} to execute * tasks */ public interface IWorker extends Runnable, Comparable> { /** * @return list of tasks this worker is working on. */ List getTasks(); /** * @return the maximum time allowed for the worker to complete the task. */ long getTimeOut(); /** * @return the priority of this task. */ int getPriority(); } testng-testng-6.9.5/src/main/java/org/testng/internal/thread/graph/IThreadWorkerFactory.java0000644000175000017500000000105312551235562031470 0ustar eugeneeugenepackage org.testng.internal.thread.graph; import java.util.List; import java.util.Set; /** * A factory that creates workers used by {@code GraphThreadPoolExecutor} * @author nullin * * @param */ public interface IThreadWorkerFactory { /** * Creates {@code IWorker} for specified set of tasks. It is not necessary that * number of workers returned be same as number of tasks entered. * * @param freeNodes tasks that need to be executed * @return list of workers */ List> createWorkers(List freeNodes); } testng-testng-6.9.5/src/main/java/org/testng/internal/thread/graph/GraphThreadPoolExecutor.java0000644000175000017500000001121212551235562032166 0ustar eugeneeugenepackage org.testng.internal.thread.graph; import org.testng.TestNGException; import org.testng.collections.Lists; import org.testng.internal.DynamicGraph; import org.testng.internal.DynamicGraph.Status; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * An Executor that launches tasks per batches. It takes a {@code DynamicGraph} * of tasks to be run and a {@code IThreadWorkerFactory} to initialize/create * {@code Runnable} wrappers around those tasks */ public class GraphThreadPoolExecutor extends ThreadPoolExecutor { private static final boolean DEBUG = false; /** Set to true if you want to generate GraphViz graphs */ private static final boolean DOT_FILES = false; private DynamicGraph m_graph; private List m_activeRunnables = Lists.newArrayList(); private IThreadWorkerFactory m_factory; private List m_dotFiles = Lists.newArrayList(); private int m_threadCount; public GraphThreadPoolExecutor(DynamicGraph graph, IThreadWorkerFactory factory, int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue /* , new TestNGThreadPoolFactory() */); ppp("Initializing executor with " + corePoolSize + " threads and following graph " + graph); m_threadCount = maximumPoolSize; m_graph = graph; m_factory = factory; if (m_graph.getFreeNodes().isEmpty()) { throw new TestNGException("The graph of methods contains a cycle:" + graph.getEdges()); } } public void run() { synchronized(m_graph) { if (DOT_FILES) { m_dotFiles.add(m_graph.toDot()); } List freeNodes = m_graph.getFreeNodes(); runNodes(freeNodes); } } /** * Create one worker per node and execute them. */ private void runNodes(List freeNodes) { List> runnables = m_factory.createWorkers(freeNodes); for (IWorker r : runnables) { m_activeRunnables.add(r); ppp("Added to active runnable"); setStatus(r, Status.RUNNING); ppp("Executing: " + r); try { execute(r); // if (m_threadCount > 1) execute(r); // else r.run(); } catch(Exception ex) { ex.printStackTrace(); } } } private void setStatus(IWorker worker, Status status) { ppp("Set status:" + worker + " status:" + status); if (status == Status.FINISHED) { m_activeRunnables.remove(worker); } synchronized(m_graph) { for (T m : worker.getTasks()) { m_graph.setStatus(m, status); } } } @Override public void afterExecute(Runnable r, Throwable t) { ppp("Finished runnable:" + r); setStatus((IWorker) r, Status.FINISHED); synchronized(m_graph) { ppp("Node count:" + m_graph.getNodeCount() + " and " + m_graph.getNodeCountWithStatus(Status.FINISHED) + " finished"); if (m_graph.getNodeCount() == m_graph.getNodeCountWithStatus(Status.FINISHED)) { ppp("Shutting down executor " + this); if (DOT_FILES) { generateFiles(m_dotFiles); } shutdown(); } else { if (DOT_FILES) { m_dotFiles.add(m_graph.toDot()); } List freeNodes = m_graph.getFreeNodes(); runNodes(freeNodes); } } // if (m_activeRunnables.isEmpty() && m_index < m_runnables.getSize()) { // runNodes(m_index++); // } } private void generateFiles(List files) { try { File dir = File.createTempFile("TestNG-", ""); dir.delete(); dir.mkdir(); for (int i = 0; i < files.size(); i++) { File f = new File(dir, "" + (i < 10 ? "0" : "") + i + ".dot"); BufferedWriter bw = new BufferedWriter(new FileWriter(f)); bw.append(files.get(i)); bw.close(); } if (DOT_FILES) { System.out.println("Created graph files in " + dir); } } catch(IOException ex) { ex.printStackTrace(); } } private void ppp(String string) { if (DEBUG) { System.out.println("============ [GraphThreadPoolExecutor] " + Thread.currentThread().getId() + " " + string); } } } class TestNGThreadPoolFactory implements ThreadFactory { private int m_count = 0; @Override public Thread newThread(Runnable r) { Thread result = new Thread(r); result.setName("TestNG-" + m_count++); return result; } } testng-testng-6.9.5/src/main/java/org/testng/internal/thread/ThreadUtil.java0000644000175000017500000001303312551235562026373 0ustar eugeneeugenepackage org.testng.internal.thread; import org.testng.collections.Lists; import org.testng.internal.Utils; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * A helper class to interface TestNG concurrency usage. * * @author tasks. The startup is synchronized so this method * emulates a load test. * @param tasks the list of tasks to be run * @param threadPoolSize the size of the parallel threads to be used to execute the tasks * @param timeout a maximum timeout to wait for tasks finalization * @param triggerAtOnce true if the parallel execution of tasks should be trigger at once */ public static final void execute(List tasks, int threadPoolSize, long timeout, boolean triggerAtOnce) { final CountDownLatch startGate= new CountDownLatch(1); final CountDownLatch endGate= new CountDownLatch(tasks.size()); Utils.log("ThreadUtil", 2, "Starting executor timeOut:" + timeout + "ms" + " workers:" + tasks.size() + " threadPoolSize:" + threadPoolSize); ExecutorService pooledExecutor = // Executors.newFixedThreadPool(threadPoolSize); new ThreadPoolExecutor(threadPoolSize, threadPoolSize, timeout, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread result = new Thread(r); result.setName(THREAD_NAME); return result; } }); List> callables = Lists.newArrayList(); for (final Runnable task : tasks) { callables.add(new Callable() { @Override public Object call() throws Exception { task.run(); return null; } }); } try { if (timeout != 0) { pooledExecutor.invokeAll(callables, timeout, TimeUnit.MILLISECONDS); } else { pooledExecutor.invokeAll(callables); } } catch (InterruptedException handled) { handled.printStackTrace(); Thread.currentThread().interrupt(); } finally { pooledExecutor.shutdown(); } } /** * Returns a readable name of the current executing thread. */ public static final String currentThreadInfo() { Thread thread= Thread.currentThread(); return String.valueOf(thread.getName() + "@" + thread.hashCode()); } public static final IExecutor createExecutor(int threadCount, String threadFactoryName) { return new ExecutorAdapter(threadCount, createFactory(threadFactoryName)); } public static final IAtomicInteger createAtomicInteger(int initialValue) { return new AtomicIntegerAdapter(initialValue); } private static final IThreadFactory createFactory(String name) { return new ThreadFactoryImpl(name); } /*private static final ICountDown createCountDown(int count) { return new CountDownAdapter(count); }*/ private static void log(int level, String msg) { Utils.log("ThreadUtil:" + ThreadUtil.currentThreadInfo(), level, msg); } /*private static final IPooledExecutor createPooledExecutor(int size) { return new PooledExecutorAdapter(size); }*/ public static class ThreadFactoryImpl implements IThreadFactory, ThreadFactory { private String m_methodName; private List m_threads = Lists.newArrayList(); public ThreadFactoryImpl(String name) { m_methodName= name; } @Override public Thread newThread(Runnable run) { Thread result = new TestNGThread(run, m_methodName); m_threads.add(result); return result; } @Override public Object getThreadFactory() { return this; } @Override public List getThreads() { return m_threads; } } /** * A special Runnable that uses CountDownLatch-s to * sync on start and to acknowledge its finish. */ private static class CountDownLatchedRunnable implements Runnable { private final Runnable m_task; private final CountDownLatch m_startGate; private final CountDownLatch m_endGate; public CountDownLatchedRunnable(Runnable task, CountDownLatch endGate, CountDownLatch startGate) { m_task= task; m_startGate= startGate; m_endGate= endGate; } @Override public void run() { if(null != m_startGate) { try { m_startGate.await(); } catch(InterruptedException handled) { log(2, "Cannot wait for startup gate when executing " + m_task + "; thread was already interrupted " + handled.getMessage()); Thread.currentThread().interrupt(); return; } } try { m_task.run(); } finally { m_endGate.countDown(); } } } } testng-testng-6.9.5/src/main/java/org/testng/internal/thread/ThreadTimeoutException.java0000755000175000017500000000102212551235562030761 0ustar eugeneeugenepackage org.testng.internal.thread; /** * Exception used to signal a thread timeout. * * @author Alexandru Popescu */ public class ThreadTimeoutException extends Exception { static final long serialVersionUID = 7009400729783393548L; public ThreadTimeoutException(String msg) { super(msg); } public ThreadTimeoutException(Throwable cause) { super(cause); } public ThreadTimeoutException(String msg, Throwable cause) { super(msg, cause); } }testng-testng-6.9.5/src/main/java/org/testng/internal/thread/ThreadExecutionException.java0000755000175000017500000000053512551235562031306 0ustar eugeneeugenepackage org.testng.internal.thread; /** * Wrapper exception for ExecutionExceptions. * * @author Alexandru Popescu * @version $Revision$ */ public interface IThreadFactory { Thread newThread(Runnable run); Object getThreadFactory(); List getThreads(); } testng-testng-6.9.5/src/main/java/org/testng/internal/thread/IPooledExecutor.java0000755000175000017500000000060012551235562027377 0ustar eugeneeugenepackage org.testng.internal.thread; /** * Reduced interface to mimic ExecutorService. * * @author Alexandru Popescu */ public interface IPooledExecutor { void execute(Runnable run); void shutdown(); void awaitTermination(long timeout) throws InterruptedException; boolean isTerminated(); } testng-testng-6.9.5/src/main/java/org/testng/internal/thread/IFutureResult.java0000755000175000017500000000041212551235562027110 0ustar eugeneeugenepackage org.testng.internal.thread; /** * Reduced interface to mimic Future. * * @author Alexandru Popescu */ public interface IFutureResult { Object get() throws InterruptedException, ThreadExecutionException; } testng-testng-6.9.5/src/main/java/org/testng/internal/thread/IExecutor.java0000755000175000017500000000060012551235562026234 0ustar eugeneeugenepackage org.testng.internal.thread; /** * Reduced interface to mimic an ExecutorService. * * @author Alexandru Popescu */ public interface IExecutor { IFutureResult submitRunnable(Runnable runnable); void shutdown(); boolean awaitTermination(long timeout); void stopNow(); StackTraceElement[][] getStackTraces(); } testng-testng-6.9.5/src/main/java/org/testng/internal/thread/ICountDown.java0000755000175000017500000000051212551235562026360 0ustar eugeneeugenepackage org.testng.internal.thread; /** * Reduced interface to mimic a CountDownLatch. * * @author Alexandru Popescu */ public interface ICountDown { void await() throws InterruptedException; boolean await(long timeout) throws InterruptedException; void countDown(); } testng-testng-6.9.5/src/main/java/org/testng/internal/thread/IAtomicInteger.java0000755000175000017500000000060412551235562027174 0ustar eugeneeugenepackage org.testng.internal.thread; import java.io.Serializable; /** * This class/interface */ public interface IAtomicInteger extends Serializable{ /** * Get the current value. * @return the current value */ int get(); /** * Atomically increment by one the current value. * * @return the updated value */ int incrementAndGet(); } testng-testng-6.9.5/src/main/java/org/testng/internal/thread/FutureResultAdapter.java0000755000175000017500000000131212551235562030300 0ustar eugeneeugenepackage org.testng.internal.thread; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; /** * A very reduced interface of Future. * * @author Alexandru Popescu */ public class ExecutorAdapter extends ThreadPoolExecutor implements IExecutor { private IThreadFactory m_threadFactory; public ExecutorAdapter(int threadCount, IThreadFactory tf) { super(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), (ThreadFactory) tf.getThreadFactory()); m_threadFactory = tf; } @Override public IFutureResult submitRunnable(final Runnable runnable) { return new FutureResultAdapter(super.submit(runnable)); } @Override public void stopNow() { super.shutdownNow(); } @Override public boolean awaitTermination(long timeout) { boolean result= false; try { result= super.awaitTermination(timeout, TimeUnit.MILLISECONDS); } catch(InterruptedException handled) { System.out.println("[WARN] ThreadPoolExecutor has been interrupted while awaiting termination"); Thread.currentThread().interrupt(); } return result; } @Override public StackTraceElement[][] getStackTraces() { List threads = m_threadFactory.getThreads(); int threadCount = threads.size(); StackTraceElement[][] result = new StackTraceElement[threadCount][]; for (int i = 0; i < result.length; i++) { result[i] = threads.get(i).getStackTrace(); } return result; } }testng-testng-6.9.5/src/main/java/org/testng/internal/thread/CountDownAdapter.java0000755000175000017500000000152612551235562027556 0ustar eugeneeugene/* * $Id$ * $Date$ */ package org.testng.internal.thread; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * ICountDown adapter using the features in JDK 1.5, e.g. * CountDownLatch. * * @author expecteds and * actuals are null, they are considered equal. * * @param message * the identifying message for the {@link AssertionError} ( * null okay) * @param expecteds * Object array or array of arrays (multi-dimensional array) with * expected values. * @param actuals * Object array or array of arrays (multi-dimensional array) with * actual values */ public void arrayEquals(String message, Object expecteds, Object actuals) throws ArrayComparisonFailure { if (expecteds == actuals) return; String header= message == null ? "" : message + ": "; int expectedsLength= assertArraysAreSameLength(expecteds, actuals, header); for (int i= 0; i < expectedsLength; i++) { Object expected= Array.get(expecteds, i); Object actual= Array.get(actuals, i); if (isArray(expected) && isArray(actual)) { try { arrayEquals(message, expected, actual); } catch (ArrayComparisonFailure e) { e.addDimension(i); throw e; } } else try { assertElementsEqual(expected, actual); } catch (AssertionError e) { throw new ArrayComparisonFailure(header, e, i); } } } private boolean isArray(Object expected) { return expected != null && expected.getClass().isArray(); } private int assertArraysAreSameLength(Object expecteds, Object actuals, String header) { if (expecteds == null) AssertJUnit.fail(header + "expected array was null"); if (actuals == null) AssertJUnit.fail(header + "actual array was null"); int actualsLength= Array.getLength(actuals); int expectedsLength= Array.getLength(expecteds); if (actualsLength != expectedsLength) AssertJUnit.fail(header + "array lengths differed, expected.length=" + expectedsLength + " actual.length=" + actualsLength); return expectedsLength; } protected abstract void assertElementsEqual(Object expected, Object actual); } testng-testng-6.9.5/src/main/java/org/testng/internal/junit/ArrayComparisonFailure.java0000644000175000017500000000303412551235562030631 0ustar eugeneeugenepackage org.testng.internal.junit; import java.util.ArrayList; import java.util.List; /** * Thrown when two array elements differ */ public class ArrayComparisonFailure extends AssertionError { private static final long serialVersionUID= 1L; private List fIndices= new ArrayList<>(); private final String fMessage; private final AssertionError fCause; /** * Construct a new ArrayComparisonFailure with an error text and the array's * dimension that was not equal * @param cause the exception that caused the array's content to fail the assertion test * @param index the array position of the objects that are not equal. */ public ArrayComparisonFailure(String message, AssertionError cause, int index) { fMessage= message; fCause= cause; addDimension(index); } public void addDimension(int index) { fIndices.add(0, index); } @Override public String getMessage() { StringBuilder builder= new StringBuilder(); if (fMessage != null) builder.append(fMessage); builder.append("arrays first differed at element "); for (int each : fIndices) { builder.append("["); builder.append(each); builder.append("]"); } builder.append("; "); builder.append(fCause.getMessage()); return builder.toString(); } /** * {@inheritDoc} */ @Override public String toString() { return getMessage(); } } testng-testng-6.9.5/src/main/java/org/testng/internal/junit/ArrayAsserts.java0000644000175000017500000002251412551235562026637 0ustar eugeneeugenepackage org.testng.internal.junit; public class ArrayAsserts { /** * Asserts that two object arrays are equal. If they are not, an * {@link AssertionError} is thrown with the given message. If * expecteds and actuals are null, * they are considered equal. * * @param message * the identifying message for the {@link AssertionError} (null * okay) * @param expecteds * Object array or array of arrays (multi-dimensional array) with * expected values. * @param actuals * Object array or array of arrays (multi-dimensional array) with * actual values */ public static void assertArrayEquals(String message, Object[] expecteds, Object[] actuals) throws ArrayComparisonFailure { internalArrayEquals(message, expecteds, actuals); } /** * Asserts that two object arrays are equal. If they are not, an * {@link AssertionError} is thrown. If expected and * actual are null, they are considered * equal. * * @param expecteds * Object array or array of arrays (multi-dimensional array) with * expected values * @param actuals * Object array or array of arrays (multi-dimensional array) with * actual values */ public static void assertArrayEquals(Object[] expecteds, Object[] actuals) { assertArrayEquals(null, expecteds, actuals); } /** * Asserts that two byte arrays are equal. If they are not, an * {@link AssertionError} is thrown with the given message. * * @param message * the identifying message for the {@link AssertionError} (null * okay) * @param expecteds * byte array with expected values. * @param actuals * byte array with actual values */ public static void assertArrayEquals(String message, byte[] expecteds, byte[] actuals) throws ArrayComparisonFailure { internalArrayEquals(message, expecteds, actuals); } /** * Asserts that two byte arrays are equal. If they are not, an * {@link AssertionError} is thrown. * * @param expecteds * byte array with expected values. * @param actuals * byte array with actual values */ public static void assertArrayEquals(byte[] expecteds, byte[] actuals) { assertArrayEquals(null, expecteds, actuals); } /** * Asserts that two char arrays are equal. If they are not, an * {@link AssertionError} is thrown with the given message. * * @param message * the identifying message for the {@link AssertionError} (null * okay) * @param expecteds * char array with expected values. * @param actuals * char array with actual values */ public static void assertArrayEquals(String message, char[] expecteds, char[] actuals) throws ArrayComparisonFailure { internalArrayEquals(message, expecteds, actuals); } /** * Asserts that two char arrays are equal. If they are not, an * {@link AssertionError} is thrown. * * @param expecteds * char array with expected values. * @param actuals * char array with actual values */ public static void assertArrayEquals(char[] expecteds, char[] actuals) { assertArrayEquals(null, expecteds, actuals); } /** * Asserts that two short arrays are equal. If they are not, an * {@link AssertionError} is thrown with the given message. * * @param message * the identifying message for the {@link AssertionError} (null * okay) * @param expecteds * short array with expected values. * @param actuals * short array with actual values */ public static void assertArrayEquals(String message, short[] expecteds, short[] actuals) throws ArrayComparisonFailure { internalArrayEquals(message, expecteds, actuals); } /** * Asserts that two short arrays are equal. If they are not, an * {@link AssertionError} is thrown. * * @param expecteds * short array with expected values. * @param actuals * short array with actual values */ public static void assertArrayEquals(short[] expecteds, short[] actuals) { assertArrayEquals(null, expecteds, actuals); } /** * Asserts that two int arrays are equal. If they are not, an * {@link AssertionError} is thrown with the given message. * * @param message * the identifying message for the {@link AssertionError} (null * okay) * @param expecteds * int array with expected values. * @param actuals * int array with actual values */ public static void assertArrayEquals(String message, int[] expecteds, int[] actuals) throws ArrayComparisonFailure { internalArrayEquals(message, expecteds, actuals); } /** * Asserts that two int arrays are equal. If they are not, an * {@link AssertionError} is thrown. * * @param expecteds * int array with expected values. * @param actuals * int array with actual values */ public static void assertArrayEquals(int[] expecteds, int[] actuals) { assertArrayEquals(null, expecteds, actuals); } /** * Asserts that two long arrays are equal. If they are not, an * {@link AssertionError} is thrown with the given message. * * @param message * the identifying message for the {@link AssertionError} (null * okay) * @param expecteds * long array with expected values. * @param actuals * long array with actual values */ public static void assertArrayEquals(String message, long[] expecteds, long[] actuals) throws ArrayComparisonFailure { internalArrayEquals(message, expecteds, actuals); } /** * Asserts that two long arrays are equal. If they are not, an * {@link AssertionError} is thrown. * * @param expecteds * long array with expected values. * @param actuals * long array with actual values */ public static void assertArrayEquals(long[] expecteds, long[] actuals) { assertArrayEquals(null, expecteds, actuals); } /** * Asserts that two double arrays are equal. If they are not, an * {@link AssertionError} is thrown with the given message. * * @param message * the identifying message for the {@link AssertionError} (null * okay) * @param expecteds * double array with expected values. * @param actuals * double array with actual values */ public static void assertArrayEquals(String message, double[] expecteds, double[] actuals, double delta) throws ArrayComparisonFailure { new InexactComparisonCriteria(delta).arrayEquals(message, expecteds, actuals); } /** * Asserts that two double arrays are equal. If they are not, an * {@link AssertionError} is thrown. * * @param expecteds * double array with expected values. * @param actuals * double array with actual values */ public static void assertArrayEquals(double[] expecteds, double[] actuals, double delta) { assertArrayEquals(null, expecteds, actuals, delta); } /** * Asserts that two float arrays are equal. If they are not, an * {@link AssertionError} is thrown with the given message. * * @param message * the identifying message for the {@link AssertionError} (null * okay) * @param expecteds * float array with expected values. * @param actuals * float array with actual values */ public static void assertArrayEquals(String message, float[] expecteds, float[] actuals, float delta) throws ArrayComparisonFailure { new InexactComparisonCriteria(delta).arrayEquals(message, expecteds, actuals); } /** * Asserts that two float arrays are equal. If they are not, an * {@link AssertionError} is thrown. * * @param expecteds * float array with expected values. * @param actuals * float array with actual values */ public static void assertArrayEquals(float[] expecteds, float[] actuals, float delta) { assertArrayEquals(null, expecteds, actuals, delta); } /** * Asserts that two object arrays are equal. If they are not, an * {@link AssertionError} is thrown with the given message. If * expecteds and actuals are null, * they are considered equal. * * @param message * the identifying message for the {@link AssertionError} (null * okay) * @param expecteds * Object array or array of arrays (multi-dimensional array) with * expected values. * @param actuals * Object array or array of arrays (multi-dimensional array) with * actual values */ private static void internalArrayEquals(String message, Object expecteds, Object actuals) throws ArrayComparisonFailure { new ExactComparisonCriteria().arrayEquals(message, expecteds, actuals); } } testng-testng-6.9.5/src/main/java/org/testng/internal/invokers/0000755000175000017500000000000012551235562024054 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/internal/invokers/InvokedMethodListenerSubtype.java0000644000175000017500000000265712551235562032553 0ustar eugeneeugenepackage org.testng.internal.invokers; import org.testng.IInvokedMethodListener; import org.testng.IInvokedMethodListener2; import org.testng.TestNGException; /** * Indicates whether a {@link InvokedMethodListenerMethod} is to be called on a simple or an * extended invoked method listener. All {@link IInvokedMethodListener}s are considered * {@link #SIMPLE_LISTENER}, instances of {@link IInvokedMethodListener2} are all considered * {@link #EXTENDED_LISTENER}. * * @author Ansgar Konermann */ enum InvokedMethodListenerSubtype { EXTENDED_LISTENER(IInvokedMethodListener2.class), SIMPLE_LISTENER(IInvokedMethodListener.class); private Class m_matchingInterface; private InvokedMethodListenerSubtype(Class listenerClass) { m_matchingInterface = listenerClass; } private boolean isInstance(IInvokedMethodListener listenerInstance) { return m_matchingInterface.isInstance(listenerInstance); } public static InvokedMethodListenerSubtype fromListener(IInvokedMethodListener listenerInstance) { if (EXTENDED_LISTENER.isInstance(listenerInstance)) { return EXTENDED_LISTENER; } else if (SIMPLE_LISTENER.isInstance(listenerInstance)) { return SIMPLE_LISTENER; } throw new TestNGException("Illegal " + IInvokedMethodListener.class.getSimpleName() + " instance: " + listenerInstance.getClass().getName() + "."); } } testng-testng-6.9.5/src/main/java/org/testng/internal/invokers/InvokedMethodListenerMethod.java0000644000175000017500000000056612551235562032335 0ustar eugeneeugenepackage org.testng.internal.invokers; import org.testng.IInvokedMethodListener; import org.testng.IInvokedMethodListener2; /** * Indicates which of the methods of a {@link IInvokedMethodListener} or * {@link IInvokedMethodListener2} should be called. * * @author Ansgar Konermann */ public enum InvokedMethodListenerMethod { BEFORE_INVOCATION, AFTER_INVOCATION } testng-testng-6.9.5/src/main/java/org/testng/internal/invokers/InvokedMethodListenerInvoker.java0000644000175000017500000001374612551235562032536 0ustar eugeneeugenepackage org.testng.internal.invokers; import org.testng.IInvokedMethod; import org.testng.IInvokedMethodListener; import org.testng.IInvokedMethodListener2; import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.collections.Maps; import java.util.Map; import static org.testng.internal.invokers.InvokedMethodListenerMethod.AFTER_INVOCATION; import static org.testng.internal.invokers.InvokedMethodListenerMethod.BEFORE_INVOCATION; import static org.testng.internal.invokers.InvokedMethodListenerSubtype.EXTENDED_LISTENER; import static org.testng.internal.invokers.InvokedMethodListenerSubtype.SIMPLE_LISTENER; /** * Hides complexity of calling methods of {@link IInvokedMethodListener} and * {@link IInvokedMethodListener2}. * * @author Ansgar Konermann */ public class InvokedMethodListenerInvoker { private InvokedMethodListenerMethod m_listenerMethod; private ITestContext m_testContext; private ITestResult m_testResult; /** * Creates a new invoker instance which can be used to call the specified {@code listenerMethod} * on any number of {@link IInvokedMethodListener}s. * * @param listenerMethod method which should be called * @param testResult test result which should be passed to the listener method upon invocation * @param testContext test context which should be passed to the listener method upon invocation. * This parameter is only used when calling methods on an {@link IInvokedMethodListener2}. */ public InvokedMethodListenerInvoker(InvokedMethodListenerMethod listenerMethod, ITestResult testResult, ITestContext testContext) { m_listenerMethod = listenerMethod; m_testContext = testContext; m_testResult = testResult; } /** * Invoke the given {@code listenerInstance}, calling the method specified in the constructor of * this {@link InvokedMethodListenerInvoker}. * * @param listenerInstance the listener instance which should be invoked. * @param invokedMethod the {@link IInvokedMethod} instance which should be passed to the * {@link IInvokedMethodListener#beforeInvocation(IInvokedMethod, ITestResult)}, * {@link IInvokedMethodListener#afterInvocation(IInvokedMethod, ITestResult)}, * {@link IInvokedMethodListener2#beforeInvocation(IInvokedMethod, ITestResult, ITestContext)} * or {@link IInvokedMethodListener2#afterInvocation(IInvokedMethod, ITestResult, ITestContext)} * method. */ @SuppressWarnings("unchecked") public void invokeListener(IInvokedMethodListener listenerInstance, IInvokedMethod invokedMethod) { final InvocationStrategy strategy = obtainStrategyFor(listenerInstance, m_listenerMethod); strategy.callMethod(listenerInstance, invokedMethod, m_testResult, m_testContext); } private InvocationStrategy obtainStrategyFor(IInvokedMethodListener listenerInstance, InvokedMethodListenerMethod listenerMethod) { InvokedMethodListenerSubtype invokedMethodListenerSubtype = InvokedMethodListenerSubtype .fromListener(listenerInstance); Map strategiesForListenerType = strategies .get(invokedMethodListenerSubtype); InvocationStrategy invocationStrategy = strategiesForListenerType.get(listenerMethod); return invocationStrategy; } private static interface InvocationStrategy { void callMethod(LISTENER_TYPE listener, IInvokedMethod invokedMethod, ITestResult testResult, ITestContext testContext); } private static class InvokeBeforeInvocationWithoutContextStrategy implements InvocationStrategy { public void callMethod(IInvokedMethodListener listener, IInvokedMethod invokedMethod, ITestResult testResult, ITestContext testContext) { listener.beforeInvocation(invokedMethod, testResult); } } private static class InvokeBeforeInvocationWithContextStrategy implements InvocationStrategy { public void callMethod(IInvokedMethodListener2 listener, IInvokedMethod invokedMethod, ITestResult testResult, ITestContext testContext) { listener.beforeInvocation(invokedMethod, testResult, testContext); } } private static class InvokeAfterInvocationWithoutContextStrategy implements InvocationStrategy { public void callMethod(IInvokedMethodListener listener, IInvokedMethod invokedMethod, ITestResult testResult, ITestContext testContext) { listener.afterInvocation(invokedMethod, testResult); } } private static class InvokeAfterInvocationWithContextStrategy implements InvocationStrategy { public void callMethod(IInvokedMethodListener2 listener, IInvokedMethod invokedMethod, ITestResult testResult, ITestContext testContext) { listener.afterInvocation(invokedMethod, testResult, testContext); } } private static final Map> strategies = Maps.newHashMap(); private static final Map INVOKE_WITH_CONTEXT_STRATEGIES = Maps.newHashMap(); private static final Map INVOKE_WITHOUT_CONTEXT_STRATEGIES = Maps.newHashMap(); static { INVOKE_WITH_CONTEXT_STRATEGIES.put(BEFORE_INVOCATION, new InvokeBeforeInvocationWithContextStrategy()); INVOKE_WITH_CONTEXT_STRATEGIES.put(AFTER_INVOCATION, new InvokeAfterInvocationWithContextStrategy()); INVOKE_WITHOUT_CONTEXT_STRATEGIES.put(BEFORE_INVOCATION, new InvokeBeforeInvocationWithoutContextStrategy()); INVOKE_WITHOUT_CONTEXT_STRATEGIES.put(AFTER_INVOCATION, new InvokeAfterInvocationWithoutContextStrategy()); strategies.put(EXTENDED_LISTENER, INVOKE_WITH_CONTEXT_STRATEGIES); strategies.put(SIMPLE_LISTENER, INVOKE_WITHOUT_CONTEXT_STRATEGIES); } } testng-testng-6.9.5/src/main/java/org/testng/internal/collections/0000755000175000017500000000000012551235562024532 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/internal/collections/Pair.java0000644000175000017500000000302312551235562026266 0ustar eugeneeugenepackage org.testng.internal.collections; import org.testng.collections.Objects; public class Pair { private final A first; private final B second; public Pair(A first, B second) { this.first = first; this.second = second; } public A first() { return first; } public B second() { return second; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((second == null) ? 0 : second.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Pair other = (Pair) obj; if (first == null) { if (other.first != null) { return false; } } else if (!first.equals(other.first)) { return false; } if (second == null) { if (other.second != null) { return false; } } else if (!second.equals(other.second)) { return false; } return true; } public static Pair create(A first, B second) { return of(first, second); } public static Pair of(A a, B b) { return new Pair<>(a, b); } @Override public String toString() { return Objects.toStringHelper(getClass()) .add("first", first()) .add("second", second()) .toString(); } }testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/0000755000175000017500000000000012551235562024551 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/internal/annotations/TestOrConfiguration.java0000755000175000017500000000345312551235562031374 0ustar eugeneeugenepackage org.testng.internal.annotations; import org.testng.annotations.ITestOrConfiguration; public class TestOrConfiguration extends BaseAnnotation implements ITestOrConfiguration { private String[] m_parameters = {}; private String[] m_groups = {}; private boolean m_enabled = true; private String[] m_dependsOnGroups = {}; private String[] m_dependsOnMethods = {}; private String m_description = ""; private int m_priority; private long m_timeOut = 0; @Override public String[] getGroups() { return m_groups; } @Override public boolean getEnabled() { return m_enabled; } @Override public void setDependsOnGroups(String[] dependsOnGroups) { m_dependsOnGroups = dependsOnGroups; } @Override public void setDependsOnMethods(String[] dependsOnMethods) { m_dependsOnMethods = dependsOnMethods; } @Override public void setGroups(String[] groups) { m_groups = groups; } @Override public String getDescription() { return m_description; } @Override public void setEnabled(boolean enabled) { m_enabled = enabled; } @Override public String[] getDependsOnGroups() { return m_dependsOnGroups; } @Override public String[] getDependsOnMethods() { return m_dependsOnMethods; } @Override public String[] getParameters() { return m_parameters; } public void setParameters(String[] parameters) { m_parameters = parameters; } @Override public void setDescription(String description) { m_description = description; } public int getPriority() { return m_priority; } public void setPriority(int priority) { m_priority = priority; } @Override public void setTimeOut(long timeOut) { m_timeOut = timeOut; } @Override public long getTimeOut() { return m_timeOut; } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/TestAnnotation.java0000755000175000017500000001133712551235562030376 0ustar eugeneeugenepackage org.testng.internal.annotations; import org.testng.IRetryAnalyzer; import org.testng.annotations.ITestAnnotation; /** * An implementation of ITest * * Created on Dec 20, 2005 * @author Cedric Beust */ public class TestAnnotation extends TestOrConfiguration implements ITestAnnotation { private long m_invocationTimeOut = 0; private int m_invocationCount = 1; private int m_threadPoolSize = 0; private int m_successPercentage = 100; private String m_dataProvider = ""; private boolean m_alwaysRun = false; private Class[] m_expectedExceptions = {}; private String m_expectedExceptionsMessageRegExp = ".*"; private String m_suiteName = ""; private String m_testName = ""; private boolean m_singleThreaded = false; private boolean m_sequential = false; private Class m_dataProviderClass = null; private IRetryAnalyzer m_retryAnalyzer = null; private boolean m_skipFailedInvocations = false; private boolean m_ignoreMissingDependencies = false; /** * @return the expectedExceptions */ @Override public Class[] getExpectedExceptions() { return m_expectedExceptions; } /** * @param expectedExceptions the expectedExceptions to set */ @Override public void setExpectedExceptions(Class[] expectedExceptions) { m_expectedExceptions = expectedExceptions; } @Override public String getExpectedExceptionsMessageRegExp() { return m_expectedExceptionsMessageRegExp; } @Override public void setExpectedExceptionsMessageRegExp( String expectedExceptionsMessageRegExp) { m_expectedExceptionsMessageRegExp = expectedExceptionsMessageRegExp; } @Override public void setAlwaysRun(boolean alwaysRun) { m_alwaysRun = alwaysRun; } @Override public void setDataProvider(String dataProvider) { m_dataProvider = dataProvider; } @Override public Class getDataProviderClass() { return m_dataProviderClass; } @Override public void setDataProviderClass(Class dataProviderClass) { m_dataProviderClass = dataProviderClass; } @Override public void setInvocationCount(int invocationCount) { m_invocationCount = invocationCount; } @Override public void setSuccessPercentage(int successPercentage) { m_successPercentage = successPercentage; } @Override public int getInvocationCount() { return m_invocationCount; } @Override public long invocationTimeOut() { return m_invocationTimeOut; } @Override public void setInvocationTimeOut(long timeOut) { m_invocationTimeOut = timeOut; } @Override public int getSuccessPercentage() { return m_successPercentage; } @Override public String getDataProvider() { return m_dataProvider; } @Override public boolean getAlwaysRun() { return m_alwaysRun; } @Override public int getThreadPoolSize() { return m_threadPoolSize; } @Override public void setThreadPoolSize(int threadPoolSize) { m_threadPoolSize = threadPoolSize; } @Override public String getSuiteName() { return m_suiteName; } @Override public void setSuiteName(String xmlSuite) { m_suiteName = xmlSuite; } @Override public String getTestName() { return m_testName; } @Override public void setTestName(String xmlTest) { m_testName = xmlTest; } @Override public boolean getSingleThreaded() { return m_singleThreaded; } @Override public void setSingleThreaded(boolean singleThreaded) { m_singleThreaded = singleThreaded; } @Override public boolean getSequential() { return m_sequential; } @Override public void setSequential(boolean sequential) { m_sequential = sequential; } @Override public IRetryAnalyzer getRetryAnalyzer() { return m_retryAnalyzer; } @Override public void setRetryAnalyzer(Class c) { m_retryAnalyzer = null; if (c != null && IRetryAnalyzer.class.isAssignableFrom(c)) { try { m_retryAnalyzer = (IRetryAnalyzer) c.newInstance(); } catch (InstantiationException | IllegalAccessException e) { // The class will never be called. } } } @Override public void setSkipFailedInvocations(boolean skip) { m_skipFailedInvocations = skip; } @Override public boolean skipFailedInvocations() { return m_skipFailedInvocations; } @Override public void setIgnoreMissingDependencies(boolean ignore) { m_ignoreMissingDependencies = ignore; } @Override public boolean ignoreMissingDependencies() { return m_ignoreMissingDependencies; } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/ParametersAnnotation.java0000755000175000017500000000076512551235562031565 0ustar eugeneeugenepackage org.testng.internal.annotations; import org.testng.annotations.IParametersAnnotation; /** * An implementation of IParameters * * Created on Dec 20, 2005 * @author Cedric Beust */ public class ParametersAnnotation extends BaseAnnotation implements IParametersAnnotation { private String[] m_value = {}; @Override public String[] getValue() { return m_value; } public void setValue(String[] value) { m_value = value; } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/ObjectFactoryAnnotation.java0000755000175000017500000000041712551235562032212 0ustar eugeneeugenepackage org.testng.internal.annotations; import org.testng.annotations.IObjectFactoryAnnotation; /** * The internal representation of @ObjectFactory * @author Hani */ public class ObjectFactoryAnnotation extends BaseAnnotation implements IObjectFactoryAnnotation {} testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/ListenersAnnotation.java0000644000175000017500000000070012551235562031414 0ustar eugeneeugenepackage org.testng.internal.annotations; import org.testng.ITestNGListener; import org.testng.annotations.IAnnotation; public class ListenersAnnotation implements IListeners, IAnnotation { private Class[] m_value; @Override public Class[] getValue() { return m_value; } @Override public void setValue(Class[] value) { m_value = value; } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/JDK15TagFactory.java0000755000175000017500000004457012551235562030173 0ustar eugeneeugenepackage org.testng.internal.annotations; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.HashSet; import java.util.List; import java.util.Set; import org.testng.IAnnotationTransformer; import org.testng.TestNGException; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterGroups; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterSuite; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; import org.testng.annotations.Configuration; import org.testng.annotations.DataProvider; import org.testng.annotations.ExpectedExceptions; import org.testng.annotations.Factory; import org.testng.annotations.IAnnotation; import org.testng.annotations.IConfigurationAnnotation; import org.testng.annotations.IDataProviderAnnotation; import org.testng.annotations.IExpectedExceptionsAnnotation; import org.testng.annotations.IFactoryAnnotation; import org.testng.annotations.IObjectFactoryAnnotation; import org.testng.annotations.IParametersAnnotation; import org.testng.annotations.ITestAnnotation; import org.testng.annotations.Listeners; import org.testng.annotations.Parameters; import org.testng.annotations.Test; import org.testng.collections.Lists; import org.testng.internal.Utils; /** * This class creates implementations of IAnnotations based on the JDK5 * annotation that was found on the Java element. * * Created on Dec 20, 2005 * @author Cedric Beust */ public class JDK15TagFactory { public A createTag(Class cls, Annotation a, Class annotationClass, IAnnotationTransformer transformer) { IAnnotation result = null; if (a != null) { if (annotationClass == IConfigurationAnnotation.class) { result = createConfigurationTag(cls, a); } else if (annotationClass == IDataProviderAnnotation.class) { result = createDataProviderTag(a); } else if (annotationClass == IExpectedExceptionsAnnotation.class) { result = createExpectedExceptionsTag(a); } else if (annotationClass == IFactoryAnnotation.class) { result = createFactoryTag(cls, a); } else if (annotationClass == IParametersAnnotation.class) { result = createParametersTag(a); } else if (annotationClass == IObjectFactoryAnnotation.class) { result = createObjectFactoryTag(a); } else if (annotationClass == ITestAnnotation.class) { result = createTestTag(cls, a, transformer); } else if (annotationClass == IListeners.class) { result = createListenersTag(cls, a, transformer); } else if (annotationClass == IBeforeSuite.class || annotationClass == IAfterSuite.class || annotationClass == IBeforeTest.class || annotationClass == IAfterTest.class || annotationClass == IBeforeGroups.class || annotationClass == IAfterGroups.class || annotationClass == IBeforeClass.class || annotationClass == IAfterClass.class || annotationClass == IBeforeMethod.class || annotationClass == IAfterMethod.class) { result = maybeCreateNewConfigurationTag(cls, a, annotationClass); } else { throw new TestNGException("Unknown annotation requested:" + annotationClass); } } //noinspection unchecked return (A) result; } private IAnnotation maybeCreateNewConfigurationTag(Class cls, Annotation a, Class annotationClass) { IAnnotation result = null; if (annotationClass == IBeforeSuite.class) { BeforeSuite bs = (BeforeSuite) a; result = createConfigurationTag(cls, a, true, false, false, false, new String[0], new String[0], false, false, false, false, bs.alwaysRun(), bs.dependsOnGroups(), bs.dependsOnMethods(), bs.description(), bs.enabled(), bs.groups(), bs.inheritGroups(), null, false, false, bs.timeOut()); } else if (annotationClass == IAfterSuite.class) { AfterSuite bs = (AfterSuite) a; result = createConfigurationTag(cls, a, false, true, false, false, new String[0], new String[0], false, false, false, false, bs.alwaysRun(), bs.dependsOnGroups(), bs.dependsOnMethods(), bs.description(), bs.enabled(), bs.groups(), bs.inheritGroups(), null, false, false, bs.timeOut()); } else if (annotationClass == IBeforeTest.class) { BeforeTest bs = (BeforeTest) a; result = createConfigurationTag(cls, a, false, false, true, false, new String[0], new String[0], false, false, false, false, bs.alwaysRun(), bs.dependsOnGroups(), bs.dependsOnMethods(), bs.description(), bs.enabled(), bs.groups(), bs.inheritGroups(), null, false, false, bs.timeOut()); } else if (annotationClass == IAfterTest.class) { AfterTest bs = (AfterTest) a; result = createConfigurationTag(cls, a, false, false, false, true, new String[0], new String[0], false, false, false, false, bs.alwaysRun(), bs.dependsOnGroups(), bs.dependsOnMethods(), bs.description(), bs.enabled(), bs.groups(), bs.inheritGroups(), null, false, false, bs.timeOut()); } else if (annotationClass == IBeforeGroups.class) { BeforeGroups bs = (BeforeGroups) a; final String[] groups= bs.value().length > 0 ? bs.value() : bs.groups(); result = createConfigurationTag(cls, a, false, false, false, false, groups, new String[0], false, false, false, false, bs.alwaysRun(), bs.dependsOnGroups(), bs.dependsOnMethods(), bs.description(), bs.enabled(), bs.groups(), bs.inheritGroups(), null, false, false, bs.timeOut()); } else if (annotationClass == IAfterGroups.class) { AfterGroups bs = (AfterGroups) a; final String[] groups= bs.value().length > 0 ? bs.value() : bs.groups(); result = createConfigurationTag(cls, a, false, false, false, false, new String[0], groups, false, false, false, false, bs.alwaysRun(), bs.dependsOnGroups(), bs.dependsOnMethods(), bs.description(), bs.enabled(), bs.groups(), bs.inheritGroups(), null, false, false, bs.timeOut()); } else if (annotationClass == IBeforeClass.class) { BeforeClass bs = (BeforeClass) a; result = createConfigurationTag(cls, a, false, false, false, false, new String[0], new String[0], true, false, false, false, bs.alwaysRun(), bs.dependsOnGroups(), bs.dependsOnMethods(), bs.description(), bs.enabled(), bs.groups(), bs.inheritGroups(), null, false, false, bs.timeOut()); } else if (annotationClass == IAfterClass.class) { AfterClass bs = (AfterClass) a; result = createConfigurationTag(cls, a, false, false, false, false, new String[0], new String[0], false, true, false, false, bs.alwaysRun(), bs.dependsOnGroups(), bs.dependsOnMethods(), bs.description(), bs.enabled(), bs.groups(), bs.inheritGroups(), null, false, false, bs.timeOut()); } else if (annotationClass == IBeforeMethod.class) { BeforeMethod bs = (BeforeMethod) a; result = createConfigurationTag(cls, a, false, false, false, false, new String[0], new String[0], false, false, true, false, bs.alwaysRun(), bs.dependsOnGroups(), bs.dependsOnMethods(), bs.description(), bs.enabled(), bs.groups(), bs.inheritGroups(), null, bs.firstTimeOnly(), false, bs.timeOut()); } else if (annotationClass == IAfterMethod.class) { AfterMethod bs = (AfterMethod) a; result = createConfigurationTag(cls, a, false, false, false, false, new String[0], new String[0], false, false, false, true, bs.alwaysRun(), bs.dependsOnGroups(), bs.dependsOnMethods(), bs.description(), bs.enabled(), bs.groups(), bs.inheritGroups(), null, false, bs.lastTimeOnly(), bs.timeOut()); } return result; } @SuppressWarnings({"deprecation"}) private ConfigurationAnnotation createConfigurationTag(Class cls, Annotation a) { ConfigurationAnnotation result = new ConfigurationAnnotation(); Configuration c = (Configuration) a; result.setBeforeTestClass(c.beforeTestClass()); result.setAfterTestClass(c.afterTestClass()); result.setBeforeTestMethod(c.beforeTestMethod()); result.setAfterTestMethod(c.afterTestMethod()); result.setBeforeTest(c.beforeTest()); result.setAfterTest(c.afterTest()); result.setBeforeSuite(c.beforeSuite()); result.setAfterSuite(c.afterSuite()); result.setBeforeGroups(c.beforeGroups()); result.setAfterGroups(c.afterGroups()); result.setParameters(c.parameters()); result.setEnabled(c.enabled()); result.setGroups(join(c.groups(), findInheritedStringArray(cls, Test.class, "groups"))); result.setDependsOnGroups(c.dependsOnGroups()); result.setDependsOnMethods(c.dependsOnMethods()); result.setAlwaysRun(c.alwaysRun()); result.setInheritGroups(c.inheritGroups()); result.setDescription(c.description()); return result; } private IAnnotation createConfigurationTag(Class cls, Annotation a, boolean beforeSuite, boolean afterSuite, boolean beforeTest, boolean afterTest, String[] beforeGroups, String[] afterGroups, boolean beforeClass, boolean afterClass, boolean beforeMethod, boolean afterMethod, boolean alwaysRun, String[] dependsOnGroups, String[] dependsOnMethods, String description, boolean enabled, String[] groups, boolean inheritGroups, String[] parameters, boolean firstTimeOnly, boolean lastTimeOnly, long timeOut) { ConfigurationAnnotation result = new ConfigurationAnnotation(); result.setFakeConfiguration(true); result.setBeforeSuite(beforeSuite); result.setAfterSuite(afterSuite); result.setBeforeTest(beforeTest); result.setAfterTest(afterTest); result.setBeforeTestClass(beforeClass); result.setAfterTestClass(afterClass); result.setBeforeGroups(beforeGroups); result.setAfterGroups(afterGroups); result.setBeforeTestMethod(beforeMethod); result.setAfterTestMethod(afterMethod); result.setAlwaysRun(alwaysRun); result.setDependsOnGroups(dependsOnGroups); result.setDependsOnMethods(dependsOnMethods); result.setDescription(description); result.setEnabled(enabled); result.setGroups(groups); result.setInheritGroups(inheritGroups); result.setParameters(parameters); result.setFirstTimeOnly(firstTimeOnly); result.setLastTimeOnly(lastTimeOnly); result.setTimeOut(timeOut); return result; } private IAnnotation createDataProviderTag(Annotation a) { DataProviderAnnotation result = new DataProviderAnnotation(); DataProvider c = (DataProvider) a; result.setName(c.name()); result.setParallel(c.parallel()); return result; } @SuppressWarnings({"deprecation"}) private IAnnotation createExpectedExceptionsTag(Annotation a) { ExpectedExceptionsAnnotation result = new ExpectedExceptionsAnnotation (); ExpectedExceptions c = (ExpectedExceptions ) a; result.setValue(c.value()); return result; } @SuppressWarnings({"deprecation"}) private IAnnotation createFactoryTag(Class cls, Annotation a) { FactoryAnnotation result = new FactoryAnnotation(); Factory c = (Factory) a; result.setParameters(c.parameters()); result.setDataProvider(c.dataProvider()); result.setDataProviderClass( findInherited(c.dataProviderClass(), cls, Factory.class, "dataProviderClass", DEFAULT_CLASS)); result.setEnabled(c.enabled()); return result; } private IAnnotation createObjectFactoryTag(Annotation a) { return new ObjectFactoryAnnotation(); } private IAnnotation createParametersTag(Annotation a) { ParametersAnnotation result = new ParametersAnnotation(); Parameters c = (Parameters) a; result.setValue(c.value()); return result; } @SuppressWarnings({"deprecation"}) private IAnnotation createListenersTag(Class cls, Annotation a, IAnnotationTransformer transformer) { ListenersAnnotation result = new ListenersAnnotation(); Listeners l = (Listeners) a; result.setValue(l.value()); return result; } @SuppressWarnings({"deprecation"}) private IAnnotation createTestTag(Class cls, Annotation a, IAnnotationTransformer transformer) { TestAnnotation result = new TestAnnotation(); Test test = (Test) a; result.setEnabled(test.enabled()); result.setGroups(join(test.groups(), findInheritedStringArray(cls, Test.class, "groups"))); result.setParameters(test.parameters()); result.setDependsOnGroups(join(test.dependsOnGroups(), findInheritedStringArray(cls, Test.class, "dependsOnGroups"))); result.setDependsOnMethods(join(test.dependsOnMethods(), findInheritedStringArray(cls, Test.class, "dependsOnMethods"))); result.setTimeOut(test.timeOut()); result.setInvocationTimeOut(test.invocationTimeOut()); result.setInvocationCount(test.invocationCount()); result.setThreadPoolSize(test.threadPoolSize()); result.setSuccessPercentage(test.successPercentage()); result.setDataProvider(test.dataProvider()); // result.setDataProviderClass(test.dataProviderClass() != Object.class ? // test.dataProviderClass() : null); result.setDataProviderClass( findInherited(test.dataProviderClass(), cls, Test.class, "dataProviderClass", DEFAULT_CLASS)); result.setAlwaysRun(test.alwaysRun()); result.setDescription( findInherited(test.description(), cls, Test.class, "description", DEFAULT_STRING)); result.setExpectedExceptions(test.expectedExceptions()); result.setExpectedExceptionsMessageRegExp(test.expectedExceptionsMessageRegExp()); result.setSuiteName(test.suiteName()); result.setTestName(test.testName()); result.setSequential(test.sequential()); result.setSingleThreaded(test.singleThreaded()); result.setRetryAnalyzer(test.retryAnalyzer()); result.setSkipFailedInvocations(test.skipFailedInvocations()); result.setIgnoreMissingDependencies(test.ignoreMissingDependencies()); result.setPriority(test.priority()); return result; } private String[] join(String[] strings, String[] strings2) { List result = Lists.newArrayList(strings); Set seen = new HashSet<>(Lists.newArrayList(strings)); for (String s : strings2) { if (! seen.contains(s)) { result.add(s); } } return result.toArray(new String[result.size()]); } /** * This interface is used to calculate the default value for various * annotation return types. This is used when looking for an annotation in a * hierarchy. We can't use null as a default since annotation don't allow * nulls, so each type has a different way of defining its own default. */ static interface Default { boolean isDefault(T t); } private static final Default> DEFAULT_CLASS = new Default>() { @Override public boolean isDefault(Class c) { return c == Object.class; } }; private static final Default DEFAULT_STRING = new Default() { @Override public boolean isDefault(String s) { return Utils.isStringEmpty(s); } }; /** * Find the value of an annotation, starting with the annotation found on the * method, then the class and then parent classes until we either find a * non-default value or we reach the top of the hierarchy (Object). */ private T findInherited(T methodValue, Class cls, Class annotationClass, String methodName, Default def) { // Look on the method first and return right away if the annotation is there if (!def.isDefault(methodValue)) { return methodValue; } // Not found, look on the class and then up the hierarchy while (cls != null && cls != Object.class) { Annotation annotation = cls.getAnnotation(annotationClass); if (annotation != null) { T result = (T) invokeMethod(annotation, methodName); if (!def.isDefault(result)) { return result; } } cls = cls.getSuperclass(); } return null; } /** * Find the value of a String[] annotation. The difference with the * findInherited method above is that TestNG aggregates String[] values across * hierarchies. For example, of the method annotation has { "a", "b" } and the * class has { "c" }, the returned value will be { "a", "b", "c" }. */ private String[] findInheritedStringArray(Class cls, Class annotationClass, String methodName) { if (null == cls) { return new String[0]; } List result = Lists.newArrayList(); while (cls != null && cls != Object.class) { Annotation annotation = cls.getAnnotation(annotationClass); if (annotation != null) { String[] g = (String[]) invokeMethod(annotation, methodName); for (String s : g) { result.add(s); } } cls = cls.getSuperclass(); } return result.toArray(new String[result.size()]); } private Object invokeMethod(Annotation test, String methodName) { Object result = null; try { // Note: we should cache methods already looked up Method m = test.getClass().getMethod(methodName, new Class[0]); result = m.invoke(test, new Object[0]); } catch (Exception e) { e.printStackTrace(); } return result; } private void ppp(String string) { System.out.println("[JDK15TagFactory] " + string); } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/JDK15AnnotationFinder.java0000755000175000017500000002203412551235562031361 0ustar eugeneeugenepackage org.testng.internal.annotations; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; 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; import org.testng.annotations.AfterSuite; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeTest; import org.testng.annotations.Configuration; import org.testng.annotations.DataProvider; import org.testng.annotations.ExpectedExceptions; import org.testng.annotations.Factory; import org.testng.annotations.IAnnotation; import org.testng.annotations.IConfigurationAnnotation; import org.testng.annotations.IDataProviderAnnotation; import org.testng.annotations.IExpectedExceptionsAnnotation; import org.testng.annotations.IFactoryAnnotation; import org.testng.annotations.IObjectFactoryAnnotation; import org.testng.annotations.IParametersAnnotation; import org.testng.annotations.ITestAnnotation; import org.testng.annotations.Listeners; import org.testng.annotations.ObjectFactory; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.testng.annotations.Test; import org.testng.annotations.TestInstance; import org.testng.internal.collections.Pair; /** * This class implements IAnnotationFinder with JDK5 annotations * * Created on Dec 20, 2005 * @author Cedric Beust */ public class JDK15AnnotationFinder implements IAnnotationFinder { private JDK15TagFactory m_tagFactory = new JDK15TagFactory(); private Map, Class> m_annotationMap = new ConcurrentHashMap<>(); private Map, IAnnotation> m_annotations = new ConcurrentHashMap<>(); private IAnnotationTransformer m_transformer = null; @SuppressWarnings({"deprecation"}) public JDK15AnnotationFinder(IAnnotationTransformer transformer) { m_transformer = transformer; m_annotationMap.put(IConfigurationAnnotation.class, Configuration.class); m_annotationMap.put(IDataProviderAnnotation.class, DataProvider.class); m_annotationMap.put(IExpectedExceptionsAnnotation.class, ExpectedExceptions.class); m_annotationMap.put(IFactoryAnnotation.class, Factory.class); m_annotationMap.put(IObjectFactoryAnnotation.class, ObjectFactory.class); m_annotationMap.put(IParametersAnnotation.class, Parameters.class); m_annotationMap.put(ITestAnnotation.class, Test.class); m_annotationMap.put(IBeforeSuite.class, BeforeSuite.class); m_annotationMap.put(IAfterSuite.class, AfterSuite.class); m_annotationMap.put(IBeforeTest.class, BeforeTest.class); m_annotationMap.put(IAfterTest.class, AfterTest.class); m_annotationMap.put(IBeforeClass.class, BeforeClass.class); m_annotationMap.put(IAfterClass.class, AfterClass.class); m_annotationMap.put(IBeforeGroups.class, BeforeGroups.class); m_annotationMap.put(IAfterGroups.class, AfterGroups.class); m_annotationMap.put(IBeforeMethod.class, BeforeMethod.class); m_annotationMap.put(IAfterMethod.class, AfterMethod.class); m_annotationMap.put(IListeners.class, Listeners.class); } private A findAnnotationInSuperClasses(Class cls, Class 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 cls.getAnnotation(a); } else { while (cls != null) { A result = cls.getAnnotation(a); if (result != null) { return result; } else { cls = cls.getSuperclass(); } } } return null; } @Override public A findAnnotation(Method m, Class annotationClass) { final Class a = m_annotationMap.get(annotationClass); if (a == null) { throw new IllegalArgumentException("Java @Annotation class for '" + annotationClass + "' not found."); } Annotation annotation = m.getAnnotation(a); return findAnnotation(m.getDeclaringClass(), annotation, annotationClass, null, null, m, new Pair<>(annotation, m)); } @Override public A findAnnotation(ITestNGMethod tm, Class annotationClass) { final Class 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(testClass, annotation, annotationClass, null, null, m, new Pair<>(annotation, m)); } private void transform(IAnnotation a, Class testClass, Constructor testConstructor, Method testMethod) { // // Transform @Test // if (a instanceof ITestAnnotation) { m_transformer.transform((ITestAnnotation) a, testClass, testConstructor, testMethod); } else if (m_transformer instanceof IAnnotationTransformer2) { IAnnotationTransformer2 transformer2 = (IAnnotationTransformer2) m_transformer; // // Transform a configuration annotation // if (a instanceof IConfigurationAnnotation) { IConfigurationAnnotation configuration = (IConfigurationAnnotation) a; transformer2.transform(configuration,testClass, testConstructor, testMethod); } // // Transform @DataProvider // else if (a instanceof IDataProviderAnnotation) { transformer2.transform((IDataProviderAnnotation) a, testMethod); } // // Transform @Factory // else if (a instanceof IFactoryAnnotation) { transformer2.transform((IFactoryAnnotation) a, testMethod); } } } @Override public A findAnnotation(Class cls, Class annotationClass) { final Class a = m_annotationMap.get(annotationClass); if (a == null) { throw new IllegalArgumentException("Java @Annotation class for '" + annotationClass + "' not found."); } Annotation annotation = findAnnotationInSuperClasses(cls, a); return findAnnotation(cls, annotation, annotationClass, cls, null, null, new Pair<>(annotation, annotationClass)); } @Override public A findAnnotation(Constructor cons, Class annotationClass) { final Class a = m_annotationMap.get(annotationClass); if (a == null) { throw new IllegalArgumentException("Java @Annotation class for '" + annotationClass + "' not found."); } Annotation annotation = cons.getAnnotation(a); return findAnnotation(cons.getDeclaringClass(), annotation, annotationClass, null, cons, null, new Pair<>(annotation, cons)); } private A findAnnotation(Class cls, Annotation a, Class annotationClass, Class testClass, Constructor testConstructor, Method testMethod, Pair p) { if (a == null) { return null; } IAnnotation result = m_annotations.get(p); if (result == null) { result = m_tagFactory.createTag(cls, a, annotationClass, m_transformer); m_annotations.put(p, result); transform(result, testClass, testConstructor, testMethod); } //noinspection unchecked return (A) result; } @Override public boolean hasTestInstance(Method method, int i) { final Annotation[][] annotations = method.getParameterAnnotations(); if (annotations.length > 0 && annotations[i].length > 0) { final Annotation[] pa = annotations[i]; for (Annotation a : pa) { if (a instanceof TestInstance) { return true; } } } return false; } @Override public String[] findOptionalValues(Method method) { return optionalValues(method.getParameterAnnotations()); } @Override public String[] findOptionalValues(Constructor method) { return optionalValues(method.getParameterAnnotations()); } private String[] optionalValues(Annotation[][] annotations) { String[] result = new String[annotations.length]; for (int i = 0; i < annotations.length; i++) { for (Annotation a : annotations[i]) { if (a instanceof Optional) { result[i] = ((Optional)a).value(); break; } } } return result; } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/ITest.java0000755000175000017500000000021612551235562026446 0ustar eugeneeugenepackage org.testng.internal.annotations; import org.testng.annotations.ITestAnnotation; public interface ITest extends ITestAnnotation { } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IListeners.java0000644000175000017500000000043212551235562027474 0ustar eugeneeugenepackage org.testng.internal.annotations; import org.testng.ITestNGListener; import org.testng.annotations.IAnnotation; public interface IListeners extends IAnnotation { Class[] getValue(); void setValue(Class[] value); } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IDataProvidable.java0000644000175000017500000000061212551235562030405 0ustar eugeneeugenepackage org.testng.internal.annotations; /** * A trait shared by all the annotations that have dataProvider/dataProviderClass attributes. * * @author Cedric Beust */ public interface IDataProvidable { public String getDataProvider(); public void setDataProvider(String v); public Class getDataProviderClass(); public void setDataProviderClass(Class v); } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IBeforeTest.java0000755000175000017500000000014512551235562027572 0ustar eugeneeugenepackage org.testng.internal.annotations; public interface IBeforeTest extends IBaseBeforeAfter { } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IBeforeSuite.java0000755000175000017500000000014612551235562027745 0ustar eugeneeugenepackage org.testng.internal.annotations; public interface IBeforeSuite extends IBaseBeforeAfter { } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IBeforeMethod.java0000755000175000017500000000014612551235562030074 0ustar eugeneeugenepackage org.testng.internal.annotations; public interface IBeforeMethod extends IBaseBeforeAfter { } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IBeforeGroups.java0000755000175000017500000000014712551235562030134 0ustar eugeneeugenepackage org.testng.internal.annotations; public interface IBeforeGroups extends IBaseBeforeAfter { } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IBeforeClass.java0000755000175000017500000000014612551235562027721 0ustar eugeneeugenepackage org.testng.internal.annotations; public interface IBeforeClass extends IBaseBeforeAfter { } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IBaseBeforeAfter.java0000755000175000017500000000424112551235562030510 0ustar eugeneeugenepackage org.testng.internal.annotations; import org.testng.annotations.ITestOrConfiguration; /** * Base interface for IBeforeSuite, IAfterSuite, etc... * * @author cbeust * @since Jun 22, 2006 */ public interface IBaseBeforeAfter extends ITestOrConfiguration { /** * Whether methods on this class/method are enabled. */ public boolean getEnabled(); /** * The list of groups this class/method belongs to. */ public String[] getGroups(); /** * The list of groups this method depends on. Every method * member of one of these groups is guaranteed to have been * invoked before this method. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. */ public String[] getDependsOnGroups(); /** * The list of methods this method depends on. There is no guarantee * on the order on which the methods depended upon will be run, but you * are guaranteed that all these methods will be run before the test method * that contains this annotation is run. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. * * If some of these methods have been overloaded, all the overloaded * versions will be run. */ public String[] getDependsOnMethods(); /** * For before methods (beforeSuite, beforeTest, beforeTestClass and * beforeTestMethod, but not beforeGroups): * If set to true, this configuration method will be run * regardless of what groups it belongs to. *
* For after methods (afterSuite, afterClass, ...): * If set to true, this configuration method will be run * even if one or more methods invoked previously failed or * was skipped. */ public boolean getAlwaysRun(); /** * If true, this @Configuration method will belong to groups specified in the * @Test annotation on the class (if any). */ public boolean getInheritGroups(); /** * The description for this method. The string used will appear in the * HTML report and also on standard output if verbose >= 2. */ public String getDescription(); } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IAnnotationTransformer.java0000755000175000017500000000025012551235562032062 0ustar eugeneeugenepackage org.testng.internal.annotations; /** * For backward compatibility. */ public interface IAnnotationTransformer extends org.testng.IAnnotationTransformer { } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IAnnotationFinder.java0000755000175000017500000000353212551235562030775 0ustar eugeneeugenepackage org.testng.internal.annotations; 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 * and constructors. It will be implemented by both JDK 1.4 and JDK 5 * annotation finders. * * @author
Cedric Beust */ public interface IAnnotationFinder { /** * @param cls * @param annotationClass * @return The annotation on the class or null if none found. */ public A findAnnotation(Class cls, Class annotationClass); /** * @param m * @param annotationClass * @return The annotation on the method. * If not found, return the annotation on the declaring class. * If not found, return null. */ public A findAnnotation(Method m, Class annotationClass); A findAnnotation(ITestNGMethod m, Class annotationClass); /** * @param cons * @param annotationClass * @return The annotation on the method. * If not found, return the annotation on the declaring class. * If not found, return null. */ public A findAnnotation(Constructor cons, Class annotationClass); /** * @return true if the ith parameter of the given method has the annotation @TestInstance. */ public boolean hasTestInstance(Method method, int i); /** * @return the @Optional values of this method's parameters (null * if the parameter isn't optional) */ public String[] findOptionalValues(Method method); /** * @return the @Optional values of this method's parameters (null * if the parameter isn't optional) */ public String[] findOptionalValues(Constructor ctor); } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IAfterTests.java0000755000175000017500000000014512551235562027614 0ustar eugeneeugenepackage org.testng.internal.annotations; public interface IAfterTests extends IBaseBeforeAfter { } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IAfterTest.java0000755000175000017500000000014412551235562027430 0ustar eugeneeugenepackage org.testng.internal.annotations; public interface IAfterTest extends IBaseBeforeAfter { } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IAfterSuite.java0000755000175000017500000000014512551235562027603 0ustar eugeneeugenepackage org.testng.internal.annotations; public interface IAfterSuite extends IBaseBeforeAfter { } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IAfterMethod.java0000755000175000017500000000014612551235562027733 0ustar eugeneeugenepackage org.testng.internal.annotations; public interface IAfterMethod extends IBaseBeforeAfter { } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IAfterGroups.java0000755000175000017500000000014612551235562027772 0ustar eugeneeugenepackage org.testng.internal.annotations; public interface IAfterGroups extends IBaseBeforeAfter { } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/IAfterClass.java0000755000175000017500000000014512551235562027557 0ustar eugeneeugenepackage org.testng.internal.annotations; public interface IAfterClass extends IBaseBeforeAfter { } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/FactoryAnnotation.java0000755000175000017500000000224312551235562031062 0ustar eugeneeugenepackage org.testng.internal.annotations; import org.testng.annotations.IFactoryAnnotation; /** * An implementation of IFactory * * Created on Dec 20, 2005 * @author Cedric Beust */ public class FactoryAnnotation extends BaseAnnotation implements IFactoryAnnotation { private String[] m_parameters = {}; private String m_dataProvider = null; private Class m_dataProviderClass; private boolean m_enabled = true; @Override public String getDataProvider() { return m_dataProvider; } @Override public void setDataProvider(String dataProvider) { m_dataProvider = dataProvider; } @Override public String[] getParameters() { return m_parameters; } public void setParameters(String[] parameters) { m_parameters = parameters; } public void setDataProviderClass(Class dataProviderClass) { m_dataProviderClass = dataProviderClass; } @Override public Class getDataProviderClass() { return m_dataProviderClass; } @Override public boolean getEnabled() { return m_enabled; } @Override public void setEnabled(boolean enabled) { m_enabled = enabled; } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/ExpectedExceptionsAnnotation.java0000755000175000017500000000101712551235562033254 0ustar eugeneeugenepackage org.testng.internal.annotations; import org.testng.annotations.IExpectedExceptionsAnnotation; /** * An implementation of IExpectedExceptions * * Created on Dec 20, 2005 * @author Cedric Beust */ public class ExpectedExceptionsAnnotation extends BaseAnnotation implements IExpectedExceptionsAnnotation { private Class[] m_value = {}; @Override public Class[] getValue() { return m_value; } public void setValue(Class[] value) { m_value = value; } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/DefaultAnnotationTransformer.java0000755000175000017500000000065712551235562033271 0ustar eugeneeugenepackage org.testng.internal.annotations; import org.testng.IAnnotationTransformer; import org.testng.annotations.ITestAnnotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class DefaultAnnotationTransformer implements IAnnotationTransformer { @Override public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/DataProviderAnnotation.java0000755000175000017500000000126512551235562032042 0ustar eugeneeugenepackage org.testng.internal.annotations; import org.testng.annotations.IDataProviderAnnotation; /** * An implementation of IDataProvider. * * Created on Dec 20, 2005 * @author Cedric Beust */ public class DataProviderAnnotation extends BaseAnnotation implements IDataProviderAnnotation { private String m_name; private boolean m_parallel; @Override public boolean isParallel() { return m_parallel; } @Override public void setParallel(boolean parallel) { m_parallel = parallel; } @Override public String getName() { return m_name; } @Override public void setName(String name) { m_name = name; } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/Converter.java0000755000175000017500000000403112551235562027364 0ustar eugeneeugenepackage org.testng.internal.annotations; import org.testng.collections.Lists; import org.testng.internal.ClassHelper; import org.testng.internal.Utils; import java.util.List; import java.util.StringTokenizer; /** * Convert a string values into primitive types. * * Created on Dec 20, 2005 * @author cbeust */ public class Converter { public static boolean getBoolean(String tagValue, boolean def) { boolean result = def; if (tagValue != null) { result = Boolean.valueOf(tagValue); } return result; } public static int getInt(String tagValue, int def) { int result = def; if (tagValue != null) { result = new Integer(tagValue); } return result; } public static String getString(String tagValue, String def) { String result = def; if (tagValue != null) { result = tagValue; } return result; } public static long getLong(String tagValue, long def) { long result = def; if (tagValue != null) { result = new Long(tagValue); } return result; } public static String[] getStringArray(String tagValue, String[] def) { String[] result = def; if (tagValue != null) { result = Utils.stringToArray(tagValue); } return result; } public static Class[] getClassArray(String tagValue, Class[] def) { Class[] result = def; List vResult = Lists.newArrayList(); if (tagValue != null) { StringTokenizer st = new StringTokenizer(tagValue, " ,"); while (st.hasMoreElements()) { String className = (String) st.nextElement(); try { Class cls = Class.forName(className); vResult.add(cls); } catch (ClassNotFoundException e) { e.printStackTrace(); } } result = (Class[]) vResult.toArray(new Class[vResult.size()]); } return result; } public static Class getClass(String namedParameter) { Class result = null; if (namedParameter != null) { result = ClassHelper.forName(namedParameter); } return result; } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/ConfigurationAnnotation.java0000755000175000017500000000750712551235562032272 0ustar eugeneeugenepackage org.testng.internal.annotations; import org.testng.annotations.IConfigurationAnnotation; /** * An implementation of IConfiguration * * Created on Dec 16, 2005 * @author cbeust */ public class ConfigurationAnnotation extends TestOrConfiguration implements IConfigurationAnnotation, IBeforeSuite, IAfterSuite, IBeforeTest, IAfterTest, IBeforeGroups, IAfterGroups, IBeforeClass, IAfterClass, IBeforeMethod, IAfterMethod { private boolean m_beforeTestClass = false; private boolean m_afterTestClass = false; private boolean m_beforeTestMethod = false; private boolean m_afterTestMethod = false; private boolean m_beforeTest = false; private boolean m_afterTest = false; private boolean m_beforeSuite = false; private boolean m_afterSuite = false; private String[] m_parameters = {}; private boolean m_alwaysRun = false; private boolean m_inheritGroups = true; private String[] m_beforeGroups = {}; private String[] m_afterGroups = {}; private boolean m_isFakeConfiguration; private boolean m_firstTimeOnly = false; private boolean m_lastTimeOnly = false; public ConfigurationAnnotation() { } public void setAfterSuite(boolean afterSuite) { m_afterSuite = afterSuite; } public void setAfterTest(boolean afterTest) { m_afterTest = afterTest; } public void setAfterTestClass(boolean afterTestClass) { m_afterTestClass = afterTestClass; } public void setAfterTestMethod(boolean afterTestMethod) { m_afterTestMethod = afterTestMethod; } public void setAlwaysRun(boolean alwaysRun) { m_alwaysRun = alwaysRun; } public void setBeforeSuite(boolean beforeSuite) { m_beforeSuite = beforeSuite; } public void setBeforeTest(boolean beforeTest) { m_beforeTest = beforeTest; } public void setBeforeTestClass(boolean beforeTestClass) { m_beforeTestClass = beforeTestClass; } public void setBeforeTestMethod(boolean beforeTestMethod) { m_beforeTestMethod = beforeTestMethod; } public void setInheritGroups(boolean inheritGroups) { m_inheritGroups = inheritGroups; } @Override public void setParameters(String[] parameters) { m_parameters = parameters; } @Override public boolean getBeforeTestClass() { return m_beforeTestClass; } @Override public boolean getAfterTestClass() { return m_afterTestClass; } @Override public boolean getBeforeTestMethod() { return m_beforeTestMethod; } @Override public boolean getAfterTestMethod() { return m_afterTestMethod; } @Override public boolean getBeforeSuite() { return m_beforeSuite; } @Override public boolean getAfterSuite() { return m_afterSuite; } @Override public boolean getBeforeTest() { return m_beforeTest; } @Override public boolean getAfterTest() { return m_afterTest; } @Override public String[] getParameters() { return m_parameters; } @Override public boolean getAlwaysRun() { return m_alwaysRun; } @Override public boolean getInheritGroups() { return m_inheritGroups; } @Override public String[] getAfterGroups() { return m_afterGroups; } public void setAfterGroups(String[] afterGroups) { m_afterGroups = afterGroups; } @Override public String[] getBeforeGroups() { return m_beforeGroups; } public void setBeforeGroups(String[] beforeGroups) { m_beforeGroups = beforeGroups; } public void setFakeConfiguration(boolean b) { m_isFakeConfiguration = b; } @Override public boolean isFakeConfiguration() { return m_isFakeConfiguration; } public void setFirstTimeOnly(boolean f) { m_firstTimeOnly = f; } public boolean isFirstTimeOnly() { return m_firstTimeOnly; } public void setLastTimeOnly(boolean f) { m_lastTimeOnly = f; } public boolean isLastTimeOnly() { return m_lastTimeOnly; } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/BeforeSuiteAnnotation.java0000755000175000017500000000015212551235562031664 0ustar eugeneeugenepackage org.testng.internal.annotations; public class BeforeSuiteAnnotation extends BaseBeforeAfter { } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/BaseBeforeAfter.java0000755000175000017500000000271412551235562030402 0ustar eugeneeugenepackage org.testng.internal.annotations; public class BaseBeforeAfter extends TestOrConfiguration implements IBaseBeforeAfter { private String[] m_parameters = {}; private boolean m_alwaysRun = false; private boolean m_inheritGroups = true; private String[] m_beforeGroups = {}; private String[] m_afterGroups = {}; private String m_description; /** * @return the description */ @Override public String getDescription() { return m_description; } /** * @param description the description to set */ @Override public void setDescription(String description) { m_description = description; } public void setAlwaysRun(boolean alwaysRun) { m_alwaysRun = alwaysRun; } public void setInheritGroups(boolean inheritGroups) { m_inheritGroups = inheritGroups; } @Override public void setParameters(String[] parameters) { m_parameters = parameters; } @Override public String[] getParameters() { return m_parameters; } @Override public boolean getAlwaysRun() { return m_alwaysRun; } @Override public boolean getInheritGroups() { return m_inheritGroups; } public String[] getAfterGroups() { return m_afterGroups; } public void setAfterGroups(String[] afterGroups) { m_afterGroups = afterGroups; } public String[] getBeforeGroups() { return m_beforeGroups; } public void setBeforeGroups(String[] beforeGroups) { m_beforeGroups = beforeGroups; } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/BaseAnnotation.java0000755000175000017500000000123212551235562030322 0ustar eugeneeugenepackage org.testng.internal.annotations; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class BaseAnnotation { private Class m_testClass; private Method m_method; private Constructor m_constructor; public Constructor getConstructor() { return m_constructor; } public void setConstructor(Constructor constructor) { m_constructor = constructor; } public Method getMethod() { return m_method; } public void setMethod(Method method) { m_method = method; } public Class getTestClass() { return m_testClass; } public void setTestClass(Class testClass) { m_testClass = testClass; } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/AnnotationHelper.java0000755000175000017500000003134212551235562030674 0ustar eugeneeugenepackage 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; import org.testng.annotations.IFactoryAnnotation; import org.testng.annotations.IParametersAnnotation; import org.testng.annotations.ITestAnnotation; import org.testng.collections.Maps; import org.testng.internal.TestNGMethod; import org.testng.internal.Utils; import org.testng.xml.XmlTest; /** * Helper methods to find @Test and @Configuration tags. They minimize * the amount of casting we need to do. * * Created on Dec 20, 2005 * @author cbeust */ public class AnnotationHelper { public static ITestAnnotation findTest(IAnnotationFinder finder, Class cls) { return finder.findAnnotation(cls, ITestAnnotation.class); } public static ITestAnnotation findTest(IAnnotationFinder finder, Method m) { 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); } public static IFactoryAnnotation findFactory(IAnnotationFinder finder, Constructor c) { return finder.findAnnotation(c, IFactoryAnnotation.class); } public static ITestAnnotation findTest(IAnnotationFinder finder, Constructor ctor) { return finder.findAnnotation(ctor, ITestAnnotation.class); } public static IConfigurationAnnotation findConfiguration(IAnnotationFinder finder, Constructor ctor) { IConfigurationAnnotation result = finder.findAnnotation(ctor, IConfigurationAnnotation.class); if (result == null) { IConfigurationAnnotation bs = (IConfigurationAnnotation) finder.findAnnotation(ctor, IBeforeSuite.class); IConfigurationAnnotation as = (IConfigurationAnnotation) finder.findAnnotation(ctor, IAfterSuite.class); IConfigurationAnnotation bt = (IConfigurationAnnotation) finder.findAnnotation(ctor, IBeforeTest.class); IConfigurationAnnotation at = (IConfigurationAnnotation) finder.findAnnotation(ctor, IAfterTest.class); IConfigurationAnnotation bg = (IConfigurationAnnotation) finder.findAnnotation(ctor, IBeforeGroups.class); IConfigurationAnnotation ag = (IConfigurationAnnotation) finder.findAnnotation(ctor, IAfterGroups.class); IConfigurationAnnotation bc = (IConfigurationAnnotation) finder.findAnnotation(ctor, IBeforeClass.class); IConfigurationAnnotation ac = (IConfigurationAnnotation) finder.findAnnotation(ctor, IAfterClass.class); IConfigurationAnnotation bm = (IConfigurationAnnotation) finder.findAnnotation(ctor, IBeforeMethod.class); IConfigurationAnnotation am = (IConfigurationAnnotation) finder.findAnnotation(ctor, IAfterMethod.class); if (bs != null || as != null || bt != null || at != null || bg != null || ag != null || bc != null || ac != null || bm != null || am != null) { result = createConfiguration(bs, as, bt, at, bg, ag, bc, ac, bm, am); } } return result; } public static IConfigurationAnnotation findConfiguration(IAnnotationFinder finder, Method m) { 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); IConfigurationAnnotation bt = (IConfigurationAnnotation) finder.findAnnotation(m, IBeforeTest.class); IConfigurationAnnotation at = (IConfigurationAnnotation) finder.findAnnotation(m, IAfterTest.class); IConfigurationAnnotation bg = (IConfigurationAnnotation) finder.findAnnotation(m, IBeforeGroups.class); IConfigurationAnnotation ag = (IConfigurationAnnotation) finder.findAnnotation(m, IAfterGroups.class); IConfigurationAnnotation bc = (IConfigurationAnnotation) finder.findAnnotation(m, IBeforeClass.class); IConfigurationAnnotation ac = (IConfigurationAnnotation) finder.findAnnotation(m, IAfterClass.class); IConfigurationAnnotation bm = (IConfigurationAnnotation) finder.findAnnotation(m, IBeforeMethod.class); IConfigurationAnnotation am = (IConfigurationAnnotation) finder.findAnnotation(m, IAfterMethod.class); if (bs != null || as != null || bt != null || at != null || bg != null || ag != null || bc != null || ac != null || bm != null || am != null) { result = createConfiguration(bs, as, bt, at, bg, ag, bc, ac, bm, am); } } return result; } private static IConfigurationAnnotation createConfiguration(IConfigurationAnnotation bs, IConfigurationAnnotation as, IConfigurationAnnotation bt, IConfigurationAnnotation at, IConfigurationAnnotation bg, IConfigurationAnnotation ag, IConfigurationAnnotation bc, IConfigurationAnnotation ac, IConfigurationAnnotation bm, IConfigurationAnnotation am) { ConfigurationAnnotation result = new ConfigurationAnnotation(); if (bs != null) { result.setBeforeSuite(true); finishInitialize(result, bs); } if (as != null) { result.setAfterSuite(true); finishInitialize(result, as); } if (bt != null) { result.setBeforeTest(true); finishInitialize(result, bt); } if (at != null) { result.setAfterTest(true); finishInitialize(result, at); } if (bg != null) { result.setBeforeGroups(bg.getBeforeGroups()); finishInitialize(result, bg); } if (ag != null) { result.setAfterGroups(ag.getAfterGroups()); finishInitialize(result, ag); } if (bc != null) { result.setBeforeTestClass(true); finishInitialize(result, bc); } if (ac != null) { result.setAfterTestClass(true); finishInitialize(result, ac); } if (bm != null) { result.setBeforeTestMethod(true); finishInitialize(result, bm); } if (am != null) { result.setAfterTestMethod(true); finishInitialize(result, am); } return result; } @SuppressWarnings({"deprecation"}) private static void finishInitialize(ConfigurationAnnotation result, IConfigurationAnnotation bs) { result.setFakeConfiguration(true); result.setAlwaysRun(bs.getAlwaysRun()); result.setDependsOnGroups(bs.getDependsOnGroups()); result.setDependsOnMethods(bs.getDependsOnMethods()); result.setDescription(bs.getDescription()); result.setEnabled(bs.getEnabled()); result.setGroups(bs.getGroups()); result.setInheritGroups(bs.getInheritGroups()); result.setParameters(bs.getParameters()); result.setTimeOut(bs.getTimeOut()); } private static Class[] ALL_ANNOTATIONS = new Class[] { ITestAnnotation.class, IConfigurationAnnotation.class, IBeforeClass.class, IAfterClass.class, IBeforeMethod.class, IAfterMethod.class, IDataProviderAnnotation.class, IExpectedExceptionsAnnotation.class, IFactoryAnnotation.class, IParametersAnnotation.class, IBeforeSuite.class, IAfterSuite.class, IBeforeTest.class, IAfterTest.class, IBeforeGroups.class, IAfterGroups.class }; public static Class[] CONFIGURATION_CLASSES = new Class[] { IConfigurationAnnotation.class, IBeforeSuite.class, IAfterSuite.class, IBeforeTest.class, IAfterTest.class, IBeforeGroups.class, IAfterGroups.class, IBeforeClass.class, IAfterClass.class, IBeforeMethod.class, IAfterMethod.class }; public static Class[] getAllAnnotations() { return ALL_ANNOTATIONS; } /** * Delegation method for creating the list of ITestMethods to be * analysed. */ public static ITestNGMethod[] findMethodsWithAnnotation(Class rootClass, Class 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 Map vResult = Maps.newHashMap(); try { vResult = Maps.newHashMap(); // Class[] classes = rootClass.getTestClasses(); Class cls = rootClass; // // If the annotation is on the class or superclass, it applies to all public methods // except methods marked with @Configuration // // // Otherwise walk through all the methods and keep those // that have the annotation // // for (Class cls : classes) { while (null != cls) { boolean hasClassAnnotation = isAnnotationPresent(annotationFinder, cls, annotationClass); Method[] methods = cls.getDeclaredMethods(); for (Method m : methods) { boolean hasMethodAnnotation = isAnnotationPresent(annotationFinder, m, annotationClass); boolean hasTestNGAnnotation = isAnnotationPresent(annotationFinder, m, IFactoryAnnotation.class) || isAnnotationPresent(annotationFinder, m, ITestAnnotation.class) || isAnnotationPresent(annotationFinder, m, CONFIGURATION_CLASSES); boolean isPublic = Modifier.isPublic(m.getModifiers()); boolean isSynthetic = m.isSynthetic(); if ((isPublic && hasClassAnnotation && !isSynthetic && (! hasTestNGAnnotation)) || hasMethodAnnotation) { // Small hack to allow users to specify @Configuration classes even though // a class-level @Test annotation is present. In this case, don't count // that method as a @Test if (isAnnotationPresent(annotationFinder, m, IConfigurationAnnotation.class) && isAnnotationPresent(annotationFinder, cls, ITestAnnotation.class)) { Utils.log("", 3, "Method " + m + " has a configuration annotation" + " and a class-level @Test. This method will only be kept as a" + " configuration method."); continue; } // Skip the method if it has a return type if (m.getReturnType() != void.class && ! xmlTest.getAllowReturnValues()) { Utils.log("", 2, "Method " + m + " has a @Test annotation" + " but also a return value:" + " ignoring it. Use to fix this"); continue; } String key = createMethodKey(m); if (null == vResult.get(key)) { ITestNGMethod tm = new TestNGMethod(/* m.getDeclaringClass(), */ m, annotationFinder, xmlTest, null); /* @@@ */ vResult.put(key,tm); } } } // for // Now explore the superclass cls = cls.getSuperclass(); } // while } catch (SecurityException e) { e.printStackTrace(); } ITestNGMethod[] result = vResult.values().toArray(new ITestNGMethod[vResult.size()]); // for (Method m : result) { // ppp(" METHOD FOUND: " + m); // } return result; } public static Annotation findAnnotationSuperClasses(Class annotationClass, Class c) { while (c != null) { Annotation result = c.getAnnotation(annotationClass); if (result != null) return result; else c = c.getSuperclass(); } return null; } private static boolean isAnnotationPresent(IAnnotationFinder annotationFinder, Method m, Class[] annotationClasses) { for (Class a : annotationClasses) { if (annotationFinder.findAnnotation(m, a) != null) { return true; } } return false; } private static boolean isAnnotationPresent(IAnnotationFinder annotationFinder, Method m, Class annotationClass) { return annotationFinder.findAnnotation(m, annotationClass) != null; } private static boolean isAnnotationPresent(IAnnotationFinder annotationFinder, Class cls, Class annotationClass) { return annotationFinder.findAnnotation(cls, annotationClass) != null; } /** * @return A hashcode representing the name of this method and its parameters, * but without its class */ private static String createMethodKey(Method m) { StringBuffer result = new StringBuffer(m.getName()); for (Class paramClass : m.getParameterTypes()) { result.append(' ').append(paramClass.toString()); } return result.toString(); } } testng-testng-6.9.5/src/main/java/org/testng/internal/annotations/AfterSuiteAnnotation.java0000755000175000017500000000015112551235562031522 0ustar eugeneeugenepackage org.testng.internal.annotations; public class AfterSuiteAnnotation extends BaseBeforeAfter { } testng-testng-6.9.5/src/main/java/org/testng/internal/YamlParser.java0000644000175000017500000000114212551235562025134 0ustar eugeneeugenepackage org.testng.internal; import org.testng.TestNGException; import org.testng.xml.ISuiteParser; import org.testng.xml.XmlSuite; import java.io.FileNotFoundException; import java.io.InputStream; public class YamlParser implements ISuiteParser { @Override public XmlSuite parse(String filePath, InputStream is, boolean loadClasses) throws TestNGException { try { return Yaml.parse(filePath, is); } catch (FileNotFoundException e) { throw new TestNGException(e); } } @Override public boolean accept(String fileName) { return fileName.endsWith(".yaml"); } } testng-testng-6.9.5/src/main/java/org/testng/internal/Yaml.java0000644000175000017500000002150612551235562023765 0ustar eugeneeugenepackage org.testng.internal; import org.testng.xml.Parser; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlPackage; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import org.xml.sax.SAXException; import org.yaml.snakeyaml.TypeDescription; import org.yaml.snakeyaml.constructor.Constructor; import javax.xml.parsers.ParserConfigurationException; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.List; import java.util.Map; /** * YAML support for TestNG. * * @author Cedric Beust */ public class Yaml { public static XmlSuite parse(String filePath, InputStream is) throws FileNotFoundException { Constructor constructor = new Constructor(XmlSuite.class); { TypeDescription suiteDescription = new TypeDescription(XmlSuite.class); suiteDescription.putListPropertyType("packages", XmlPackage.class); suiteDescription.putListPropertyType("listeners", String.class); suiteDescription.putListPropertyType("tests", XmlTest.class); suiteDescription.putListPropertyType("method-selectors", XmlMethodSelector.class); constructor.addTypeDescription(suiteDescription); } { TypeDescription testDescription = new TypeDescription(XmlTest.class); testDescription.putListPropertyType("classes", XmlClass.class); testDescription.putMapPropertyType("metaGroups", String.class, List.class); testDescription.putListPropertyType("method-selectors", XmlMethodSelector.class); constructor.addTypeDescription(testDescription); } org.yaml.snakeyaml.Yaml y = new org.yaml.snakeyaml.Yaml(constructor); if (is == null) is = new FileInputStream(new File(filePath)); XmlSuite result = (XmlSuite) y.load(is); result.setFileName(filePath); // DEBUG // System.out.println("[Yaml] " + result.toXml()); // Adjust XmlTest parents and indices for (XmlTest t : result.getTests()) { t.setSuite(result); int index = 0; for (XmlClass c : t.getClasses()) { c.setIndex(index++); } } return result; } private static void maybeAdd(StringBuilder sb, String key, Object value, Object def) { maybeAdd(sb, "", key, value, def); } private static void maybeAdd(StringBuilder sb, String sp, String key, Object value, Object def) { if (value != null && ! value.equals(def)) { sb.append(sp).append(key).append(": ").append(value.toString()).append("\n"); } } /** * The main entry point to convert an XmlSuite into YAML. This method is allowed to be used * by external tools (e.g. Eclipse). */ public static StringBuilder toYaml(XmlSuite suite) { StringBuilder result = new StringBuilder(); maybeAdd(result, "name", suite.getName(), null); maybeAdd(result, "junit", suite.isJUnit(), XmlSuite.DEFAULT_JUNIT); maybeAdd(result, "verbose", suite.getVerbose(), XmlSuite.DEFAULT_VERBOSE); maybeAdd(result, "threadCount", suite.getThreadCount(), XmlSuite.DEFAULT_THREAD_COUNT); maybeAdd(result, "dataProviderThreadCount", suite.getDataProviderThreadCount(), XmlSuite.DEFAULT_DATA_PROVIDER_THREAD_COUNT); maybeAdd(result, "timeOut", suite.getTimeOut(), null); maybeAdd(result, "parallel", suite.getParallel(), XmlSuite.DEFAULT_PARALLEL); maybeAdd(result, "skipFailedInvocationCounts", suite.skipFailedInvocationCounts(), XmlSuite.DEFAULT_SKIP_FAILED_INVOCATION_COUNTS); toYaml(result, "parameters", "", suite.getParameters()); toYaml(result, suite.getPackages()); if (suite.getListeners().size() > 0) { result.append("listeners:\n"); toYaml(result, " ", suite.getListeners()); } if (suite.getPackages().size() > 0) { result.append("packages:\n"); toYaml(result, suite.getPackages()); } if (suite.getTests().size() > 0) { result.append("tests:\n"); for (XmlTest t : suite.getTests()) { toYaml(result, " ", t); } } if (suite.getChildSuites().size() > 0) { result.append("suite-files:\n"); toYaml(result, " ", suite.getSuiteFiles()); } return result; } private static void toYaml(StringBuilder result, String sp, XmlTest t) { String sp2 = sp + " "; result.append(sp).append("- name: ").append(t.getName()).append("\n"); maybeAdd(result, sp2, "junit", t.isJUnit(), XmlSuite.DEFAULT_JUNIT); maybeAdd(result, sp2, "verbose", t.getVerbose(), XmlSuite.DEFAULT_VERBOSE); maybeAdd(result, sp2, "timeOut", t.getTimeOut(), null); maybeAdd(result, sp2, "parallel", t.getParallel(), XmlSuite.DEFAULT_PARALLEL); maybeAdd(result, sp2, "skipFailedInvocationCounts", t.skipFailedInvocationCounts(), XmlSuite.DEFAULT_SKIP_FAILED_INVOCATION_COUNTS); maybeAdd(result, "preserveOrder", sp2, t.getPreserveOrder(), XmlSuite.DEFAULT_PRESERVE_ORDER); toYaml(result, "parameters", sp2, t.getTestParameters()); if (t.getIncludedGroups().size() > 0) { result.append(sp2).append("includedGroups: [ ") .append(Utils.join(t.getIncludedGroups(), ",")) .append(" ]\n"); } if (t.getExcludedGroups().size() > 0) { result.append(sp2).append("excludedGroups: [ ") .append(Utils.join(t.getExcludedGroups(), ",")) .append(" ]\n"); } Map> mg = t.getMetaGroups(); if (mg.size() > 0) { result.append(sp2).append("metaGroups: { "); boolean first = true; for (String group : mg.keySet()) { if (! first) result.append(", "); result.append(group).append(": [ ") .append(Utils.join(mg.get(group), ",")).append(" ] "); first = false; } result.append(" }\n"); } if (t.getXmlPackages().size() > 0) { result.append(sp2).append("xmlPackages:\n"); for (XmlPackage xp : t.getXmlPackages()) { toYaml(result, sp2 + " - ", xp); } } if (t.getXmlClasses().size() > 0) { result.append(sp2).append("classes:\n"); for (XmlClass xc : t.getXmlClasses()) { toYaml(result, sp2 + " ", xc); } } result.append("\n"); } private static void toYaml(StringBuilder result, String sp2, XmlClass xc) { List im = xc.getIncludedMethods(); List em = xc.getExcludedMethods(); String name = im.size() > 0 || em.size() > 0 ? "name: " : ""; result.append(sp2).append("- " + name).append(xc.getName()).append("\n"); if (im.size() > 0) { result.append(sp2 + " includedMethods:\n"); for (XmlInclude xi : im) { toYaml(result, sp2 + " ", xi); } } if (em.size() > 0) { result.append(sp2 + " excludedMethods:\n"); toYaml(result, sp2 + " ", em); } } private static void toYaml(StringBuilder result, String sp2, XmlInclude xi) { result.append(sp2 + "- " + xi.getName()).append("\n"); } private static void toYaml(StringBuilder result, String sp, List strings) { for (String l : strings) { result.append(sp).append("- ").append(l).append("\n"); } } private static final String SP = " "; private static void toYaml(StringBuilder sb, List packages) { if (packages.size() > 0) { sb.append("packages:\n"); for (XmlPackage p : packages) { toYaml(sb, " ", p); } } for (XmlPackage p : packages) { toYaml(sb, " ", p); } } private static void toYaml(StringBuilder sb, String sp, XmlPackage p) { sb.append(sp).append("name: ").append(p.getName()).append("\n"); generateIncludeExclude(sb, sp, "includes", p.getInclude()); generateIncludeExclude(sb, sp, "excludes", p.getExclude()); } private static void generateIncludeExclude(StringBuilder sb, String sp, String key, List includes) { if (includes.size() > 0) { sb.append(sp).append(" ").append(key).append("\n"); for (String inc : includes) { sb.append(sp).append(" ").append(inc); } } } private static void mapToYaml(Map map, StringBuilder out) { if (map.size() > 0) { out.append("{ "); boolean first = true; for (Map.Entry e : map.entrySet()) { if (! first) out.append(", "); first = false; out.append(e.getKey() + ": " + e.getValue()); } out.append(" }\n"); } } private static void toYaml(StringBuilder sb, String key, String sp, Map parameters) { if (parameters.size() > 0) { sb.append(sp).append(key).append(": "); mapToYaml(parameters, sb); } } public static void main(String[] args) throws FileNotFoundException, ParserConfigurationException, SAXException, IOException { Collection s = new Parser(args[0]).parse(); System.out.println(s.iterator().next().toXml()); } } testng-testng-6.9.5/src/main/java/org/testng/internal/XmlMethodSelector.java0000755000175000017500000002753612551235562026501 0ustar eugeneeugenepackage org.testng.internal; import java.lang.reflect.Method; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import org.testng.IMethodSelector; import org.testng.IMethodSelectorContext; import org.testng.ITestNGMethod; import org.testng.TestNGException; import org.testng.collections.ListMultiMap; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; /** * This class is the default method selector used by TestNG to determine * which methods need to be included and excluded based on the specification * given in testng.xml. * * Created on Sep 30, 2005 * @author cbeust */ public class XmlMethodSelector implements IMethodSelector { private static final long serialVersionUID = -9030548178025605629L; // Groups included and excluded for this run private Map m_includedGroups = Maps.newHashMap(); private Map m_excludedGroups = Maps.newHashMap(); private List m_classes = null; // The BeanShell expression for this test, if any private String m_expression = null; // List of methods included implicitly private ListMultiMap m_includedMethods = Maps.newListMultiMap(); private IBsh m_bsh = Dynamic.hasBsh() ? new Bsh() : new BshMock(); @Override public boolean includeMethod(IMethodSelectorContext context, ITestNGMethod tm, boolean isTestMethod) { // ppp("XML METHOD SELECTOR " + tm + " " + m_isInitialized); if (! m_isInitialized) { m_isInitialized = true; init(context); } boolean result = false; if (null != m_expression) { return m_bsh.includeMethodFromExpression(m_expression, tm); } else { result = includeMethodFromIncludeExclude(tm, isTestMethod); } return result; } private boolean includeMethodFromIncludeExclude(ITestNGMethod tm, boolean isTestMethod) { boolean result = false; Method m = tm.getMethod(); String[] groups = tm.getGroups(); Map includedGroups = m_includedGroups; Map excludedGroups = m_excludedGroups; List includeList = m_includedMethods.get(MethodHelper.calculateMethodCanonicalName(tm)); // // No groups were specified: // if (includedGroups.size() == 0 && excludedGroups.size() == 0 && ! hasIncludedMethods() && ! hasExcludedMethods()) // // If we don't include or exclude any methods, method is in // { result = true; } // // If it's a configuration method and no groups were requested, we want it in // else if (includedGroups.size() == 0 && excludedGroups.size() == 0 && ! isTestMethod) { result = true; } // // Is this method included implicitly? // else if (includeList != null) { result = true; } // // Include or Exclude groups were specified: // else { // // Only add this method if it belongs to an included group and not // to an excluded group // { boolean isIncludedInGroups = isIncluded(groups, m_includedGroups.values()); boolean isExcludedInGroups = isExcluded(groups, m_excludedGroups.values()); // // Calculate the run methods by groups first // if (isIncludedInGroups && !isExcludedInGroups) { result = true; } else if (isExcludedInGroups) { result = false; } } if(isTestMethod) { // // Now filter by method name // Method method = tm.getMethod(); Class methodClass = method.getDeclaringClass(); String fullMethodName = methodClass.getName() + "." + method.getName(); String[] fullyQualifiedMethodName = new String[] { fullMethodName }; // // Iterate through all the classes so we can gather all the included and // excluded methods // for (XmlClass xmlClass : m_classes) { // Only consider included/excluded methods that belong to the same class // we are looking at Class cls = xmlClass.getSupportClass(); if(!assignable(methodClass, cls)) { continue; } List includedMethods = createQualifiedMethodNames(xmlClass, toStringList(xmlClass.getIncludedMethods())); boolean isIncludedInMethods = isIncluded(fullyQualifiedMethodName, includedMethods); List excludedMethods = createQualifiedMethodNames(xmlClass, xmlClass.getExcludedMethods()); boolean isExcludedInMethods = isExcluded(fullyQualifiedMethodName, excludedMethods); if (result) { // If we're about to include this method by group, make sure // it's included by method and not excluded by method result = isIncludedInMethods && ! isExcludedInMethods; } // otherwise it's already excluded and nothing will bring it back, // since exclusions preempt inclusions } } } Package pkg = m.getDeclaringClass().getPackage(); String methodName = pkg != null ? pkg.getName() + "." + m.getName() : m.getName(); logInclusion(result ? "Including" : "Excluding", "method", methodName + "()"); return result; } @SuppressWarnings({"unchecked"}) private boolean assignable(Class sourceClass, Class targetClass) { return sourceClass.isAssignableFrom(targetClass) || targetClass.isAssignableFrom(sourceClass); } private Map m_logged = Maps.newHashMap(); private void logInclusion(String including, String type, String name) { if (! m_logged.containsKey(name)) { log(4, including + " " + type + " " + name); m_logged.put(name, name); } } private boolean hasIncludedMethods() { for (XmlClass xmlClass : m_classes) { if (xmlClass.getIncludedMethods().size() > 0) { return true; } } return false; } private boolean hasExcludedMethods() { for (XmlClass xmlClass : m_classes) { if (xmlClass.getExcludedMethods().size() > 0) { return true; } } return false; } private List toStringList(List methods) { List result = Lists.newArrayList(); for (XmlInclude m : methods) { result.add(m.getName()); } return result; } private List createQualifiedMethodNames(XmlClass xmlClass, List methods) { List vResult = Lists.newArrayList(); Class cls = xmlClass.getSupportClass(); while (null != cls) { for (String im : methods) { String methodName = im; Method[] allMethods = cls.getDeclaredMethods(); Pattern pattern = Pattern.compile(methodName); for (Method m : allMethods) { if (pattern.matcher(m.getName()).matches()) { vResult.add(makeMethodName(cls.getName(), m.getName())); } } } cls = cls.getSuperclass(); } return vResult; } private String makeMethodName(String className, String methodName) { return className + "." + methodName; } private void checkMethod(Class c, String methodName) { Pattern p = Pattern.compile(methodName); for (Method m : c.getMethods()) { if (p.matcher(m.getName()).matches()) { return; } } Utils.log("Warning", 2, "The regular expression \"" + methodName + "\" didn't match any" + " method in class " + c.getName()); } public void setXmlClasses(List classes) { m_classes = classes; for (XmlClass c : classes) { for (XmlInclude m : c.getIncludedMethods()) { checkMethod(c.getSupportClass(), m.getName()); String methodName = makeMethodName(c.getName(), m.getName()); m_includedMethods.put(methodName, m); } } } /** * @return Returns the excludedGroups. */ public Map getExcludedGroups() { return m_excludedGroups; } /** * @return Returns the includedGroups. */ public Map getIncludedGroups() { return m_includedGroups; } /** * @param excludedGroups The excludedGroups to set. */ public void setExcludedGroups(Map excludedGroups) { m_excludedGroups = excludedGroups; } /** * @param includedGroups The includedGroups to set. */ public void setIncludedGroups(Map includedGroups) { m_includedGroups = includedGroups; } private static boolean isIncluded(String[] groups, Collection includedGroups) { if (includedGroups.size() == 0) { return true; } else { return isMemberOf(groups, includedGroups); } } private static boolean isExcluded(String[] groups, Collection excludedGroups) { return isMemberOf(groups, excludedGroups); } /** * * @param groups Array of groups on the method * @param list Map of regexps of groups to be run */ private static boolean isMemberOf(String[] groups, Collection list) { for (String group : groups) { for (Object o : list) { String regexpStr = o.toString(); boolean match = Pattern.matches(regexpStr, group); if (match) { return true; } } } return false; } private static void log(int level, String s) { Utils.log("XmlMethodSelector", level, s); } private static void ppp(String s) { System.out.println("[XmlMethodSelector] " + s); } public void setExpression(String expression) { m_expression = expression; } private boolean m_isInitialized = false; private List m_testMethods = null; @Override public void setTestMethods(List testMethods) { // Caution: this variable is initialized with an empty list first and then modified // externally by the caller (TestRunner#fixMethodWithClass). Ugly. m_testMethods = testMethods; } private void init(IMethodSelectorContext context) { String[] groups = m_includedGroups.keySet().toArray(new String[m_includedGroups.size()]); Set groupClosure = new HashSet<>(); Set methodClosure = new HashSet<>(); List includedMethods = Lists.newArrayList(); for (ITestNGMethod m : m_testMethods) { if (includeMethod(context, m, true)) { includedMethods.add(m); } } MethodGroupsHelper.findGroupTransitiveClosure(this, includedMethods, m_testMethods, groups, groupClosure, methodClosure); // If we are asked to include or exclude specific groups, calculate // the transitive closure of all the included groups. If no include groups // were specified, don't do anything. // Any group that is part of the transitive closure but not part of // m_includedGroups is being added implicitly by TestNG so that if someone // includes a group z that depends on a, b and c, they don't need to // include a, b and c explicitly. if (m_includedGroups.size() > 0) { // Make the transitive closure our new included groups for (String g : groupClosure) { log(4, "Including group " + (m_includedGroups.containsKey(g) ? ": " : "(implicitly): ") + g); m_includedGroups.put(g, g); } // Make the transitive closure our new included methods for (ITestNGMethod m : methodClosure) { String methodName = m.getMethod().getDeclaringClass().getName() + "." + m.getMethodName(); // m_includedMethods.add(methodName); List includeList = m_includedMethods.get(methodName); XmlInclude xi = new XmlInclude(methodName); // TODO: set the XmlClass on this xi or we won't get inheritance of parameters m_includedMethods.put(methodName, xi); logInclusion("Including", "method ", methodName); } } } } testng-testng-6.9.5/src/main/java/org/testng/internal/Utils.java0000644000175000017500000005751712551235562024176 0ustar eugeneeugenepackage org.testng.internal; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.StringReader; import java.io.StringWriter; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import java.util.logging.FileHandler; import java.util.logging.Level; import java.util.logging.Logger; import org.testng.ITestNGMethod; import org.testng.TestNG; import org.testng.TestNGException; import org.testng.TestRunner; import org.testng.annotations.IConfigurationAnnotation; import org.testng.annotations.ITestAnnotation; import org.testng.collections.Lists; import org.testng.internal.annotations.AnnotationHelper; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.log.TextFormatter; import org.testng.reporters.XMLStringBuffer; import org.testng.xml.XmlClass; /** * Helper methods to parse annotations. * * @author Cedric Beust, Apr 26, 2004 */ public final class Utils { private static final String LINE_SEP = System.getProperty("line.separator"); public static final char[] SPECIAL_CHARACTERS = {'*','/','\\','?','%',':',';','<','>','&','~','|'}; public static final char CHAR_REPLACEMENT = '_'; public static final char UNICODE_REPLACEMENT = 0xFFFD; /** * Hide constructor for utility class. */ private Utils() { // Hide constructor } /** * Splits the given String s into tokens where the separator is * either the space character or the comma character. For example, * if s is "a,b, c" this method returns {"a", "b", "c"} * * @param s the string to split * @return the split token */ public static String[] stringToArray(String s) { // TODO CQ would s.split() be a better way of doing this? StringTokenizer st = new StringTokenizer(s, " ,"); String[] result = new String[st.countTokens()]; for (int i = 0; i < result.length; i++) { result[i] = st.nextToken(); } return result; } public static XmlClass[] classesToXmlClasses(Class[] classes) { List result = Lists.newArrayList(); for (Class cls : classes) { result.add(new XmlClass(cls, true /* load classes */)); } return result.toArray(new XmlClass[classes.length]); } public static String[] parseMultiLine(String line) { List vResult = Lists.newArrayList(); if (isStringNotBlank(line)) { StringTokenizer st = new StringTokenizer(line, " "); while (st.hasMoreTokens()) { vResult.add(st.nextToken()); } // Bug in split when passed " " : returns one too many result // result = line.split(" "); } return vResult.toArray(new String[vResult.size()]); } public static void writeUtf8File(String outputDir, String fileName, XMLStringBuffer xsb, String prefix) { try { final File file = new File(outputDir, fileName); if (!file.exists()) { file.createNewFile(); } final OutputStreamWriter w = new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); if (prefix != null) { w.append(prefix); } xsb.toWriter(w); w.close(); } catch(IOException ex) { ex.printStackTrace(); } } /** * Writes the content of the sb string to the file named filename in outDir encoding the output as UTF-8. * If outDir does not exist, it is created. * * @param outputDir the output directory (may not exist). If null then current directory is used. * @param fileName the filename * @param sb the file content */ public static void writeUtf8File(@Nullable String outputDir, String fileName, String sb) { final String outDirPath= outputDir != null ? outputDir : ""; final File outDir= new File(outDirPath); writeFile(outDir, fileName, escapeUnicode(sb), "UTF-8", false /* don't append */); } /** * Writes the content of the sb string to the file named filename in outDir. If * outDir does not exist, it is created. * * @param outputDir the output directory (may not exist). If null then current directory is used. * @param fileName the filename * @param sb the file content */ public static void writeFile(@Nullable String outputDir, String fileName, String sb) { final String outDirPath= outputDir != null ? outputDir : ""; final File outDir= new File(outDirPath); writeFile(outDir, fileName, sb, null, false /* don't append */); } /** * Appends contents of the string to the specified file. If output directory/file don't * exist, they are created. * @param outputDir output directory. If null, then current directory is used * @param fileName file name * @param sb string to be appended to file */ public static void appendToFile(@Nullable String outputDir, String fileName, String sb) { String outDirPath= outputDir != null ? outputDir : ""; File outDir= new File(outDirPath); writeFile(outDir, fileName, sb, null, true /* append */); } /** * Writes the content of the sb string to the file named filename in outDir. If * outDir does not exist, it is created. * * @param outDir the output directory (may not exist). If null then current directory is used. * @param fileName the filename * @param sb the file content */ private static void writeFile(@Nullable File outDir, String fileName, String sb, @Nullable String encoding, boolean append) { try { if (outDir == null) { outDir = new File("").getAbsoluteFile(); } if (!outDir.exists()) { outDir.mkdirs(); } fileName = replaceSpecialCharacters(fileName); File outputFile = new File(outDir, fileName); if (!append) { outputFile.delete(); outputFile.createNewFile(); } writeFile(outputFile, sb, encoding, append); } catch (IOException e) { if (TestRunner.getVerbose() > 1) { e.printStackTrace(); } else { log("[Utils]", 1, e.getMessage()); } } } private static void writeFile(File outputFile, String sb, @Nullable String encoding, boolean append) { BufferedWriter fw = null; try { if (!outputFile.exists()) { outputFile.createNewFile(); } OutputStreamWriter osw= null; if (null != encoding) { osw = new OutputStreamWriter(new FileOutputStream(outputFile, append), encoding); } else { osw = new OutputStreamWriter(new FileOutputStream(outputFile, append)); } fw = new BufferedWriter(osw); fw.write(sb); Utils.log("", 3, "Creating " + outputFile.getAbsolutePath()); } catch(IOException ex) { if (TestRunner.getVerbose() > 1) { System.err.println("ERROR WHILE WRITING TO " + outputFile); ex.printStackTrace(); } else { log("[Utils]", 1, "Error while writing to " + outputFile + ": " + ex.getMessage()); } } finally { try { if (fw != null) { fw.close(); } } catch (IOException e) { ; // ignore } } } private static void ppp(String s) { Utils.log("Utils", 0, s); } /** * @param result */ public static void dumpMap(Map result) { System.out.println("vvvvv"); for (Map.Entry entry : result.entrySet()) { System.out.println(entry.getKey() + " => " + entry.getValue()); } System.out.println("^^^^^"); } /** * @param allMethods */ public static void dumpMethods(List allMethods) { ppp("======== METHODS:"); for (ITestNGMethod tm : allMethods) { ppp(" " + tm); } } /** * @return The list of dependent groups for this method, including the * class groups */ public static String[] dependentGroupsForThisMethodForTest(Method m, IAnnotationFinder finder) { List vResult = Lists.newArrayList(); Class cls = m.getDeclaringClass(); // Collect groups on the class ITestAnnotation tc = AnnotationHelper.findTest(finder, cls); if (null != tc) { for (String group : tc.getDependsOnGroups()) { vResult.add(group); } } // Collect groups on the method ITestAnnotation tm = AnnotationHelper.findTest(finder, m); if (null != tm) { String[] groups = tm.getDependsOnGroups(); // ppp("Method:" + m + " #Groups:" + groups.length); for (String group : groups) { vResult.add(group); } } return vResult.toArray(new String[vResult.size()]); } /** * @return The list of groups this method belongs to, including the * class groups */ public static String[] groupsForThisMethodForTest(Method m, IAnnotationFinder finder) { List vResult = Lists.newArrayList(); Class cls = m.getDeclaringClass(); // Collect groups on the class ITestAnnotation tc = AnnotationHelper.findTest(finder, cls); if (null != tc) { for (String group : tc.getGroups()) { vResult.add(group); } } // Collect groups on the method ITestAnnotation tm = AnnotationHelper.findTest(finder, m); if (null != tm) { String[] groups = tm.getGroups(); // ppp("Method:" + m + " #Groups:" + groups.length); for (String group : groups) { vResult.add(group); } } return vResult.toArray(new String[vResult.size()]); } /** * @return The list of groups this method belongs to, including the * class groups */ public static String[] groupsForThisMethodForConfiguration(Method m, IAnnotationFinder finder) { String[] result = {}; // Collect groups on the method ITestAnnotation tm = AnnotationHelper.findTest(finder, m); if (null != tm) { result = tm.getGroups(); } return result; } /** * @return The list of groups this method depends on, including the * class groups */ public static String[] dependentGroupsForThisMethodForConfiguration(Method m, IAnnotationFinder finder) { String[] result = {}; // Collect groups on the method IConfigurationAnnotation tm = AnnotationHelper.findConfiguration(finder, m); if (null != tm) { result = tm.getDependsOnGroups(); } return result; } public static void log(String msg) { log("Utils", 2, msg); } /** * Logs the the message to System.out if level is greater than * or equal to TestRunner.getVerbose(). The message is logged as: *
   *     "[cls] msg"
   * 
* * @param cls the class name to prefix the log message. * @param level the logging level of the message. * @param msg the message to log to System.out. */ public static void log(String cls, int level, String msg) { // Why this coupling on a static member of TestRunner.getVerbose()? if (TestRunner.getVerbose() >= level) { if (cls.length() > 0) { System.out.println("[" + cls + "] " + msg); } else { System.out.println(msg); } } } public static void error(String errorMessage) { System.err.println("[Error] " + errorMessage); } /** * @return The number of methods invoked, taking into account the number * of instances. */ // public static int calculateInvokedMethodCount(IResultMap map) { // return calculateInvokedMethodCount( // (ITestNGMethod[]) map.getAllMethods().toArray(new ITestNGMethod[map.size()])); // } public static int calculateInvokedMethodCount(ITestNGMethod[] methods) { return methods.length; // int result = 0; // // for (ITestNGMethod method : methods) { // int instanceCount = method.getInvocationCount(); // result += instanceCount; // } // // return result; } // public static int calculateInvokedMethodCount(Map methods) { // return calculateInvokedMethodCount(methods.keySet().toArray(new ITestNGMethod[methods.values() // .size()])); // } /** * Tokenize the string using the separator. */ public static String[] split(String string, String sep) { if ((string == null) || (string.length() == 0)) { return new String[0]; } // TODO How different is this from: // return string.split(sep); int start = 0; int idx = string.indexOf(sep, start); int len = sep.length(); List strings = Lists.newArrayList(); while (idx != -1) { strings.add(string.substring(start, idx).trim()); start = idx + len; idx = string.indexOf(sep, start); } strings.add(string.substring(start).trim()); return strings.toArray(new String[strings.size()]); } public static void initLogger(Logger logger, String outputLogPath) { try { logger.setUseParentHandlers(false); FileHandler fh = new FileHandler(outputLogPath); fh.setFormatter(new TextFormatter()); fh.setLevel(Level.INFO); logger.addHandler(fh); } catch (SecurityException | IOException se) { se.printStackTrace(); } } public static void logInvocation(String reason, Method thisMethod, Object[] parameters) { String clsName = thisMethod.getDeclaringClass().getName(); int n = clsName.lastIndexOf("."); if (n >= 0) { clsName = clsName.substring(n + 1); } String methodName = clsName + '.' + thisMethod.getName(); if (TestRunner.getVerbose() >= 2) { StringBuffer paramString = new StringBuffer(); if (parameters != null) { for (Object p : parameters) { paramString.append(p.toString()).append(' '); } } log("", 2, "Invoking " + reason + methodName + '(' + paramString + ')'); } } public static void writeResourceToFile(File file, String resourceName, Class clasz) throws IOException { InputStream inputStream = clasz.getResourceAsStream("/" + resourceName); if (inputStream == null) { System.err.println("Couldn't find resource on the class path: " + resourceName); // throw new IllegalArgumentException("Resource does not exist: " + resourceName); } else { try { FileOutputStream outputStream = new FileOutputStream(file); try { int nread; byte[] buffer = new byte[4096]; while (0 < (nread = inputStream.read(buffer))) { outputStream.write(buffer, 0, nread); } } finally { outputStream.close(); } } finally { inputStream.close(); } } } public static String defaultIfStringEmpty(String s, String defaultValue) { return isStringEmpty(s) ? defaultValue : s; } public static boolean isStringBlank(String s) { return s == null || "".equals(s.trim()); } public static boolean isStringEmpty(String s) { return s == null || "".equals(s); } public static boolean isStringNotBlank(String s) { return !isStringBlank(s); } public static boolean isStringNotEmpty(String s) { return !isStringEmpty(s); } /** * @return an array of two strings: the short stack trace and the long stack trace. */ public static String[] stackTrace(Throwable t, boolean toHtml) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); t.printStackTrace(pw); pw.flush(); String fullStackTrace = sw.getBuffer().toString(); String shortStackTrace; if (Boolean.getBoolean(TestNG.SHOW_TESTNG_STACK_FRAMES) || TestRunner.getVerbose() >= 2) { shortStackTrace = fullStackTrace; } else { shortStackTrace = filterTrace(sw.getBuffer().toString()); } if (toHtml) { shortStackTrace = escapeHtml(shortStackTrace); fullStackTrace = escapeHtml(fullStackTrace); } return new String[] { shortStackTrace, fullStackTrace }; } private static final Map ESCAPES = new HashMap() { private static final long serialVersionUID = 1285607660247157523L; { put('<', "<"); put('>', ">"); put('\'', "'"); put('"', """); put('&', "&"); }}; public static String escapeHtml(String s) { if (s == null) { return null; } StringBuilder result = new StringBuilder(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); String nc = ESCAPES.get(c); if (nc != null) { result.append(nc); } else { result.append(c); } } return result.toString(); } public static String escapeUnicode(String s) { if (s == null) { return null; } StringBuilder result = new StringBuilder(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); char ca = (Character.isDefined(c)) ? c: UNICODE_REPLACEMENT; result.append(ca); } return result.toString(); } private static String filterTrace(String trace) { StringReader stringReader = new StringReader(trace); BufferedReader bufferedReader = new BufferedReader(stringReader); StringBuffer buf = new StringBuffer(); try { // first line contains the thrown exception String line = bufferedReader.readLine(); if(line == null) { return ""; } buf.append(line).append(LINE_SEP); // // the stack frames of the trace // String[] excludedStrings = new String[] { "org.testng", "reflect", "org.apache.maven.surefire" }; int excludedCount = 0; while((line = bufferedReader.readLine()) != null) { boolean isExcluded = false; for (String excluded : excludedStrings) { if(line.contains(excluded)) { isExcluded = true; excludedCount++; break; } } if (! isExcluded) { buf.append(line).append(LINE_SEP); } } if (excludedCount > 0) { buf.append("... Removed " + excludedCount + " stack frames"); } } catch(IOException ioex) { ; // do nothing } return buf.toString(); } public static String toString(Object object, Class objectClass) { if(null == object) { return "null"; } final String toString= object.toString(); if(isStringEmpty(toString)) { return "\"\""; } else if (String.class.equals(objectClass)) { return "\"" + toString + '\"'; } else { return toString; } } public static String detailedMethodName(ITestNGMethod method, boolean fqn) { StringBuffer buf= new StringBuffer(); if(method.isBeforeSuiteConfiguration()) { buf.append("@BeforeSuite "); } else if(method.isBeforeTestConfiguration()) { buf.append("@BeforeTest "); } else if(method.isBeforeClassConfiguration()) { buf.append("@BeforeClass "); } else if(method.isBeforeGroupsConfiguration()) { buf.append("@BeforeGroups "); } else if(method.isBeforeMethodConfiguration()) { buf.append("@BeforeMethod "); } else if(method.isAfterMethodConfiguration()) { buf.append("@AfterMethod "); } else if(method.isAfterGroupsConfiguration()) { buf.append("@AfterGroups "); } else if(method.isAfterClassConfiguration()) { buf.append("@AfterClass "); } else if(method.isAfterTestConfiguration()) { buf.append("@AfterTest "); } else if(method.isAfterSuiteConfiguration()) { buf.append("@AfterSuite "); } return buf.append(fqn ? method.toString() : method.getMethodName()).toString(); } public static String arrayToString(String[] strings) { StringBuffer result = new StringBuffer(""); if ((strings != null) && (strings.length > 0)) { for (int i = 0; i < strings.length; i++) { result.append(strings[i]); if (i < strings.length - 1) { result.append(", "); } } } return result.toString(); } /** * If the file name contains special characters like *,/,\ and so on, * exception will be thrown and report file will not be created.
* Special characters are platform specific and they are not same for * example on Windows and Macintosh. * is not allowed on Windows, but it is on Macintosh.
* In order to have the same behavior of testng on the all platforms, characters like * will * be replaced on all platforms whether they are causing the problem or not. * * @param fileName file name that could contain special characters. * @return fileName with special characters replaced * @author Borojevic */ public static String replaceSpecialCharacters(String fileName) { if (fileName == null || fileName.length() == 0) { return fileName; } for (char element : SPECIAL_CHARACTERS) { fileName = fileName.replace(element, CHAR_REPLACEMENT); } return fileName; } public static String join(List objects, String separator) { StringBuilder result = new StringBuilder(); for (int i = 0; i < objects.size(); i++) { if (i > 0) { result.append(separator); } result.append(objects.get(i).toString()); } return result.toString(); } public static void copyFile(File from, File to) { try{ InputStream in = new FileInputStream(from); //For Append the file. // OutputStream out = new FileOutputStream(f2,true); //For Overwrite the file. to.getParentFile().mkdirs(); OutputStream out = new FileOutputStream(to); byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0){ out.write(buf, 0, len); } in.close(); out.close(); } catch(IOException e){ e.printStackTrace(); } } /** * @return a temporary file with the given content. */ public static File createTempFile(String content) { try { // Create temp file. File result = File.createTempFile("testng-tmp", ""); // Delete temp file when program exits. result.deleteOnExit(); // Write to temp file BufferedWriter out = new BufferedWriter(new FileWriter(result)); out.write(content); out.close(); return result; } catch (IOException e) { throw new TestNGException(e); } } /** * Make sure that either we have an instance or if not, that the method is static */ public static void checkInstanceOrStatic(Object instance, Method method) { if (instance == null && ! Modifier.isStatic(method.getModifiers())) { throw new TestNGException("Can't invoke " + method + ": either make it static or add " + "a no-args constructor to your class"); } } /** * Returns the string representation of the specified object, transparently * handling null references and arrays. * * @param obj * the object * @return the string representation */ public static String toString(Object obj) { String result; if (obj != null) { if (obj instanceof boolean[]) { result = Arrays.toString((boolean[]) obj); } else if (obj instanceof byte[]) { result = Arrays.toString((byte[]) obj); } else if (obj instanceof char[]) { result = Arrays.toString((char[]) obj); } else if (obj instanceof double[]) { result = Arrays.toString((double[]) obj); } else if (obj instanceof float[]) { result = Arrays.toString((float[]) obj); } else if (obj instanceof int[]) { result = Arrays.toString((int[]) obj); } else if (obj instanceof long[]) { result = Arrays.toString((long[]) obj); } else if (obj instanceof Object[]) { result = Arrays.deepToString((Object[]) obj); } else if (obj instanceof short[]) { result = Arrays.toString((short[]) obj); } else { result = obj.toString(); } } else { result = "null"; } return result; } } testng-testng-6.9.5/src/main/java/org/testng/internal/TestResult.java0000644000175000017500000001602312551235562025177 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IAttributes; import org.testng.IClass; import org.testng.ITest; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.ITestResult; import org.testng.Reporter; import org.testng.collections.Objects; import java.util.List; import java.util.Set; /** * This class represents the result of a test. * * @author Cedric Beust, May 2, 2004 */ public class TestResult implements ITestResult { private static final long serialVersionUID = 6273017418233324556L; private IClass m_testClass = null; private ITestNGMethod m_method = null; private int m_status = -1; private Throwable m_throwable = null; private long m_startMillis = 0; private long m_endMillis = 0; private String m_name = null; private String m_host; transient private Object[] m_parameters = {}; transient private Object m_instance; private String m_instanceName; private ITestContext m_context; public TestResult() { } public TestResult(IClass testClass, Object instance, ITestNGMethod method, Throwable throwable, long start, long end, ITestContext context) { init(testClass, instance, method, throwable, start, end, context); } /** * * @param testClass * @param instance * @param method * @param throwable * @param start * @param end */ public void init (IClass testClass, Object instance, ITestNGMethod method, Throwable throwable, long start, long end, ITestContext context) { m_testClass = testClass; m_throwable = throwable; m_instanceName = m_testClass.getName(); if (null == m_throwable) { m_status = ITestResult.SUCCESS; } m_startMillis = start; m_endMillis = end; m_method = method; m_context = context; m_instance = instance; // Calculate the name: either the method name, ITest#getTestName or // toString() if it's been overridden. if (m_instance == null) { m_name = m_method.getMethodName(); } else { if (m_instance instanceof ITest) { m_name = ((ITest) m_instance).getTestName(); } else { String string = m_instance.toString(); // Only display toString() if it's been overridden by the user m_name = getMethod().getMethodName(); try { if (!Object.class.getMethod("toString") .equals(m_instance.getClass().getMethod("toString"))) { m_instanceName = string.startsWith("class ") ? string.substring("class ".length()) : string; m_name = m_name + " on " + m_instanceName; } } catch(NoSuchMethodException ignore) { // ignore } } } } private static void ppp(String s) { System.out.println("[TestResult] " + s); } @Override public void setEndMillis(long millis) { m_endMillis = millis; } /** * If this result's related instance implements ITest, returns its test name, * otherwise returns null. */ @Override public String getTestName() { if (m_instance instanceof ITest) { return ((ITest) m_instance).getTestName(); } return null; } @Override public String getName() { return m_name; } /** * @return Returns the method. */ @Override public ITestNGMethod getMethod() { return m_method; } /** * @param method The method to set. */ public void setMethod(ITestNGMethod method) { m_method = method; } /** * @return Returns the status. */ @Override public int getStatus() { return m_status; } /** * @param status The status to set. */ @Override public void setStatus(int status) { m_status = status; } @Override public boolean isSuccess() { return ITestResult.SUCCESS == m_status; } /** * @return Returns the testClass. */ @Override public IClass getTestClass() { return m_testClass; } /** * @param testClass The testClass to set. */ public void setTestClass(IClass testClass) { m_testClass = testClass; } /** * @return Returns the throwable. */ @Override public Throwable getThrowable() { return m_throwable; } /** * @param throwable The throwable to set. */ @Override public void setThrowable(Throwable throwable) { m_throwable = throwable; } /** * @return Returns the endMillis. */ @Override public long getEndMillis() { return m_endMillis; } /** * @return Returns the startMillis. */ @Override public long getStartMillis() { return m_startMillis; } // public List getOutput() { // return m_output; // } @Override public String toString() { List output = Reporter.getOutput(this); String result = Objects.toStringHelper(getClass()) .omitNulls() .omitEmptyStrings() .add("name", getName()) .add("status", toString(m_status)) .add("method", m_method) .add("output", output != null && output.size() > 0 ? output.get(0) : null) .toString(); return result; } private String toString(int status) { switch(status) { case SUCCESS: return "SUCCESS"; case FAILURE: return "FAILURE"; case SKIP: return "SKIP"; case SUCCESS_PERCENTAGE_FAILURE: return "SUCCESS WITHIN PERCENTAGE"; case STARTED: return "STARTED"; default: throw new RuntimeException(); } } @Override public String getHost() { return m_host; } public void setHost(String host) { m_host = host; } @Override public Object[] getParameters() { return m_parameters; } @Override public void setParameters(Object[] parameters) { m_parameters = parameters; } @Override public Object getInstance() { return m_instance; } private IAttributes m_attributes = new Attributes(); @Override public Object getAttribute(String name) { return m_attributes.getAttribute(name); } @Override public void setAttribute(String name, Object value) { m_attributes.setAttribute(name, value); } @Override public Set getAttributeNames() { return m_attributes.getAttributeNames(); } @Override public Object removeAttribute(String name) { return m_attributes.removeAttribute(name); } @Override public ITestContext getTestContext() { return m_context; } public void setContext(ITestContext context) { m_context = context; } @Override public int compareTo(ITestResult comparison) { if( getStartMillis() > comparison.getStartMillis() ) { return 1; } else if( getStartMillis() < comparison.getStartMillis()) { return -1; } else { return 0; } } @Override public String getInstanceName() { return m_instanceName; } } testng-testng-6.9.5/src/main/java/org/testng/internal/TestNGProperty.java0000755000175000017500000000206512551235562025776 0ustar eugeneeugenepackage org.testng.internal; /** * Describes a property * * @author Cedric Beust, May 2, 2004 * */ public class TestNGProperty { private String m_commandLineName = null; private String m_name = null; private String m_documentation = null; private String m_default = null; public TestNGProperty(String clName, String name, String doc, String def) { init(clName, name, doc, def); } public TestNGProperty(String name, String doc, String def) { init(name, name, doc, def); } private void init(String clName, String name, String doc, String def) { m_commandLineName = clName; m_name = name; m_documentation = doc; m_default = def; } /** * @return Returns the default. */ public String getDefault() { return m_default; } /** * @return Returns the documentation. */ public String getDocumentation() { return m_documentation; } /** * @return Returns the name. */ public String getName() { return m_name; } public String getCommandLineName() { return m_commandLineName; } } testng-testng-6.9.5/src/main/java/org/testng/internal/TestNGMethodFinder.java0000755000175000017500000002034412551235562026522 0ustar eugeneeugenepackage 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; import org.testng.annotations.ITestAnnotation; import org.testng.collections.Lists; import org.testng.internal.annotations.AnnotationHelper; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.xml.XmlTest; /** * The default strategy for finding test methods: look up * annotations @Test in front of methods. * * @author Cedric Beust, May 3, 2004 * @author Alexandru Popescu */ public class TestNGMethodFinder implements ITestMethodFinder { private static final int BEFORE_SUITE = 1; private static final int AFTER_SUITE = 2; private static final int BEFORE_TEST = 3; private static final int AFTER_TEST = 4; private static final int BEFORE_CLASS = 5; private static final int AFTER_CLASS = 6; private static final int BEFORE_TEST_METHOD = 7; private static final int AFTER_TEST_METHOD = 8; private static final int BEFORE_GROUPS = 9; private static final int AFTER_GROUPS = 10; private RunInfo m_runInfo = null; private IAnnotationFinder m_annotationFinder = null; public TestNGMethodFinder(RunInfo runInfo, IAnnotationFinder annotationFinder) { m_runInfo = runInfo; m_annotationFinder = annotationFinder; } @Override public ITestNGMethod[] getTestMethods(Class clazz, XmlTest xmlTest) { return AnnotationHelper.findMethodsWithAnnotation( clazz, ITestAnnotation.class, m_annotationFinder, xmlTest); } @Override public ITestNGMethod[] getBeforeClassMethods(Class cls) { return findConfiguration(cls, BEFORE_CLASS); } @Override public ITestNGMethod[] getAfterClassMethods(Class cls) { return findConfiguration(cls, AFTER_CLASS); } @Override public ITestNGMethod[] getBeforeTestMethods(Class cls) { return findConfiguration(cls, BEFORE_TEST_METHOD); } @Override public ITestNGMethod[] getAfterTestMethods(Class cls) { return findConfiguration(cls, AFTER_TEST_METHOD); } @Override public ITestNGMethod[] getBeforeSuiteMethods(Class cls) { return findConfiguration(cls, BEFORE_SUITE); } @Override public ITestNGMethod[] getAfterSuiteMethods(Class cls) { return findConfiguration(cls, AFTER_SUITE); } @Override public ITestNGMethod[] getBeforeTestConfigurationMethods(Class clazz) { return findConfiguration(clazz, BEFORE_TEST); } @Override public ITestNGMethod[] getAfterTestConfigurationMethods(Class clazz) { return findConfiguration(clazz, AFTER_TEST); } @Override public ITestNGMethod[] getBeforeGroupsConfigurationMethods(Class clazz) { return findConfiguration(clazz, BEFORE_GROUPS); } @Override public ITestNGMethod[] getAfterGroupsConfigurationMethods(Class clazz) { return findConfiguration(clazz, AFTER_GROUPS); } private ITestNGMethod[] findConfiguration(final Class clazz, final int configurationType) { List vResult = Lists.newArrayList(); Set methods = ClassHelper.getAvailableMethods(clazz); for (Method m : methods) { IConfigurationAnnotation configuration = AnnotationHelper.findConfiguration(m_annotationFinder, m); if (null == configuration) { continue; } boolean create = false; boolean isBeforeSuite = false; boolean isAfterSuite = false; boolean isBeforeTest = false; boolean isAfterTest = false; boolean isBeforeClass = false; boolean isAfterClass = false; boolean isBeforeTestMethod = false; boolean isAfterTestMethod = false; String[] beforeGroups = null; String[] afterGroups = null; switch(configurationType) { case BEFORE_SUITE: create = configuration.getBeforeSuite(); isBeforeSuite = true; break; case AFTER_SUITE: create = configuration.getAfterSuite(); isAfterSuite = true; break; case BEFORE_TEST: create = configuration.getBeforeTest(); isBeforeTest = true; break; case AFTER_TEST: create = configuration.getAfterTest(); isAfterTest = true; break; case BEFORE_CLASS: create = configuration.getBeforeTestClass(); isBeforeClass = true; break; case AFTER_CLASS: create = configuration.getAfterTestClass(); isAfterClass = true; break; case BEFORE_TEST_METHOD: create = configuration.getBeforeTestMethod(); isBeforeTestMethod = true; break; case AFTER_TEST_METHOD: create = configuration.getAfterTestMethod(); isAfterTestMethod = true; break; case BEFORE_GROUPS: beforeGroups = configuration.getBeforeGroups(); create = beforeGroups.length > 0; isBeforeTestMethod = true; break; case AFTER_GROUPS: afterGroups = configuration.getAfterGroups(); create = afterGroups.length > 0; isBeforeTestMethod = true; break; } if(create) { addConfigurationMethod(clazz, vResult, m, isBeforeSuite, isAfterSuite, isBeforeTest, isAfterTest, isBeforeClass, isAfterClass, isBeforeTestMethod, isAfterTestMethod, beforeGroups, afterGroups, null); /* @@@ */ } } List excludedMethods = Lists.newArrayList(); boolean unique = configurationType == BEFORE_SUITE || configurationType == AFTER_SUITE; ITestNGMethod[] tmResult = MethodHelper.collectAndOrderMethods(Lists.newArrayList(vResult), false /* forTests */, m_runInfo, m_annotationFinder, unique, excludedMethods); return tmResult; } private void addConfigurationMethod(Class clazz, List results, Method method, boolean isBeforeSuite, boolean isAfterSuite, boolean isBeforeTest, boolean isAfterTest, boolean isBeforeClass, boolean isAfterClass, boolean isBeforeTestMethod, boolean isAfterTestMethod, String[] beforeGroups, String[] afterGroups, Object instance) { if(method.getDeclaringClass().isAssignableFrom(clazz)) { ITestNGMethod confMethod = new ConfigurationMethod(new ConstructorOrMethod(method), m_annotationFinder, isBeforeSuite, isAfterSuite, isBeforeTest, isAfterTest, isBeforeClass, isAfterClass, isBeforeTestMethod, isAfterTestMethod, beforeGroups, afterGroups, instance); results.add(confMethod); } } } testng-testng-6.9.5/src/main/java/org/testng/internal/TestNGMethod.java0000755000175000017500000001567712551235562025407 0ustar eugeneeugenepackage org.testng.internal; import org.testng.ITestClass; import org.testng.ITestNGMethod; import org.testng.annotations.ITestAnnotation; import org.testng.internal.annotations.AnnotationHelper; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlTest; import java.io.Serializable; import java.lang.reflect.Method; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * This class represents a test method. * * @author Cedric Beust, May 3, 2004 * @author Alexandru Popescu */ 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; /** * Constructs a TestNGMethod * * @param method * @param finder */ public TestNGMethod(Method method, IAnnotationFinder finder, XmlTest xmlTest, Object instance) { this(method, finder, true, xmlTest, instance); } private TestNGMethod(Method method, IAnnotationFinder finder, boolean initialize, XmlTest xmlTest, Object instance) { super(method.getName(), method, finder, instance); if(initialize) { init(xmlTest); } } /** * {@inheritDoc} */ @Override public int getInvocationCount() { return m_invocationCount; } /** * {@inheritDoc} */ @Override public int getTotalInvocationCount() { return m_totalInvocationCount; } /** * {@inheritDoc} */ @Override public int getSuccessPercentage() { return m_successPercentage; } /** * {@inheritDoc} */ @Override public boolean isTest() { return true; } private void ppp(String s) { System.out.println("[TestNGMethod] " + s); } private void init(XmlTest xmlTest) { setXmlTest(xmlTest); setInvocationNumbers(xmlTest.getInvocationNumbers( m_method.getDeclaringClass().getName() + "." + m_method.getName())); { ITestAnnotation testAnnotation = AnnotationHelper.findTest(getAnnotationFinder(), m_method.getMethod()); if (testAnnotation == null) { // Try on the class testAnnotation = AnnotationHelper.findTest(getAnnotationFinder(), m_method.getDeclaringClass()); } if (null != testAnnotation) { setTimeOut(testAnnotation.getTimeOut()); m_successPercentage = testAnnotation.getSuccessPercentage(); setInvocationCount(testAnnotation.getInvocationCount()); m_totalInvocationCount = testAnnotation.getInvocationCount(); setThreadPoolSize(testAnnotation.getThreadPoolSize()); setAlwaysRun(testAnnotation.getAlwaysRun()); setDescription(findDescription(testAnnotation, xmlTest)); setEnabled(testAnnotation.getEnabled()); setRetryAnalyzer(testAnnotation.getRetryAnalyzer()); setSkipFailedInvocations(testAnnotation.skipFailedInvocations()); setInvocationTimeOut(testAnnotation.invocationTimeOut()); setIgnoreMissingDependencies(testAnnotation.ignoreMissingDependencies()); setPriority(testAnnotation.getPriority()); } // Groups { initGroups(ITestAnnotation.class); } } } private String findDescription(ITestAnnotation testAnnotation, XmlTest xmlTest) { String result = testAnnotation.getDescription(); if (result == null) { List classes = xmlTest.getXmlClasses(); for (XmlClass c : classes) { if (c.getName().equals(m_method.getMethod().getDeclaringClass().getName())) { for (XmlInclude include : c.getIncludedMethods()) { if (include.getName().equals(m_method.getName())) { result = include.getDescription(); if (result != null) { break; } } } } } } return result; } /** * {@inheritDoc} */ @Override public int getThreadPoolSize() { return m_threadPoolSize; } /** * Sets the number of threads on which this method should be invoked. */ @Override public void setThreadPoolSize(int threadPoolSize) { m_threadPoolSize = threadPoolSize; } /** * Sets the number of invocations for this method. */ @Override public void setInvocationCount(int counter) { m_invocationCount= counter; } /** * Clones the current TestNGMethod and its @BeforeMethod and @AfterMethod methods. * @see org.testng.internal.BaseTestMethod#clone() */ @Override public BaseTestMethod clone() { TestNGMethod clone= new TestNGMethod(getMethod(), getAnnotationFinder(), false, getXmlTest(), getInstance()); ITestClass tc= getTestClass(); NoOpTestClass testClass= new NoOpTestClass(tc); testClass.setBeforeTestMethods(clone(tc.getBeforeTestMethods())); testClass.setAfterTestMethod(clone(tc.getAfterTestMethods())); clone.m_testClass= testClass; clone.setDate(getDate()); clone.setGroups(getGroups()); clone.setGroupsDependedUpon(getGroupsDependedUpon(), Collections.emptyList()); clone.setMethodsDependedUpon(getMethodsDependedUpon()); clone.setAlwaysRun(isAlwaysRun()); clone.m_beforeGroups= getBeforeGroups(); clone.m_afterGroups= getAfterGroups(); clone.m_currentInvocationCount= m_currentInvocationCount; clone.setMissingGroup(getMissingGroup()); clone.setThreadPoolSize(getThreadPoolSize()); clone.setDescription(getDescription()); clone.setEnabled(getEnabled()); clone.setParameterInvocationCount(getParameterInvocationCount()); clone.setInvocationCount(getInvocationCount()); clone.m_totalInvocationCount = getTotalInvocationCount(); clone.m_successPercentage = getSuccessPercentage(); clone.setTimeOut(getTimeOut()); clone.setRetryAnalyzer(getRetryAnalyzer()); clone.setSkipFailedInvocations(skipFailedInvocations()); clone.setInvocationNumbers(getInvocationNumbers()); clone.setPriority(getPriority()); return clone; } private ITestNGMethod[] clone(ITestNGMethod[] sources) { ITestNGMethod[] clones= new ITestNGMethod[sources.length]; for(int i= 0; i < sources.length; i++) { clones[i]= sources[i].clone(); } return clones; } /** Sorts ITestNGMethod by Class name. */ public static final Comparator SORT_BY_CLASS = new Comparator() { @Override public int compare(ITestNGMethod o1, ITestNGMethod o2) { String c1 = o1.getTestClass().getName(); String c2 = o2.getTestClass().getName(); return c1.compareTo(c2); } }; } testng-testng-6.9.5/src/main/java/org/testng/internal/TestNGClassFinder.java0000644000175000017500000002241712551235562026347 0ustar eugeneeugenepackage org.testng.internal; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.List; import java.util.Map; import java.util.Set; import org.testng.IClass; import org.testng.IInstanceInfo; import org.testng.ITestContext; import org.testng.ITestObjectFactory; import org.testng.TestNGException; import org.testng.annotations.IAnnotation; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.internal.annotations.AnnotationHelper; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.xml.XmlClass; import org.testng.xml.XmlTest; /** * This class creates an ITestClass from a test class. * * @author Cedric Beust */ public class TestNGClassFinder extends BaseClassFinder { private ITestContext m_testContext = null; private Map> m_instanceMap = Maps.newHashMap(); public TestNGClassFinder(ClassInfoMap cim, Map> instanceMap, XmlTest xmlTest, IConfiguration configuration, ITestContext testContext) { m_testContext = testContext; if(null == instanceMap) { instanceMap= Maps.newHashMap(); } IAnnotationFinder annotationFinder = configuration.getAnnotationFinder(); ITestObjectFactory objectFactory = configuration.getObjectFactory(); // // Find all the new classes and their corresponding instances // Set> allClasses= cim.getClasses(); //very first pass is to find ObjectFactory, can't create anything else until then if(objectFactory == null) { objectFactory = new ObjectFactoryImpl(); outer: for (Class cls : allClasses) { try { if (null != cls) { 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) { if (!ITestObjectFactory.class.isAssignableFrom(m.getReturnType())) { throw new TestNGException("Return type of " + m + " is not IObjectFactory"); } try { Object instance = cls.newInstance(); if (m.getParameterTypes().length > 0 && m.getParameterTypes()[0].equals(ITestContext.class)) { objectFactory = (ITestObjectFactory) m.invoke(instance, testContext); } else { objectFactory = (ITestObjectFactory) m.invoke(instance); } break outer; } catch (Exception ex) { throw new TestNGException("Error creating object factory: " + cls, ex); } } } } } catch (NoClassDefFoundError e) { Utils.log("[TestNGClassFinder]", 1, "Unable to read methods on class " + cls.getName() + " - unable to resolve class reference " + e.getMessage()); for (XmlClass xmlClass : xmlTest.getXmlClasses()) { if (xmlClass.loadClasses() && xmlClass.getName().equals(cls.getName())) { throw e; } } } } } for(Class cls : allClasses) { if((null == cls)) { ppp("FOUND NULL CLASS IN FOLLOWING ARRAY:"); int i= 0; for(Class c : allClasses) { ppp(" " + i + ": " + c); } continue; } if(isTestNGClass(cls, annotationFinder)) { List allInstances= instanceMap.get(cls); Object thisInstance= (null != allInstances) ? allInstances.get(0) : null; // If annotation class and instances are abstract, skip them if ((null == thisInstance) && Modifier.isAbstract(cls.getModifiers())) { Utils.log("", 5, "[WARN] Found an abstract class with no valid instance attached: " + cls); continue; } IClass ic= findOrCreateIClass(m_testContext, cls, cim.getXmlClass(cls), thisInstance, xmlTest, annotationFinder, objectFactory); if(null != ic) { Object[] theseInstances = ic.getInstances(false); if (theseInstances.length == 0) { theseInstances = ic.getInstances(true); } Object instance= theseInstances[0]; putIClass(cls, ic); ConstructorOrMethod factoryMethod = ClassHelper.findDeclaredFactoryMethod(cls, annotationFinder); if (factoryMethod != null && factoryMethod.getEnabled()) { FactoryMethod fm = new FactoryMethod( /* cls, */ factoryMethod, instance, xmlTest, annotationFinder, m_testContext); ClassInfoMap moreClasses = new ClassInfoMap(); { // ppp("INVOKING FACTORY " + fm + " " + this.hashCode()); Object[] instances= fm.invoke(); // // If the factory returned IInstanceInfo, get the class from it, // otherwise, just call getClass() on the returned instances // if (instances.length > 0) { if (instances[0] != null) { Class elementClass = instances[0].getClass(); if(IInstanceInfo.class.isAssignableFrom(elementClass)) { for(Object o : instances) { IInstanceInfo ii = (IInstanceInfo) o; addInstance(ii.getInstanceClass(), ii.getInstance()); moreClasses.addClass(ii.getInstanceClass()); } } else { for (int i = 0; i < instances.length; i++) { Object o = instances[i]; if (o == null) { throw new TestNGException("The factory " + fm + " returned a null instance" + "at index " + i); } else { addInstance(o.getClass(), o); if(!classExists(o.getClass())) { moreClasses.addClass(o.getClass()); } } } } } } } if(moreClasses.getSize() > 0) { TestNGClassFinder finder= new TestNGClassFinder(moreClasses, m_instanceMap, xmlTest, configuration, m_testContext); IClass[] moreIClasses= finder.findTestClasses(); for(IClass ic2 : moreIClasses) { putIClass(ic2.getRealClass(), ic2); } } // if moreClasses.size() > 0 } } // null != ic } // if not TestNG class else { Utils.log("TestNGClassFinder", 3, "SKIPPING CLASS " + cls + " no TestNG annotations found"); } } // for // // Add all the instances we found to their respective IClasses // for(Class c : m_instanceMap.keySet()) { List instances= m_instanceMap.get(c); for(Object instance : instances) { IClass ic= getIClass(c); if(null != ic) { ic.addInstance(instance); } } } } /** * @return true if this class contains TestNG annotations (either on itself * or on a superclass). */ public static boolean isTestNGClass(Class c, IAnnotationFinder annotationFinder) { Class[] allAnnotations= AnnotationHelper.getAllAnnotations(); Class cls = c; try { for(Class annotation : allAnnotations) { for (cls = c; cls != null; cls = cls.getSuperclass()) { // Try on the methods for (Method m : cls.getMethods()) { IAnnotation ma= annotationFinder.findAnnotation(m, annotation); if(null != ma) { return true; } } // Try on the class IAnnotation a= annotationFinder.findAnnotation(cls, annotation); if(null != a) { return true; } // Try on the constructors for (Constructor ctor : cls.getConstructors()) { IAnnotation ca= annotationFinder.findAnnotation(ctor, annotation); if(null != ca) { return true; } } } } return false; } catch (NoClassDefFoundError e) { Utils.log("[TestNGClassFinder]", 1, "Unable to read methods on class " + cls.getName() + " - unable to resolve class reference " + e.getMessage()); return false; } } private void addInstance(Class clazz, Object o) { List list= m_instanceMap.get(clazz); if(null == list) { list= Lists.newArrayList(); m_instanceMap.put(clazz, list); } list.add(o); } public static void ppp(String s) { System.out.println("[TestNGClassFinder] " + s); } } testng-testng-6.9.5/src/main/java/org/testng/internal/TestMethodWorker.java0000644000175000017500000002304712551235562026337 0ustar eugeneeugenepackage org.testng.internal; import org.testng.ClassMethodMap; import org.testng.IMethodInstance; import org.testng.ITestClass; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.ITestResult; import org.testng.collections.Lists; import org.testng.internal.thread.ThreadUtil; import org.testng.internal.thread.graph.IWorker; import org.testng.xml.XmlSuite; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * FIXME: reduce contention when this class is used through parallel invocation due to * invocationCount and threadPoolSize by not invoking the @BeforeClass and @AfterClass * which are already invoked on the original method. * * This class implements Runnable and will invoke the ITestMethod passed in its * constructor on its run() method. * * @author Cedric Beust * @author Alexandru Popescu */ public class TestMethodWorker implements IWorker { // Map of the test methods and their associated instances // It has to be a set because the same method can be passed several times // and associated to a different instance private IMethodInstance[] m_methodInstances; private final IInvoker m_invoker; private final Map m_parameters; private final XmlSuite m_suite; private List m_testResults = Lists.newArrayList(); private final ConfigurationGroupMethods m_groupMethods; private final ClassMethodMap m_classMethodMap; private final ITestContext m_testContext; public TestMethodWorker(IInvoker invoker, IMethodInstance[] testMethods, XmlSuite suite, Map parameters, ConfigurationGroupMethods groupMethods, ClassMethodMap classMethodMap, ITestContext testContext) { m_invoker = invoker; m_methodInstances = testMethods; m_suite = suite; m_parameters = parameters; m_groupMethods = groupMethods; m_classMethodMap = classMethodMap; m_testContext = testContext; } /** * Retrieves the maximum specified timeout of all ITestNGMethods to * be run. * * @return the max timeout or 0 if no timeout was specified */ @Override public long getTimeOut() { long result = 0; for (IMethodInstance mi : m_methodInstances) { ITestNGMethod tm = mi.getMethod(); if (tm.getTimeOut() > result) { result = tm.getTimeOut(); } } return result; } @Override public String toString() { StringBuilder result = new StringBuilder("[Worker thread:" + Thread.currentThread().getId() + " priority:" + getPriority() + " "); for (IMethodInstance m : m_methodInstances) { result.append(m.getMethod()).append(" "); } result.append("]"); return result.toString(); } /** * Run all the ITestNGMethods passed in through the constructor. * * @see java.lang.Runnable#run() */ @Override public void run() { for (IMethodInstance testMthdInst : m_methodInstances) { ITestNGMethod testMethod = testMthdInst.getMethod(); ITestClass testClass = testMethod.getTestClass(); invokeBeforeClassMethods(testClass, testMthdInst); // Invoke test method try { invokeTestMethods(testMethod, testMthdInst.getInstance(), m_testContext); } finally { invokeAfterClassMethods(testClass, testMthdInst); } } } protected void invokeTestMethods(ITestNGMethod tm, Object instance, ITestContext testContext) { // Potential bug here: we look up the method index of tm among all // the test methods (not very efficient) but if this method appears // several times and these methods are run in parallel, the results // are unpredictable... Need to think about this more (and make it // more efficient) List testResults = m_invoker.invokeTestMethods(tm, m_suite, m_parameters, m_groupMethods, instance, testContext); if (testResults != null) { m_testResults.addAll(testResults); } } /** * Invoke the @BeforeClass methods if not done already * @param testClass * @param mi */ protected void invokeBeforeClassMethods(ITestClass testClass, IMethodInstance mi) { // if no BeforeClass than return immediately // used for parallel case when BeforeClass were already invoked if( (null == m_classMethodMap) || (null == m_classMethodMap.getInvokedBeforeClassMethods())) { return; } ITestNGMethod[] classMethods= testClass.getBeforeClassMethods(); if(null == classMethods || classMethods.length == 0) { return; } // the whole invocation must be synchronized as other threads must // get a full initialized test object (not the same for @After) Map> invokedBeforeClassMethods = m_classMethodMap.getInvokedBeforeClassMethods(); // System.out.println("SYNCHRONIZING ON " + testClass // + " thread:" + Thread.currentThread().getId() // + " invokedMap:" + invokedBeforeClassMethods.hashCode() + " " // + invokedBeforeClassMethods); synchronized(testClass) { Set instances= invokedBeforeClassMethods.get(testClass); if(null == instances) { instances= new HashSet<>(); invokedBeforeClassMethods.put(testClass, instances); } for(Object instance: mi.getInstances()) { if (! instances.contains(instance)) { instances.add(instance); m_invoker.invokeConfigurations(testClass, testClass.getBeforeClassMethods(), m_suite, m_parameters, null, /* no parameter values */ instance); } } } } /** * Invoke the @AfterClass methods if not done already * @param testClass * @param mi */ protected void invokeAfterClassMethods(ITestClass testClass, IMethodInstance mi) { // if no BeforeClass than return immediately // used for parallel case when BeforeClass were already invoked if( (null == m_classMethodMap) || (null == m_classMethodMap.getInvokedAfterClassMethods()) ) { return; } ITestNGMethod[] afterClassMethods= testClass.getAfterClassMethods(); if(null == afterClassMethods || afterClassMethods.length == 0) { return; } // // Invoke after class methods if this test method is the last one // List invokeInstances= Lists.newArrayList(); ITestNGMethod tm= mi.getMethod(); if (m_classMethodMap.removeAndCheckIfLast(tm, mi.getInstance())) { Map> invokedAfterClassMethods = m_classMethodMap.getInvokedAfterClassMethods(); synchronized(invokedAfterClassMethods) { Set instances = invokedAfterClassMethods.get(testClass); if(null == instances) { instances= new HashSet<>(); invokedAfterClassMethods.put(testClass, instances); } for(Object inst: mi.getInstances()) { if(! instances.contains(inst)) { invokeInstances.add(inst); } } } for(Object inst: invokeInstances) { m_invoker.invokeConfigurations(testClass, afterClassMethods, m_suite, m_parameters, null, /* no parameter values */ inst); } } } protected int indexOf(ITestNGMethod tm, ITestNGMethod[] allTestMethods) { for (int i = 0; i < allTestMethods.length; i++) { if (allTestMethods[i] == tm) { return i; } } return -1; } public List getTestResults() { return m_testResults; } private void ppp(String s) { Utils.log("TestMethodWorker", 2, ThreadUtil.currentThreadInfo() + ":" + s); } @Override public List getTasks() { List result = Lists.newArrayList(); for (IMethodInstance m : m_methodInstances) { result.add(m.getMethod()); } return result; } @Override public int compareTo(IWorker other) { return getPriority() - other.getPriority(); } /** * The priority of a worker is the priority of the first method it's going to run. */ @Override public int getPriority() { return m_methodInstances.length > 0 ? m_methodInstances[0].getMethod().getPriority() : 0; } } /** * Extends {@code TestMethodWorker} and is used to work on only a single method * instance */ class SingleTestMethodWorker extends TestMethodWorker { private static final ConfigurationGroupMethods EMPTY_GROUP_METHODS = new ConfigurationGroupMethods(new ITestNGMethod[0], new HashMap>(), new HashMap>()); public SingleTestMethodWorker(IInvoker invoker, MethodInstance testMethod, XmlSuite suite, Map parameters, ITestContext testContext) { super(invoker, new MethodInstance[] {testMethod}, suite, parameters, EMPTY_GROUP_METHODS, null, testContext); } } testng-testng-6.9.5/src/main/java/org/testng/internal/TestMethodWithDataProviderMethodWorker.java0000755000175000017500000001120212551235562032632 0ustar eugeneeugenepackage org.testng.internal; import org.testng.ITestClass; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.ITestResult; import org.testng.collections.Lists; import org.testng.xml.XmlSuite; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; public class TestMethodWithDataProviderMethodWorker implements Callable> { private ITestNGMethod m_testMethod; private Object[] m_parameterValues; private Object m_instance; private XmlSuite m_xmlSuite; private Map m_parameters; private ITestClass m_testClass; private ITestNGMethod[] m_beforeMethods; private ITestNGMethod[] m_afterMethods; private ConfigurationGroupMethods m_groupMethods; private Invoker m_invoker; private ExpectedExceptionsHolder m_expectedExceptionHolder; private ITestContext m_testContext; private int m_parameterIndex; private boolean m_skipFailedInvocationCounts; private int m_invocationCount; private ITestResultNotifier m_notifier; private List m_testResults = Lists.newArrayList(); private int m_failureCount; public TestMethodWithDataProviderMethodWorker(Invoker invoker, ITestNGMethod testMethod, int parameterIndex, Object[] parameterValues, Object instance, XmlSuite suite, Map parameters, ITestClass testClass, ITestNGMethod[] beforeMethods, ITestNGMethod[] afterMethods, ConfigurationGroupMethods groupMethods, ExpectedExceptionsHolder expectedExceptionHolder, ITestContext testContext, boolean skipFailedInvocationCounts, int invocationCount, int failureCount, ITestResultNotifier notifier) { m_invoker = invoker; m_testMethod = testMethod; m_parameterIndex = parameterIndex; m_parameterValues = parameterValues; m_instance = instance; m_xmlSuite = suite; m_parameters = parameters; m_testClass = testClass; m_beforeMethods = beforeMethods; m_afterMethods = afterMethods; m_groupMethods = groupMethods; m_expectedExceptionHolder = expectedExceptionHolder; m_skipFailedInvocationCounts = skipFailedInvocationCounts; m_testContext = testContext; m_invocationCount = invocationCount; m_failureCount = failureCount; m_notifier = notifier; } public long getMaxTimeOut() { return 500; } @Override public List call() { List tmpResults = Lists.newArrayList(); long start = System.currentTimeMillis(); final Invoker.FailureContext failure = new Invoker.FailureContext(); failure.count = m_failureCount; try { tmpResults.add(m_invoker.invokeTestMethod(m_instance, m_testMethod, m_parameterValues, m_parameterIndex, m_xmlSuite, m_parameters, m_testClass, m_beforeMethods, m_afterMethods, m_groupMethods, failure)); } finally { m_failureCount = failure.count; if (failure.instances.isEmpty()) { m_testResults.addAll(tmpResults); } else { for (Object instance : failure.instances) { List retryResults = Lists.newArrayList(); m_failureCount = m_invoker.retryFailed( instance, m_testMethod, m_xmlSuite, m_testClass, m_beforeMethods, m_afterMethods, m_groupMethods, retryResults, m_failureCount, m_expectedExceptionHolder, m_testContext, m_parameters, m_parameterIndex); m_testResults.addAll(retryResults); } } // // If we have a failure, skip all the // other invocationCounts // // If not specified globally, use the attribute // on the annotation // if (! m_skipFailedInvocationCounts) { m_skipFailedInvocationCounts = m_testMethod.skipFailedInvocations(); } if (m_failureCount > 0 && m_skipFailedInvocationCounts) { while (m_invocationCount-- > 0) { ITestResult r = new TestResult(m_testMethod.getTestClass(), m_instance, m_testMethod, null, start, System.currentTimeMillis(), m_testContext); r.setStatus(TestResult.SKIP); m_testResults.add(r); m_invoker.runTestListeners(r); m_notifier.addSkippedTest(m_testMethod, r); } } } m_parameterIndex++; return m_testResults; } public List getTestResults() { return m_testResults; } public int getInvocationCount() { return m_invocationCount; } public int getFailureCount() { return m_failureCount; } } testng-testng-6.9.5/src/main/java/org/testng/internal/Tarjan.java0000755000175000017500000000333612551235562024306 0ustar eugeneeugenepackage org.testng.internal; import org.testng.collections.Lists; import org.testng.collections.Maps; import java.util.List; import java.util.Map; import java.util.Stack; /** * Implementation of the Tarjan algorithm to find and display a cycle in a graph. * @author cbeust */ public class Tarjan { int m_index = 0; private Stack m_s; Map m_indices = Maps.newHashMap(); Map m_lowlinks = Maps.newHashMap(); private List m_cycle; public Tarjan(Graph graph, T start) { m_s = new Stack<>(); run(graph, start); } private void run(Graph graph, T v) { m_indices.put(v, m_index); m_lowlinks.put(v, m_index); m_index++; m_s.push(v); for (T vprime : graph.getPredecessors(v)) { if (! m_indices.containsKey(vprime)) { run(graph, vprime); int min = Math.min(m_lowlinks.get(v), m_lowlinks.get(vprime)); m_lowlinks.put(v, min); } else if (m_s.contains(vprime)) { m_lowlinks.put(v, Math.min(m_lowlinks.get(v), m_indices.get(vprime))); } } if (m_lowlinks.get(v) == m_indices.get(v)) { m_cycle = Lists.newArrayList(); T n; do { n = m_s.pop(); m_cycle.add(n); } while (! n.equals(v)); } } public static void main(String[] args) { Graph g = new Graph<>(); g.addNode("a"); g.addNode("b"); g.addNode("c"); g.addNode("d"); String[] edges = new String[] { "a", "b", "b", "a", "c", "d", "d", "a", "a", "c", }; for (int i = 0; i < edges.length; i += 2) { g.addPredecessor(edges[i], edges[i+1]); } new Tarjan<>(g, "a"); } public List getCycle() { return m_cycle; } }testng-testng-6.9.5/src/main/java/org/testng/internal/SuiteRunnerMap.java0000644000175000017500000000132112551235562025775 0ustar eugeneeugenepackage org.testng.internal; import org.testng.ISuite; import org.testng.TestNGException; import org.testng.collections.Maps; import org.testng.xml.XmlSuite; import java.util.Collection; import java.util.Map; public class SuiteRunnerMap { private Map m_map = Maps.newHashMap(); public void put(XmlSuite xmlSuite, ISuite suite) { final String name = xmlSuite.getName(); if (m_map.containsKey(name)) { throw new TestNGException("SuiteRunnerMap already have runner for suite " + name); } m_map.put(name, suite); } public ISuite get(XmlSuite xmlSuite) { return m_map.get(xmlSuite.getName()); } public Collection values() { return m_map.values(); } } testng-testng-6.9.5/src/main/java/org/testng/internal/RunInfo.java0000755000175000017500000000442312551235562024445 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IMethodSelector; import org.testng.IMethodSelectorContext; import org.testng.ITestNGMethod; import org.testng.collections.Lists; import java.io.Serializable; import java.util.Collections; import java.util.List; /** * This class contains all the information needed to determine * what methods should be run. It gets invoked by the TestRunner * and then goes through its list of method selectors to decide what methods * need to be run. * * @author Cedric Beust */ public class RunInfo implements Serializable { private static final long serialVersionUID = -9085221672822562888L; transient private List m_methodSelectors = Lists.newArrayList(); public void addMethodSelector(IMethodSelector selector, int priority) { Utils.log("RunInfo", 3, "Adding method selector: " + selector + " priority: " + priority); MethodSelectorDescriptor md = new MethodSelectorDescriptor(selector, priority); m_methodSelectors.add(md); } /** * @return true as soon as we fond a Method Selector that returns * true for the method "tm". */ public boolean includeMethod(ITestNGMethod tm, boolean isTestMethod) { Collections.sort(m_methodSelectors); boolean foundNegative = false; IMethodSelectorContext context = new DefaultMethodSelectorContext(); boolean result = false; for (MethodSelectorDescriptor mds : m_methodSelectors) { // If we found any negative priority, we break as soon as we encounter // a selector with a positive priority if (! foundNegative) { foundNegative = mds.getPriority() < 0; } if (foundNegative && mds.getPriority() >= 0) { break; } // Proceeed normally IMethodSelector md = mds.getMethodSelector(); result = md.includeMethod(context, tm, isTestMethod); if (context.isStopped()) { return result; } // This selector returned false, move on to the next } return result; } public static void ppp(String s) { System.out.println("[RunInfo] " + s); } public void setTestMethods(List testMethods) { for (MethodSelectorDescriptor mds : m_methodSelectors) { mds.setTestMethods(testMethods); } } } testng-testng-6.9.5/src/main/java/org/testng/internal/ResultMap.java0000755000175000017500000000316112551235562024777 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IResultMap; import org.testng.ITestNGMethod; import org.testng.ITestResult; import org.testng.collections.Objects; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public class ResultMap implements IResultMap { /** * */ private static final long serialVersionUID = 80134376515999093L; private Map m_map = new ConcurrentHashMap<>(); @Override public void addResult(ITestResult result, ITestNGMethod method) { m_map.put(result, method); } @Override public Set getResults(ITestNGMethod method) { Set result = new HashSet<>(); for (ITestResult tr : m_map.keySet()) { if (m_map.get(tr).equals(method)) { result.add(tr); } } return result; } @Override public void removeResult(ITestNGMethod m) { for (Entry entry : m_map.entrySet()) { if (entry.getValue().equals(m)) { m_map.remove(entry.getKey()); return; } } } @Override public void removeResult(ITestResult r) { m_map.remove(r); } @Override public Set getAllResults() { return m_map.keySet(); } @Override public int size() { return m_map.size(); } @Override public Collection getAllMethods() { return m_map.values(); } @Override public String toString() { return Objects.toStringHelper(getClass()) .add("map", m_map) .toString(); } } testng-testng-6.9.5/src/main/java/org/testng/internal/RegexpExpectedExceptionsHolder.java0000755000175000017500000000371312551235562031202 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IExpectedExceptionsHolder; import org.testng.ITestNGMethod; import org.testng.annotations.IExpectedExceptionsAnnotation; import org.testng.annotations.ITestAnnotation; import org.testng.internal.annotations.IAnnotationFinder; import java.util.regex.Pattern; /** * A class that contains the expected exceptions and the message regular expression. * @author cbeust */ public class RegexpExpectedExceptionsHolder implements IExpectedExceptionsHolder { public static final String DEFAULT_REGEXP = ".*"; private final IAnnotationFinder finder; private final ITestNGMethod method; public RegexpExpectedExceptionsHolder(IAnnotationFinder finder, ITestNGMethod method) { this.finder = finder; this.method = method; } /** * message / regEx .* other * null true false * non-null true match */ @Override public boolean isThrowableMatching(Throwable ite) { String messageRegExp = getRegExp(); if (DEFAULT_REGEXP.equals(messageRegExp)) { return true; } final String message = ite.getMessage(); return message != null && Pattern.compile(messageRegExp, Pattern.DOTALL).matcher(message).matches(); } public String getWrongExceptionMessage(Throwable ite) { return "The exception was thrown with the wrong message:" + " expected \"" + getRegExp() + "\"" + " but got \"" + ite.getMessage() + "\""; } private String getRegExp() { IExpectedExceptionsAnnotation expectedExceptions = finder.findAnnotation(method, IExpectedExceptionsAnnotation.class); if (expectedExceptions != null) { // Old syntax => default value return DEFAULT_REGEXP; } // New syntax ITestAnnotation testAnnotation = finder.findAnnotation(method, ITestAnnotation.class); if (testAnnotation != null) { return testAnnotation.getExpectedExceptionsMessageRegExp(); } return DEFAULT_REGEXP; } } testng-testng-6.9.5/src/main/java/org/testng/internal/PropertyUtils.java0000755000175000017500000000601712551235562025733 0ustar eugeneeugenepackage org.testng.internal; import org.testng.log4testng.Logger; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * Utility class for setting JavaBeans-style properties on instances. * * @author Cosmin Marginean, Apr 12, 2007 */ public class PropertyUtils { private static final Logger LOGGER = Logger.getLogger(PropertyUtils.class); public static void setProperty(Object instance, String name, String value) { if (instance == null) { LOGGER.warn("Cannot set property " + name + " with value " + value + ". The target instance is null"); return; } Class propClass = getPropertyType(instance.getClass(), name); if (propClass == null) { LOGGER.warn("Cannot set property " + name + " with value " + value + ". Property class could not be found"); return; } Object realValue = Parameters.convertType(propClass, value, name); //TODO: Here the property desc is serched again setPropertyRealValue(instance, name, realValue); } public static Class getPropertyType(Class instanceClass, String propertyName) { if (instanceClass == null) { LOGGER.warn("Cannot retrieve property class for " + propertyName + ". Target instance class is null"); } PropertyDescriptor propDesc = getPropertyDescriptor(instanceClass, propertyName); return propDesc.getPropertyType(); } private static PropertyDescriptor getPropertyDescriptor(Class targetClass, String propertyName) { PropertyDescriptor result = null; if (targetClass == null) { LOGGER.warn("Cannot retrieve property " + propertyName + ". Class is null"); } else { try { BeanInfo beanInfo = Introspector.getBeanInfo(targetClass); PropertyDescriptor[] propDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor propDesc : propDescriptors) { if (propDesc.getName().equals(propertyName)) { result = propDesc; break; } } } catch (IntrospectionException ie) { LOGGER.warn("Cannot retrieve property " + propertyName + ". Cause is: " + ie); } } return result; } public static void setPropertyRealValue(Object instance, String name, Object value) { if (instance == null) { LOGGER.warn("Cannot set property " + name + " with value " + value + ". Targe instance is null"); return; } PropertyDescriptor propDesc = getPropertyDescriptor(instance.getClass(), name); if (propDesc == null) { LOGGER.warn("Cannot set property " + name + " with value " + value + ". Property does not exist"); return; } Method method = propDesc.getWriteMethod(); try { method.invoke(instance, new Object[]{value}); } catch (IllegalAccessException | InvocationTargetException iae) { LOGGER.warn("Cannot set property " + name + " with value " + value + ". Cause " + iae); } } } testng-testng-6.9.5/src/main/java/org/testng/internal/PropertiesFile.java0000755000175000017500000000202112551235562026011 0ustar eugeneeugenepackage org.testng.internal; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; /** * This class loads and abstracts remote.properties * * @author cbeust * @author Guy Korland * @since April 13, 2006 */ public class PropertiesFile { private Properties m_properties = new Properties(); /** * Loads a Properties file. * * @param fileName properties file path * @throws IOException if an error occurred when reading from the Properties file. */ public PropertiesFile(String fileName) throws IOException { FileInputStream fis = null; // // Parse the Properties file // try { fis = new FileInputStream(new File(fileName)); m_properties.load(fis); } finally { if( fis != null) { fis.close(); } } } /** * Returns the properties loaded. * @return loaded properties. */ public Properties getProperties() { return m_properties; } } testng-testng-6.9.5/src/main/java/org/testng/internal/PoolService.java0000755000175000017500000000331512551235562025316 0ustar eugeneeugenepackage org.testng.internal; import org.testng.TestNGException; import org.testng.collections.Lists; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadFactory; /** * Simple wrapper for an ExecutorCompletionService. */ public class PoolService { private ExecutorCompletionService m_completionService; private ThreadFactory m_threadFactory; private ExecutorService m_executor; public PoolService(int threadPoolSize) { m_threadFactory = new ThreadFactory() { private int m_threadIndex = 0; @Override public Thread newThread(Runnable r) { Thread result = new Thread(r); result.setName("PoolService-" + m_threadIndex); m_threadIndex++; return result; } }; m_executor = Executors.newFixedThreadPool(threadPoolSize, m_threadFactory); m_completionService = new ExecutorCompletionService<>(m_executor); } public List submitTasksAndWait(List> tasks) { List result = Lists.newArrayList(); for (Callable callable : tasks) { m_completionService.submit(callable); } for (int i = 0; i < tasks.size(); i++) { try { Future take = m_completionService.take(); result.add(take.get()); } catch (InterruptedException | ExecutionException e) { throw new TestNGException(e); } } m_executor.shutdown(); return result; } } testng-testng-6.9.5/src/main/java/org/testng/internal/Parameters.java0000755000175000017500000004301212551235562025165 0ustar eugeneeugenepackage org.testng.internal; import com.google.inject.Injector; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; 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; import org.testng.TestNGException; import org.testng.annotations.IConfigurationAnnotation; import org.testng.annotations.IDataProviderAnnotation; import org.testng.annotations.IParameterizable; import org.testng.annotations.IParametersAnnotation; import org.testng.annotations.ITestAnnotation; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.internal.ParameterHolder.ParameterOrigin; import org.testng.internal.annotations.AnnotationHelper; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.internal.annotations.IDataProvidable; import org.testng.util.Strings; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; /** * Methods that bind parameters declared in testng.xml to actual values * used to invoke methods. * * @author Cedric Beust */ public class Parameters { public static final String NULL_VALUE= "null"; /** * Creates the parameters needed for constructing a test class instance. * @param finder TODO */ public static Object[] createInstantiationParameters(Constructor ctor, String methodAnnotation, IAnnotationFinder finder, String[] parameterNames, Map params, XmlSuite xmlSuite) { return createParameters(ctor.toString(), ctor.getParameterTypes(), finder.findOptionalValues(ctor), methodAnnotation, finder, parameterNames, new MethodParameters(params, Collections.emptyMap()), xmlSuite); } /** * Creates the parameters needed for the specified @Configuration Method. * * @param m the configuraton method * @param currentTestMethod the current @Test method or null if no @Test is available (this is not * only in case the configuration method is a @Before/@AfterMethod * @param finder the annotation finder */ public static Object[] createConfigurationParameters(Method m, Map params, Object[] parameterValues, @Nullable ITestNGMethod currentTestMethod, IAnnotationFinder finder, XmlSuite xmlSuite, ITestContext ctx, ITestResult testResult) { Method currentTestMeth= currentTestMethod != null ? currentTestMethod.getMethod() : null; Map methodParams = currentTestMethod != null ? currentTestMethod.findMethodParameters(ctx.getCurrentXmlTest()) : Collections.emptyMap(); return createParameters(m, new MethodParameters(params, methodParams, parameterValues, currentTestMeth, ctx, testResult), finder, xmlSuite, IConfigurationAnnotation.class, "@Configuration"); } //////////////////////////////////////////////////////// public static Object getInjectedParameter(Class c, Method method, ITestContext context, ITestResult testResult) { Object result = null; if (Method.class.equals(c)) { result = method; } else if (ITestContext.class.equals(c)) { result = context; } else if (XmlTest.class.equals(c)) { result = context.getCurrentXmlTest(); } else if (ITestResult.class.equals(c)) { result = testResult; } return result; } /** * @return An array of parameters suitable to invoke this method, possibly * picked from the property file */ private static Object[] createParameters(String methodName, Class[] parameterTypes, String[] optionalValues, String methodAnnotation, IAnnotationFinder finder, String[] parameterNames, MethodParameters params, XmlSuite xmlSuite) { Object[] result = new Object[0]; if(parameterTypes.length > 0) { List vResult = Lists.newArrayList(); checkParameterTypes(methodName, parameterTypes, methodAnnotation, parameterNames); for(int i = 0, j = 0; i < parameterTypes.length; i++) { Object inject = getInjectedParameter(parameterTypes[i], params.currentTestMethod, params.context, params.testResult); if (inject != null) { vResult.add(inject); } else { if (j < parameterNames.length) { String p = parameterNames[j]; String value = params.xmlParameters.get(p); if(null == value) { // try SysEnv entries value= System.getProperty(p); } if (null == value) { if (optionalValues != null) { value = optionalValues[i]; } if (null == value) { throw new TestNGException("Parameter '" + p + "' is required by " + methodAnnotation + " on method " + methodName + " but has not been marked @Optional or defined\n" + (xmlSuite.getFileName() != null ? "in " + xmlSuite.getFileName() : "")); } } vResult.add(convertType(parameterTypes[i], value, p)); j++; } } } result = vResult.toArray(new Object[vResult.size()]); } return result; } private static void checkParameterTypes(String methodName, Class[] parameterTypes, String methodAnnotation, String[] parameterNames) { int totalLength = parameterTypes.length; Set injectedTypes = new HashSet() { private static final long serialVersionUID = -5324894581793435812L; { add(ITestContext.class); add(ITestResult.class); add(XmlTest.class); add(Method.class); add(Object[].class); }}; for (Class parameterType : parameterTypes) { if (injectedTypes.contains(parameterType)) { totalLength--; } } if (parameterNames.length != totalLength) { throw new TestNGException( "Method " + methodName + " requires " + parameterTypes.length + " parameters but " + parameterNames.length + " were supplied in the " + methodAnnotation + " annotation."); } } public static Object convertType(Class type, String value, String paramName) { Object result = null; if(NULL_VALUE.equals(value.toLowerCase())) { if(type.isPrimitive()) { Utils.log("Parameters", 2, "Attempt to pass null value to primitive type parameter '" + paramName + "'"); } return null; // null value must be used } if(type == String.class) { result = value; } else if(type == int.class || type == Integer.class) { result = Integer.parseInt(value); } else if(type == boolean.class || type == Boolean.class) { result = Boolean.valueOf(value); } else if(type == byte.class || type == Byte.class) { result = Byte.parseByte(value); } else if(type == char.class || type == Character.class) { result = value.charAt(0); } else if(type == double.class || type == Double.class) { result = Double.parseDouble(value); } else if(type == float.class || type == Float.class) { result = Float.parseFloat(value); } else if(type == long.class || type == Long.class) { result = Long.parseLong(value); } else if(type == short.class || type == Short.class) { result = Short.parseShort(value); } else if (type.isEnum()) { result = Enum.valueOf(type, value); } else { assert false : "Unsupported type parameter : " + type; } return result; } private static DataProviderHolder findDataProvider(Object instance, ITestClass clazz, ConstructorOrMethod m, IAnnotationFinder finder, ITestContext context) { DataProviderHolder result = null; IDataProvidable dp = findDataProviderInfo(clazz, m, finder); if (dp != null) { String dataProviderName = dp.getDataProvider(); Class dataProviderClass = dp.getDataProviderClass(); if (! Utils.isStringEmpty(dataProviderName)) { result = findDataProvider(instance, clazz, finder, dataProviderName, dataProviderClass, context); if(null == result) { throw new TestNGException("Method " + m + " requires a @DataProvider named : " + dataProviderName + (dataProviderClass != null ? " in class " + dataProviderClass.getName() : "") ); } } } return result; } /** * 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(ITestClass clazz, ConstructorOrMethod m, IAnnotationFinder finder) { IDataProvidable result; if (m.getMethod() != null) { // // @Test(dataProvider) on a method // result = AnnotationHelper.findTest(finder, m.getMethod()); if (result == null) { // // @Factory(dataProvider) on a method // result = AnnotationHelper.findFactory(finder, m.getMethod()); } if (result == null) { // // @Test(dataProvider) on a class result = AnnotationHelper.findTest(finder, clazz.getRealClass()); } } else { // // @Factory(dataProvider) on a constructor // result = AnnotationHelper.findFactory(finder, m.getConstructor()); } return result; } /** * Find a method that has a @DataProvider(name=name) */ 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; shouldBeStatic = true; } for (Method m : ClassHelper.getAvailableMethods(cls)) { IDataProviderAnnotation dp = finder.findAnnotation(m, IDataProviderAnnotation.class); if (null != dp && name.equals(getDataProviderName(dp, m))) { if (shouldBeStatic && (m.getModifiers() & Modifier.STATIC) == 0) { 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, instance); } } return result; } private static String getDataProviderName(IDataProviderAnnotation dp, Method m) { return Strings.isNullOrEmpty(dp.getName()) ? m.getName() : dp.getName(); } @SuppressWarnings({"deprecation"}) private static Object[] createParameters(Method m, MethodParameters params, IAnnotationFinder finder, XmlSuite xmlSuite, Class annotationClass, String atName) { List result = Lists.newArrayList(); Object[] extraParameters; // // Try to find an @Parameters annotation // IParametersAnnotation annotation = finder.findAnnotation(m, IParametersAnnotation.class); Class[] types = m.getParameterTypes(); if(null != annotation) { String[] parameterNames = annotation.getValue(); extraParameters = createParameters(m.getName(), types, finder.findOptionalValues(m), atName, finder, parameterNames, params, xmlSuite); } // // Else, use the deprecated syntax // else { IParameterizable a = (IParameterizable) finder.findAnnotation(m, annotationClass); if(null != a && a.getParameters().length > 0) { String[] parameterNames = a.getParameters(); extraParameters = createParameters(m.getName(), types, finder.findOptionalValues(m), atName, finder, parameterNames, params, xmlSuite); } else { extraParameters = createParameters(m.getName(), types, finder.findOptionalValues(m), atName, finder, new String[0], params, xmlSuite); } } // // Add the extra parameters we found // Collections.addAll(result, extraParameters); // If the method declared an Object[] parameter and we have parameter values, inject them for (int i = 0; i < types.length; i++) { if (Object[].class.equals(types[i])) { result.add(i, params.parameterValues); } } return result.toArray(new Object[result.size()]); } /** * If the method has parameters, fill them in. Either by using a @DataProvider * if any was provided, or by looking up in testng.xml * @return An Iterator over the values for each parameter of this * method. */ public static ParameterHolder handleParameters(ITestNGMethod testMethod, Map allParameterNames, Object instance, MethodParameters methodParams, XmlSuite xmlSuite, IAnnotationFinder annotationFinder, Object fedInstance) { ParameterHolder result; Iterator parameters; /* * Do we have a @DataProvider? If yes, then we have several * sets of parameters for this method */ DataProviderHolder dataProviderHolder = findDataProvider(instance, testMethod.getTestClass(), testMethod.getConstructorOrMethod(), annotationFinder, methodParams.context); if (null != dataProviderHolder) { int parameterCount = testMethod.getConstructorOrMethod().getParameterTypes().length; for (int i = 0; i < parameterCount; i++) { String n = "param" + i; allParameterNames.put(n, n); } parameters = MethodInvocationHelper.invokeDataProvider( dataProviderHolder.instance, /* a test instance or null if the dataprovider is static*/ dataProviderHolder.method, testMethod, methodParams.context, fedInstance, annotationFinder); Iterator filteredParameters = filterParameters(parameters, testMethod.getInvocationNumbers()); result = new ParameterHolder(filteredParameters, ParameterOrigin.ORIGIN_DATA_PROVIDER, dataProviderHolder); } else { // // Normal case: we have only one set of parameters coming from testng.xml // allParameterNames.putAll(methodParams.xmlParameters); // Create an Object[][] containing just one row of parameters Object[][] allParameterValuesArray = new Object[1][]; allParameterValuesArray[0] = createParameters(testMethod.getMethod(), methodParams, annotationFinder, xmlSuite, ITestAnnotation.class, "@Test"); // Mark that this method needs to have at least a certain // number of invocations (needed later to call AfterGroups // at the right time). testMethod.setParameterInvocationCount(allParameterValuesArray.length); // Turn it into an Iterable parameters = MethodHelper.createArrayIterator(allParameterValuesArray); result = new ParameterHolder(parameters, ParameterOrigin.ORIGIN_XML, null); } return result; } /** * If numbers is empty, return parameters, otherwise, return a subset of parameters * whose ordinal number match these found in numbers. */ static private Iterator filterParameters(Iterator parameters, List list) { if (list.isEmpty()) { return parameters; } else { List result = Lists.newArrayList(); int i = 0; while (parameters.hasNext()) { Object[] next = parameters.next(); if (list.contains(i)) { result.add(next); } i++; } return new ArrayIterator(result.toArray(new Object[list.size()][])); } } private static void ppp(String s) { System.out.println("[Parameters] " + s); } /** A parameter passing helper class. */ public static class MethodParameters { private final Map xmlParameters; private final Method currentTestMethod; private final ITestContext context; private Object[] parameterValues; public ITestResult testResult; public MethodParameters(Map params, Map methodParams) { this(params, methodParams, null, null, null, null); } public MethodParameters(Map params, Map methodParams, Method m) { this(params, methodParams, null, m, null, null); } /** * @param params parameters found in the suite and test tags * @param methodParams parameters found in the include tag * @param pv * @param m * @param ctx * @param tr */ public MethodParameters(Map params, Map methodParams, Object[] pv, Method m, ITestContext ctx, ITestResult tr) { Map allParams = Maps.newHashMap(); allParams.putAll(params); allParams.putAll(methodParams); xmlParameters = allParams; currentTestMethod = m; context = ctx; parameterValues = pv; testResult = tr; } } } testng-testng-6.9.5/src/main/java/org/testng/internal/ParameterHolder.java0000755000175000017500000000135012551235562026137 0ustar eugeneeugenepackage org.testng.internal; import java.util.Iterator; /** * A simple holder for parameters that contains the parameters and where these came from * (data provider or testng.xml) * @author cbeust * */ public class ParameterHolder { /** * Origin of the parameters. */ public enum ParameterOrigin { ORIGIN_DATA_PROVIDER, // A data provider ORIGIN_XML // TestNG XML suite }; public DataProviderHolder dataProviderHolder; public Iterator parameters; public ParameterOrigin origin; public ParameterHolder(Iterator parameters, ParameterOrigin origin, DataProviderHolder dph) { super(); this.parameters = parameters; this.origin = origin; this.dataProviderHolder = dph; } } testng-testng-6.9.5/src/main/java/org/testng/internal/PackageUtils.java0000644000175000017500000002325112551235562025436 0ustar eugeneeugenepackage org.testng.internal; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.lang.reflect.Method; import java.net.JarURLConnection; import java.net.URL; import java.net.URLConnection; import java.net.URLDecoder; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Vector; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.regex.Pattern; import org.testng.TestNG; import org.testng.collections.Lists; /** * Utility class that finds all the classes in a given package. * * Created on Feb 24, 2006 * @author Cedric Beust */ public class PackageUtils { private static String[] s_testClassPaths; /** The additional class loaders to find classes in. */ private static final List m_classLoaders = new Vector<>(); /** Add a class loader to the searchable loaders. */ public static void addClassLoader(final ClassLoader loader) { m_classLoaders.add(loader); } /** * * @param packageName * @return The list of all the classes inside this package * @throws IOException */ public static String[] findClassesInPackage(String packageName, List included, List excluded) throws IOException { String packageOnly = packageName; boolean recursive = false; if (packageName.endsWith(".*")) { packageOnly = packageName.substring(0, packageName.lastIndexOf(".*")); recursive = true; } List vResult = Lists.newArrayList(); String packageDirName = packageOnly.replace('.', '/') + (packageOnly.length() > 0 ? "/" : ""); Vector dirs = new Vector<>(); // go through additional class loaders Vector allClassLoaders = new Vector<>(); ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if (contextClassLoader != null) { allClassLoaders.add(contextClassLoader); } if (m_classLoaders != null) { allClassLoaders.addAll(m_classLoaders); } int count = 0; for (ClassLoader classLoader : allClassLoaders) { ++count; if (null == classLoader) { continue; } Enumeration dirEnumeration = classLoader.getResources(packageDirName); while(dirEnumeration.hasMoreElements()){ URL dir = dirEnumeration.nextElement(); dirs.add(dir); } } Iterator dirIterator = dirs.iterator(); while (dirIterator.hasNext()) { URL url = dirIterator.next(); String protocol = url.getProtocol(); if(!matchTestClasspath(url, packageDirName, recursive)) { continue; } if ("file".equals(protocol)) { findClassesInDirPackage(packageOnly, included, excluded, URLDecoder.decode(url.getFile(), "UTF-8"), recursive, vResult); } else if ("jar".equals(protocol)) { JarFile jar = ((JarURLConnection) url.openConnection()).getJarFile(); Enumeration entries = jar.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String name = entry.getName(); if (name.charAt(0) == '/') { name = name.substring(1); } if (name.startsWith(packageDirName)) { int idx = name.lastIndexOf('/'); if (idx != -1) { packageName = name.substring(0, idx).replace('/', '.'); } 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"); includeOrExcludeClass(packageName, className, included, excluded, vResult); } } } } } else if ("bundleresource".equals(protocol)) { try { Class params[] = {}; // BundleURLConnection URLConnection connection = url.openConnection(); Method thisMethod = url.openConnection().getClass() .getDeclaredMethod("getFileURL", params); Object paramsObj[] = {}; URL fileUrl = (URL) thisMethod.invoke(connection, paramsObj); findClassesInDirPackage(packageOnly, included, excluded, URLDecoder.decode(fileUrl.getFile(), "UTF-8"), recursive, vResult); } catch (Exception ex) { // ignore - probably not an Eclipse OSGi bundle } } } String[] result = vResult.toArray(new String[vResult.size()]); return result; } private static String[] getTestClasspath() { if (null != s_testClassPaths) { return s_testClassPaths; } String testClasspath = System.getProperty(TestNG.TEST_CLASSPATH); if (null == testClasspath) { return null; } String[] classpathFragments= Utils.split(testClasspath, File.pathSeparator); s_testClassPaths= new String[classpathFragments.length]; for(int i= 0; i < classpathFragments.length; i++) { String path= null; if(classpathFragments[i].toLowerCase().endsWith(".jar") || classpathFragments[i].toLowerCase().endsWith(".zip")) { path= classpathFragments[i] + "!/"; } else { if(classpathFragments[i].endsWith(File.separator)) { path= classpathFragments[i]; } else { path= classpathFragments[i] + "/"; } } s_testClassPaths[i]= path.replace('\\', '/'); } return s_testClassPaths; } private static boolean matchTestClasspath(URL url, String lastFragment, boolean recursive) { String[] classpathFragments= getTestClasspath(); if(null == classpathFragments) { return true; } String fileName= null; try { fileName= URLDecoder.decode(url.getFile(), "UTF-8"); } catch(UnsupportedEncodingException ueex) { ; // ignore. should never happen } for(String classpathFrag: classpathFragments) { String path= classpathFrag + lastFragment; int idx= fileName.indexOf(path); if((idx == -1) || (idx > 0 && fileName.charAt(idx-1) != '/')) { continue; } if(fileName.endsWith(classpathFrag + lastFragment) || (recursive && fileName.charAt(idx + path.length()) == '/')) { return true; } } return false; } private static void findClassesInDirPackage(String packageName, List included, List excluded, String packagePath, final boolean recursive, List classes) { File dir = new File(packagePath); if (!dir.exists() || !dir.isDirectory()) { return; } File[] dirfiles = dir.listFiles(new FileFilter() { @Override public boolean accept(File file) { return (recursive && file.isDirectory()) || (file.getName().endsWith(".class")) || (file.getName().endsWith(".groovy")); } }); Utils.log("PackageUtils", 4, "Looking for test classes in the directory: " + dir); for (File file : dirfiles) { if (file.isDirectory()) { findClassesInDirPackage(makeFullClassName(packageName, file.getName()), included, excluded, file.getAbsolutePath(), recursive, classes); } else { String className = file.getName().substring(0, file.getName().lastIndexOf(".")); Utils.log("PackageUtils", 4, "Found class " + className + ", seeing it if it's included or excluded"); includeOrExcludeClass(packageName, className, included, excluded, classes); } } } private static String makeFullClassName(String pkg, String cls) { return pkg.length() > 0 ? pkg + "." + cls : cls; } private static void includeOrExcludeClass(String packageName, String className, List included, List excluded, List classes) { if (isIncluded(packageName, included, excluded)) { Utils.log("PackageUtils", 4, "... Including class " + className); classes.add(makeFullClassName(packageName, className)); } else { Utils.log("PackageUtils", 4, "... Excluding class " + className); } } /** * @return true if name should be included. */ private static boolean isIncluded(String name, List included, List excluded) { boolean result = false; // // If no includes nor excludes were specified, return true. // if (included.size() == 0 && excluded.size() == 0) { result = true; } else { boolean isIncluded = PackageUtils.find(name, included); boolean isExcluded = PackageUtils.find(name, excluded); if (isIncluded && !isExcluded) { result = true; } else if (isExcluded) { result = false; } else { result = included.size() == 0; } } return result; } private static boolean find(String name, List list) { for (String regexpStr : list) { if (Pattern.matches(regexpStr, name)) { return true; } } return false; } } testng-testng-6.9.5/src/main/java/org/testng/internal/OverrideProcessor.java0000644000175000017500000000226412551235562026542 0ustar eugeneeugenepackage org.testng.internal; import org.testng.xml.IPostProcessor; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import java.util.Arrays; import java.util.Collection; /** * Override the groups included in the XML file with groups specified on the command line. * * @author Cedric Beust */ public class OverrideProcessor implements IPostProcessor { private String[] m_groups; private String[] m_excludedGroups; public OverrideProcessor(String[] groups, String[] excludedGroups) { m_groups = groups; m_excludedGroups = excludedGroups; } @Override public Collection process(Collection suites) { for (XmlSuite s : suites) { if (m_groups != null && m_groups.length > 0) { for (XmlTest t : s.getTests()) { t.getIncludedGroups().clear(); t.getIncludedGroups().addAll(Arrays.asList(m_groups)); } } if (m_excludedGroups != null && m_excludedGroups.length > 0) { for (XmlTest t : s.getTests()) { t.getExcludedGroups().clear(); t.getExcludedGroups().addAll(Arrays.asList(m_excludedGroups)); } } } return suites; } } testng-testng-6.9.5/src/main/java/org/testng/internal/ObjectFactoryImpl.java0000755000175000017500000000242412551235562026444 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IObjectFactory; import org.testng.TestNGException; import java.lang.reflect.Constructor; /** * Default factory for test creation. * Note that if no constructor is found matching the specified parameters, * this factory will try to invoke a constructor that takes in a string object * * @author Hani Suleiman * Date: Mar 6, 2007 * Time: 12:00:27 PM * @since 5.6 */ public class ObjectFactoryImpl implements IObjectFactory { /** * */ private static final long serialVersionUID = -4547389328475540017L; @Override public Object newInstance(Constructor constructor, Object... params) { try { constructor.setAccessible(true); return constructor.newInstance(params); } catch (IllegalAccessException ex) { return ClassHelper.tryOtherConstructor(constructor.getDeclaringClass()); } catch (InstantiationException ex) { return ClassHelper.tryOtherConstructor(constructor.getDeclaringClass()); } catch(Exception ex) { throw new TestNGException("Cannot instantiate class " + (constructor != null ? constructor.getDeclaringClass().getName() : ": couldn't find a suitable constructor"), ex); } } } testng-testng-6.9.5/src/main/java/org/testng/internal/Nullable.java0000644000175000017500000000051712551235562024620 0ustar eugeneeugenepackage org.testng.internal; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.PARAMETER; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({FIELD, PARAMETER}) public @interface Nullable { } testng-testng-6.9.5/src/main/java/org/testng/internal/NoOpTestClass.java0000755000175000017500000001202012551235562025556 0ustar eugeneeugenepackage org.testng.internal; import org.testng.ITestClass; import org.testng.ITestNGMethod; import org.testng.xml.XmlClass; import org.testng.xml.XmlTest; public class NoOpTestClass implements ITestClass { private static final long serialVersionUID = -4544061405329040593L; protected Class m_testClass= null; // Test methods protected ITestNGMethod[] m_beforeClassMethods= null; protected ITestNGMethod[] m_beforeTestMethods= null; protected ITestNGMethod[] m_testMethods= null; protected ITestNGMethod[] m_afterClassMethods= null; protected ITestNGMethod[] m_afterTestMethods= null; protected ITestNGMethod[] m_beforeSuiteMethods= null; protected ITestNGMethod[] m_afterSuiteMethods= null; protected ITestNGMethod[] m_beforeTestConfMethods= null; protected ITestNGMethod[] m_afterTestConfMethods= null; protected ITestNGMethod[] m_beforeGroupsMethods= null; protected ITestNGMethod[] m_afterGroupsMethods= null; private transient Object[] m_instances; private long[] m_instanceHashes; private XmlTest m_xmlTest; private XmlClass m_xmlClass; protected NoOpTestClass() { } public NoOpTestClass(ITestClass testClass) { m_testClass= testClass.getRealClass(); m_beforeSuiteMethods= testClass.getBeforeSuiteMethods(); m_beforeTestConfMethods= testClass.getBeforeTestConfigurationMethods(); m_beforeGroupsMethods= testClass.getBeforeGroupsMethods(); m_beforeClassMethods= testClass.getBeforeClassMethods(); m_beforeTestMethods= testClass.getBeforeTestMethods(); m_afterSuiteMethods= testClass.getAfterSuiteMethods(); m_afterTestConfMethods= testClass.getAfterTestConfigurationMethods(); m_afterGroupsMethods= testClass.getAfterGroupsMethods(); m_afterClassMethods= testClass.getAfterClassMethods(); m_afterTestMethods= testClass.getAfterTestMethods(); m_instances= testClass.getInstances(true); m_instanceHashes= testClass.getInstanceHashCodes(); m_xmlTest = testClass.getXmlTest(); m_xmlClass = testClass.getXmlClass(); } public void setBeforeTestMethods(ITestNGMethod[] beforeTestMethods) { m_beforeTestMethods= beforeTestMethods; } public void setAfterTestMethod(ITestNGMethod[] afterTestMethods) { m_afterTestMethods= afterTestMethods; } /** * @return Returns the afterClassMethods. */ @Override public ITestNGMethod[] getAfterClassMethods() { return m_afterClassMethods; } /** * @return Returns the afterTestMethods. */ @Override public ITestNGMethod[] getAfterTestMethods() { return m_afterTestMethods; } /** * @return Returns the beforeClassMethods. */ @Override public ITestNGMethod[] getBeforeClassMethods() { return m_beforeClassMethods; } /** * @return Returns the beforeTestMethods. */ @Override public ITestNGMethod[] getBeforeTestMethods() { return m_beforeTestMethods; } /** * @return Returns the testMethods. */ @Override public ITestNGMethod[] getTestMethods() { return m_testMethods; } @Override public ITestNGMethod[] getBeforeSuiteMethods() { return m_beforeSuiteMethods; } @Override public ITestNGMethod[] getAfterSuiteMethods() { return m_afterSuiteMethods; } @Override public ITestNGMethod[] getBeforeTestConfigurationMethods() { return m_beforeTestConfMethods; } @Override public ITestNGMethod[] getAfterTestConfigurationMethods() { return m_afterTestConfMethods; } /** * @return all @Configuration methods that should be invoked before certain groups */ @Override public ITestNGMethod[] getBeforeGroupsMethods() { return m_beforeGroupsMethods; } /** * @return all @Configuration methods that should be invoked after certain groups */ @Override public ITestNGMethod[] getAfterGroupsMethods() { return m_afterGroupsMethods; } /** * @see org.testng.ITestClass#getInstanceCount() */ @Override public int getInstanceCount() { return m_instances.length; } /** * @see org.testng.ITestClass#getInstanceHashCodes() */ @Override public long[] getInstanceHashCodes() { return m_instanceHashes; } /** * @see org.testng.ITestClass#getInstances(boolean) */ @Override public Object[] getInstances(boolean reuse) { return m_instances; } @Override public String getName() { return m_testClass.getName(); } @Override public Class getRealClass() { return m_testClass; } /** * @see org.testng.IClass#addInstance(java.lang.Object) */ @Override public void addInstance(Object instance) { } public void setTestClass(Class< ? > declaringClass) { m_testClass = declaringClass; } @Override public String getTestName() { // TODO Auto-generated method stub return null; } @Override public XmlTest getXmlTest() { return m_xmlTest; } @Override public XmlClass getXmlClass() { return m_xmlClass; } } testng-testng-6.9.5/src/main/java/org/testng/internal/MethodSelectorDescriptor.java0000755000175000017500000000211612551235562030042 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IMethodSelector; import org.testng.ITestNGMethod; import java.util.List; /** * This class describes a method selector: * - The class that implements it * - Its priority * * Created on Sep 26, 2005 * @author cbeust */ public class MethodSelectorDescriptor implements Comparable { private IMethodSelector m_methodSelector; private int m_priority; public int getPriority() { return m_priority; } public IMethodSelector getMethodSelector() { return m_methodSelector; } public MethodSelectorDescriptor(IMethodSelector selector, int priority) { m_methodSelector = selector; m_priority = priority; } @Override public int compareTo(MethodSelectorDescriptor other) { int result = 0; try { int p1 = getPriority(); int p2 = other.getPriority(); result = p1 - p2; } catch(Exception ex) { // ignore } return result; } public void setTestMethods(List testMethods) { m_methodSelector.setTestMethods(testMethods); } } testng-testng-6.9.5/src/main/java/org/testng/internal/MethodInvocationHelper.java0000644000175000017500000003072312551235562027476 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IConfigurable; import org.testng.IConfigureCallBack; import org.testng.IHookCallBack; import org.testng.IHookable; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.ITestResult; import org.testng.TestNGException; import org.testng.annotations.DataProvider; import org.testng.collections.Lists; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.internal.collections.Pair; import org.testng.internal.thread.IExecutor; import org.testng.internal.thread.IFutureResult; import org.testng.internal.thread.ThreadExecutionException; import org.testng.internal.thread.ThreadTimeoutException; import org.testng.internal.thread.ThreadUtil; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * Collections of helper methods to help deal with invocation of TestNG methods * * @author Cedric Beust * @author nullin * */ public class MethodInvocationHelper { protected static Object invokeMethod(Method thisMethod, Object instance, Object[] parameters) throws InvocationTargetException, IllegalAccessException { Utils.checkInstanceOrStatic(instance, thisMethod); // TESTNG-326, allow IObjectFactory to load from non-standard classloader // If the instance has a different classloader, its class won't match the // method's class if (instance == null || !thisMethod.getDeclaringClass().isAssignableFrom(instance.getClass())) { // for some reason, we can't call this method on this class // is it static? boolean isStatic = Modifier.isStatic(thisMethod.getModifiers()); if (!isStatic) { // not static, so grab a method with the same name and signature in this case Class clazz = instance.getClass(); try { thisMethod = clazz.getMethod(thisMethod.getName(), thisMethod.getParameterTypes()); } catch (Exception e) { // ignore, the method may be private boolean found = false; for (; clazz != null; clazz = clazz.getSuperclass()) { try { thisMethod = clazz.getDeclaredMethod(thisMethod.getName(), thisMethod.getParameterTypes()); found = true; break; } catch (Exception e2) { } } if (!found) { // should we assert here? Or just allow it to fail on invocation? if (thisMethod.getDeclaringClass().getName().equals(instance.getClass().getName())) { throw new RuntimeException("Can't invoke method " + thisMethod + ", probably due to classloader mismatch"); } throw new RuntimeException("Can't invoke method " + thisMethod + " on this instance of " + instance.getClass() + " due to class mismatch"); } } } } synchronized(thisMethod) { if (! Modifier.isPublic(thisMethod.getModifiers())) { thisMethod.setAccessible(true); } } return thisMethod.invoke(instance, parameters); } protected static Iterator invokeDataProvider(Object instance, Method dataProvider, ITestNGMethod method, ITestContext testContext, Object fedInstance, IAnnotationFinder annotationFinder) { Iterator result; final ConstructorOrMethod com = method.getConstructorOrMethod(); // If it returns an Object[][], convert it to an Iterable try { List lParameters = Lists.newArrayList(); // Go through all the parameters declared on this Data Provider and // make sure we have at most one Method and one ITestContext. // Anything else is an error Class[] parameterTypes = dataProvider.getParameterTypes(); final Collection>> unresolved = new ArrayList<>(parameterTypes.length); int i = 0; for (Class cls : parameterTypes) { boolean isTestInstance = annotationFinder.hasTestInstance(dataProvider, i++); if (cls.equals(Method.class)) { lParameters.add(com.getMethod()); } else if (cls.equals(Constructor.class)) { lParameters.add(com.getConstructor()); } else if (cls.equals(ConstructorOrMethod.class)) { lParameters.add(com); } else if (cls.equals(ITestNGMethod.class)) { lParameters.add(method); } else if (cls.equals(ITestContext.class)) { lParameters.add(testContext); } else if (isTestInstance) { lParameters.add(fedInstance); } else { unresolved.add(new Pair>(i, cls)); } } if (!unresolved.isEmpty()) { final StringBuilder sb = new StringBuilder(); sb.append("Some DataProvider ").append(dataProvider).append(" parameters unresolved: "); for (Pair> pair : unresolved) { sb.append(" at ").append(pair.first()).append(" type ").append(pair.second()).append("\n"); } throw new TestNGException(sb.toString()); } Object[] parameters = lParameters.toArray(new Object[lParameters.size()]); Class returnType = dataProvider.getReturnType(); if (Object[][].class.isAssignableFrom(returnType)) { Object[][] originalResult = (Object[][]) invokeMethod(dataProvider, instance, parameters); // If the data provider is restricting the indices to return, filter them out int[] indices = dataProvider.getAnnotation(DataProvider.class).indices(); Object[][] oResult; if (indices.length > 0) { oResult = new Object[indices.length][]; for (int j = 0; j < indices.length; j++) { oResult[j] = originalResult[indices[j]]; } } else { oResult = originalResult; } method.setParameterInvocationCount(oResult.length); result = MethodHelper.createArrayIterator(oResult); } else if (Iterator.class.isAssignableFrom(returnType)) { // Already an Iterator, assign it directly result = (Iterator) invokeMethod(dataProvider, instance, parameters); } else { throw new TestNGException("Data Provider " + dataProvider + " must return" + " either Object[][] or Iterator[], not " + returnType); } } catch (InvocationTargetException | IllegalAccessException e) { // Don't throw TestNGException here or this test won't be reported as a // skip or failure throw new RuntimeException(e.getCause()); } return result; } /** * Invokes the run method of the IHookable. * * @param testInstance * the instance to invoke the method in * @param parameters * the parameters to be passed to IHookCallBack * @param thisMethod * the method to be invoked through the IHookCallBack * @param testResult * the current ITestResult passed to * IHookable.run * @throws NoSuchMethodException * @throws IllegalAccessException * @throws InvocationTargetException * @throws Throwable * thrown if the reflective call to * thisMethod results in an exception */ protected static void invokeHookable(final Object testInstance, final Object[] parameters, final IHookable hookable, final Method thisMethod, final ITestResult testResult) throws Throwable { final Throwable[] error = new Throwable[1]; IHookCallBack callback = new IHookCallBack() { @Override public void runTestMethod(ITestResult tr) { try { invokeMethod(thisMethod, testInstance, parameters); } catch (Throwable t) { error[0] = t; tr.setThrowable(t); // make Throwable available to IHookable } } @Override public Object[] getParameters() { return parameters; } }; hookable.run(callback, testResult); if (error[0] != null) { throw error[0]; } } /** * Invokes a method on a separate thread in order to allow us to timeout the * invocation. It uses as implementation an Executor and a * CountDownLatch. */ protected static void invokeWithTimeout(ITestNGMethod tm, Object instance, Object[] parameterValues, ITestResult testResult) throws InterruptedException, ThreadExecutionException { invokeWithTimeout(tm, instance, parameterValues, testResult, null); } protected static void invokeWithTimeout(ITestNGMethod tm, Object instance, Object[] parameterValues, ITestResult testResult, IHookable hookable) throws InterruptedException, ThreadExecutionException { if (ThreadUtil.isTestNGThread()) { // We are already running in our own executor, don't create another one (or we will // lose the time out of the enclosing executor). invokeWithTimeoutWithNoExecutor(tm, instance, parameterValues, testResult, hookable); } else { invokeWithTimeoutWithNewExecutor(tm, instance, parameterValues, testResult, hookable); } } private static void invokeWithTimeoutWithNoExecutor(ITestNGMethod tm, Object instance, Object[] parameterValues, ITestResult testResult, IHookable hookable) { InvokeMethodRunnable imr = new InvokeMethodRunnable(tm, instance, parameterValues, hookable, testResult); try { imr.run(); testResult.setStatus(ITestResult.SUCCESS); } catch (Exception ex) { testResult.setThrowable(ex.getCause()); testResult.setStatus(ITestResult.FAILURE); } } private static void invokeWithTimeoutWithNewExecutor(ITestNGMethod tm, Object instance, Object[] parameterValues, ITestResult testResult, IHookable hookable) throws InterruptedException, ThreadExecutionException { IExecutor exec = ThreadUtil.createExecutor(1, tm.getMethodName()); InvokeMethodRunnable imr = new InvokeMethodRunnable(tm, instance, parameterValues, hookable, testResult); IFutureResult future = exec.submitRunnable(imr); exec.shutdown(); long realTimeOut = MethodHelper.calculateTimeOut(tm); boolean finished = exec.awaitTermination(realTimeOut); if (!finished) { exec.stopNow(); ThreadTimeoutException exception = new ThreadTimeoutException("Method " + tm.getClass().getName() + "." + tm.getMethodName() + "()" + " didn't finish within the time-out " + realTimeOut); exception.setStackTrace(exec.getStackTraces()[0]); testResult.setThrowable(exception); testResult.setStatus(ITestResult.FAILURE); } else { Utils.log("Invoker " + Thread.currentThread().hashCode(), 3, "Method " + tm.getMethodName() + " completed within the time-out " + tm.getTimeOut()); // We don't need the result from the future but invoking get() on it // will trigger the exception that was thrown, if any future.get(); // done.await(); testResult.setStatus(ITestResult.SUCCESS); // if no exception till here // than SUCCESS } } protected static void invokeConfigurable(final Object instance, final Object[] parameters, final IConfigurable configurableInstance, final Method thisMethod, final ITestResult testResult) throws Throwable { final Throwable[] error = new Throwable[1]; IConfigureCallBack callback = new IConfigureCallBack() { @Override public void runConfigurationMethod(ITestResult tr) { try { invokeMethod(thisMethod, instance, parameters); } catch (Throwable t) { error[0] = t; tr.setThrowable(t); // make Throwable available to IConfigurable } } @Override public Object[] getParameters() { return parameters; } }; configurableInstance.run(callback, testResult); if (error[0] != null) { throw error[0]; } } } testng-testng-6.9.5/src/main/java/org/testng/internal/MethodInstance.java0000755000175000017500000000635212551235562025775 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IMethodInstance; import org.testng.ITestNGMethod; import org.testng.collections.Objects; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlTest; import java.util.Comparator; import java.util.List; public class MethodInstance implements IMethodInstance { private ITestNGMethod m_method; public MethodInstance(ITestNGMethod method) { m_method = method; } @Override public ITestNGMethod getMethod() { return m_method; } @Override public Object[] getInstances() { return new Object[] { getInstance() }; } @Override public Object getInstance() { return m_method.getInstance(); } @Override public String toString() { return Objects.toStringHelper(getClass()) .add("method", m_method) .add("instance", getInstance()) .toString(); } public static final Comparator SORT_BY_INDEX = new Comparator() { @Override public int compare(IMethodInstance o1, IMethodInstance o2) { // If the two methods are in different XmlTest test1 = o1.getMethod().getTestClass().getXmlTest(); XmlTest test2 = o2.getMethod().getTestClass().getXmlTest(); // If the two methods are not in the same , we can't compare them if (! test1.getName().equals(test2.getName())) { return 0; } int result = 0; // If the two methods are in the same , compare them by their method // index, otherwise compare them with their class index. XmlClass class1 = o1.getMethod().getTestClass().getXmlClass(); XmlClass class2 = o2.getMethod().getTestClass().getXmlClass(); // This can happen if these classes came from a @Factory, in which case, they // don't have an associated XmlClass if (class1 == null || class2 == null) { if (class1 != null) return -1; if (class2 != null) return 1; return 0; } if (! class1.getName().equals(class2.getName())) { int index1 = class1.getIndex(); int index2 = class2.getIndex(); result = index1 - index2; } else { XmlInclude include1 = findXmlInclude(class1.getIncludedMethods(), o1.getMethod().getMethodName()); XmlInclude include2 = findXmlInclude(class2.getIncludedMethods(), o2.getMethod().getMethodName()); if (include1 != null && include2 != null) { result = include1.getIndex() - include2.getIndex(); } } return result; } private XmlInclude findXmlInclude(List includedMethods, String methodName) { for (XmlInclude xi : includedMethods) { if (xi.getName().equals(methodName)) { return xi; } } return null; } }; // public static final Comparator SORT_BY_CLASS // = new Comparator() { // public int compare(IMethodInstance o1, IMethodInstance o2) { // int result= o1.getMethod().getTestClass().getName() // .compareTo(o2.getMethod().getTestClass().getName()); // return result; // } // }; } testng-testng-6.9.5/src/main/java/org/testng/internal/MethodInheritance.java0000755000175000017500000001163312551235562026460 0ustar eugeneeugenepackage org.testng.internal; import java.util.Collections; import java.util.List; import java.util.Map; import org.testng.ITestNGMethod; import org.testng.collections.Lists; import org.testng.collections.Maps; public class MethodInheritance { /** * Look in map for a class that is a superclass of methodClass */ private static List findMethodListSuperClass(Map> map, Class< ? extends ITestNGMethod> methodClass) { for (Map.Entry> entry : map.entrySet()) { if (entry.getKey().isAssignableFrom(methodClass)) { return entry.getValue(); } } return null; } /** * Look in map for a class that is a subclass of methodClass */ private static Class findSubClass(Map> map, Class< ? extends ITestNGMethod> methodClass) { for (Class cls : map.keySet()) { if (methodClass.isAssignableFrom(cls)) { return cls; } } return null; } /** * Fix the methodsDependedUpon to make sure that @Configuration methods * respect inheritance (before methods are invoked in the order Base first * and after methods are invoked in the order Child first) * * @param methods the list of methods * @param before true if we are handling a before method (meaning, the methods * need to be sorted base class first and subclass last). false otherwise (subclass * methods first, base classes last). */ public static void fixMethodInheritance(ITestNGMethod[] methods, boolean before) { // Map of classes -> List of methods that belong to this class or same hierarchy Map> map = Maps.newHashMap(); // // Put the list of methods in their hierarchy buckets // for (ITestNGMethod method : methods) { Class< ? extends ITestNGMethod> methodClass = method.getRealClass(); List l = findMethodListSuperClass(map, methodClass); if (null != l) { l.add(method); } else { Class subClass = findSubClass(map, methodClass); if (null != subClass) { l = map.get(subClass); l.add(method); map.remove(subClass); map.put(methodClass, l); } else { l = Lists.newArrayList(); l.add(method); map.put(methodClass, l); } } } // // Each bucket that has a list bigger than one element gets sorted // for (List l : map.values()) { if (l.size() > 1) { // Sort them sortMethodsByInheritance(l, before); /* * Set methodDependedUpon accordingly * E.g. Base class can have multiple @BeforeClass methods. Need to ensure * that @BeforeClass methods in derived class depend on all @BeforeClass methods * of base class. Vice versa for @AfterXXX methods */ for (int i = 0; i < l.size() - 1; i++) { ITestNGMethod m1 = l.get(i); for (int j = i + 1; j < l.size(); j++) { ITestNGMethod m2 = l.get(j); if (!equalsEffectiveClass(m1, m2) && !dependencyExists(m1, m2, methods)) { Utils.log("MethodInheritance", 4, m2 + " DEPENDS ON " + m1); m2.addMethodDependedUpon(MethodHelper.calculateMethodCanonicalName(m1)); } } } } } } private static boolean dependencyExists(ITestNGMethod m1, ITestNGMethod m2, ITestNGMethod[] methods) { return internalDependencyExists(m1, m2, methods) || internalDependencyExists(m2, m1, methods); } private static boolean internalDependencyExists(ITestNGMethod m1, ITestNGMethod m2, ITestNGMethod[] methods) { ITestNGMethod[] methodsNamed = MethodHelper.findDependedUponMethods(m1, methods); for (ITestNGMethod method : methodsNamed) { if (method.equals(m2)) { return true; } } for (String group : m1.getGroupsDependedUpon()) { ITestNGMethod[] methodsThatBelongToGroup = MethodGroupsHelper.findMethodsThatBelongToGroup(m1, methods, group); for (ITestNGMethod method : methodsThatBelongToGroup) { if (method.equals(m2)) { return true; } } } return false; } private static boolean equalsEffectiveClass(ITestNGMethod m1, ITestNGMethod m2) { try { Class c1 = m1.getRealClass(); Class c2 = m2.getRealClass(); return c1 == null ? c2 == null : c1.equals(c2); } catch(Exception ex) { return false; } } /** * Given a list of methods belonging to the same class hierarchy, orders them * from the base class to the child (if true) or from child to base class (if false) * @param methods */ private static void sortMethodsByInheritance(List methods, boolean baseClassToChild) { Collections.sort(methods); if (! baseClassToChild) { Collections.reverse(methods); } } } testng-testng-6.9.5/src/main/java/org/testng/internal/MethodHelper.java0000644000175000017500000003005312551235562025440 0ustar eugeneeugenepackage org.testng.internal; import java.lang.reflect.Method; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; import org.testng.ITestNGMethod; import org.testng.TestNGException; 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.collections.Pair; /** * Collection of helper methods to help sort and arrange methods. * * @author Cedric Beust * @author Alexandru Popescu */ public class MethodHelper { private static final Map> GRAPH_CACHE = new ConcurrentHashMap<>(); private static final Map CANONICAL_NAME_CACHE = new ConcurrentHashMap<>(); private static final Map, Boolean> MATCH_CACHE = new ConcurrentHashMap<>(); /** * Collects and orders test or configuration methods * @param methods methods to be worked on * @param forTests true for test methods, false for configuration methods * @param runInfo * @param finder annotation finder * @param unique true for unique methods, false otherwise * @param outExcludedMethods * @return list of ordered methods */ public static ITestNGMethod[] collectAndOrderMethods(List methods, boolean forTests, RunInfo runInfo, IAnnotationFinder finder, boolean unique, List outExcludedMethods) { List includedMethods = Lists.newArrayList(); MethodGroupsHelper.collectMethodsByGroup(methods.toArray(new ITestNGMethod[methods.size()]), forTests, includedMethods, outExcludedMethods, runInfo, finder, unique); return sortMethods(forTests, includedMethods, finder).toArray(new ITestNGMethod[]{}); } /** * Finds TestNG methods that the specified TestNG method depends upon * @param m TestNG method * @param methods list of methods to search for depended upon methods * @return list of methods that match the criteria */ protected static ITestNGMethod[] findDependedUponMethods(ITestNGMethod m, ITestNGMethod[] methods) { String canonicalMethodName = calculateMethodCanonicalName(m); List vResult = Lists.newArrayList(); String regexp = null; for (String fullyQualifiedRegexp : m.getMethodsDependedUpon()) { boolean foundAtLeastAMethod = false; if (null != fullyQualifiedRegexp) { // Escapes $ in regexps as it is not meant for end - line matching, but inner class matches. regexp = fullyQualifiedRegexp.replace("$", "\\$"); boolean usePackage = regexp.indexOf('.') != -1; Pattern pattern = Pattern.compile(regexp); for (ITestNGMethod method : methods) { Method thisMethod = method.getMethod(); String thisMethodName = thisMethod.getName(); String methodName = usePackage ? calculateMethodCanonicalName(thisMethod) : thisMethodName; Pair cacheKey = Pair.create(regexp, methodName); Boolean match = MATCH_CACHE.get(cacheKey); if (match == null) { match = pattern.matcher(methodName).matches(); MATCH_CACHE.put(cacheKey, match); } if (match) { vResult.add(method); foundAtLeastAMethod = true; } } } if (!foundAtLeastAMethod) { if (m.ignoreMissingDependencies()) { continue; } if (m.isAlwaysRun()) { continue; } Method maybeReferringTo = findMethodByName(m, regexp); if (maybeReferringTo != null) { throw new TestNGException(canonicalMethodName + "() is depending on method " + maybeReferringTo + ", which is not annotated with @Test or not included."); } throw new TestNGException(canonicalMethodName + "() depends on nonexistent method " + regexp); } }//end for return vResult.toArray(new ITestNGMethod[vResult.size()]); } /** * Finds method based on regex and TestNGMethod. If regex doesn't represent the * class name, uses the TestNG method's class name. * @param testngMethod TestNG method * @param regExp regex representing a method and/or related class name */ private static Method findMethodByName(ITestNGMethod testngMethod, String regExp) { if (regExp == null) { return null; } int lastDot = regExp.lastIndexOf('.'); String className, methodName; if (lastDot == -1) { className = testngMethod.getMethod().getDeclaringClass().getCanonicalName(); methodName = regExp; } else { methodName = regExp.substring(lastDot + 1); className = regExp.substring(0, lastDot); } try { Class c = Class.forName(className); for (Method m : c.getDeclaredMethods()) { if (methodName.equals(m.getName())) { return m; } } } catch (Exception e) { //only logging Utils.log("MethodHelper", 3, "Caught exception while searching for methods using regex"); } return null; } protected static boolean isEnabled(Class objectClass, IAnnotationFinder finder) { ITestAnnotation testClassAnnotation = AnnotationHelper.findTest(finder, objectClass); return isEnabled(testClassAnnotation); } protected static boolean isEnabled(Method m, IAnnotationFinder finder) { ITestAnnotation annotation = AnnotationHelper.findTest(finder, m); // If no method annotation, look for one on the class if (null == annotation) { annotation = AnnotationHelper.findTest(finder, m.getDeclaringClass()); } return isEnabled(annotation); } protected static boolean isEnabled(ITestOrConfiguration test) { return null == test || test.getEnabled(); } /** * Extracts the unique list of ITestNGMethods. */ public static List uniqueMethodList(Collection> methods) { Set resultSet = Sets.newHashSet(); for (List l : methods) { resultSet.addAll(l); } return Lists.newArrayList(resultSet); } private static Graph topologicalSort(ITestNGMethod[] methods, List sequentialList, List parallelList) { Graph result = new Graph<>(); if (methods.length == 0) { return result; } // // Create the graph // for (ITestNGMethod m : methods) { result.addNode(m); List predecessors = Lists.newArrayList(); String[] methodsDependedUpon = m.getMethodsDependedUpon(); String[] groupsDependedUpon = m.getGroupsDependedUpon(); if (methodsDependedUpon.length > 0) { ITestNGMethod[] methodsNamed = MethodHelper.findDependedUponMethods(m, methods); for (ITestNGMethod pred : methodsNamed) { predecessors.add(pred); } } if (groupsDependedUpon.length > 0) { for (String group : groupsDependedUpon) { ITestNGMethod[] methodsThatBelongToGroup = MethodGroupsHelper.findMethodsThatBelongToGroup(m, methods, group); for (ITestNGMethod pred : methodsThatBelongToGroup) { predecessors.add(pred); } } } for (ITestNGMethod predecessor : predecessors) { result.addPredecessor(m, predecessor); } } result.topologicalSort(); sequentialList.addAll(result.getStrictlySortedNodes()); parallelList.addAll(result.getIndependentNodes()); return result; } protected static String calculateMethodCanonicalName(ITestNGMethod m) { return calculateMethodCanonicalName(m.getMethod()); } private static String calculateMethodCanonicalName(Method m) { String result = CANONICAL_NAME_CACHE.get(m); if (result != null) { return result; } String packageName = m.getDeclaringClass().getName() + "." + m.getName(); // Try to find the method on this class or parents Class cls = m.getDeclaringClass(); while (cls != Object.class) { try { if (cls.getDeclaredMethod(m.getName(), m.getParameterTypes()) != null) { packageName = cls.getName(); break; } } catch (Exception e) { // ignore } cls = cls.getSuperclass(); } result = packageName + "." + m.getName(); CANONICAL_NAME_CACHE.put(m, result); return result; } private static List sortMethods(boolean forTests, List allMethods, IAnnotationFinder finder) { List sl = Lists.newArrayList(); List pl = Lists.newArrayList(); ITestNGMethod[] allMethodsArray = allMethods.toArray(new ITestNGMethod[allMethods.size()]); // Fix the method inheritance if these are @Configuration methods to make // sure base classes are invoked before child classes if 'before' and the // other way around if they are 'after' if (!forTests && allMethodsArray.length > 0) { ITestNGMethod m = allMethodsArray[0]; boolean before = m.isBeforeClassConfiguration() || m.isBeforeMethodConfiguration() || m.isBeforeSuiteConfiguration() || m.isBeforeTestConfiguration(); MethodInheritance.fixMethodInheritance(allMethodsArray, before); } topologicalSort(allMethodsArray, sl, pl); List result = Lists.newArrayList(); result.addAll(sl); result.addAll(pl); return result; } /** * @return A sorted array containing all the methods 'method' depends on */ public static List getMethodsDependedUpon(ITestNGMethod method, ITestNGMethod[] methods) { Graph g = GRAPH_CACHE.get(methods); if (g == null) { List parallelList = Lists.newArrayList(); List sequentialList = Lists.newArrayList(); g = topologicalSort(methods, sequentialList, parallelList); GRAPH_CACHE.put(methods, g); } List result = g.findPredecessors(method); return result; } protected static Iterator createArrayIterator(final Object[][] objects) { ArrayIterator result = new ArrayIterator(objects); return result; } protected static String calculateMethodCanonicalName(Class methodClass, String methodName) { Set methods = ClassHelper.getAvailableMethods(methodClass); // TESTNG-139 Method result = null; for (Method m : methods) { if (methodName.equals(m.getName())) { result = m; break; } } return result != null ? calculateMethodCanonicalName(result) : null; } protected static long calculateTimeOut(ITestNGMethod tm) { long result = tm.getTimeOut() > 0 ? tm.getTimeOut() : tm.getInvocationTimeOut(); return result; } } /** * Custom iterator class over a 2D array * */ class ArrayIterator implements Iterator { private Object[][] m_objects; private int m_count; public ArrayIterator(Object[][] objects) { m_objects = objects; m_count = 0; } @Override public boolean hasNext() { return m_count < m_objects.length; } @Override public Object[] next() { return m_objects[m_count++]; } @Override public void remove() { throw new UnsupportedOperationException("Remove operation is not supported on this iterator"); } } testng-testng-6.9.5/src/main/java/org/testng/internal/MethodGroupsHelper.java0000644000175000017500000002414212551235562026642 0ustar eugeneeugenepackage org.testng.internal; import java.lang.reflect.Method; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; import org.testng.ITestClass; import org.testng.ITestNGMethod; import org.testng.annotations.IConfigurationAnnotation; import org.testng.annotations.ITestOrConfiguration; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.internal.annotations.AnnotationHelper; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.internal.collections.Pair; /** * Collections of helper methods to help deal with test methods * * @author Cedric Beust * @author nullin * */ public class MethodGroupsHelper { private static final Map PATTERN_CACHE = new ConcurrentHashMap<>(); private static final Map, Boolean> MATCH_CACHE = new ConcurrentHashMap<>(); /** * Collect all the methods that belong to the included groups and exclude all * the methods that belong to an excluded group. */ static void collectMethodsByGroup(ITestNGMethod[] methods, boolean forTests, List outIncludedMethods, List outExcludedMethods, RunInfo runInfo, IAnnotationFinder finder, boolean unique) { for (ITestNGMethod tm : methods) { boolean in = false; Method m = tm.getMethod(); // // @Test method // if (forTests) { in = MethodGroupsHelper.includeMethod(AnnotationHelper.findTest(finder, m), runInfo, tm, forTests, unique, outIncludedMethods); } // // @Configuration method // else { IConfigurationAnnotation annotation = AnnotationHelper.findConfiguration(finder, m); if (annotation.getAlwaysRun()) { if (!unique || !MethodGroupsHelper.isMethodAlreadyPresent(outIncludedMethods, tm)) { in = true; } } else { in = MethodGroupsHelper.includeMethod(AnnotationHelper.findTest(finder, tm), runInfo, tm, forTests, unique, outIncludedMethods); } } if (in) { outIncludedMethods.add(tm); } else { outExcludedMethods.add(tm); } } } private static boolean includeMethod(ITestOrConfiguration annotation, RunInfo runInfo, ITestNGMethod tm, boolean forTests, boolean unique, List outIncludedMethods) { boolean result = false; if (MethodHelper.isEnabled(annotation)) { if (runInfo.includeMethod(tm, forTests)) { if (unique) { if (!MethodGroupsHelper.isMethodAlreadyPresent(outIncludedMethods, tm)) { result = true; } } else { result = true; } } } return result; } /** * @param result * @param tm * @return true if a method by a similar name (and same hierarchy) already * exists */ private static boolean isMethodAlreadyPresent(List result, ITestNGMethod tm) { for (ITestNGMethod m : result) { Method jm1 = m.getMethod(); Method jm2 = tm.getMethod(); if (jm1.getName().equals(jm2.getName())) { // Same names, see if they are in the same hierarchy Class c1 = jm1.getDeclaringClass(); Class c2 = jm2.getDeclaringClass(); if (c1.isAssignableFrom(c2) || c2.isAssignableFrom(c1)) { return true; } } } return false; } /** * Extracts the map of groups and their corresponding methods from the classes. */ public static Map> findGroupsMethods(Collection classes, boolean before) { Map> result = Maps.newHashMap(); for (ITestClass cls : classes) { ITestNGMethod[] methods = before ? cls.getBeforeGroupsMethods() : cls.getAfterGroupsMethods(); for (ITestNGMethod method : methods) { for (String group : before ? method.getBeforeGroups() : method.getAfterGroups()) { List methodList = result.get(group); if (methodList == null) { methodList = Lists.newArrayList(); result.put(group, methodList); } // NOTE(cbeust, 2007/01/23) // BeforeGroups/AfterGroups methods should only be invoked once. // I should probably use a map instead of a list for a contains(), but // this list should usually be fairly short if (! methodList.contains(method)) { methodList.add(method); } } } } return result; } protected static void findGroupTransitiveClosure(XmlMethodSelector xms, List includedMethods, List allMethods, String[] includedGroups, Set outGroups, Set outMethods) { Map runningMethods = Maps.newHashMap(); for (ITestNGMethod m : includedMethods) { runningMethods.put(m, m); } Map runningGroups = Maps.newHashMap(); for (String thisGroup : includedGroups) { runningGroups.put(thisGroup, thisGroup); } boolean keepGoing = true; Map newMethods = Maps.newHashMap(); while (keepGoing) { for (ITestNGMethod m : includedMethods) { // // Depends on groups? // Adds all included methods to runningMethods // String[] ig = m.getGroupsDependedUpon(); for (String g : ig) { if (! runningGroups.containsKey(g)) { // Found a new included group, add all the methods it contains to // our outMethod closure runningGroups.put(g, g); ITestNGMethod[] im = MethodGroupsHelper.findMethodsThatBelongToGroup(m, allMethods.toArray(new ITestNGMethod[allMethods.size()]), g); for (ITestNGMethod thisMethod : im) { if (! runningMethods.containsKey(thisMethod)) { runningMethods.put(thisMethod, thisMethod); newMethods.put(thisMethod, thisMethod); } } } } // groups // // Depends on methods? // Adds all depended methods to runningMethods // String[] mdu = m.getMethodsDependedUpon(); for (String tm : mdu) { ITestNGMethod thisMethod = MethodGroupsHelper.findMethodNamed(tm, allMethods); if (thisMethod != null && ! runningMethods.containsKey(thisMethod)) { runningMethods.put(thisMethod, thisMethod); newMethods.put(thisMethod, thisMethod); } } } // methods // // Only keep going if new methods have been added // keepGoing = newMethods.size() > 0; includedMethods = Lists.newArrayList(); includedMethods.addAll(newMethods.keySet()); newMethods = Maps.newHashMap(); } // while keepGoing outMethods.addAll(runningMethods.keySet()); outGroups.addAll(runningGroups.keySet()); } private static ITestNGMethod findMethodNamed(String tm, List allMethods) { for (ITestNGMethod m : allMethods) { // TODO(cbeust): account for package String methodName = m.getMethod().getDeclaringClass().getName() + "." + m.getMethodName(); if (methodName.equals(tm)) { return m; } } return null; } /** * Only used if a group is missing to flag an error on that method * * @param method if no group is found, group regex is set as this method's missing group * @param methods list of methods to search * @param groupRegexp regex representing the group * * @return all the methods that belong to the group specified by the regular * expression groupRegExp. methods[] is the list of all the methods we * are choosing from and method is the method that owns the dependsOnGroups * statement (only used if a group is missing to flag an error on that method). */ protected static ITestNGMethod[] findMethodsThatBelongToGroup( ITestNGMethod method, ITestNGMethod[] methods, String groupRegexp) { ITestNGMethod[] found = findMethodsThatBelongToGroup(methods, groupRegexp); if (found.length == 0) { method.setMissingGroup(groupRegexp); } return found; } /** * @param methods list of methods to search * @param groupRegexp regex representing the group * * @return all the methods that belong to the group specified by the regular * expression groupRegExp. methods[] is the list of all the methods we * are choosing from. */ protected static ITestNGMethod[] findMethodsThatBelongToGroup(ITestNGMethod[] methods, String groupRegexp) { List vResult = Lists.newArrayList(); final Pattern pattern = getPattern(groupRegexp); for (ITestNGMethod tm : methods) { String[] groups = tm.getGroups(); for (String group : groups) { Boolean match = isMatch(pattern, group); if (match) { vResult.add(tm); } } } return vResult.toArray(new ITestNGMethod[vResult.size()]); } private static Boolean isMatch(Pattern pattern, String group) { Pair cacheKey = Pair.create(pattern.pattern(), group); Boolean match = MATCH_CACHE.get(cacheKey); if (match == null) { match = pattern.matcher(group).matches(); MATCH_CACHE.put(cacheKey, match); } return match; } private static Pattern getPattern(String groupRegexp) { Pattern groupPattern = PATTERN_CACHE.get(groupRegexp); if (groupPattern == null) { groupPattern = Pattern.compile(groupRegexp); PATTERN_CACHE.put(groupRegexp, groupPattern); } return groupPattern; } } testng-testng-6.9.5/src/main/java/org/testng/internal/Invoker.java0000644000175000017500000020222012551235562024472 0ustar eugeneeugenepackage org.testng.internal; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.testng.IClass; import org.testng.IConfigurable; import org.testng.IConfigurationListener; import org.testng.IConfigurationListener2; import org.testng.IHookable; import org.testng.IInvokedMethod; import org.testng.IInvokedMethodListener; import org.testng.IRetryAnalyzer; import org.testng.ITestClass; import org.testng.ITestContext; import org.testng.ITestListener; import org.testng.ITestNGMethod; import org.testng.ITestResult; import org.testng.Reporter; import org.testng.SkipException; import org.testng.SuiteRunState; import org.testng.TestException; import org.testng.TestNGException; 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.invokers.InvokedMethodListenerInvoker; import org.testng.internal.invokers.InvokedMethodListenerMethod; import org.testng.internal.thread.ThreadExecutionException; import org.testng.internal.thread.ThreadUtil; import org.testng.internal.thread.graph.IWorker; import org.testng.xml.XmlClass; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import static org.testng.internal.invokers.InvokedMethodListenerMethod.AFTER_INVOCATION; import static org.testng.internal.invokers.InvokedMethodListenerMethod.BEFORE_INVOCATION; /** * This class is responsible for invoking methods: * - test methods * - configuration methods * - possibly in a separate thread * and then for notifying the result listeners. * * @author Cedric Beust * @author Alexandru Popescu */ public class Invoker implements IInvoker { private final ITestContext m_testContext; private final ITestResultNotifier m_notifier; private final IAnnotationFinder m_annotationFinder; private final SuiteRunState m_suiteState; private final boolean m_skipFailedInvocationCounts; private final List m_invokedMethodListeners; private final boolean m_continueOnFailedConfiguration; /** Group failures must be synced as the Invoker is accessed concurrently */ private Map m_beforegroupsFailures = Maps.newHashtable(); /** Class failures must be synced as the Invoker is accessed concurrently */ private Map, Set> m_classInvocationResults = Maps.newHashtable(); /** Test methods whose configuration methods have failed. */ private Map> m_methodInvocationResults = Maps.newHashtable(); private IConfiguration m_configuration; /** Predicate to filter methods */ private static Predicate CAN_RUN_FROM_CLASS = new CanRunFromClassPredicate(); /** Predicate to filter methods */ private static final Predicate SAME_CLASS = new SameClassNamePredicate(); private void setClassInvocationFailure(Class clazz, Object instance) { Set instances = m_classInvocationResults.get( clazz ); if (instances == null) { instances = Sets.newHashSet(); m_classInvocationResults.put(clazz, instances); } instances.add(instance); } private void setMethodInvocationFailure(ITestNGMethod method, Object instance) { Set instances = m_methodInvocationResults.get(method); if (instances == null) { instances = Sets.newHashSet(); m_methodInvocationResults.put(method, instances); } instances.add(getMethodInvocationToken(method, instance)); } public Invoker(IConfiguration configuration, ITestContext testContext, ITestResultNotifier notifier, SuiteRunState state, boolean skipFailedInvocationCounts, List invokedMethodListeners) { m_configuration = configuration; m_testContext= testContext; m_suiteState= state; m_notifier= notifier; m_annotationFinder= configuration.getAnnotationFinder(); m_skipFailedInvocationCounts = skipFailedInvocationCounts; m_invokedMethodListeners = invokedMethodListeners; m_continueOnFailedConfiguration = XmlSuite.CONTINUE.equals(testContext.getSuite().getXmlSuite().getConfigFailurePolicy()); } /** * Invoke configuration methods if they belong to the same TestClass passed * in parameter..

TODO: Calculate ahead of time which methods should be * invoked for each class. Might speed things up for users who invoke the * same test class with different parameters in the same suite run. * * If instance is non-null, the configuration will be run on it. If it is null, * the configuration methods will be run on all the instances retrieved * from the ITestClass. */ @Override public void invokeConfigurations(IClass testClass, ITestNGMethod[] allMethods, XmlSuite suite, Map params, Object[] parameterValues, Object instance) { invokeConfigurations(testClass, null, allMethods, suite, params, parameterValues, instance, null); } private void invokeConfigurations(IClass testClass, ITestNGMethod currentTestMethod, ITestNGMethod[] allMethods, XmlSuite suite, Map params, Object[] parameterValues, Object instance, ITestResult testMethodResult) { if(null == allMethods) { log(5, "No configuration methods found"); return; } ITestNGMethod[] methods= filterMethods(testClass, allMethods, SAME_CLASS); for(ITestNGMethod tm : methods) { if(null == testClass) { testClass= tm.getTestClass(); } ITestResult testResult= new TestResult(testClass, instance, tm, null, System.currentTimeMillis(), System.currentTimeMillis(), m_testContext); IConfigurationAnnotation configurationAnnotation= null; try { Object inst = tm.getInstance(); if (inst == null) { inst = instance; } Class objectClass= inst.getClass(); Method method= tm.getMethod(); // Only run the configuration if // - the test is enabled and // - the Configuration method belongs to the same class or a parent configurationAnnotation = AnnotationHelper.findConfiguration(m_annotationFinder, method); boolean alwaysRun= isAlwaysRun(configurationAnnotation); if(MethodHelper.isEnabled(objectClass, m_annotationFinder) || alwaysRun) { if (MethodHelper.isEnabled(configurationAnnotation)) { if (!confInvocationPassed(tm, currentTestMethod, testClass, instance) && !alwaysRun) { handleConfigurationSkip(tm, testResult, configurationAnnotation, currentTestMethod, instance, suite); continue; } log(3, "Invoking " + Utils.detailedMethodName(tm, true)); Object[] parameters = Parameters.createConfigurationParameters(tm.getMethod(), params, parameterValues, currentTestMethod, m_annotationFinder, suite, m_testContext, testMethodResult); testResult.setParameters(parameters); Object newInstance = null != instance ? instance: inst; runConfigurationListeners(testResult, true /* before */); invokeConfigurationMethod(newInstance, tm, parameters, testResult); // TODO: probably we should trigger the event for each instance??? testResult.setEndMillis(System.currentTimeMillis()); runConfigurationListeners(testResult, false /* after */); } else { log(3, "Skipping " + Utils.detailedMethodName(tm, true) + " because it is not enabled"); } } // if is enabled else { log(3, "Skipping " + Utils.detailedMethodName(tm, true) + " because " + objectClass.getName() + " is not enabled"); } } catch(InvocationTargetException ex) { handleConfigurationFailure(ex, tm, testResult, configurationAnnotation, currentTestMethod, instance, suite); } catch(Throwable ex) { // covers the non-wrapper exceptions handleConfigurationFailure(ex, tm, testResult, configurationAnnotation, currentTestMethod, instance, suite); } } // for methods } /** * Marks the current TestResult as skipped and invokes the listeners. */ private void handleConfigurationSkip(ITestNGMethod tm, ITestResult testResult, IConfigurationAnnotation annotation, ITestNGMethod currentTestMethod, Object instance, XmlSuite suite) { recordConfigurationInvocationFailed(tm, testResult.getTestClass(), annotation, currentTestMethod, instance, suite); testResult.setStatus(ITestResult.SKIP); runConfigurationListeners(testResult, false /* after */); } /** * Is the IConfiguration marked as alwaysRun. */ private boolean isAlwaysRun(IConfigurationAnnotation configurationAnnotation) { if(null == configurationAnnotation) { return false; } boolean alwaysRun= false; if ((configurationAnnotation.getAfterSuite() || configurationAnnotation.getAfterTest() || configurationAnnotation.getAfterTestClass() || configurationAnnotation.getAfterTestMethod() || configurationAnnotation.getBeforeTestMethod() || configurationAnnotation.getBeforeTestClass() || configurationAnnotation.getBeforeTest() || configurationAnnotation.getBeforeSuite()) && configurationAnnotation.getAlwaysRun()) { alwaysRun= true; } return alwaysRun; } private void handleConfigurationFailure(Throwable ite, ITestNGMethod tm, ITestResult testResult, IConfigurationAnnotation annotation, ITestNGMethod currentTestMethod, Object instance, XmlSuite suite) { Throwable cause= ite.getCause() != null ? ite.getCause() : ite; if(isSkipExceptionAndSkip(cause)) { testResult.setThrowable(cause); handleConfigurationSkip(tm, testResult, annotation, currentTestMethod, instance, suite); return; } Utils.log("", 3, "Failed to invoke configuration method " + tm.getRealClass().getName() + "." + tm.getMethodName() + ":" + cause.getMessage()); handleException(cause, tm, testResult, 1); runConfigurationListeners(testResult, false /* after */); // // If in TestNG mode, need to take a look at the annotation to figure out // what kind of @Configuration method we're dealing with // if (null != annotation) { recordConfigurationInvocationFailed(tm, testResult.getTestClass(), annotation, currentTestMethod, instance, suite); } } /** * @return All the classes that belong to the same tag as @param cls */ private XmlClass[] findClassesInSameTest(Class cls, XmlSuite suite) { Map vResult= Maps.newHashMap(); String className= cls.getName(); for(XmlTest test : suite.getTests()) { for(XmlClass testClass : test.getXmlClasses()) { if(testClass.getName().equals(className)) { // Found it, add all the classes in this test in the result for(XmlClass thisClass : test.getXmlClasses()) { vResult.put(thisClass.getName(), thisClass); } // Note: we need to iterate through the entire suite since the same // class might appear in several tags } } } XmlClass[] result= vResult.values().toArray(new XmlClass[vResult.size()]); return result; } /** * Record internally the failure of a Configuration, so that we can determine * later if @Test should be skipped. */ private void recordConfigurationInvocationFailed(ITestNGMethod tm, IClass testClass, IConfigurationAnnotation annotation, ITestNGMethod currentTestMethod, Object instance, XmlSuite suite) { // If beforeTestClass or afterTestClass failed, mark either the config method's // entire class as failed, or the class under tests as failed, depending on // the configuration failure policy if (annotation.getBeforeTestClass() || annotation.getAfterTestClass()) { // tm is the configuration method, and currentTestMethod is null for BeforeClass // methods, so we need testClass if (m_continueOnFailedConfiguration) { setClassInvocationFailure(testClass.getRealClass(), instance); } else { setClassInvocationFailure(tm.getRealClass(), instance); } } // If before/afterTestMethod failed, mark either the config method's entire // class as failed, or just the current test method as failed, depending on // the configuration failure policy else if (annotation.getBeforeTestMethod() || annotation.getAfterTestMethod()) { if (m_continueOnFailedConfiguration) { setMethodInvocationFailure(currentTestMethod, instance); } else { setClassInvocationFailure(tm.getRealClass(), instance); } } // If beforeSuite or afterSuite failed, mark *all* the classes as failed // for configurations. At this point, the entire Suite is screwed else if (annotation.getBeforeSuite() || annotation.getAfterSuite()) { m_suiteState.failed(); } // beforeTest or afterTest: mark all the classes in the same // stanza as failed for configuration else if (annotation.getBeforeTest() || annotation.getAfterTest()) { setClassInvocationFailure(tm.getRealClass(), instance); XmlClass[] classes= findClassesInSameTest(tm.getRealClass(), suite); for(XmlClass xmlClass : classes) { setClassInvocationFailure(xmlClass.getSupportClass(), instance); } } String[] beforeGroups= annotation.getBeforeGroups(); if(null != beforeGroups && beforeGroups.length > 0) { for(String group: beforeGroups) { m_beforegroupsFailures.put(group, Boolean.FALSE); } } } /** * @return true if this class or a parent class failed to initialize. */ private boolean classConfigurationFailed(Class cls) { for (Class c : m_classInvocationResults.keySet()) { if (c == cls || c.isAssignableFrom(cls)) { return true; } } return false; } /** * @return true if this class has successfully run all its @Configuration * method or false if at least one of these methods failed. */ private boolean confInvocationPassed(ITestNGMethod method, ITestNGMethod currentTestMethod, IClass testClass, Object instance) { boolean result= true; Class cls = testClass.getRealClass(); if(m_suiteState.isFailed()) { result= false; } else { if (classConfigurationFailed(cls)) { if (! m_continueOnFailedConfiguration) { result = !classConfigurationFailed(cls); } else { result = !m_classInvocationResults.get(cls).contains(instance); } } // if method is BeforeClass, currentTestMethod will be null else if (m_continueOnFailedConfiguration && currentTestMethod != null && m_methodInvocationResults.containsKey(currentTestMethod)) { result = !m_methodInvocationResults.get(currentTestMethod).contains(getMethodInvocationToken(currentTestMethod, instance)); } else if (! m_continueOnFailedConfiguration) { for(Class clazz: m_classInvocationResults.keySet()) { // if (clazz == cls) { if(clazz.isAssignableFrom(cls)) { result= false; break; } } } } // check if there are failed @BeforeGroups String[] groups= method.getGroups(); if(null != groups && groups.length > 0) { for(String group: groups) { if(m_beforegroupsFailures.containsKey(group)) { result= false; break; } } } return result; } // Creates a token for tracking a unique invocation of a method on an instance. // Is used when configFailurePolicy=continue. private Object getMethodInvocationToken(ITestNGMethod method, Object instance) { return String.format("%s+%d", instance.toString(), method.getCurrentInvocationCount()); } /** * Effectively invokes a configuration method on all passed in instances. * TODO: Should change this method to be more like invokeMethod() so that we can * handle calls to {@code IInvokedMethodListener} better. * * @param targetInstance the instance to invoke the configuration method on * @param tm the configuration method * @param params the parameters needed for method invocation * @param testResult * @throws InvocationTargetException * @throws IllegalAccessException */ private void invokeConfigurationMethod(Object targetInstance, ITestNGMethod tm, Object[] params, ITestResult testResult) throws InvocationTargetException, IllegalAccessException { // Mark this method with the current thread id tm.setId(ThreadUtil.currentThreadInfo()); { InvokedMethod invokedMethod= new InvokedMethod(targetInstance, tm, params, System.currentTimeMillis(), testResult); runInvokedMethodListeners(BEFORE_INVOCATION, invokedMethod, testResult); m_notifier.addInvokedMethod(invokedMethod); try { Reporter.setCurrentTestResult(testResult); Method method = tm.getMethod(); // // If this method is a IConfigurable, invoke its run() method // IConfigurable configurableInstance = IConfigurable.class.isAssignableFrom(tm.getMethod().getDeclaringClass()) ? (IConfigurable) targetInstance : m_configuration.getConfigurable(); if (configurableInstance != null) { MethodInvocationHelper.invokeConfigurable(targetInstance, params, configurableInstance, method, testResult); } else { // // Not a IConfigurable, invoke directly // if (MethodHelper.calculateTimeOut(tm) <= 0) { MethodInvocationHelper.invokeMethod(method, targetInstance, params); } else { MethodInvocationHelper.invokeWithTimeout(tm, targetInstance, params, testResult); if (!testResult.isSuccess()) { // A time out happened throwConfigurationFailure(testResult, testResult.getThrowable()); throw testResult.getThrowable(); } } } } catch (InvocationTargetException | IllegalAccessException ex) { throwConfigurationFailure(testResult, ex); throw ex; } catch (Throwable ex) { throwConfigurationFailure(testResult, ex); throw new TestNGException(ex); } finally { Reporter.setCurrentTestResult(testResult); runInvokedMethodListeners(AFTER_INVOCATION, invokedMethod, testResult); Reporter.setCurrentTestResult(null); } } } private void throwConfigurationFailure(ITestResult testResult, Throwable ex) { testResult.setStatus(ITestResult.FAILURE);; testResult.setThrowable(ex.getCause() == null ? ex : ex.getCause()); } private void runInvokedMethodListeners(InvokedMethodListenerMethod listenerMethod, IInvokedMethod invokedMethod, ITestResult testResult) { if ( noListenersPresent() ) { return; } InvokedMethodListenerInvoker invoker = new InvokedMethodListenerInvoker(listenerMethod, testResult, m_testContext); for (IInvokedMethodListener currentListener : m_invokedMethodListeners) { invoker.invokeListener(currentListener, invokedMethod); } } private boolean noListenersPresent() { return (m_invokedMethodListeners == null) || (m_invokedMethodListeners.size() == 0); } // pass both paramValues and paramIndex to be thread safe in case parallel=true + dataprovider. private ITestResult invokeMethod(Object instance, final ITestNGMethod tm, Object[] parameterValues, int parametersIndex, XmlSuite suite, Map params, ITestClass testClass, ITestNGMethod[] beforeMethods, ITestNGMethod[] afterMethods, ConfigurationGroupMethods groupMethods, FailureContext failureContext) { TestResult testResult = new TestResult(); // // Invoke beforeGroups configurations // invokeBeforeGroupsConfigurations(testClass, tm, groupMethods, suite, params, instance); // // Invoke beforeMethods only if // - firstTimeOnly is not set // - firstTimeOnly is set, and we are reaching at the first invocationCount // invokeConfigurations(testClass, tm, filterConfigurationMethods(tm, beforeMethods, true /* beforeMethods */), suite, params, parameterValues, instance, testResult); // // Create the ExtraOutput for this method // InvokedMethod invokedMethod = null; try { testResult.init(testClass, instance, tm, null, System.currentTimeMillis(), 0, m_testContext); testResult.setParameters(parameterValues); testResult.setHost(m_testContext.getHost()); testResult.setStatus(ITestResult.STARTED); invokedMethod= new InvokedMethod(instance, tm, parameterValues, System.currentTimeMillis(), testResult); // Fix from ansgarkonermann // invokedMethod is used in the finally, which can be invoked if // any of the test listeners throws an exception, therefore, // invokedMethod must have a value before we get here runTestListeners(testResult); runInvokedMethodListeners(BEFORE_INVOCATION, invokedMethod, testResult); m_notifier.addInvokedMethod(invokedMethod); Method thisMethod = tm.getConstructorOrMethod().getMethod(); if(confInvocationPassed(tm, tm, testClass, instance)) { log(3, "Invoking " + tm.getRealClass().getName() + "." + tm.getMethodName()); Reporter.setCurrentTestResult(testResult); // If this method is a IHookable, invoke its run() method IHookable hookableInstance = IHookable.class.isAssignableFrom(tm.getRealClass()) ? (IHookable) instance : m_configuration.getHookable(); if (MethodHelper.calculateTimeOut(tm) <= 0) { if (hookableInstance != null) { MethodInvocationHelper.invokeHookable(instance, parameterValues, hookableInstance, thisMethod, testResult); } else { // Not a IHookable, invoke directly MethodInvocationHelper.invokeMethod(thisMethod, instance, parameterValues); } testResult.setStatus(ITestResult.SUCCESS); } else { // Method with a timeout MethodInvocationHelper.invokeWithTimeout(tm, instance, parameterValues, testResult, hookableInstance); } } else { testResult.setStatus(ITestResult.SKIP); } } catch(InvocationTargetException ite) { testResult.setThrowable(ite.getCause()); testResult.setStatus(ITestResult.FAILURE); } catch(ThreadExecutionException tee) { // wrapper for TestNGRuntimeException Throwable cause= tee.getCause(); if(TestNGRuntimeException.class.equals(cause.getClass())) { testResult.setThrowable(cause.getCause()); } else { testResult.setThrowable(cause); } testResult.setStatus(ITestResult.FAILURE); } catch(Throwable thr) { // covers the non-wrapper exceptions testResult.setThrowable(thr); testResult.setStatus(ITestResult.FAILURE); } finally { // Set end time ASAP testResult.setEndMillis(System.currentTimeMillis()); ExpectedExceptionsHolder expectedExceptionClasses = new ExpectedExceptionsHolder(m_annotationFinder, tm, new RegexpExpectedExceptionsHolder(m_annotationFinder, tm)); List results = Lists.newArrayList(testResult); handleInvocationResults(tm, results, expectedExceptionClasses, false, false /* collect results */, failureContext); // If this method has a data provider and just failed, memorize the number // at which it failed. // Note: we're not exactly testing that this method has a data provider, just // that it has parameters, so might have to revisit this if bugs get reported // for the case where this method has parameters that don't come from a data // provider if (testResult.getThrowable() != null && parameterValues.length > 0) { tm.addFailedInvocationNumber(parametersIndex); } // // Increment the invocation count for this method // tm.incrementCurrentInvocationCount(); // Run invokedMethodListeners after updating TestResult runInvokedMethodListeners(AFTER_INVOCATION, invokedMethod, testResult); runTestListeners(testResult); // Do not notify if will retry. if (!results.isEmpty()) { collectResults(tm, Collections.singleton(testResult)); } // // Invoke afterMethods only if // - lastTimeOnly is not set // - lastTimeOnly is set, and we are reaching the last invocationCount // invokeConfigurations(testClass, tm, filterConfigurationMethods(tm, afterMethods, false /* beforeMethods */), suite, params, parameterValues, instance, testResult); // // Invoke afterGroups configurations // invokeAfterGroupsConfigurations(testClass, tm, groupMethods, suite, params, instance); // Reset the test result last. If we do this too early, Reporter.log() // invocations from listeners will be discarded Reporter.setCurrentTestResult(null); } return testResult; } void collectResults(ITestNGMethod testMethod, Collection results) { for (ITestResult result : results) { // Collect the results final int status = result.getStatus(); if(ITestResult.SUCCESS == status) { m_notifier.addPassedTest(testMethod, result); } else if(ITestResult.SKIP == status) { m_notifier.addSkippedTest(testMethod, result); } else if(ITestResult.FAILURE == status) { m_notifier.addFailedTest(testMethod, result); } else if(ITestResult.SUCCESS_PERCENTAGE_FAILURE == status) { m_notifier.addFailedButWithinSuccessPercentageTest(testMethod, result); } else { assert false : "UNKNOWN STATUS:" + status; } } } /** * The array of methods contains @BeforeMethods if isBefore if true, @AfterMethods * otherwise. This function removes all the methods that should not be run at this * point because they are either firstTimeOnly or lastTimeOnly and we haven't reached * the current invocationCount yet */ private ITestNGMethod[] filterConfigurationMethods(ITestNGMethod tm, ITestNGMethod[] methods, boolean isBefore) { List result = Lists.newArrayList(); for (ITestNGMethod m : methods) { ConfigurationMethod cm = (ConfigurationMethod) m; if (isBefore) { if (! cm.isFirstTimeOnly() || (cm.isFirstTimeOnly() && tm.getCurrentInvocationCount() == 0)) { result.add(m); } } else { int current = tm.getCurrentInvocationCount(); boolean isLast = false; // If we have parameters, set the boolean if we are about to run // the last invocation if (tm.getParameterInvocationCount() > 0) { 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.getTotalInvocationCount() > 1) { isLast = current == tm.getTotalInvocationCount(); } if (! cm.isLastTimeOnly() || (cm.isLastTimeOnly() && isLast)) { result.add(m); } } } return result.toArray(new ITestNGMethod[result.size()]); } /** * invokeTestMethods() eventually converge here to invoke a single @Test method. *

* This method is responsible for actually invoking the method. It decides if the invocation * must be done: *

    *
  • through an IHookable
  • *
  • directly (through reflection)
  • *
  • in a separate thread (in case it needs to timeout) *
* *

* This method is also responsible for invoking @BeforeGroup, @BeforeMethod, @AfterMethod, @AfterGroup * if it is the case for the passed in @Test method. */ protected ITestResult invokeTestMethod(Object instance, final ITestNGMethod tm, Object[] parameterValues, int parametersIndex, XmlSuite suite, Map params, ITestClass testClass, ITestNGMethod[] beforeMethods, ITestNGMethod[] afterMethods, ConfigurationGroupMethods groupMethods, FailureContext failureContext) { // Mark this method with the current thread id tm.setId(ThreadUtil.currentThreadInfo()); ITestResult result = invokeMethod(instance, tm, parameterValues, parametersIndex, suite, params, testClass, beforeMethods, afterMethods, groupMethods, failureContext); return result; } /** * Filter all the beforeGroups methods and invoke only those that apply * to the current test method */ private void invokeBeforeGroupsConfigurations(ITestClass testClass, ITestNGMethod currentTestMethod, ConfigurationGroupMethods groupMethods, XmlSuite suite, Map params, Object instance) { synchronized(groupMethods) { List filteredMethods = Lists.newArrayList(); String[] groups = currentTestMethod.getGroups(); Map> beforeGroupMap = groupMethods.getBeforeGroupsMap(); for (String group : groups) { List methods = beforeGroupMap.get(group); if (methods != null) { filteredMethods.addAll(methods); } } ITestNGMethod[] beforeMethodsArray = filteredMethods.toArray(new ITestNGMethod[filteredMethods.size()]); // // Invoke the right groups methods // if(beforeMethodsArray.length > 0) { // don't pass the IClass or the instance as the method may be external // the invocation must be similar to @BeforeTest/@BeforeSuite invokeConfigurations(null, beforeMethodsArray, suite, params, null, /* no parameter values */ null); } // // Remove them so they don't get run again // groupMethods.removeBeforeGroups(groups); } } private void invokeAfterGroupsConfigurations(ITestClass testClass, ITestNGMethod currentTestMethod, ConfigurationGroupMethods groupMethods, XmlSuite suite, Map params, Object instance) { // Skip this if the current method doesn't belong to any group // (only a method that belongs to a group can trigger the invocation // of afterGroups methods) if (currentTestMethod.getGroups().length == 0) { return; } // See if the currentMethod is the last method in any of the groups // it belongs to Map filteredGroups = Maps.newHashMap(); String[] groups = currentTestMethod.getGroups(); synchronized(groupMethods) { for (String group : groups) { if (groupMethods.isLastMethodForGroup(group, currentTestMethod)) { filteredGroups.put(group, group); } } if(filteredGroups.isEmpty()) { return; } // The list of afterMethods to run Map afterMethods = Maps.newHashMap(); // Now filteredGroups contains all the groups for which we need to run the afterGroups // method. Find all the methods that correspond to these groups and invoke them. Map> map = groupMethods.getAfterGroupsMap(); for (String g : filteredGroups.values()) { List methods = map.get(g); // Note: should put them in a map if we want to make sure the same afterGroups // doesn't get run twice if (methods != null) { for (ITestNGMethod m : methods) { afterMethods.put(m, m); } } } // Got our afterMethods, invoke them ITestNGMethod[] afterMethodsArray = afterMethods.keySet().toArray(new ITestNGMethod[afterMethods.size()]); // don't pass the IClass or the instance as the method may be external // the invocation must be similar to @BeforeTest/@BeforeSuite invokeConfigurations(null, afterMethodsArray, suite, params, null, /* no parameter values */ null); // Remove the groups so they don't get run again groupMethods.removeAfterGroups(filteredGroups.keySet()); } } private Object[] getParametersFromIndex(Iterator parametersValues, int index) { while (parametersValues.hasNext()) { Object[] parameters = parametersValues.next(); if (index == 0) { return parameters; } index--; } return null; } int retryFailed(Object instance, final ITestNGMethod tm, XmlSuite suite, ITestClass testClass, ITestNGMethod[] beforeMethods, ITestNGMethod[] afterMethods, ConfigurationGroupMethods groupMethods, List result, int failureCount, ExpectedExceptionsHolder expectedExceptionHolder, ITestContext testContext, Map parameters, int parametersIndex) { final FailureContext failure = new FailureContext(); failure.count = failureCount; do { failure.instances = Lists.newArrayList (); Map allParameters = Maps.newHashMap(); /** * TODO: This recreates all the parameters every time when we only need * one specific set. Should optimize it by only recreating the set needed. */ ParameterBag bag = createParameters(tm, parameters, allParameters, suite, testContext, null /* fedInstance */); Object[] parameterValues = getParametersFromIndex(bag.parameterHolder.parameters, parametersIndex); result.add(invokeMethod(instance, tm, parameterValues, parametersIndex, suite, allParameters, testClass, beforeMethods, afterMethods, groupMethods, failure)); // It's already handled inside 'invokeMethod' but results not collected handleInvocationResults(tm, result, expectedExceptionHolder, true, true/* collect results */, failure); } while (!failure.instances.isEmpty()); return failure.count; } private ParameterBag createParameters(ITestNGMethod testMethod, Map parameters, Map allParameterNames, XmlSuite suite, ITestContext testContext, Object fedInstance) { Object instance; if (fedInstance != null) { instance = fedInstance; } else { instance = testMethod.getInstance(); } ParameterBag bag = handleParameters(testMethod, instance, allParameterNames, parameters, null, suite, testContext, fedInstance, null); return bag; } /** * Invoke all the test methods. Note the plural: the method passed in * parameter might be invoked several times if the test class it belongs * to has more than one instance (i.e., if an @Factory method has been * declared somewhere that returns several instances of this TestClass). * If no @Factory method was specified, testMethod will only be invoked * once. *

* Note that this method also takes care of invoking the beforeTestMethod * and afterTestMethod, if any. * * Note (alex): this method can be refactored to use a SingleTestMethodWorker that * directly invokes * {@link #invokeTestMethod(Object, ITestNGMethod, Object[], int, XmlSuite, Map, ITestClass, ITestNGMethod[], ITestNGMethod[], ConfigurationGroupMethods, FailureContext)} * and this would simplify the implementation (see how DataTestMethodWorker is used) */ @Override public List invokeTestMethods(ITestNGMethod testMethod, XmlSuite suite, Map testParameters, ConfigurationGroupMethods groupMethods, Object instance, ITestContext testContext) { // Potential bug here if the test method was declared on a parent class assert null != testMethod.getTestClass() : "COULDN'T FIND TESTCLASS FOR " + testMethod.getRealClass(); if (!MethodHelper.isEnabled(testMethod.getMethod(), m_annotationFinder)) { // return if the method is not enabled. No need to do any more calculations return Collections.emptyList(); } // By the time this testMethod to be invoked, // all dependencies should be already run or we need to skip this method, // so invocation count should not affect dependencies check final String okToProceed = checkDependencies(testMethod, testContext.getAllTestMethods()); if (okToProceed != null) { // // Not okToProceed. Test is being skipped // ITestResult result = registerSkippedTestResult(testMethod, null, System.currentTimeMillis(), new Throwable(okToProceed)); m_notifier.addSkippedTest(testMethod, result); return Collections.singletonList(result); } final Map parameters = testMethod.findMethodParameters(testContext.getCurrentXmlTest()); // For invocationCount > 1 and threadPoolSize > 1 run this method in its own pool thread. if (testMethod.getInvocationCount() > 1 && testMethod.getThreadPoolSize() > 1) { return invokePooledTestMethods(testMethod, suite, parameters, groupMethods, testContext); } long timeOutInvocationCount = testMethod.getInvocationTimeOut(); //FIXME: Is this correct? boolean onlyOne = testMethod.getThreadPoolSize() > 1 || timeOutInvocationCount > 0; int invocationCount = onlyOne ? 1 : testMethod.getInvocationCount(); ExpectedExceptionsHolder expectedExceptionHolder = new ExpectedExceptionsHolder(m_annotationFinder, testMethod, new RegexpExpectedExceptionsHolder(m_annotationFinder, testMethod)); final ITestClass testClass= testMethod.getTestClass(); final List result = Lists.newArrayList(); final FailureContext failure = new FailureContext(); final ITestNGMethod[] beforeMethods = filterMethods(testClass, testClass.getBeforeTestMethods(), CAN_RUN_FROM_CLASS); final ITestNGMethod[] afterMethods = filterMethods(testClass, testClass.getAfterTestMethods(), CAN_RUN_FROM_CLASS); while(invocationCount-- > 0) { if(false) { // Prevent code formatting } // // No threads, regular invocation // else { // Used in catch statement long start = System.currentTimeMillis(); Map allParameterNames = Maps.newHashMap(); ParameterBag bag = createParameters(testMethod, parameters, allParameterNames, suite, testContext, instance); if (bag.hasErrors()) { final ITestResult tr = bag.errorResult; tr.setStatus(ITestResult.SKIP); runTestListeners(tr); m_notifier.addSkippedTest(testMethod, tr); result.add(tr); continue; } Iterator allParameterValues = bag.parameterHolder.parameters; int parametersIndex = 0; try { List workers = Lists.newArrayList(); if (bag.parameterHolder.origin == ParameterOrigin.ORIGIN_DATA_PROVIDER && bag.parameterHolder.dataProviderHolder.annotation.isParallel()) { while (allParameterValues.hasNext()) { Object[] parameterValues = injectParameters(allParameterValues.next(), testMethod.getMethod(), testContext, null /* test result */); TestMethodWithDataProviderMethodWorker w = new TestMethodWithDataProviderMethodWorker(this, testMethod, parametersIndex, parameterValues, instance, suite, parameters, testClass, beforeMethods, afterMethods, groupMethods, expectedExceptionHolder, testContext, m_skipFailedInvocationCounts, invocationCount, failure.count, m_notifier); workers.add(w); // testng387: increment the param index in the bag. parametersIndex++; } PoolService> ps = new PoolService<>(suite.getDataProviderThreadCount()); List> r = ps.submitTasksAndWait(workers); for (List l2 : r) { result.addAll(l2); } } else { while (allParameterValues.hasNext()) { Object[] parameterValues = injectParameters(allParameterValues.next(), testMethod.getMethod(), testContext, null /* test result */); List tmpResults = Lists.newArrayList(); try { tmpResults.add(invokeTestMethod(instance, testMethod, parameterValues, parametersIndex, suite, parameters, testClass, beforeMethods, afterMethods, groupMethods, failure)); } finally { if (failure.instances.isEmpty()) { result.addAll(tmpResults); } else { for (Object failedInstance : failure.instances) { List retryResults = Lists.newArrayList(); failure.count = retryFailed( failedInstance, testMethod, suite, testClass, beforeMethods, afterMethods, groupMethods, retryResults, failure.count, expectedExceptionHolder, testContext, parameters, parametersIndex); result.addAll(retryResults); } } // // If we have a failure, skip all the // other invocationCounts // if (failure.count > 0 && (m_skipFailedInvocationCounts || testMethod.skipFailedInvocations())) { while (invocationCount-- > 0) { result.add(registerSkippedTestResult(testMethod, instance, System.currentTimeMillis(), null)); } break; } }// end finally parametersIndex++; } } } catch (Throwable cause) { ITestResult r = new TestResult(testMethod.getTestClass(), instance, testMethod, cause, start, System.currentTimeMillis(), m_testContext); r.setStatus(TestResult.FAILURE); result.add(r); runTestListeners(r); m_notifier.addFailedTest(testMethod, r); } // catch } } return result; } // invokeTestMethod private ITestResult registerSkippedTestResult(ITestNGMethod testMethod, Object instance, long start, Throwable throwable) { ITestResult result = new TestResult(testMethod.getTestClass(), instance, testMethod, throwable, start, System.currentTimeMillis(), m_testContext); result.setStatus(TestResult.SKIP); runTestListeners(result); return result; } /** * Gets an array of parameter values returned by data provider or the ones that * are injected based on parameter type. The method also checks for {@code NoInjection} * annotation * @param parameterValues parameter values from a data provider * @param method method to be invoked * @param context test context * @param testResult test result */ private Object[] injectParameters(Object[] parameterValues, Method method, ITestContext context, ITestResult testResult) throws TestNGException { List vResult = Lists.newArrayList(); int i = 0; int numValues = parameterValues.length; int numParams = method.getParameterTypes().length; if (numValues > numParams && ! method.isVarArgs()) { throw new TestNGException("The data provider is trying to pass " + numValues + " parameters but the method " + method.getDeclaringClass().getName() + "#" + method.getName() + " takes " + numParams); } // beyond this, numValues <= numParams for (Class cls : method.getParameterTypes()) { Annotation[] annotations = method.getParameterAnnotations()[i]; boolean noInjection = false; for (Annotation a : annotations) { if (a instanceof NoInjection) { noInjection = true; break; } } Object injected = Parameters.getInjectedParameter(cls, method, context, testResult); if (injected != null && ! noInjection) { vResult.add(injected); } else { try { if (method.isVarArgs()) vResult.add(parameterValues); else vResult.add(parameterValues[i++]); } catch (ArrayIndexOutOfBoundsException ex) { throw new TestNGException("The data provider is trying to pass " + numValues + " parameters but the method " + method.getDeclaringClass().getName() + "#" + method.getName() + " takes " + numParams + " and TestNG is unable in inject a suitable object", ex); } } } return vResult.toArray(new Object[vResult.size()]); } private ParameterBag handleParameters(ITestNGMethod testMethod, Object instance, Map allParameterNames, Map parameters, Object[] parameterValues, XmlSuite suite, ITestContext testContext, Object fedInstance, ITestResult testResult) { try { return new ParameterBag( Parameters.handleParameters(testMethod, allParameterNames, instance, new Parameters.MethodParameters(parameters, testMethod.findMethodParameters(testContext.getCurrentXmlTest()), parameterValues, testMethod.getMethod(), testContext, testResult), suite, m_annotationFinder, fedInstance)); } // catch(TestNGException ex) { // throw ex; // } catch(Throwable cause) { return new ParameterBag( new TestResult( testMethod.getTestClass(), instance, testMethod, cause, System.currentTimeMillis(), System.currentTimeMillis(), m_testContext)); } } /** * Invokes a method that has a specified threadPoolSize. */ private List invokePooledTestMethods(ITestNGMethod testMethod, XmlSuite suite, Map parameters, ConfigurationGroupMethods groupMethods, ITestContext testContext) { // // Create the workers // List> workers = Lists.newArrayList(); // Create one worker per invocationCount for (int i = 0; i < testMethod.getInvocationCount(); i++) { // we use clones for reporting purposes ITestNGMethod clonedMethod= testMethod.clone(); clonedMethod.setInvocationCount(1); clonedMethod.setThreadPoolSize(1); MethodInstance mi = new MethodInstance(clonedMethod); workers.add(new SingleTestMethodWorker(this, mi, suite, parameters, testContext)); } return runWorkers(testMethod, workers, testMethod.getThreadPoolSize(), groupMethods, suite, parameters); } static class FailureContext { int count = 0; List instances = Lists.newArrayList(); } void handleInvocationResults(ITestNGMethod testMethod, List result, ExpectedExceptionsHolder expectedExceptionsHolder, boolean triggerListeners, boolean collectResults, FailureContext failure) { // // Go through all the results and create a TestResult for each of them // List resultsToRetry = Lists.newArrayList(); for (ITestResult testResult : result) { Throwable ite= testResult.getThrowable(); int status= testResult.getStatus(); boolean handled = false; // Exception thrown? if (ite != null) { if (isSkipExceptionAndSkip(ite)){ status = ITestResult.SKIP; } // Invocation caused an exception, see if the method was annotated with @ExpectedException else if (expectedExceptionsHolder != null) { if (expectedExceptionsHolder.isExpectedException(ite)) { testResult.setStatus(ITestResult.SUCCESS); status = ITestResult.SUCCESS; } else { testResult.setThrowable(expectedExceptionsHolder.wrongException(ite)); status= ITestResult.FAILURE; } } else { handleException(ite, testMethod, testResult, failure.count++); handled = true; status = testResult.getStatus(); } } // No exception thrown, make sure we weren't expecting one else if(status != ITestResult.SKIP && expectedExceptionsHolder != null) { TestException exception = expectedExceptionsHolder.noException(testMethod); if (exception != null) { testResult.setThrowable(exception); status= ITestResult.FAILURE; } } IRetryAnalyzer retryAnalyzer = testMethod.getRetryAnalyzer(); boolean willRetry = retryAnalyzer != null && status == ITestResult.FAILURE && failure.instances != null && retryAnalyzer.retry(testResult); if (willRetry) { resultsToRetry.add(testResult); failure.instances.add(testResult.getInstance()); testResult.setStatus(ITestResult.SKIP); } else { testResult.setStatus(status); if (status == ITestResult.FAILURE && !handled) { handleException(ite, testMethod, testResult, failure.count++); } } if (collectResults) { // Collect the results collectResults(testMethod, Collections.singleton(testResult)); // if (triggerListeners && status != ITestResult.SUCCESS) { // runTestListeners(testResult); // } } } // for results removeResultsToRetryFromResult(resultsToRetry, result, failure); } private boolean isSkipExceptionAndSkip(Throwable ite) { return SkipException.class.isAssignableFrom(ite.getClass()) && ((SkipException) ite).isSkip(); } private void removeResultsToRetryFromResult(List resultsToRetry, List result, FailureContext failure) { if (resultsToRetry != null) { for (ITestResult res : resultsToRetry) { result.remove(res); failure.count--; } } } /** * To reduce thread contention and also to correctly handle thread-confinement * this method invokes the @BeforeGroups and @AfterGroups corresponding to the current @Test method. */ private List runWorkers(ITestNGMethod testMethod, List> workers, int threadPoolSize, ConfigurationGroupMethods groupMethods, XmlSuite suite, Map parameters) { // Invoke @BeforeGroups on the original method (reduce thread contention, // and also solve thread confinement) ITestClass testClass= testMethod.getTestClass(); Object[] instances = testClass.getInstances(true); for(Object instance: instances) { invokeBeforeGroupsConfigurations(testClass, testMethod, groupMethods, suite, parameters, instance); } long maxTimeOut= -1; // 10 seconds for(IWorker tmw : workers) { long mt= tmw.getTimeOut(); if(mt > maxTimeOut) { maxTimeOut= mt; } } ThreadUtil.execute(workers, threadPoolSize, maxTimeOut, true); // // Collect all the TestResults // List result = Lists.newArrayList(); for (IWorker tmw : workers) { if (tmw instanceof TestMethodWorker) { result.addAll(((TestMethodWorker)tmw).getTestResults()); } } for(Object instance: instances) { invokeAfterGroupsConfigurations(testClass, testMethod, groupMethods, suite, parameters, instance); } return result; } /** * Checks to see of the test method has certain dependencies that prevents * TestNG from executing it * @param testMethod test method being checked for * @return error message or null if dependencies have been run successfully */ private String checkDependencies(ITestNGMethod testMethod, ITestNGMethod[] allTestMethods) { // If this method is marked alwaysRun, no need to check for its dependencies if (testMethod.isAlwaysRun()) { return null; } // Any missing group? if (testMethod.getMissingGroup() != null && !testMethod.ignoreMissingDependencies()) { return "Method " + testMethod + " depends on nonexistent group \"" + testMethod.getMissingGroup() + "\""; } // If this method depends on groups, collect all the methods that // belong to these groups and make sure they have been run successfully final String[] groups = testMethod.getGroupsDependedUpon(); if (null != groups && groups.length > 0) { // Get all the methods that belong to the group depended upon for (String element : groups) { ITestNGMethod[] methods = MethodGroupsHelper.findMethodsThatBelongToGroup(testMethod, m_testContext.getAllTestMethods(), element); if (methods.length == 0 && !testMethod.ignoreMissingDependencies()) { // Group is missing return "Method " + testMethod + " depends on nonexistent group \"" + element + "\""; } if (!haveBeenRunSuccessfully(testMethod, methods)) { return "Method " + testMethod + " depends on not successfully finished methods in group \"" + element + "\""; } } } // depends on groups // If this method depends on other methods, make sure all these other // methods have been run successfully if (dependsOnMethods(testMethod)) { ITestNGMethod[] methods = MethodHelper.findDependedUponMethods(testMethod, allTestMethods); if (!haveBeenRunSuccessfully(testMethod, methods)) { return "Method " + testMethod + " depends on not successfully finished methods"; } } return null; } /** * @return the test results that apply to one of the instances of the testMethod. */ private Set keepSameInstances(ITestNGMethod method, Set results) { Set result = Sets.newHashSet(); for (ITestResult r : results) { final Object o = method.getInstance(); // Keep this instance if 1) It's on a different class or 2) It's on the same class // and on the same instance Object instance = r.getInstance() != null ? r.getInstance() : r.getMethod().getInstance(); if (r.getTestClass() != method.getTestClass() || instance == o) result.add(r); } return result; } /** * @return true if all the methods have been run successfully */ private boolean haveBeenRunSuccessfully(ITestNGMethod testMethod, ITestNGMethod[] methods) { // Make sure the method has been run successfully for (ITestNGMethod method : methods) { Set results = keepSameInstances(testMethod, m_notifier.getPassedTests(method)); Set failedAndSkippedMethods = Sets.newHashSet(); failedAndSkippedMethods.addAll(m_notifier.getFailedTests(method)); failedAndSkippedMethods.addAll(m_notifier.getSkippedTests(method)); Set failedresults = keepSameInstances(testMethod, failedAndSkippedMethods); // If failed results were returned on the same instance, then these tests didn't pass if (failedresults != null && failedresults.size() > 0) { return false; } for (ITestResult result : results) { if(!result.isSuccess()) { return false; } } } return true; } // private boolean containsInstance(Set failedresults, Object[] instances) { // for (ITestResult tr : failedresults) { // for (Object o : instances) { // if (o == tr.getInstance()) { // return true; // } // } // } // return false; // } /** * An exception was thrown by the test, determine if this method * should be marked as a failure or as failure_but_within_successPercentage */ private void handleException(Throwable throwable, ITestNGMethod testMethod, ITestResult testResult, int failureCount) { if (throwable != null) { testResult.setThrowable(throwable); } int successPercentage= testMethod.getSuccessPercentage(); int invocationCount= testMethod.getInvocationCount(); float numberOfTestsThatCanFail= ((100 - successPercentage) * invocationCount) / 100f; if(failureCount < numberOfTestsThatCanFail) { testResult.setStatus(ITestResult.SUCCESS_PERCENTAGE_FAILURE); } else { testResult.setStatus(ITestResult.FAILURE); } } static interface Predicate { boolean isTrue(K k, T v); } static class CanRunFromClassPredicate implements Predicate { @Override public boolean isTrue(ITestNGMethod m, IClass v) { return m.canRunFromClass(v); } } static class SameClassNamePredicate implements Predicate { @Override public boolean isTrue(ITestNGMethod m, IClass c) { return c == null || m.getTestClass().getName().equals(c.getName()); } } /** * @return Only the ITestNGMethods applicable for this testClass */ private ITestNGMethod[] filterMethods(IClass testClass, ITestNGMethod[] methods, Predicate predicate) { List vResult= Lists.newArrayList(); for(ITestNGMethod tm : methods) { if (predicate.isTrue(tm, testClass)) { log(10, "Keeping method " + tm + " for class " + testClass); vResult.add(tm); } else { log(10, "Filtering out method " + tm + " for class " + testClass); } } ITestNGMethod[] result= vResult.toArray(new ITestNGMethod[vResult.size()]); return result; } /** * @return true if this method depends on certain methods. */ private boolean dependsOnMethods(ITestNGMethod tm) { String[] methods = tm.getMethodsDependedUpon(); return null != methods && methods.length > 0; } private void runConfigurationListeners(ITestResult tr, boolean before) { if (before) { for(IConfigurationListener icl: m_notifier.getConfigurationListeners()) { if (icl instanceof IConfigurationListener2) { ((IConfigurationListener2) icl).beforeConfiguration(tr); } } } else { for(IConfigurationListener icl: m_notifier.getConfigurationListeners()) { switch(tr.getStatus()) { case ITestResult.SKIP: icl.onConfigurationSkip(tr); break; case ITestResult.FAILURE: icl.onConfigurationFailure(tr); break; case ITestResult.SUCCESS: icl.onConfigurationSuccess(tr); break; } } } } void runTestListeners(ITestResult tr) { runTestListeners(tr, m_notifier.getTestListeners()); } // TODO: move this from here as it is directly called from TestNG public static void runTestListeners(ITestResult tr, List listeners) { for (ITestListener itl : listeners) { switch(tr.getStatus()) { case ITestResult.SKIP: { itl.onTestSkipped(tr); break; } case ITestResult.SUCCESS_PERCENTAGE_FAILURE: { itl.onTestFailedButWithinSuccessPercentage(tr); break; } case ITestResult.FAILURE: { itl.onTestFailure(tr); break; } case ITestResult.SUCCESS: { itl.onTestSuccess(tr); break; } case ITestResult.STARTED: { itl.onTestStart(tr); break; } default: { assert false : "UNKNOWN STATUS:" + tr; } } } } private void log(int level, String s) { Utils.log("Invoker " + Thread.currentThread().hashCode(), level, s); } /** * This class holds a {@code ParameterHolder} or in case of an error, a non-null * {@code TestResult} containing the cause */ private static class ParameterBag { final ParameterHolder parameterHolder; final ITestResult errorResult; public ParameterBag(ParameterHolder parameterHolder) { this.parameterHolder = parameterHolder; this.errorResult = null; } public ParameterBag(ITestResult errorResult) { this.parameterHolder = null; this.errorResult = errorResult; } public boolean hasErrors() { return errorResult != null; } } } testng-testng-6.9.5/src/main/java/org/testng/internal/InvokedMethod.java0000755000175000017500000000442012551235562025622 0ustar eugeneeugenepackage org.testng.internal; import java.io.Serializable; import org.testng.IInvokedMethod; import org.testng.ITestNGMethod; import org.testng.ITestResult; public class InvokedMethod implements Serializable, IInvokedMethod { private static final long serialVersionUID = 2126127194102819222L; transient private Object m_instance; private ITestNGMethod m_testMethod; private Object[] m_parameters; private long m_date = System.currentTimeMillis(); private ITestResult m_testResult; public InvokedMethod(Object instance, ITestNGMethod method, Object[] parameters, long date, ITestResult testResult) { m_instance = instance; m_testMethod = method; m_parameters = parameters; m_date = date; m_testResult = testResult; } /* (non-Javadoc) * @see org.testng.internal.IInvokedMethod#isTestMethod() */ @Override public boolean isTestMethod() { return m_testMethod.isTest(); } @Override public String toString() { StringBuffer result = new StringBuffer(m_testMethod.toString()); for (Object p : m_parameters) { result.append(p).append(" "); } result.append(" ").append(m_instance != null ? m_instance.hashCode() : " "); return result.toString(); } /* (non-Javadoc) * @see org.testng.internal.IInvokedMethod#isConfigurationMethod() */ @Override public boolean 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) * @see org.testng.internal.IInvokedMethod#getTestMethod() */ @Override public ITestNGMethod getTestMethod() { return m_testMethod; } /* (non-Javadoc) * @see org.testng.internal.IInvokedMethod#getDate() */ @Override public long getDate() { return m_date; } @Override public ITestResult getTestResult() { return m_testResult; } } testng-testng-6.9.5/src/main/java/org/testng/internal/InvokeMethodRunnable.java0000644000175000017500000000426112551235562027145 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IHookable; import org.testng.ITestNGMethod; import org.testng.ITestResult; import java.lang.reflect.Method; /** * A Runnable Method invoker. * * @author Cedric Beust * @author Alexandru Popescu */ public interface ITestResultNotifier { Set getPassedTests(ITestNGMethod tm); Set getFailedTests(ITestNGMethod tm); Set getSkippedTests(ITestNGMethod tm); void addPassedTest(ITestNGMethod tm, ITestResult tr); void addSkippedTest(ITestNGMethod tm, ITestResult tr); void addFailedTest(ITestNGMethod tm, ITestResult tr); void addFailedButWithinSuccessPercentageTest(ITestNGMethod tm, ITestResult tr); void addInvokedMethod(InvokedMethod im); XmlTest getTest(); List getTestListeners(); List getConfigurationListeners(); } testng-testng-6.9.5/src/main/java/org/testng/internal/IResultListener2.java0000644000175000017500000000024212551235562026234 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IConfigurationListener2; public interface IResultListener2 extends IResultListener, IConfigurationListener2 { } testng-testng-6.9.5/src/main/java/org/testng/internal/IResultListener.java0000755000175000017500000000053412551235562026161 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IConfigurationListener; import org.testng.ITestListener; /** * A convenient interface to use when implementing listeners. * @author Alexandru Popescu */ public interface IResultListener extends ITestListener, IConfigurationListener { } testng-testng-6.9.5/src/main/java/org/testng/internal/IInvoker.java0000755000175000017500000000335012551235562024611 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IClass; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.ITestResult; import org.testng.xml.XmlSuite; import java.util.List; import java.util.Map; /** * This class defines an invoker. * * @author Cedric Beust */ public interface IInvoker { /** * Invoke configuration methods if they belong to the same TestClass * passed in parameter.. * * TODO: Calculate ahead of time which methods should be * invoked for each class. Might speed things up for users who invoke the same * test class with different parameters in the same suite run. * * @param testClass the class whose configuration methods must be run */ public void invokeConfigurations(IClass testClass, ITestNGMethod[] allMethods, XmlSuite suite, Map parameters, Object[] parameterValues, Object instance); /** * Invoke the given method * * @param testMethod * @param suite * @param parameters * @param groupMethods * * @return a list containing the results of the test methods invocations */ public List invokeTestMethods(ITestNGMethod testMethod, XmlSuite suite, Map parameters, ConfigurationGroupMethods groupMethods, Object instance, ITestContext testContext); } testng-testng-6.9.5/src/main/java/org/testng/internal/IConfiguration.java0000644000175000017500000000157412551235562026006 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IConfigurable; import org.testng.IConfigurationListener; import org.testng.IExecutionListener; import org.testng.IHookable; import org.testng.ITestObjectFactory; import org.testng.internal.annotations.IAnnotationFinder; import java.util.List; public interface IConfiguration { IAnnotationFinder getAnnotationFinder(); void setAnnotationFinder(IAnnotationFinder finder); ITestObjectFactory getObjectFactory(); void setObjectFactory(ITestObjectFactory m_objectFactory); IHookable getHookable(); void setHookable(IHookable h); IConfigurable getConfigurable(); void setConfigurable(IConfigurable c); List getExecutionListeners(); void addExecutionListener(IExecutionListener l); List getConfigurationListeners(); void addConfigurationListener(IConfigurationListener cl); } testng-testng-6.9.5/src/main/java/org/testng/internal/IBsh.java0000644000175000017500000000024612551235562023706 0ustar eugeneeugenepackage org.testng.internal; import org.testng.ITestNGMethod; public interface IBsh { boolean includeMethodFromExpression(String expression, ITestNGMethod tm); } testng-testng-6.9.5/src/main/java/org/testng/internal/Graph.java0000644000175000017500000002066212551235562024126 0ustar eugeneeugenepackage org.testng.internal; import org.testng.TestNGException; import org.testng.collections.Lists; import org.testng.collections.Maps; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; /** * Simple graph class to implement topological sort (used to sort methods based on what groups * they depend on). * * @author Cedric Beust, Aug 19, 2004 */ public class Graph { private static boolean m_verbose = false; private Map> m_nodes = Maps.newLinkedHashMap(); private List m_strictlySortedNodes = null; // A map of nodes that are not the predecessors of any node // (not needed for the algorithm but convenient to calculate // the parallel/sequential lists in TestNG). private Map> m_independentNodes = null; public void addNode(T tm) { ppp("ADDING NODE " + tm + " " + tm.hashCode()); m_nodes.put(tm, new Node<>(tm)); // Initially, all the nodes are put in the independent list as well } public Set getPredecessors(T node) { return findNode(node).getPredecessors().keySet(); } public boolean isIndependent(T object) { return m_independentNodes.containsKey(object); } private Node findNode(T object) { return m_nodes.get(object); } public void addPredecessor(T tm, T predecessor) { Node node = findNode(tm); if (null == node) { throw new TestNGException("Non-existing node: " + tm); } else { node.addPredecessor(predecessor); addNeighbor(tm, predecessor); // Remove these two nodes from the independent list if (null == m_independentNodes) { m_independentNodes = Maps.newHashMap(); m_independentNodes.putAll(m_nodes); } m_independentNodes.remove(predecessor); m_independentNodes.remove(tm); ppp(" REMOVED " + predecessor + " FROM INDEPENDENT OBJECTS"); } } private void addNeighbor(T tm, T predecessor) { findNode(tm).addNeighbor(findNode(predecessor)); } public Set getNeighbors(T t) { Set result = new HashSet<>(); for (Node n : findNode(t).getNeighbors()) { result.add(n.getObject()); } return result; } private Collection> getNodes() { return m_nodes.values(); } public Collection getNodeValues() { return m_nodes.keySet(); } /** * @return All the nodes that don't have any order with each other. */ public Set getIndependentNodes() { return m_independentNodes.keySet(); } /** * @return All the nodes that have an order with each other, sorted * in one of the valid sorts. */ public List getStrictlySortedNodes() { return m_strictlySortedNodes; } public void topologicalSort() { ppp("================ SORTING"); m_strictlySortedNodes = Lists.newArrayList(); if (null == m_independentNodes) { m_independentNodes = Maps.newHashMap(); } // // Clone the list of nodes but only keep those that are // not independent. // List> nodes2 = Lists.newArrayList(); for (Node n : getNodes()) { if (! isIndependent(n.getObject())) { ppp("ADDING FOR SORT: " + n.getObject()); nodes2.add(n.clone()); } else { ppp("SKIPPING INDEPENDENT NODE " + n); } } // // Sort the nodes alphabetically to make sure that methods of the same class // get run close to each other as much as possible // Collections.sort(nodes2); // // Sort // while (! nodes2.isEmpty()) { // // Find all the nodes that don't have any predecessors, add // them to the result and mark them for removal // Node node = findNodeWithNoPredecessors(nodes2); if (null == node) { List cycle = new Tarjan<>(this, nodes2.get(0).getObject()).getCycle(); StringBuilder sb = new StringBuilder(); sb.append("The following methods have cyclic dependencies:\n"); for (T m : cycle) { sb.append(m).append("\n"); } throw new TestNGException(sb.toString()); } else { m_strictlySortedNodes.add(node.getObject()); removeFromNodes(nodes2, node); } } ppp("=============== DONE SORTING"); if (m_verbose) { dumpSortedNodes(); } } private void dumpSortedNodes() { System.out.println("====== SORTED NODES"); for (T n : m_strictlySortedNodes) { System.out.println(" " + n); } System.out.println("====== END SORTED NODES"); } /** * Remove a node from a list of nodes and update the list of predecessors * for all the remaining nodes. */ private void removeFromNodes(List> nodes, Node node) { nodes.remove(node); for (Node n : nodes) { n.removePredecessor(node.getObject()); } } private static void ppp(String s) { if (m_verbose) { System.out.println("[Graph] " + s); } } private Node findNodeWithNoPredecessors(List> nodes) { for (Node n : nodes) { if (! n.hasPredecessors()) { return n; } } return null; } /** * @param o * @return A list of all the predecessors for o */ public List findPredecessors(T o) { // Locate the node Node node = findNode(o); if (null == node) { // This can happen if an interceptor returned new methods return Lists.newArrayList(); } // If we found the node, use breadth first search to find all // all of the predecessors of o. "result" is the growing list // of all predecessors. "visited" is the set of items we've // already encountered. "queue" is the queue of items whose // predecessors we haven't yet explored. LinkedList result = new LinkedList<>(); Set visited = new HashSet<>(); LinkedList queue = new LinkedList<>(); visited.add(o); queue.addLast(o); while (! queue.isEmpty()) { for (T obj : getPredecessors(queue.removeFirst())) { if (! visited.contains(obj)) { visited.add(obj); queue.addLast(obj); result.addFirst(obj); } } } return result; } @Override public String toString() { StringBuilder result = new StringBuilder("[Graph "); for (T node : m_nodes.keySet()) { result.append(findNode(node)).append(" "); } result.append("]"); return result.toString(); } ///// // class Node // public static class Node implements Comparable> { private T m_object = null; private Map m_predecessors = Maps.newHashMap(); public Node(T tm) { m_object = tm; } private Set> m_neighbors = new HashSet<>(); public void addNeighbor(Node neighbor) { m_neighbors.add(neighbor); } public Set> getNeighbors() { return m_neighbors; } @Override public Node clone() { Node result = new Node<>(m_object); for (T pred : m_predecessors.values()) { result.addPredecessor(pred); } return result; } public T getObject() { return m_object; } public Map getPredecessors() { return m_predecessors; } /** * * @return true if this predecessor was found and removed */ public boolean removePredecessor(T o) { boolean result = false; T pred = m_predecessors.get(o); if (null != pred) { result = null != m_predecessors.remove(o); if (result) { ppp(" REMOVED PRED " + o + " FROM NODE " + m_object); } else { ppp(" FAILED TO REMOVE PRED " + o + " FROM NODE " + m_object); } } return result; } @Override public String toString() { StringBuilder sb = new StringBuilder("[Node:" + m_object); sb.append(" pred:"); for (T o : m_predecessors.values()) { sb.append(" ").append(o); } sb.append("]"); String result = sb.toString(); return result; } public void addPredecessor(T tm) { ppp(" ADDING PREDECESSOR FOR " + m_object + " ==> " + tm); m_predecessors.put(tm, tm); } public boolean hasPredecessors() { return m_predecessors.size() > 0; } public boolean hasPredecessor(T m) { return m_predecessors.containsKey(m); } @Override public int compareTo(Node o) { return getObject().toString().compareTo(o.getObject().toString()); } } } testng-testng-6.9.5/src/main/java/org/testng/internal/FactoryMethod.java0000644000175000017500000000627512551235562025641 0ustar eugeneeugenepackage org.testng.internal; import java.util.Iterator; import java.util.List; import java.util.Map; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.TestNGException; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.xml.XmlTest; /** * This class represents a method annotated with @Factory * * @author Cedric Beust */ public class FactoryMethod extends BaseTestMethod { /** * */ private static final long serialVersionUID = -7329918821346197099L; private Object m_instance = null; private XmlTest m_xmlTest = null; private ITestContext m_testContext = null; public FactoryMethod(ConstructorOrMethod com, Object instance, XmlTest xmlTest, IAnnotationFinder annotationFinder, ITestContext testContext) { super(com.getName(), com, annotationFinder, instance); // Utils.checkInstanceOrStatic(instance, method); Class declaringClass = com.getDeclaringClass(); if (instance != null && ! declaringClass.isAssignableFrom(instance.getClass())) { throw new TestNGException("Mismatch between instance/method classes:" + instance.getClass() + " " + declaringClass); } m_instance = instance; m_xmlTest = xmlTest; m_testContext = testContext; NoOpTestClass tc = new NoOpTestClass(); tc.setTestClass(declaringClass); m_testClass = tc; } private static void ppp(String s) { System.out.println("[FactoryMethod] " + s); } public Object[] invoke() { List result = Lists.newArrayList(); Map allParameterNames = Maps.newHashMap(); Iterator parameterIterator = Parameters.handleParameters(this, allParameterNames, m_instance, new Parameters.MethodParameters(m_xmlTest.getAllParameters(), findMethodParameters(m_xmlTest), null, null, m_testContext, null /* testResult */), m_xmlTest.getSuite(), m_annotationFinder, null /* fedInstance */).parameters; try { while (parameterIterator.hasNext()) { Object[] parameters = parameterIterator.next(); Object[] testInstances; ConstructorOrMethod com = getConstructorOrMethod(); if (com.getMethod() != null) { testInstances = (Object[]) getMethod().invoke(m_instance, parameters); for (Object testInstance : testInstances) { result.add(testInstance); } } else { Object instance = com.getConstructor().newInstance(parameters); result.add(instance); } } } catch (Throwable t) { ConstructorOrMethod com = getConstructorOrMethod(); throw new TestNGException("The factory method " + com.getDeclaringClass() + "." + com.getName() + "() threw an exception", t); } return result.toArray(new Object[result.size()]); } @Override public ITestNGMethod clone() { throw new IllegalStateException("clone is not supported for FactoryMethod"); } } testng-testng-6.9.5/src/main/java/org/testng/internal/ExtraOutput.java0000755000175000017500000000123712551235562025371 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IExtraOutput; import org.testng.collections.Lists; import java.util.List; /** * This class is used by Reporter to store the extra output to be later * included in the HTML report: * - User-generated report * - Parameter info * * Created on Feb 16, 2006 * @author Cedric Beust */ public class ExtraOutput implements IExtraOutput { /** * */ private static final long serialVersionUID = 8195388419611912192L; private List m_parameterOutput = Lists.newArrayList(); @Override public List getParameterOutput() { return m_parameterOutput; } } testng-testng-6.9.5/src/main/java/org/testng/internal/ExpectedExceptionsHolder.java0000644000175000017500000000632012551235562030021 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IExpectedExceptionsHolder; import org.testng.ITestNGMethod; import org.testng.TestException; import org.testng.annotations.IExpectedExceptionsAnnotation; import org.testng.annotations.ITestAnnotation; import org.testng.internal.annotations.IAnnotationFinder; import java.util.Arrays; public class ExpectedExceptionsHolder { protected final IAnnotationFinder finder; protected final ITestNGMethod method; private final Class[] expectedClasses; private final IExpectedExceptionsHolder holder; protected ExpectedExceptionsHolder(IAnnotationFinder finder, ITestNGMethod method, IExpectedExceptionsHolder holder) { this.finder = finder; this.method = method; expectedClasses = findExpectedClasses(finder, method); this.holder = holder; } private static Class[] findExpectedClasses(IAnnotationFinder finder, ITestNGMethod method) { IExpectedExceptionsAnnotation expectedExceptions = finder.findAnnotation(method, IExpectedExceptionsAnnotation.class); // Old syntax if (expectedExceptions != null) { return expectedExceptions.getValue(); } // New syntax ITestAnnotation testAnnotation = finder.findAnnotation(method, ITestAnnotation.class); if (testAnnotation != null) { return testAnnotation.getExpectedExceptions(); } return new Class[0]; } /** * @param ite The exception that was just thrown * @return true if the exception that was just thrown is part of the * expected exceptions */ public boolean isExpectedException(Throwable ite) { if (!hasExpectedClasses()) { return false; } // TestException is the wrapper exception that TestNG will be throwing when an exception was // expected but not thrown if (ite.getClass() == TestException.class) { return false; } Class realExceptionClass= ite.getClass(); for (Class exception : expectedClasses) { if (exception.isAssignableFrom(realExceptionClass) && holder.isThrowableMatching(ite)) { return true; } } return false; } public Throwable wrongException(Throwable ite) { if (!hasExpectedClasses()) { return ite; } if (holder.isThrowableMatching(ite)) { return new TestException("Expected exception of " + getExpectedExceptionsPluralize() + " but got " + ite, ite); } else { return new TestException(holder.getWrongExceptionMessage(ite), ite); } } public TestException noException(ITestNGMethod testMethod) { if (!hasExpectedClasses()) { return null; } return new TestException("Method " + testMethod + " should have thrown an exception of " + getExpectedExceptionsPluralize()); } private boolean hasExpectedClasses() { return expectedClasses != null && expectedClasses.length > 0; } private String getExpectedExceptionsPluralize() { StringBuilder sb = new StringBuilder(); if (expectedClasses.length > 1) { sb.append("any of types "); sb.append(Arrays.toString(expectedClasses)); } else { sb.append("type "); sb.append(expectedClasses[0]); } return sb.toString(); } } testng-testng-6.9.5/src/main/java/org/testng/internal/EclipseInterface.java0000644000175000017500000000131712551235562026266 0ustar eugeneeugenepackage org.testng.internal; /** * Symbols in this class are used by the Eclipse plug-in, do not modify them * without updating the plug-in as well. * * @author Cedric Beust * @since Aug 25, 2012 */ public class EclipseInterface { public static final Character OPENING_CHARACTER = '['; public static final Character CLOSING_CHARACTER = ']'; public static final String ASSERT_LEFT = "expected " + OPENING_CHARACTER; public static final String ASSERT_LEFT2 = "expected not same " + OPENING_CHARACTER; public static final String ASSERT_MIDDLE = CLOSING_CHARACTER + " but found " + OPENING_CHARACTER; public static final String ASSERT_RIGHT = Character.toString(CLOSING_CHARACTER); } testng-testng-6.9.5/src/main/java/org/testng/internal/DynamicGraph.java0000644000175000017500000001350312551235562025427 0ustar eugeneeugenepackage org.testng.internal; import org.testng.collections.ListMultiMap; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.collections.Sets; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Set; /** * Representation of the graph of methods. */ public class DynamicGraph { private static final boolean DEBUG = false; private Set m_nodesReady = Sets.newLinkedHashSet(); private Set m_nodesRunning = Sets.newLinkedHashSet(); private Set m_nodesFinished = Sets.newLinkedHashSet(); private Comparator m_nodeComparator = null; private ListMultiMap m_dependedUpon = Maps.newListMultiMap(); private ListMultiMap m_dependingOn = Maps.newListMultiMap(); public static enum Status { READY, RUNNING, FINISHED } /** * Define a comparator for the nodes of this graph, which will be used * to order the free nodes when they are asked. */ public void setComparator(Comparator c) { m_nodeComparator = c; } /** * Add a node to the graph. */ public void addNode(T node) { m_nodesReady.add(node); } /** * Add an edge between two nodes, which don't have to already be in the graph * (they will be added by this method). */ public void addEdge(T from, T to) { addNode(from); addNode(to); m_dependingOn.put(to, from); m_dependedUpon.put(from, to); } /** * @return a set of all the nodes that don't depend on any other nodes. */ public List getFreeNodes() { List result = Lists.newArrayList(); for (T m : m_nodesReady) { // A node is free if... List du = m_dependedUpon.get(m); // - no other nodes depend on it if (!m_dependedUpon.containsKey(m)) { result.add(m); } else if (getUnfinishedNodes(du).size() == 0) { result.add(m); } } // Sort the free nodes if requested (e.g. priorities) if (result != null && ! result.isEmpty()) { if (m_nodeComparator != null) { Collections.sort(result, m_nodeComparator); ppp("Nodes after sorting:" + result.get(0)); } } return result; } /** * @return a list of all the nodes that have a status other than FINISHED. */ private Collection getUnfinishedNodes(List nodes) { Set result = Sets.newHashSet(); for (T node : nodes) { if (m_nodesReady.contains(node) || m_nodesRunning.contains(node)) { result.add(node); } } return result; } /** * Set the status for a set of nodes. */ public void setStatus(Collection nodes, Status status) { for (T n : nodes) { setStatus(n, status); } } /** * Set the status for a node. */ public void setStatus(T node, Status status) { removeNode(node); switch(status) { case READY: m_nodesReady.add(node); break; case RUNNING: m_nodesRunning.add(node); break; case FINISHED: m_nodesFinished.add(node); break; default: throw new IllegalArgumentException(); } } private void removeNode(T node) { if (!m_nodesReady.remove(node)) { if (!m_nodesRunning.remove(node)) { m_nodesFinished.remove(node); } } } /** * @return the number of nodes in this graph. */ public int getNodeCount() { int result = m_nodesReady.size() + m_nodesRunning.size() + m_nodesFinished.size(); return result; } public int getNodeCountWithStatus(Status status) { switch(status) { case READY: return m_nodesReady.size(); case RUNNING: return m_nodesRunning.size(); case FINISHED: return m_nodesFinished.size(); default: throw new IllegalArgumentException(); } } private static void ppp(String string) { if (DEBUG) { System.out.println(" [GroupThreadPoolExecutor] " + Thread.currentThread().getId() + " " + string); } } @Override public String toString() { StringBuilder result = new StringBuilder("[DynamicGraph "); result.append("\n Ready:" + m_nodesReady); result.append("\n Running:" + m_nodesRunning); result.append("\n Finished:" + m_nodesFinished); result.append("\n Edges:\n"); for (Map.Entry> es : m_dependingOn.entrySet()) { result.append(" " + es.getKey() + "\n"); for (T t : es.getValue()) { result.append(" " + t + "\n"); } } result.append("]"); return result.toString(); } private String getName(T t) { String s = t.toString(); int n1 = s.lastIndexOf('.') + 1; int n2 = s.indexOf('('); return s.substring(n1, n2); } /** * @return a .dot file (GraphViz) version of this graph. */ public String toDot() { String FREE = "[style=filled color=yellow]"; String RUNNING = "[style=filled color=green]"; String FINISHED = "[style=filled color=grey]"; StringBuilder result = new StringBuilder("digraph g {\n"); List freeNodes = getFreeNodes(); String color; for (T n : m_nodesReady) { color = freeNodes.contains(n) ? FREE : ""; result.append(" " + getName(n) + color + "\n"); } for (T n : m_nodesRunning) { color = freeNodes.contains(n) ? FREE : RUNNING; result.append(" " + getName(n) + color + "\n"); } for (T n : m_nodesFinished) { result.append(" " + getName(n) + FINISHED+ "\n"); } result.append("\n"); for (T k : m_dependingOn.keySet()) { List nodes = m_dependingOn.get(k); for (T n : nodes) { String dotted = m_nodesFinished.contains(k) ? "style=dotted" : ""; result.append(" " + getName(k) + " -> " + getName(n) + " [dir=back " + dotted + "]\n"); } } result.append("}\n"); return result.toString(); } public ListMultiMap getEdges() { return m_dependingOn; } } testng-testng-6.9.5/src/main/java/org/testng/internal/Dynamic.java0000644000175000017500000000045612551235562024450 0ustar eugeneeugenepackage org.testng.internal; /** * Determine the availability of certain jar files at runtime. */ public class Dynamic { public static boolean hasBsh() { try { Class.forName("bsh.Interpreter"); return true; } catch (ClassNotFoundException e) { return false; } } } testng-testng-6.9.5/src/main/java/org/testng/internal/DefaultMethodSelectorContext.java0000755000175000017500000000134612551235562030661 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IMethodSelectorContext; import org.testng.collections.Maps; import java.util.Map; /** * Simple implementation of IMethodSelectorContext * * Created on Jan 3, 2007 * @author Cedric Beust */ public class DefaultMethodSelectorContext implements IMethodSelectorContext { private Map m_userData = Maps.newHashMap(); private boolean m_isStopped = false; @Override public Map getUserData() { return m_userData; } @Override public boolean isStopped() { return m_isStopped; } @Override public void setStopped(boolean stopped) { m_isStopped = stopped; } } testng-testng-6.9.5/src/main/java/org/testng/internal/DataProviderHolder.java0000755000175000017500000000075412551235562026612 0ustar eugeneeugenepackage org.testng.internal; import org.testng.annotations.IDataProviderAnnotation; 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, Object instance) { this.annotation = annotation; this.method = method; this.instance = instance; } } testng-testng-6.9.5/src/main/java/org/testng/internal/ConstructorOrMethod.java0000644000175000017500000000424312551235562027051 0ustar eugeneeugenepackage org.testng.internal; import java.lang.reflect.Constructor; import java.lang.reflect.Method; /** * Encapsulation of either a method or a constructor. * * @author Cedric Beust */ public class ConstructorOrMethod { private Method m_method; private Constructor m_constructor; private boolean m_enabled = true; public ConstructorOrMethod(Method m) { m_method = m; } public ConstructorOrMethod(Constructor c) { m_constructor = c; } public Class getDeclaringClass() { return getMethod() != null ? getMethod().getDeclaringClass() : getConstructor().getDeclaringClass(); } public String getName() { return getMethod() != null ? getMethod().getName() : getConstructor().getName(); } public Class[] getParameterTypes() { return getMethod() != null ? getMethod().getParameterTypes() : getConstructor().getParameterTypes(); } public Method getMethod() { return m_method; } public Constructor getConstructor() { return m_constructor; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((getConstructor() == null) ? 0 : getConstructor().hashCode()); result = prime * result + ((getMethod() == null) ? 0 : getMethod().hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ConstructorOrMethod other = (ConstructorOrMethod) obj; if (getConstructor() == null) { if (other.getConstructor() != null) return false; } else if (!getConstructor().equals(other.getConstructor())) return false; if (getMethod() == null) { if (other.getMethod() != null) return false; } else if (!getMethod().equals(other.getMethod())) return false; return true; } public void setEnabled(boolean enabled) { m_enabled = enabled; } public boolean getEnabled() { return m_enabled; } @Override public String toString() { if (m_method != null) return m_method.toString(); else return m_constructor.toString(); } } testng-testng-6.9.5/src/main/java/org/testng/internal/Constants.java0000755000175000017500000000604712551235562025045 0ustar eugeneeugenepackage org.testng.internal; import java.util.Map; import java.util.Properties; import org.testng.ITestResult; import org.testng.collections.Maps; /** * Constants used by TestNG * * @author Cedric Beust, May 2, 2004 * */ public class Constants { private static final String NAMESPACE = "testng"; //////// // // Properties // public static final String PROP_OUTPUT_DIR = NAMESPACE + "." + "outputDir"; // public static final String PROP_NAME = NAMESPACE + "." + "name"; // public static final String PROP_INCLUDED_GROUPS = NAMESPACE + "." + "includedGroups"; // public static final String PROP_EXCLUDED_GROUPS = NAMESPACE + "." + "excludedGroups"; // public static final String PROP_CLASS_NAMES = NAMESPACE + "." + "classNames"; // public static final String PROP_VERBOSE = NAMESPACE + "." + "verbose"; // public static final String PROP_JUNIT= NAMESPACE + "." + "junit"; // public static final String PROP_QUIET= NAMESPACE + "." + "quiet"; // public static final String PROP_GROUP= NAMESPACE + "." + "group"; private static final TestNGProperty[] COMMAND_LINE_PARAMETERS = { new TestNGProperty("-d", PROP_OUTPUT_DIR, "Directory where the result files will be created.", "test-output"), }; private static final Map m_propertiesByName = Maps.newHashMap(); static { // for (int i = 0; i < PROPERTIES.length; i++) { // m_propertiesByName.put(PROPERTIES[i].getName(), PROPERTIES[i]); // } for (TestNGProperty element : COMMAND_LINE_PARAMETERS) { m_propertiesByName.put(element.getName(), element); } } private static TestNGProperty getProperty(String propertyName) { TestNGProperty result = m_propertiesByName.get(propertyName); assert null != result : "Unknown property : " + propertyName; return result; } public static String getPropertyValue(Properties p, String propertyName) { TestNGProperty r= getProperty(propertyName); assert null != r : "Unknown property : " + propertyName; String result = p.getProperty(r.getName()); return result; } public static boolean getBooleanPropertyValue(Properties properties, String propertyName) { TestNGProperty p = getProperty(propertyName); String r = properties.getProperty(propertyName, p.getDefault()); boolean result = "true".equalsIgnoreCase(r); return Boolean.valueOf(result); } public static int getIntegerPropertyValue(Properties properties, String propertyName) { TestNGProperty p = getProperty(propertyName); String r = properties.getProperty(propertyName, p.getDefault()); int result = Integer.parseInt(r); return result; } public static String getDefaultValueFor(String propertyName) { TestNGProperty p = getProperty(propertyName); return p.getDefault(); } public static String displayStatus(int status) { if (ITestResult.SKIP == status) { return "SKIP"; } else if (ITestResult.SUCCESS == status) { return "SUCCESS"; } else if (ITestResult.FAILURE == status) { return "FAILURE"; } else { return "UNKNOWN_STATUS"; } } } testng-testng-6.9.5/src/main/java/org/testng/internal/ConfigurationMethod.java0000755000175000017500000003442412551235562027041 0ustar eugeneeugenepackage org.testng.internal; import java.lang.reflect.Method; import java.util.Collections; import java.util.List; import java.util.Map; import org.testng.ITestNGMethod; import org.testng.annotations.IAnnotation; import org.testng.annotations.IConfigurationAnnotation; import org.testng.annotations.ITestAnnotation; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.internal.annotations.AnnotationHelper; import org.testng.internal.annotations.ConfigurationAnnotation; import org.testng.internal.annotations.IAfterClass; import org.testng.internal.annotations.IAfterGroups; import org.testng.internal.annotations.IAfterMethod; import org.testng.internal.annotations.IAfterSuite; import org.testng.internal.annotations.IAfterTest; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.internal.annotations.IBeforeClass; import org.testng.internal.annotations.IBeforeGroups; import org.testng.internal.annotations.IBeforeMethod; import org.testng.internal.annotations.IBeforeSuite; import org.testng.internal.annotations.IBeforeTest; public class ConfigurationMethod extends BaseTestMethod { /** * */ private static final long serialVersionUID = -6537771498553619645L; private final boolean m_isBeforeSuiteConfiguration; private final boolean m_isAfterSuiteConfiguration; private final boolean m_isBeforeTestConfiguration; private final boolean m_isAfterTestConfiguration; private final boolean m_isBeforeClassConfiguration; private final boolean m_isAfterClassConfiguration; private final boolean m_isBeforeMethodConfiguration; private final boolean m_isAfterMethodConfiguration; private boolean m_inheritGroupsFromTestClass = false; private ConfigurationMethod(ConstructorOrMethod com, IAnnotationFinder annotationFinder, boolean isBeforeSuite, boolean isAfterSuite, boolean isBeforeTest, boolean isAfterTest, boolean isBeforeClass, boolean isAfterClass, boolean isBeforeMethod, boolean isAfterMethod, String[] beforeGroups, String[] afterGroups, boolean initialize, Object instance) { super(com.getName(), com, annotationFinder, instance); if(initialize) { init(); } m_isBeforeSuiteConfiguration = isBeforeSuite; m_isAfterSuiteConfiguration = isAfterSuite; m_isBeforeTestConfiguration = isBeforeTest; m_isAfterTestConfiguration = isAfterTest; m_isBeforeClassConfiguration = isBeforeClass; m_isAfterClassConfiguration = isAfterClass; m_isBeforeMethodConfiguration = isBeforeMethod; m_isAfterMethodConfiguration = isAfterMethod; m_beforeGroups = beforeGroups; m_afterGroups = afterGroups; } /** * @deprecated use #ConfigurationMethod(ConstructorOrMethod,...) instead. */ @Deprecated public ConfigurationMethod(Method method, IAnnotationFinder annotationFinder, boolean isBeforeSuite, boolean isAfterSuite, boolean isBeforeTest, boolean isAfterTest, boolean isBeforeClass, boolean isAfterClass, boolean isBeforeMethod, boolean isAfterMethod, String[] beforeGroups, String[] afterGroups, Object instance) { this(new ConstructorOrMethod(method), annotationFinder, isBeforeSuite, isAfterSuite, isBeforeTest, isAfterTest, isBeforeClass, isAfterClass, isBeforeMethod, isAfterMethod, beforeGroups, afterGroups, instance); } public ConfigurationMethod(ConstructorOrMethod com, IAnnotationFinder annotationFinder, boolean isBeforeSuite, boolean isAfterSuite, boolean isBeforeTest, boolean isAfterTest, boolean isBeforeClass, boolean isAfterClass, boolean isBeforeMethod, boolean isAfterMethod, String[] beforeGroups, String[] afterGroups, Object instance) { this(com, annotationFinder, isBeforeSuite, isAfterSuite, isBeforeTest, isAfterTest, isBeforeClass, isAfterClass, isBeforeMethod, isAfterMethod, beforeGroups, afterGroups, true, instance); } private static ITestNGMethod[] createMethods(ITestNGMethod[] methods, IAnnotationFinder finder, boolean isBeforeSuite, boolean isAfterSuite, boolean isBeforeTest, boolean isAfterTest, boolean isBeforeClass, boolean isAfterClass, boolean isBeforeMethod, boolean isAfterMethod, String[] beforeGroups, String[] afterGroups, Object instance) { List result = Lists.newArrayList(); for (ITestNGMethod method : methods) { result.add(new ConfigurationMethod(method.getConstructorOrMethod(), finder, isBeforeSuite, isAfterSuite, isBeforeTest, isAfterTest, isBeforeClass, isAfterClass, isBeforeMethod, isAfterMethod, new String[0], new String[0], instance)); } return result.toArray(new ITestNGMethod[result.size()]); } public static ITestNGMethod[] createSuiteConfigurationMethods(ITestNGMethod[] methods, IAnnotationFinder annotationFinder, boolean isBefore, Object instance) { return createMethods(methods, annotationFinder, isBefore, !isBefore, false, false, false, false, false, false, new String[0], new String[0], instance); } public static ITestNGMethod[] createTestConfigurationMethods(ITestNGMethod[] methods, IAnnotationFinder annotationFinder, boolean isBefore, Object instance) { return createMethods(methods, annotationFinder, false, false, isBefore, !isBefore, false, false, false, false, new String[0], new String[0], instance); } public static ITestNGMethod[] createClassConfigurationMethods(ITestNGMethod[] methods, IAnnotationFinder annotationFinder, boolean isBefore, Object instance) { return createMethods(methods, annotationFinder, false, false, false, false, isBefore, !isBefore, false, false, new String[0], new String[0], instance); } public static ITestNGMethod[] createBeforeConfigurationMethods(ITestNGMethod[] methods, IAnnotationFinder annotationFinder, boolean isBefore, Object instance) { ITestNGMethod[] result = new ITestNGMethod[methods.length]; for(int i = 0; i < methods.length; i++) { result[i] = new ConfigurationMethod(methods[i].getConstructorOrMethod(), annotationFinder, false, false, false, false, false, false, false, false, isBefore ? methods[i].getBeforeGroups() : new String[0], new String[0], instance); } return result; } public static ITestNGMethod[] createAfterConfigurationMethods(ITestNGMethod[] methods, IAnnotationFinder annotationFinder, boolean isBefore, Object instance) { ITestNGMethod[] result = new ITestNGMethod[methods.length]; for(int i = 0; i < methods.length; i++) { result[i] = new ConfigurationMethod(methods[i].getConstructorOrMethod(), annotationFinder, false, false, false, false, false, false, false, false, new String[0], isBefore ? new String[0] : methods[i].getAfterGroups(), instance); } return result; } public static ITestNGMethod[] createTestMethodConfigurationMethods(ITestNGMethod[] methods, IAnnotationFinder annotationFinder, boolean isBefore, Object instance) { return createMethods(methods, annotationFinder, false, false, false, false, false, false, isBefore, !isBefore, new String[0], new String[0], instance); } /** * @return Returns the isAfterClassConfiguration. */ @Override public boolean isAfterClassConfiguration() { return m_isAfterClassConfiguration; } /** * @return Returns the isAfterMethodConfiguration. */ @Override public boolean isAfterMethodConfiguration() { return m_isAfterMethodConfiguration; } /** * @return Returns the isBeforeClassConfiguration. */ @Override public boolean isBeforeClassConfiguration() { return m_isBeforeClassConfiguration; } /** * @return Returns the isBeforeMethodConfiguration. */ @Override public boolean isBeforeMethodConfiguration() { return m_isBeforeMethodConfiguration; } /** * @return Returns the isAfterSuiteConfiguration. */ @Override public boolean isAfterSuiteConfiguration() { return m_isAfterSuiteConfiguration; } /** * @return Returns the isBeforeSuiteConfiguration. */ @Override public boolean isBeforeSuiteConfiguration() { return m_isBeforeSuiteConfiguration; } @Override public boolean isBeforeTestConfiguration() { return m_isBeforeTestConfiguration; } @Override public boolean isAfterTestConfiguration() { return m_isAfterTestConfiguration; } @Override public boolean isBeforeGroupsConfiguration() { return m_beforeGroups != null && m_beforeGroups.length > 0; } @Override public boolean isAfterGroupsConfiguration() { return m_afterGroups != null && m_afterGroups.length > 0; } private boolean inheritGroupsFromTestClass() { return m_inheritGroupsFromTestClass; } private void init() { IAnnotation a = AnnotationHelper.findConfiguration(m_annotationFinder, m_method.getMethod()); IConfigurationAnnotation annotation = (IConfigurationAnnotation) a; if (a != null) { m_inheritGroupsFromTestClass = annotation.getInheritGroups(); setEnabled(annotation.getEnabled()); setDescription(annotation.getDescription()); } if (annotation != null && annotation.isFakeConfiguration()) { if (annotation.getBeforeSuite()) { initGroups(IBeforeSuite.class); } if (annotation.getAfterSuite()) { initGroups(IAfterSuite.class); } if (annotation.getBeforeTest()) { initGroups(IBeforeTest.class); } if (annotation.getAfterTest()) { initGroups(IAfterTest.class); } if (annotation.getBeforeGroups().length != 0) { initGroups(IBeforeGroups.class); } if (annotation.getAfterGroups().length != 0) { initGroups(IAfterGroups.class); } if (annotation.getBeforeTestClass()) { initGroups(IBeforeClass.class); } if (annotation.getAfterTestClass()) { initGroups(IAfterClass.class); } if (annotation.getBeforeTestMethod()) { initGroups(IBeforeMethod.class); } if (annotation.getAfterTestMethod()) { initGroups(IAfterMethod.class); } } else { initGroups(IConfigurationAnnotation.class); } // If this configuration method has inherit-groups=true, add the groups // defined in the @Test class if (inheritGroupsFromTestClass()) { ITestAnnotation classAnnotation = m_annotationFinder.findAnnotation(m_methodClass, ITestAnnotation.class); if (classAnnotation != null) { String[] groups = classAnnotation.getGroups(); Map newGroups = Maps.newHashMap(); for (String g : getGroups()) { newGroups.put(g, g); } if (groups != null) { for (String g : groups) { newGroups.put(g, g); } setGroups(newGroups.values().toArray(new String[newGroups.size()])); } } } if (annotation != null) { setTimeOut(annotation.getTimeOut()); } } private static void ppp(String s) { System.out.println("[ConfigurationMethod] " + s); } @Override public ConfigurationMethod clone() { ConfigurationMethod clone= new ConfigurationMethod(getConstructorOrMethod(), getAnnotationFinder(), isBeforeSuiteConfiguration(), isAfterSuiteConfiguration(), isBeforeTestConfiguration(), isAfterTestConfiguration(), isBeforeClassConfiguration(), isAfterClassConfiguration(), isBeforeMethodConfiguration(), isAfterMethodConfiguration(), getBeforeGroups(), getAfterGroups(), false /* do not call init() */, getInstance() ); clone.m_testClass= getTestClass(); clone.setDate(getDate()); clone.setGroups(getGroups()); clone.setGroupsDependedUpon(getGroupsDependedUpon(), Collections.emptyList()); clone.setMethodsDependedUpon(getMethodsDependedUpon()); clone.setAlwaysRun(isAlwaysRun()); clone.setMissingGroup(getMissingGroup()); clone.setDescription(getDescription()); clone.setEnabled(getEnabled()); clone.setParameterInvocationCount(getParameterInvocationCount()); clone.m_inheritGroupsFromTestClass= inheritGroupsFromTestClass(); return clone; } public boolean isFirstTimeOnly() { boolean result = false; IAnnotation before = m_annotationFinder.findAnnotation(getMethod(), IBeforeMethod.class); if (before != null) { result = ((ConfigurationAnnotation) before).isFirstTimeOnly(); } return result; } public boolean isLastTimeOnly() { boolean result = false; IAnnotation before = m_annotationFinder.findAnnotation(getMethod(), IAfterMethod.class); if (before != null) { result = ((ConfigurationAnnotation) before).isLastTimeOnly(); } return result; } } testng-testng-6.9.5/src/main/java/org/testng/internal/ConfigurationGroupMethods.java0000755000175000017500000001116412551235562030235 0ustar eugeneeugenepackage org.testng.internal; import org.testng.ITestNGMethod; import org.testng.collections.Lists; import org.testng.collections.Maps; import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.Map; /** * This class wraps access to beforeGroups and afterGroups methods, * since they are passed around the various invokers and potentially * modified in different threads. * * @author Cedric Beust * @author Alexandru Popescu * @since 5.3 (Mar 2, 2006) */ public class ConfigurationGroupMethods implements Serializable { /** Use serialVersionUID for interoperability. */ private final static long serialVersionUID= 1660798519864898480L; /** The list of beforeGroups methods keyed by the name of the group */ private final Map> m_beforeGroupsMethods; /** The list of afterGroups methods keyed by the name of the group */ private final Map> m_afterGroupsMethods; /** The list of all test methods */ private final ITestNGMethod[] m_allMethods; /**A map that returns the last method belonging to the given group */ private Map> m_afterGroupsMap= null; public ConfigurationGroupMethods(ITestNGMethod[] allMethods, Map> beforeGroupsMethods, Map> afterGroupsMethods) { m_allMethods= allMethods; m_beforeGroupsMethods= beforeGroupsMethods; m_afterGroupsMethods= afterGroupsMethods; } public Map> getBeforeGroupsMethods() { return m_beforeGroupsMethods; } public Map> getAfterGroupsMethods() { return m_afterGroupsMethods; } /** * @return true if the passed method is the last to run for the group. * This method is used to figure out when is the right time to invoke * afterGroups methods. */ public synchronized boolean isLastMethodForGroup(String group, ITestNGMethod method) { // If we have more invocation to do, this is not the last one yet int invocationCount= method.getCurrentInvocationCount(); if(invocationCount < (method.getInvocationCount() * method.getParameterInvocationCount())) { return false; } // Lazy initialization since we might never be called if(m_afterGroupsMap == null) { m_afterGroupsMap= initializeAfterGroupsMap(); } List methodsInGroup= m_afterGroupsMap.get(group); if(null == methodsInGroup || methodsInGroup.isEmpty()) { return false; } methodsInGroup.remove(method); // Note: == is not good enough here as we may work with ITestNGMethod clones return methodsInGroup.isEmpty(); } private synchronized Map> initializeAfterGroupsMap() { Map> result= Maps.newHashMap(); for(ITestNGMethod m : m_allMethods) { String[] groups= m.getGroups(); for(String g : groups) { List methodsInGroup= result.get(g); if(null == methodsInGroup) { methodsInGroup= Lists.newArrayList(); result.put(g, methodsInGroup); } methodsInGroup.add(m); } } return result; } public synchronized void removeBeforeMethod(String group, ITestNGMethod method) { List methods= m_beforeGroupsMethods.get(group); if(methods != null) { Object success= methods.remove(method); if(success == null) { log("Couldn't remove beforeGroups method " + method + " for group " + group); } } else { log("Couldn't find any beforeGroups method for group " + group); } } private void log(String string) { Utils.log("ConfigurationGroupMethods", 2, string); } synchronized public Map> getBeforeGroupsMap() { return m_beforeGroupsMethods; } synchronized public Map> getAfterGroupsMap() { return m_afterGroupsMethods; } synchronized public void removeBeforeGroups(String[] groups) { for(String group : groups) { // log("Removing before group " + group); m_beforeGroupsMethods.remove(group); } } synchronized public void removeAfterGroups(Collection groups) { for(String group : groups) { // log("Removing before group " + group); m_afterGroupsMethods.remove(group); } } } testng-testng-6.9.5/src/main/java/org/testng/internal/Configuration.java0000644000175000017500000000447412551235562025677 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IConfigurable; import org.testng.IConfigurationListener; import org.testng.IExecutionListener; import org.testng.IHookable; import org.testng.ITestObjectFactory; import org.testng.collections.Lists; import org.testng.internal.annotations.DefaultAnnotationTransformer; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.internal.annotations.JDK15AnnotationFinder; import java.util.List; public class Configuration implements IConfiguration { IAnnotationFinder m_annotationFinder; ITestObjectFactory m_objectFactory; IHookable m_hookable; IConfigurable m_configurable; List m_executionListeners = Lists.newArrayList(); private List m_configurationListeners = Lists.newArrayList(); public Configuration() { init(new JDK15AnnotationFinder(new DefaultAnnotationTransformer())); } public Configuration(IAnnotationFinder finder) { init(finder); } private void init(IAnnotationFinder finder) { m_annotationFinder = finder; } @Override public IAnnotationFinder getAnnotationFinder() { return m_annotationFinder; } @Override public void setAnnotationFinder(IAnnotationFinder finder) { m_annotationFinder = finder; } @Override public ITestObjectFactory getObjectFactory() { return m_objectFactory; } @Override public void setObjectFactory(ITestObjectFactory factory) { m_objectFactory = factory; } @Override public IHookable getHookable() { return m_hookable; } @Override public void setHookable(IHookable h) { m_hookable = h; } @Override public IConfigurable getConfigurable() { return m_configurable; } @Override public void setConfigurable(IConfigurable c) { m_configurable = c; } @Override public List getExecutionListeners() { return m_executionListeners; } @Override public void addExecutionListener(IExecutionListener l) { m_executionListeners.add(l); } @Override public List getConfigurationListeners() { return Lists.newArrayList(m_configurationListeners); } @Override public void addConfigurationListener(IConfigurationListener cl) { if (! m_configurationListeners.contains(cl)) { m_configurationListeners.add(cl); } } }testng-testng-6.9.5/src/main/java/org/testng/internal/ClonedMethod.java0000755000175000017500000001570312551235562025435 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IClass; import org.testng.IRetryAnalyzer; import org.testng.ITestClass; import org.testng.ITestNGMethod; import org.testng.collections.Lists; import org.testng.xml.XmlTest; import java.lang.reflect.Method; import java.util.Collections; import java.util.List; import java.util.Map; public class ClonedMethod implements ITestNGMethod { private static final long serialVersionUID = 1L; private ITestNGMethod m_method; transient private Method m_javaMethod; private String m_id; private int m_currentInvocationCount; private long m_date; private List m_invocationNumbers = Lists.newArrayList(); private List m_failedInvocationNumbers = Lists.newArrayList(); public ClonedMethod(ITestNGMethod method, Method javaMethod) { m_method = method; m_javaMethod = javaMethod; } @Override public void addMethodDependedUpon(String methodName) { // nop } @Override public boolean canRunFromClass(IClass testClass) { return m_method.canRunFromClass(testClass); } @Override public String[] getAfterGroups() { return m_method.getAfterGroups(); } @Override public String[] getBeforeGroups() { return m_method.getBeforeGroups(); } @Override public int getCurrentInvocationCount() { return m_currentInvocationCount; } @Override public long getDate() { return m_method.getDate(); } @Override public String getDescription() { return ""; } @Override public void setDescription(String description) { m_method.setDescription(description); } @Override public boolean getEnabled() { return true; } @Override public String[] getGroups() { return m_method.getGroups(); } @Override public String[] getGroupsDependedUpon() { return new String[0]; } @Override public String getId() { return m_id; } @Override public long[] getInstanceHashCodes() { return m_method.getInstanceHashCodes(); } @Override public Object[] getInstances() { return m_method.getInstances(); } @Override public Object getInstance() { return m_method.getInstance(); } @Override public int getInvocationCount() { return 1; } @Override public int getTotalInvocationCount() { return 1; } @Override public long getInvocationTimeOut() { return m_method.getInvocationTimeOut(); } @Override public Method getMethod() { return m_javaMethod; } @Override public String getMethodName() { return m_javaMethod.getName(); } @Override public String[] getMethodsDependedUpon() { return new String[0]; } @Override public String getMissingGroup() { return null; } @Override public int getParameterInvocationCount() { return 1; } @Override public Class getRealClass() { return m_javaMethod.getClass(); } @Override public IRetryAnalyzer getRetryAnalyzer() { return m_method.getRetryAnalyzer(); } @Override public int getSuccessPercentage() { return 100; } @Override public ITestClass getTestClass() { return m_method.getTestClass(); } @Override public int getThreadPoolSize() { return m_method.getThreadPoolSize(); } @Override public long getTimeOut() { return m_method.getTimeOut(); } @Override public void setTimeOut(long timeOut) { m_method.setTimeOut(timeOut); } @Override public boolean ignoreMissingDependencies() { return false; } @Override public void incrementCurrentInvocationCount() { m_currentInvocationCount++; } @Override public boolean isAfterClassConfiguration() { return false; } @Override public boolean isAfterGroupsConfiguration() { return false; } @Override public boolean isAfterMethodConfiguration() { return false; } @Override public boolean isAfterSuiteConfiguration() { return false; } @Override public boolean isAfterTestConfiguration() { return false; } @Override public boolean isAlwaysRun() { return false; } @Override public boolean isBeforeClassConfiguration() { return false; } @Override public boolean isBeforeGroupsConfiguration() { return false; } @Override public boolean isBeforeMethodConfiguration() { return false; } @Override public boolean isBeforeSuiteConfiguration() { return false; } @Override public boolean isBeforeTestConfiguration() { return false; } @Override public boolean isTest() { return true; } @Override public void setDate(long date) { m_date = date; } @Override public void setId(String id) { m_id = id; } @Override public void setIgnoreMissingDependencies(boolean ignore) { } @Override public void setInvocationCount(int count) { } @Override public void setMissingGroup(String group) { } @Override public void setParameterInvocationCount(int n) { } @Override public void setRetryAnalyzer(IRetryAnalyzer retryAnalyzer) { } @Override public void setSkipFailedInvocations(boolean skip) { } @Override public void setTestClass(ITestClass cls) { } @Override public void setThreadPoolSize(int threadPoolSize) { } @Override public boolean skipFailedInvocations() { return false; } @Override public int compareTo(Object o) { int result = -2; Class thisClass = getRealClass(); Class otherClass = ((ITestNGMethod) o).getRealClass(); if (thisClass.isAssignableFrom(otherClass)) { result = -1; } else if (otherClass.isAssignableFrom(thisClass)) { result = 1; } else if (equals(o)) { result = 0; } return result; } @Override public ClonedMethod clone() { return new ClonedMethod(m_method, m_javaMethod); } @Override public String toString() { Method m = getMethod(); String cls = m.getDeclaringClass().getName(); StringBuffer result = new StringBuffer(cls + "." + m.getName() + "("); int i = 0; for (Class p : m.getParameterTypes()) { if (i++ > 0) { result.append(", "); } result.append(p.getName()); } result.append(")"); return result.toString(); } @Override public List getInvocationNumbers() { return m_invocationNumbers; } @Override public void setInvocationNumbers(List count) { m_invocationNumbers = count; } @Override public List getFailedInvocationNumbers() { return m_failedInvocationNumbers; } @Override public void addFailedInvocationNumber(int number) { m_failedInvocationNumbers.add(number); } @Override public int getPriority() { return m_method.getPriority(); } @Override public void setPriority(int priority) { // ignored } @Override public XmlTest getXmlTest() { return m_method.getXmlTest(); } @Override public ConstructorOrMethod getConstructorOrMethod() { return null; } @Override public Map findMethodParameters(XmlTest test) { return Collections.emptyMap(); } } testng-testng-6.9.5/src/main/java/org/testng/internal/ClassInfoMap.java0000644000175000017500000000301512551235562025375 0ustar eugeneeugenepackage org.testng.internal; import org.testng.collections.Maps; import org.testng.xml.XmlClass; import java.util.List; import java.util.Map; import java.util.Set; public class ClassInfoMap { private Map, XmlClass> m_map = Maps.newLinkedHashMap(); private boolean includeNestedClasses; public ClassInfoMap() { } public ClassInfoMap(List classes) { this(classes, true); } public ClassInfoMap(List classes, boolean includeNested) { includeNestedClasses = includeNested; for (XmlClass xmlClass : classes) { try { Class c = xmlClass.getSupportClass(); registerClass(c, xmlClass); } catch (NoClassDefFoundError e) { Utils.log("[ClassInfoMap]", 1, "Unable to open class " + xmlClass.getName() + " - unable to resolve class reference " + e.getMessage()); if (xmlClass.loadClasses()) { throw e; } } } } private void registerClass(Class cl, XmlClass xmlClass) { m_map.put(cl, xmlClass); if (includeNestedClasses) { for (Class c : cl.getClasses()) { if (! m_map.containsKey(c)) registerClass(c, xmlClass); } } } public void addClass(Class cls) { m_map.put(cls, null); } public XmlClass getXmlClass(Class cls) { return m_map.get(cls); } public void put(Class cls, XmlClass xmlClass) { m_map.put(cls, xmlClass); } public Set> getClasses() { return m_map.keySet(); } public int getSize() { return m_map.size(); } } testng-testng-6.9.5/src/main/java/org/testng/internal/ClassImpl.java0000755000175000017500000001361512551235562024757 0ustar eugeneeugenepackage org.testng.internal; 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; import org.testng.ISuite; import org.testng.ITest; import org.testng.ITestContext; import org.testng.ITestObjectFactory; import org.testng.TestNGException; import org.testng.annotations.Guice; import org.testng.collections.Lists; import org.testng.collections.Objects; import org.testng.internal.annotations.AnnotationHelper; import org.testng.internal.annotations.IAnnotationFinder; 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; /** * Implementation of an IClass. * * @author Cedric Beust */ public class ClassImpl implements IClass { private static final long serialVersionUID = 1118178273317520344L; transient private Class m_class = null; transient private Object m_defaultInstance = null; private XmlTest m_xmlTest = null; transient private IAnnotationFinder m_annotationFinder = null; transient private List m_instances = Lists.newArrayList(); transient private Map m_classes = null; private int m_instanceCount; private long[] m_instanceHashCodes; private transient Object m_instance; private ITestObjectFactory m_objectFactory; private String m_testName = null; private XmlClass m_xmlClass; private ITestContext m_testContext; private final boolean m_hasParentModule; public ClassImpl(ITestContext context, Class cls, XmlClass xmlClass, Object instance, Map classes, XmlTest xmlTest, IAnnotationFinder annotationFinder, ITestObjectFactory objectFactory) { m_testContext = context; m_class = cls; m_classes = classes; m_xmlClass = xmlClass; m_xmlTest = xmlTest; m_annotationFinder = annotationFinder; m_instance = instance; m_objectFactory = objectFactory; if (instance instanceof ITest) { m_testName = ((ITest) instance).getTestName(); } m_hasParentModule = isStringNotEmpty(m_testContext.getSuite().getParentModule()); } private static void ppp(String s) { System.out.println("[ClassImpl] " + s); } @Override public String getTestName() { return m_testName; } @Override public String getName() { return m_class.getName(); } @Override public Class getRealClass() { return m_class; } @Override public int getInstanceCount() { return m_instanceCount; } @Override public long[] getInstanceHashCodes() { return m_instanceHashCodes; } @Override public XmlTest getXmlTest() { return m_xmlTest; } @Override public XmlClass getXmlClass() { return m_xmlClass; } private Object getDefaultInstance() { if (m_defaultInstance == null) { if (m_instance != null) { m_defaultInstance = m_instance; } else { Object instance = getInstanceFromGuice(); if (instance != null) { m_defaultInstance = instance; } else { m_defaultInstance = ClassHelper.createInstance(m_class, m_classes, m_xmlTest, m_annotationFinder, m_objectFactory); } } } return m_defaultInstance; } /** * @return an instance from Guice if @Test(guiceModule) attribute was found, null otherwise */ @SuppressWarnings("unchecked") private Object getInstanceFromGuice() { Injector injector = m_testContext.getInjector(this); if (injector == null) return null; return injector.getInstance(m_class); } public Injector getParentInjector() { ISuite suite = m_testContext.getSuite(); // 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 = (Class) ClassHelper.forName(suite.getParentModule()); if (parentModule == null) { throw new TestNGException("Cannot load parent Guice module class: " + parentModule); } Module module = newModule(parentModule); injector = com.google.inject.Guice.createInjector(stage, module); } else { injector = com.google.inject.Guice.createInjector(stage); } suite.setParentInjector(injector); } return injector; } private Module newModule(Class module) { try { Constructor moduleConstructor = module.getDeclaredConstructor(ITestContext.class); return ClassHelper.newInstance(moduleConstructor, m_testContext); } catch (NoSuchMethodException e) { return ClassHelper.newInstance(module); } } @Override public Object[] getInstances(boolean create) { Object[] result = {}; if (m_xmlTest.isJUnit()) { if (create) { result = new Object[] { ClassHelper.createInstance(m_class, m_classes, m_xmlTest, m_annotationFinder, m_objectFactory) }; } } else { result = new Object[] { getDefaultInstance() }; } if (m_instances.size() > 0) { result = m_instances.toArray(new Object[m_instances.size()]); } m_instanceCount = m_instances.size(); m_instanceHashCodes = new long[m_instanceCount]; for (int i = 0; i < m_instanceCount; i++) { m_instanceHashCodes[i] = m_instances.get(i).hashCode(); } return result; } @Override public String toString() { return Objects.toStringHelper(getClass()) .add("class", m_class.getName()) .toString(); } @Override public void addInstance(Object instance) { m_instances.add(instance); } } testng-testng-6.9.5/src/main/java/org/testng/internal/ClassHelper.java0000644000175000017500000005064412551235562025275 0ustar eugeneeugenepackage org.testng.internal; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; import org.testng.IClass; import org.testng.IMethodSelector; import org.testng.IObjectFactory; import org.testng.IObjectFactory2; import org.testng.ITestObjectFactory; import org.testng.TestNGException; 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.junit.IJUnitTestRunner; import org.testng.xml.XmlTest; /** * Utility class for different class manipulations. */ public final class ClassHelper { private static final String JUNIT_TESTRUNNER= "org.testng.junit.JUnitTestRunner"; private static final String JUNIT_4_TESTRUNNER = "org.testng.junit.JUnit4TestRunner"; /** The additional class loaders to find classes in. */ private static final List m_classLoaders = new Vector<>(); /** Add a class loader to the searchable loaders. */ public static void addClassLoader(final ClassLoader loader) { m_classLoaders.add(loader); } /** Hide constructor. */ private ClassHelper() { // Hide Constructor } public static T newInstance(Class clazz) { try { T instance = clazz.newInstance(); return instance; } catch(IllegalAccessException iae) { throw new TestNGException("Class " + clazz.getName() + " does not have a no-args constructor", iae); } catch(InstantiationException ie) { throw new TestNGException("Cannot instantiate class " + clazz.getName(), ie); } catch(ExceptionInInitializerError eiierr) { throw new TestNGException("An exception occurred in static initialization of class " + clazz.getName(), eiierr); } catch(SecurityException se) { throw new TestNGException(se); } } public static T newInstance(Constructor 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 * class loading methods in that it does not throw an exception if the class * is not found but returns null instead. * * @param className the class name to be loaded. * * @return the class or null if the class is not found. */ public static Class forName(final String className) { Vector allClassLoaders = new Vector<>(); ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if (contextClassLoader != null) { allClassLoaders.add(contextClassLoader); } if (m_classLoaders != null) { allClassLoaders.addAll(m_classLoaders); } for (ClassLoader classLoader : allClassLoaders) { if (null == classLoader) { continue; } try { return classLoader.loadClass(className); } catch(ClassNotFoundException ex) { // With additional class loaders, it is legitimate to ignore ClassNotFoundException if (null == m_classLoaders || m_classLoaders.size() == 0) { logClassNotFoundError(className, ex); } } } try { return Class.forName(className); } catch(ClassNotFoundException cnfe) { logClassNotFoundError(className, cnfe); return null; } } private static void logClassNotFoundError(String className, Exception ex) { Utils.log("ClassHelper", 2, "Could not instantiate " + className + " : Class doesn't exist (" + ex.getMessage() + ")"); } /** * For the given class, returns the method annotated with @Factory or null * if none is found. This method does not search up the superclass hierarchy. * If more than one method is @Factory annotated, a TestNGException is thrown. * @param cls The class to search for the @Factory annotation. * @param finder The finder (JDK 1.4 or JDK 5.0+) use to search for the annotation. * * @return the @Factory method or null * * FIXME: @Factory method must be public! */ public static ConstructorOrMethod findDeclaredFactoryMethod(Class cls, IAnnotationFinder finder) { ConstructorOrMethod result = null; for (Method method : cls.getMethods()) { IFactoryAnnotation f = finder.findAnnotation(method, IFactoryAnnotation.class); if (null != f) { result = new ConstructorOrMethod(method); result.setEnabled(f.getEnabled()); break; } } if (result == null) { for (Constructor constructor : cls.getDeclaredConstructors()) { IAnnotation f = finder.findAnnotation(constructor, IFactoryAnnotation.class); if (f != null) { result = new ConstructorOrMethod(constructor); } } } // If we didn't find anything, look for nested classes // if (null == result) { // Class[] subClasses = cls.getClasses(); // for (Class subClass : subClasses) { // result = findFactoryMethod(subClass, finder); // if (null != result) { // break; // } // } // } // Found the method, verify that it returns an array of objects // TBD return result; } /** * Extract all callable methods of a class and all its super (keeping in mind * the Java access rules). */ public static Set getAvailableMethods(Class clazz) { Set methods = Sets.newHashSet(); methods.addAll(Arrays.asList(clazz.getDeclaredMethods())); Class parent = clazz.getSuperclass(); while (Object.class != parent) { methods.addAll(extractMethods(clazz, parent, methods)); parent = parent.getSuperclass(); } return methods; } public static IJUnitTestRunner createTestRunner(TestRunner runner) { try { //try to get runner for JUnit 4 first Class.forName("org.junit.Test"); IJUnitTestRunner tr = (IJUnitTestRunner) ClassHelper.forName(JUNIT_4_TESTRUNNER).newInstance(); tr.setTestResultNotifier(runner); return tr; } catch (Throwable t) { Utils.log("ClassHelper", 2, "JUnit 4 was not found on the classpath"); try { //fallback to JUnit 3 Class.forName("junit.framework.Test"); IJUnitTestRunner tr = (IJUnitTestRunner) ClassHelper.forName(JUNIT_TESTRUNNER).newInstance(); tr.setTestResultNotifier(runner); return tr; } catch (Exception ex) { Utils.log("ClassHelper", 2, "JUnit 3 was not found on the classpath"); //there's no JUnit on the classpath throw new TestNGException("Cannot create JUnit runner", ex); } } } private static Set extractMethods(Class childClass, Class clazz, Set collected) { Set methods = Sets.newHashSet(); Method[] declaredMethods = clazz.getDeclaredMethods(); Package childPackage = childClass.getPackage(); Package classPackage = clazz.getPackage(); boolean isSamePackage = false; if ((null == childPackage) && (null == classPackage)) { isSamePackage = true; } if ((null != childPackage) && (null != classPackage)) { isSamePackage = childPackage.getName().equals(classPackage.getName()); } for (Method method : declaredMethods) { int methodModifiers = method.getModifiers(); if ((Modifier.isPublic(methodModifiers) || Modifier.isProtected(methodModifiers)) || (isSamePackage && !Modifier.isPrivate(methodModifiers))) { if (!isOverridden(method, collected) && !Modifier.isAbstract(methodModifiers)) { methods.add(method); } } } return methods; } private static boolean isOverridden(Method method, Set collectedMethods) { Class methodClass = method.getDeclaringClass(); Class[] methodParams = method.getParameterTypes(); for (Method m: collectedMethods) { Class[] paramTypes = m.getParameterTypes(); if (method.getName().equals(m.getName()) && methodClass.isAssignableFrom(m.getDeclaringClass()) && methodParams.length == paramTypes.length) { boolean sameParameters = true; for (int i= 0; i < methodParams.length; i++) { if (!methodParams[i].equals(paramTypes[i])) { sameParameters = false; break; } } if (sameParameters) { return true; } } } return false; } public static IMethodSelector createSelector(org.testng.xml.XmlMethodSelector selector) { try { Class cls = Class.forName(selector.getClassName()); return (IMethodSelector) cls.newInstance(); } catch(Exception ex) { throw new TestNGException("Couldn't find method selector : " + selector.getClassName(), ex); } } /** * Create an instance for the given class. */ public static Object createInstance(Class declaringClass, Map classes, XmlTest xmlTest, IAnnotationFinder finder, ITestObjectFactory objectFactory) { if (objectFactory instanceof IObjectFactory) { return createInstance1(declaringClass, classes, xmlTest, finder, (IObjectFactory) objectFactory); } else if (objectFactory instanceof IObjectFactory2) { return createInstance2(declaringClass, (IObjectFactory2) objectFactory); } else { throw new AssertionError("Unknown object factory type:" + objectFactory); } } private static Object createInstance2(Class declaringClass, IObjectFactory2 objectFactory) { return objectFactory.newInstance(declaringClass); } public static Object createInstance1(Class declaringClass, Map classes, XmlTest xmlTest, IAnnotationFinder finder, IObjectFactory objectFactory) { Object result = null; try { // // Any annotated constructor? // Constructor constructor = findAnnotatedConstructor(finder, declaringClass); if (null != constructor) { IParametersAnnotation annotation = finder.findAnnotation(constructor, IParametersAnnotation.class); String[] parameterNames = annotation.getValue(); Object[] parameters = Parameters.createInstantiationParameters(constructor, "@Parameters", finder, parameterNames, xmlTest.getAllParameters(), xmlTest.getSuite()); result = objectFactory.newInstance(constructor, parameters); } // // No, just try to instantiate the parameterless constructor (or the one // with a String) // else { // If this class is a (non-static) nested class, the constructor contains a hidden // parameter of the type of the enclosing class Class[] parameterTypes = new Class[0]; Object[] parameters = new Object[0]; Class ec = getEnclosingClass(declaringClass); boolean isStatic = 0 != (declaringClass.getModifiers() & Modifier.STATIC); // Only add the extra parameter if the nested class is not static if ((null != ec) && !isStatic) { parameterTypes = new Class[] { ec }; // Create an instance of the enclosing class so we can instantiate // the nested class (actually, we reuse the existing instance). IClass enclosingIClass = classes.get(ec); Object[] enclosingInstances; if (null != enclosingIClass) { enclosingInstances = enclosingIClass.getInstances(false); if ((null == enclosingInstances) || (enclosingInstances.length == 0)) { Object o = objectFactory.newInstance(ec.getConstructor(parameterTypes)); enclosingIClass.addInstance(o); enclosingInstances = new Object[] { o }; } } else { enclosingInstances = new Object[] { ec.newInstance() }; } Object enclosingClassInstance = enclosingInstances[0]; // Utils.createInstance(ec, classes, xmlTest, finder); parameters = new Object[] { enclosingClassInstance }; } // isStatic Constructor ct; try { ct = declaringClass.getDeclaredConstructor(parameterTypes); } catch (NoSuchMethodException ex) { ct = declaringClass.getDeclaredConstructor(String.class); parameters = new Object[] { "Default test name" }; // If ct == null here, we'll pass a null // constructor to the factory and hope it can deal with it } result = objectFactory.newInstance(ct, parameters); } } catch (TestNGException ex) { throw ex; // throw new TestNGException("Couldn't instantiate class:" + declaringClass); } catch (NoSuchMethodException ex) { } catch (Throwable cause) { // Something else went wrong when running the constructor throw new TestNGException("An error occurred while instantiating class " + declaringClass.getName() + ": " + cause.getMessage(), cause); } if (result == null) { if (! Modifier.isPublic(declaringClass.getModifiers())) { //result should not be null throw new TestNGException("An error occurred while instantiating class " + declaringClass.getName() + ". Check to make sure it can be accessed/instantiated."); // } else { // Utils.log(ClassHelper.class.getName(), 2, "Couldn't instantiate class " + declaringClass); } } return result; } /** * Class.getEnclosingClass() only exists on JDK5, so reimplementing it * here. */ private static Class getEnclosingClass(Class declaringClass) { Class result = null; String className = declaringClass.getName(); int index = className.indexOf("$"); if (index != -1) { String ecn = className.substring(0, index); try { result = Class.forName(ecn); } catch (ClassNotFoundException e) { e.printStackTrace(); } } return result; } /** * Find the best constructor given the parameters found on the annotation */ private static Constructor findAnnotatedConstructor(IAnnotationFinder finder, Class declaringClass) { Constructor[] constructors = declaringClass.getDeclaredConstructors(); for (Constructor result : constructors) { IParametersAnnotation annotation = finder.findAnnotation(result, IParametersAnnotation.class); if (null != annotation) { String[] parameters = annotation.getValue(); Class[] parameterTypes = result.getParameterTypes(); if (parameters.length != parameterTypes.length) { throw new TestNGException("Parameter count mismatch: " + result + "\naccepts " + parameterTypes.length + " parameters but the @Test annotation declares " + parameters.length); } else { return result; } } } return null; } public static T tryOtherConstructor(Class declaringClass) { T result; try { // Special case for inner classes if (declaringClass.getModifiers() == 0) { return null; } Constructor ctor = declaringClass.getConstructor(String.class); result = ctor.newInstance("Default test name"); } catch (Exception e) { String message = e.getMessage(); if ((message == null) && (e.getCause() != null)) { message = e.getCause().getMessage(); } String error = "Could not create an instance of class " + declaringClass + ((message != null) ? (": " + message) : "") + ".\nPlease make sure it has a constructor that accepts either a String or no parameter."; throw new TestNGException(error); } return result; } /** * When given a file name to form a class name, the file name is parsed and divided * into segments. For example, "c:/java/classes/com/foo/A.class" would be divided * into 6 segments {"C:" "java", "classes", "com", "foo", "A"}. The first segment * actually making up the class name is [3]. This value is saved in m_lastGoodRootIndex * so that when we parse the next file name, we will try 3 right away. If 3 fails we * will take the long approach. This is just a optimization cache value. */ private static int m_lastGoodRootIndex = -1; /** * Returns the Class object corresponding to the given name. The name may be * of the following form: *
    *
  • A class name: "org.testng.TestNG"
  • *
  • A class file name: "/testng/src/org/testng/TestNG.class"
  • *
  • A class source name: "d:\testng\src\org\testng\TestNG.java"
  • *
* * @param file * the class name. * @return the class corresponding to the name specified. */ public static Class fileToClass(String file) { Class result = null; if(!file.endsWith(".class") && !file.endsWith(".java")) { // Doesn't end in .java or .class, assume it's a class name if (file.startsWith("class ")) { file = file.substring("class ".length()); } result = ClassHelper.forName(file); if (null == result) { throw new TestNGException("Cannot load class from file: " + file); } return result; } int classIndex = file.lastIndexOf(".class"); if (-1 == classIndex) { classIndex = file.lastIndexOf(".java"); // // if(-1 == classIndex) { // result = ClassHelper.forName(file); // // if (null == result) { // throw new TestNGException("Cannot load class from file: " + file); // } // // return result; // } // } // Transforms the file name into a class name. // Remove the ".class" or ".java" extension. String shortFileName = file.substring(0, classIndex); // Split file name into segments. For example "c:/java/classes/com/foo/A" // becomes {"c:", "java", "classes", "com", "foo", "A"} String[] segments = shortFileName.split("[/\\\\]", -1); // // Check if the last good root index works for this one. For example, if the previous // name was "c:/java/classes/com/foo/A.class" then m_lastGoodRootIndex is 3 and we // try to make a class name ignoring the first m_lastGoodRootIndex segments (3). This // will succeed rapidly if the path is the same as the one from the previous name. // if (-1 != m_lastGoodRootIndex) { // TODO use a SringBuffer here String className = segments[m_lastGoodRootIndex]; for (int i = m_lastGoodRootIndex + 1; i < segments.length; i++) { className += "." + segments[i]; } result = ClassHelper.forName(className); if (null != result) { return result; } } // // We haven't found a good root yet, start by resolving the class from the end segment // and work our way up. For example, if we start with "c:/java/classes/com/foo/A" // we'll start by resolving "A", then "foo.A", then "com.foo.A" until something // resolves. When it does, we remember the path we are at as "lastGoodRoodIndex". // // TODO CQ use a StringBuffer here String className = null; for (int i = segments.length - 1; i >= 0; i--) { if (null == className) { className = segments[i]; } else { className = segments[i] + "." + className; } result = ClassHelper.forName(className); if (null != result) { m_lastGoodRootIndex = i; break; } } if (null == result) { throw new TestNGException("Cannot load class from file: " + file); } return result; } } testng-testng-6.9.5/src/main/java/org/testng/internal/BshMock.java0000644000175000017500000000034112551235562024403 0ustar eugeneeugenepackage org.testng.internal; import org.testng.ITestNGMethod; public class BshMock implements IBsh { @Override public boolean includeMethodFromExpression(String expression, ITestNGMethod tm) { return false; } } testng-testng-6.9.5/src/main/java/org/testng/internal/Bsh.java0000644000175000017500000000354612551235562023603 0ustar eugeneeugenepackage org.testng.internal; import bsh.EvalError; import bsh.Interpreter; import org.testng.ITestNGMethod; import org.testng.TestNGException; import org.testng.collections.Maps; import java.lang.reflect.Method; import java.util.Map; public class Bsh implements IBsh { private static Interpreter s_interpreter; @Override public boolean includeMethodFromExpression(String expression, ITestNGMethod tm) { boolean result = false; Interpreter interpreter = getInterpreter(); try { Map groups = Maps.newHashMap(); for (String group : tm.getGroups()) { groups.put(group, group); } setContext(interpreter, tm.getMethod(), groups, tm); Object evalResult = interpreter.eval(expression); result = (Boolean) evalResult; } catch (EvalError evalError) { Utils.log("bsh.Interpreter", 2, "Cannot evaluate expression:" + expression + ":" + evalError.getMessage()); } finally { resetContext(interpreter); } return result; } private static Interpreter getInterpreter() { if(null == s_interpreter) { s_interpreter= new Interpreter(); } return s_interpreter; } private void setContext(Interpreter interpreter, Method method, Map groups, ITestNGMethod tm) { try { interpreter.set("method", method); interpreter.set("groups", groups); interpreter.set("testngMethod", tm); } catch(EvalError evalError) { throw new TestNGException("Cannot set BSH interpreter", evalError); } } private void resetContext(Interpreter interpreter) { try { interpreter.unset("method"); interpreter.unset("groups"); interpreter.unset("testngMethod"); } catch(EvalError evalError) { Utils.log("bsh.Interpreter", 2, "Cannot reset interpreter:" + evalError.getMessage()); } } } testng-testng-6.9.5/src/main/java/org/testng/internal/BaseTestMethod.java0000755000175000017500000004501112551235562025736 0ustar eugeneeugenepackage org.testng.internal; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import org.testng.IClass; import org.testng.IRetryAnalyzer; import org.testng.ITestClass; import org.testng.ITestNGMethod; import org.testng.annotations.ITestOrConfiguration; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.collections.Sets; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.internal.thread.IAtomicInteger; import org.testng.internal.thread.ThreadUtil; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlTest; /** * Superclass to represent both @Test and @Configuration methods. */ public abstract class BaseTestMethod implements ITestNGMethod { private static final long serialVersionUID = -2666032602580652173L; private static final Pattern SPACE_SEPARATOR_PATTERN = Pattern.compile(" +"); /** * The test class on which the test method was found. Note that this is not * necessarily the declaring class. */ protected ITestClass m_testClass; protected final transient Class m_methodClass; protected final transient ConstructorOrMethod m_method; private final transient String m_signature; protected String m_id = ""; protected long m_date = -1; protected final transient IAnnotationFinder m_annotationFinder; protected String[] m_groups = {}; protected String[] m_groupsDependedUpon = {}; protected String[] m_methodsDependedUpon = {}; protected String[] m_beforeGroups = {}; protected String[] m_afterGroups = {}; private boolean m_isAlwaysRun; private boolean m_enabled; private final String m_methodName; // If a depended group is not found private String m_missingGroup; private String m_description = null; protected IAtomicInteger m_currentInvocationCount = ThreadUtil.createAtomicInteger(0); private int m_parameterInvocationCount = 1; private IRetryAnalyzer m_retryAnalyzer = null; private boolean m_skipFailedInvocations = true; private long m_invocationTimeOut = 0L; private List m_invocationNumbers = Lists.newArrayList(); private final List m_failedInvocationNumbers = Collections.synchronizedList(Lists.newArrayList()); private long m_timeOut = 0; private boolean m_ignoreMissingDependencies; private int m_priority; private XmlTest m_xmlTest; private Object m_instance; /** * Constructs a BaseTestMethod TODO cquezel JavaDoc. * * @param method * @param annotationFinder * @param instance */ public BaseTestMethod(String methodName, Method method, IAnnotationFinder annotationFinder, Object instance) { this(methodName, new ConstructorOrMethod(method), annotationFinder, instance); } public BaseTestMethod(String methodName, ConstructorOrMethod com, IAnnotationFinder annotationFinder, Object instance) { m_methodClass = com.getDeclaringClass(); m_method = com; m_methodName = methodName; m_annotationFinder = annotationFinder; m_instance = instance; m_signature = computeSignature(); } /** * {@inheritDoc} */ @Override public boolean isAlwaysRun() { return m_isAlwaysRun; } /** * TODO cquezel JavaDoc. * * @param alwaysRun */ protected void setAlwaysRun(boolean alwaysRun) { m_isAlwaysRun = alwaysRun; } /** * {@inheritDoc} */ @Override public Class getRealClass() { return m_methodClass; } /** * {@inheritDoc} */ @Override public ITestClass getTestClass() { return m_testClass; } /** * {@inheritDoc} */ @Override public void setTestClass(ITestClass tc) { assert null != tc; if (! tc.getRealClass().equals(m_method.getDeclaringClass())) { assert m_method.getDeclaringClass().isAssignableFrom(tc.getRealClass()) : "\nMISMATCH : " + tc.getRealClass() + " " + m_method.getDeclaringClass(); } m_testClass = tc; } @Override public int compareTo(Object o) { int result = -2; Class thisClass = getRealClass(); Class otherClass = ((ITestNGMethod) o).getRealClass(); if (this == o) { result = 0; } else if (thisClass.isAssignableFrom(otherClass)) { result = -1; } else if (otherClass.isAssignableFrom(thisClass)) { result = 1; } else if (equals(o)) { result = 0; } return result; } /** * {@inheritDoc} */ @Override public Method getMethod() { return m_method.getMethod(); } /** * {@inheritDoc} */ @Override public String getMethodName() { return m_methodName; } /** * {@inheritDoc} */ @Override public Object[] getInstances() { return new Object[] { getInstance() }; } @Override public Object getInstance() { return m_instance; } /** * {@inheritDoc} */ @Override public long[] getInstanceHashCodes() { return m_testClass.getInstanceHashCodes(); } /** * {@inheritDoc} * @return the addition of groups defined on the class and on this method. */ @Override public String[] getGroups() { return m_groups; } /** * {@inheritDoc} */ @Override public String[] getGroupsDependedUpon() { return m_groupsDependedUpon; } /** * {@inheritDoc} */ @Override public String[] getMethodsDependedUpon() { return m_methodsDependedUpon; } /** * {@inheritDoc} */ @Override public boolean isTest() { return false; } /** * {@inheritDoc} */ @Override public boolean isBeforeSuiteConfiguration() { return false; } /** * {@inheritDoc} */ @Override public boolean isAfterSuiteConfiguration() { return false; } /** * {@inheritDoc} */ @Override public boolean isBeforeTestConfiguration() { return false; } /** * {@inheritDoc} */ @Override public boolean isAfterTestConfiguration() { return false; } /** * {@inheritDoc} */ @Override public boolean isBeforeGroupsConfiguration() { return false; } /** * {@inheritDoc} */ @Override public boolean isAfterGroupsConfiguration() { return false; } /** * {@inheritDoc} */ @Override public boolean isBeforeClassConfiguration() { return false; } /** * {@inheritDoc} */ @Override public boolean isAfterClassConfiguration() { return false; } /** * {@inheritDoc} */ @Override public boolean isBeforeMethodConfiguration() { return false; } /** * {@inheritDoc} */ @Override public boolean isAfterMethodConfiguration() { return false; } /** * {@inheritDoc} */ @Override public long getTimeOut() { long result = m_timeOut != 0 ? m_timeOut : (m_xmlTest != null ? m_xmlTest.getTimeOut(0) : 0); return result; } @Override public void setTimeOut(long timeOut) { m_timeOut = timeOut; } /** * {@inheritDoc} * @return the number of times this method needs to be invoked. */ @Override public int getInvocationCount() { return 1; } /** * No-op. */ @Override public void setInvocationCount(int counter) { } /** * {@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 public int getSuccessPercentage() { return 100; } /** * {@inheritDoc} */ @Override public String getId() { return m_id; } /** * {@inheritDoc} */ @Override public void setId(String id) { m_id = id; } /** * {@inheritDoc} * @return Returns the date. */ @Override public long getDate() { return m_date; } /** * {@inheritDoc} * @param date The date to set. */ @Override public void setDate(long date) { m_date = date; } /** * {@inheritDoc} */ @Override public boolean canRunFromClass(IClass testClass) { return m_methodClass.isAssignableFrom(testClass.getRealClass()); } /** * {@inheritDoc} Compares two BaseTestMethod using the test class then the associated * Java Method. */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } BaseTestMethod other = (BaseTestMethod) obj; boolean isEqual = m_testClass == null ? other.m_testClass == null : other.m_testClass != null && m_testClass.getRealClass().equals(other.m_testClass.getRealClass()) && m_instance == other.getInstance(); return isEqual && getConstructorOrMethod().equals(other.getConstructorOrMethod()); } /** * {@inheritDoc} This implementation returns the associated Java Method's hash code. * @return the associated Java Method's hash code. */ @Override public int hashCode() { return m_method.hashCode(); } protected void initGroups(Class annotationClass) { // // Init groups // { ITestOrConfiguration annotation = getAnnotationFinder().findAnnotation(getMethod(), annotationClass); ITestOrConfiguration classAnnotation = getAnnotationFinder().findAnnotation(getMethod().getDeclaringClass(), annotationClass); setGroups(getStringArray(null != annotation ? annotation.getGroups() : null, null != classAnnotation ? classAnnotation.getGroups() : null)); } // // Init groups depended upon // { ITestOrConfiguration annotation = getAnnotationFinder().findAnnotation(getMethod(), annotationClass); ITestOrConfiguration classAnnotation = getAnnotationFinder().findAnnotation(getMethod().getDeclaringClass(), annotationClass); Map> xgd = calculateXmlGroupDependencies(m_xmlTest); List xmlGroupDependencies = Lists.newArrayList(); for (String g : getGroups()) { Set gdu = xgd.get(g); if (gdu != null) { xmlGroupDependencies.addAll(gdu); } } setGroupsDependedUpon( getStringArray(null != annotation ? annotation.getDependsOnGroups() : null, null != classAnnotation ? classAnnotation.getDependsOnGroups() : null), xmlGroupDependencies); String[] methodsDependedUpon = getStringArray(null != annotation ? annotation.getDependsOnMethods() : null, null != classAnnotation ? classAnnotation.getDependsOnMethods() : null); // Qualify these methods if they don't have a package for (int i = 0; i < methodsDependedUpon.length; i++) { String m = methodsDependedUpon[i]; if (!m.contains(".")) { m = MethodHelper.calculateMethodCanonicalName(m_methodClass, methodsDependedUpon[i]); methodsDependedUpon[i] = m != null ? m : methodsDependedUpon[i]; } } setMethodsDependedUpon(methodsDependedUpon); } } private static Map> calculateXmlGroupDependencies(XmlTest xmlTest) { Map> result = Maps.newHashMap(); if (xmlTest == null) { return result; } for (Map.Entry e : xmlTest.getXmlDependencyGroups().entrySet()) { String name = e.getKey(); String dependsOn = e.getValue(); Set set = result.get(name); if (set == null) { set = Sets.newHashSet(); result.put(name, set); } set.addAll(Arrays.asList(SPACE_SEPARATOR_PATTERN.split(dependsOn))); } return result; } protected IAnnotationFinder getAnnotationFinder() { return m_annotationFinder; } protected IClass getIClass() { return m_testClass; } private String computeSignature() { String classLong = m_method.getDeclaringClass().getName(); String cls = classLong.substring(classLong.lastIndexOf(".") + 1); StringBuilder result = new StringBuilder(cls).append(".").append(m_method.getName()).append("("); int i = 0; for (Class p : m_method.getParameterTypes()) { if (i++ > 0) { result.append(", "); } result.append(p.getName()); } result.append(")"); result.append("[pri:").append(getPriority()).append(", instance:").append(m_instance).append("]"); return result.toString(); } protected String getSignature() { return m_signature; } /** * {@inheritDoc} */ @Override public String toString() { return getSignature(); } protected String[] getStringArray(String[] methodArray, String[] classArray) { final Set vResult = Sets.newHashSet(); if (null != methodArray) { Collections.addAll(vResult, methodArray); } if (null != classArray) { Collections.addAll(vResult, classArray); } return vResult.toArray(new String[vResult.size()]); } protected void setGroups(String[] groups) { m_groups = groups; } protected void setGroupsDependedUpon(String[] groups, Collection xmlGroupDependencies) { List l = Lists.newArrayList(); l.addAll(Arrays.asList(groups)); l.addAll(xmlGroupDependencies); m_groupsDependedUpon = l.toArray(new String[l.size()]); } protected void setMethodsDependedUpon(String[] methods) { m_methodsDependedUpon = methods; } /** * {@inheritDoc} */ @Override public void addMethodDependedUpon(String method) { String[] newMethods = new String[m_methodsDependedUpon.length + 1]; newMethods[0] = method; System.arraycopy(m_methodsDependedUpon, 0, newMethods, 1, m_methodsDependedUpon.length); m_methodsDependedUpon = newMethods; } private static void ppp(String s) { System.out.println("[BaseTestMethod] " + s); } /** Compares two ITestNGMethod by date. */ public static final Comparator DATE_COMPARATOR = new Comparator() { @Override public int compare(Object o1, Object o2) { try { ITestNGMethod m1 = (ITestNGMethod) o1; ITestNGMethod m2 = (ITestNGMethod) o2; return (int) (m1.getDate() - m2.getDate()); } catch(Exception ex) { return 0; // TODO CQ document this logic } } }; /** * {@inheritDoc} */ @Override public String getMissingGroup() { return m_missingGroup; } /** * {@inheritDoc} */ @Override public void setMissingGroup(String group) { m_missingGroup = group; } /** * {@inheritDoc} */ @Override public int getThreadPoolSize() { return 0; } /** * No-op. */ @Override public void setThreadPoolSize(int threadPoolSize) { } @Override public void setDescription(String description) { m_description = description; } /** * {@inheritDoc} */ @Override public String getDescription() { return m_description; } public void setEnabled(boolean enabled) { m_enabled = enabled; } @Override public boolean getEnabled() { return m_enabled; } /** * {@inheritDoc} */ @Override public String[] getBeforeGroups() { return m_beforeGroups; } /** * {@inheritDoc} */ @Override public String[] getAfterGroups() { return m_afterGroups; } @Override public void incrementCurrentInvocationCount() { m_currentInvocationCount.incrementAndGet(); } @Override public int getCurrentInvocationCount() { return m_currentInvocationCount.get(); } @Override public void setParameterInvocationCount(int n) { m_parameterInvocationCount = n; } @Override public int getParameterInvocationCount() { return m_parameterInvocationCount; } @Override public abstract ITestNGMethod clone(); @Override public IRetryAnalyzer getRetryAnalyzer() { return m_retryAnalyzer; } @Override public void setRetryAnalyzer(IRetryAnalyzer retryAnalyzer) { m_retryAnalyzer = retryAnalyzer; } @Override public boolean skipFailedInvocations() { return m_skipFailedInvocations; } @Override public void setSkipFailedInvocations(boolean s) { m_skipFailedInvocations = s; } public void setInvocationTimeOut(long timeOut) { m_invocationTimeOut = timeOut; } @Override public long getInvocationTimeOut() { return m_invocationTimeOut; } @Override public boolean ignoreMissingDependencies() { return m_ignoreMissingDependencies; } @Override public void setIgnoreMissingDependencies(boolean i) { m_ignoreMissingDependencies = i; } @Override public List getInvocationNumbers() { return m_invocationNumbers; } @Override public void setInvocationNumbers(List numbers) { m_invocationNumbers = numbers; } @Override public List getFailedInvocationNumbers() { return m_failedInvocationNumbers; } @Override public void addFailedInvocationNumber(int number) { m_failedInvocationNumbers.add(number); } @Override public int getPriority() { return m_priority; } @Override public void setPriority(int priority) { m_priority = priority; } @Override public XmlTest getXmlTest() { return m_xmlTest; } public void setXmlTest(XmlTest xmlTest) { m_xmlTest = xmlTest; } @Override public ConstructorOrMethod getConstructorOrMethod() { return m_method; } @Override public Map findMethodParameters(XmlTest test) { // Get the test+suite parameters Map result = test.getAllParameters(); for (XmlClass xmlClass: test.getXmlClasses()) { if (xmlClass.getName().equals(getTestClass().getName())) { result.putAll(xmlClass.getLocalParameters()); for (XmlInclude include : xmlClass.getIncludedMethods()) { if (include.getName().equals(getMethodName())) { result.putAll(include.getLocalParameters()); break; } } } } return result; } } testng-testng-6.9.5/src/main/java/org/testng/internal/BaseClassFinder.java0000755000175000017500000000332712551235562026057 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IClass; import org.testng.ITestClassFinder; import org.testng.ITestContext; import org.testng.ITestObjectFactory; import org.testng.collections.Maps; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.xml.XmlClass; import org.testng.xml.XmlTest; import java.util.Map; /** * This class * * @author Cedric Beust */ abstract public class BaseClassFinder implements ITestClassFinder { private Map m_classes = Maps.newLinkedHashMap(); @Override public IClass getIClass(Class cls) { return m_classes.get(cls); } protected void putIClass(Class cls, IClass iClass) { if (! m_classes.containsKey(cls)) { m_classes.put(cls, iClass); } } private void ppp(String s) { System.out.println("[BaseClassFinder] " + s); } /** * @param cls * @return An IClass for the given class, or null if we have * already treated this class. */ protected IClass findOrCreateIClass(ITestContext context, Class cls, XmlClass xmlClass, Object instance, XmlTest xmlTest, IAnnotationFinder annotationFinder, ITestObjectFactory objectFactory) { IClass result = m_classes.get(cls); if (null == result) { result = new ClassImpl(context, cls, xmlClass, instance, m_classes, xmlTest, annotationFinder, objectFactory); m_classes.put(cls, result); } return result; } protected Map getExistingClasses() { return m_classes; } protected boolean classExists(Class cls) { return m_classes.containsKey(cls); } @Override public IClass[] findTestClasses() { return m_classes.values().toArray(new IClass[m_classes.size()]); } } testng-testng-6.9.5/src/main/java/org/testng/internal/Attributes.java0000644000175000017500000000153212551235562025206 0ustar eugeneeugenepackage org.testng.internal; import org.testng.IAttributes; import org.testng.collections.Maps; import java.util.Map; import java.util.Set; /** * Simple implementation of IAttributes. * * @author cbeust@google.com (Cedric Beust), March 16th, 2010 */ public class Attributes implements IAttributes { /** * */ private static final long serialVersionUID = 6701159979281335152L; private Map m_attributes = Maps.newHashMap(); @Override public Object getAttribute(String name) { return m_attributes.get(name); } @Override public Set getAttributeNames() { return m_attributes.keySet(); } @Override public void setAttribute(String name, Object value) { m_attributes.put(name, value); } @Override public Object removeAttribute(String name) { return m_attributes.remove(name); } } testng-testng-6.9.5/src/main/java/org/testng/collections/0000755000175000017500000000000012551235562022716 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/collections/Sets.java0000644000175000017500000000067512551235562024507 0ustar eugeneeugenepackage org.testng.collections; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; public final class Sets { private Sets() {} public static Set newHashSet() { return new HashSet<>(); } public static Set newHashSet(Collection c) { return new HashSet<>(c); } public static Set newLinkedHashSet() { return new LinkedHashSet<>(); } } testng-testng-6.9.5/src/main/java/org/testng/collections/SetMultiMap.java0000644000175000017500000000040212551235562025761 0ustar eugeneeugenepackage org.testng.collections; import java.util.Set; /** * A container to hold sets indexed by a key. */ public class SetMultiMap extends MultiMap> { @Override protected Set createValue() { return Sets.newHashSet(); } } testng-testng-6.9.5/src/main/java/org/testng/collections/Objects.java0000644000175000017500000000412212551235562025151 0ustar eugeneeugenepackage org.testng.collections; import org.testng.util.Strings; import java.util.List; public final class Objects { private Objects() {} private static class ValueHolder { private String m_name; private String m_value; public ValueHolder(String name, String value) { m_name = name; m_value = value; } boolean isNull() { return m_value == null; } @Override public String toString() { return m_name + "=" + m_value; } public boolean isEmptyString() { return Strings.isNullOrEmpty(m_value); } } public static class ToStringHelper { private String m_className; private List values = Lists.newArrayList(); private boolean m_omitNulls = false; private boolean m_omitEmptyStrings = false; public ToStringHelper(String className) { m_className = className; } public ToStringHelper omitNulls() { m_omitNulls = true; return this; } public ToStringHelper omitEmptyStrings() { m_omitEmptyStrings = true; return this; } public ToStringHelper add(String name, String value) { values.add(new ValueHolder(name, s(value))); return this; } public ToStringHelper add(String name, Object value) { values.add(new ValueHolder(name, s(value))); return this; } private String s(Object o) { return o != null ? (o.toString().isEmpty() ? "\"\"" : o.toString()) : "{null}"; } @Override public String toString() { StringBuilder result = new StringBuilder("[" + m_className + " "); for (int i = 0; i < values.size(); i++) { ValueHolder vh = values.get(i); if (m_omitNulls && vh.isNull()) continue; if (m_omitEmptyStrings && vh.isEmptyString()) continue; if (i > 0) { result.append(" "); } result.append(vh.toString()); } result.append("]"); return result.toString(); } } public static ToStringHelper toStringHelper(Class class1) { return new ToStringHelper(class1.getSimpleName()); } } testng-testng-6.9.5/src/main/java/org/testng/collections/MultiMap.java0000644000175000017500000000424612551235562025317 0ustar eugeneeugenepackage 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> { protected final Map 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 getKeys() { return new ArrayList<>(keySet()); } public Set 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 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> getEntrySet() { return entrySet(); } public Set> entrySet() { return m_objects.entrySet(); } @Deprecated public Collection getValues() { return values(); } public Collection values() { return m_objects.values(); } public boolean putAll(K k, Collection values) { boolean result = false; for (V v : values) { result = put(k, v) || result; } return result; } } testng-testng-6.9.5/src/main/java/org/testng/collections/Maps.java0000755000175000017500000000133212551235562024463 0ustar eugeneeugenepackage org.testng.collections; import java.util.HashMap; import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.Map; public class Maps { public static Map newHashMap() { return new HashMap<>(); } public static Map newHashtable() { return new Hashtable<>(); } public static ListMultiMap newListMultiMap() { return new ListMultiMap<>(); } public static SetMultiMap newSetMultiMap() { return new SetMultiMap<>(); } public static Map newLinkedHashMap() { return new LinkedHashMap<>(); } public static Map newHashMap(Map parameters) { return new HashMap<>(parameters); } } testng-testng-6.9.5/src/main/java/org/testng/collections/Lists.java0000755000175000017500000000116312551235562024663 0ustar eugeneeugenepackage org.testng.collections; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; public final class Lists { private Lists() {} public static List newArrayList() { return new ArrayList<>(); } public static List newArrayList(Collection c) { return new ArrayList<>(c); } public static List newArrayList(K... elements) { List result = new ArrayList<>(); Collections.addAll(result, elements); return result; } public static List newArrayList(int size) { return new ArrayList<>(size); } } testng-testng-6.9.5/src/main/java/org/testng/collections/ListMultiMap.java0000644000175000017500000000056612551235562026154 0ustar eugeneeugenepackage org.testng.collections; import java.util.List; /** * A container to hold lists indexed by a key. */ public class ListMultiMap extends MultiMap> { @Override protected List createValue() { return Lists.newArrayList(); } @Deprecated public static ListMultiMap create() { return Maps.newListMultiMap(); } } testng-testng-6.9.5/src/main/java/org/testng/collections/CollectionUtils.java0000644000175000017500000000053712551235562026702 0ustar eugeneeugenepackage org.testng.collections; import java.util.Collection; import java.util.Map; public final class CollectionUtils { private CollectionUtils() {} public static boolean hasElements(Collection c) { return c != null && ! c.isEmpty(); } public static boolean hasElements(Map c) { return c != null && ! c.isEmpty(); } } testng-testng-6.9.5/src/main/java/org/testng/asserts/0000755000175000017500000000000012551235562022064 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/asserts/SoftAssert.java0000644000175000017500000000257012551235562025030 0ustar eugeneeugenepackage org.testng.asserts; import java.util.Map; import org.testng.collections.Maps; /** * When an assertion fails, don't throw an exception but record the failure. * Calling {@code assertAll()} will cause an exception to be thrown if at * least one assertion failed. */ public class SoftAssert extends Assertion { // LinkedHashMap to preserve the order private Map> m_errors = Maps.newLinkedHashMap(); @Override protected void doAssert(IAssert a) { onBeforeAssert(a); try { a.doAssert(); onAssertSuccess(a); } catch (AssertionError ex) { onAssertFailure(a, ex); m_errors.put(ex, a); } finally { onAfterAssert(a); } } public void assertAll() { if (! m_errors.isEmpty()) { StringBuilder sb = new StringBuilder("The following asserts failed:"); boolean first = true; for (Map.Entry> ae : m_errors.entrySet()) { if (first) { first = false; } else { sb.append(", "); } sb.append("\n\t"); final String message = ae.getValue().getMessage(); if (message != null) { sb.append(message).append("\t"); } //noinspection ThrowableResultOfMethodCallIgnored sb.append(ae.getKey().getMessage()); } throw new AssertionError(sb.toString()); } } } testng-testng-6.9.5/src/main/java/org/testng/asserts/LoggingAssert.java0000644000175000017500000000066512551235562025506 0ustar eugeneeugenepackage org.testng.asserts; import org.testng.collections.Lists; import java.util.List; /** * Log the messages of all the assertions that get run. */ public class LoggingAssert extends Assertion { private List m_messages = Lists.newArrayList(); @Override public void onBeforeAssert(IAssert a) { m_messages.add("Test:" + a.getMessage()); } public List getMessages() { return m_messages; } } testng-testng-6.9.5/src/main/java/org/testng/asserts/IAssertLifecycle.java0000644000175000017500000000151312551235562026121 0ustar eugeneeugenepackage org.testng.asserts; /** * Life cycle methods for the assertion class. */ public interface IAssertLifecycle { /** * Run the assert command in parameter. */ void executeAssert(IAssert assertCommand); /** * Invoked when an assert succeeds. */ void onAssertSuccess(IAssert assertCommand); /** * Invoked when an assert fails. * * @deprecated use onAssertFailure(IAssert assertCommand, AssertionError ex) instead of. */ void onAssertFailure(IAssert assertCommand); /** * Invoked when an assert fails. * */ void onAssertFailure(IAssert assertCommand, AssertionError ex); /** * Invoked before an assert is run. */ void onBeforeAssert(IAssert assertCommand); /** * Invoked after an assert is run. */ void onAfterAssert(IAssert assertCommand); } testng-testng-6.9.5/src/main/java/org/testng/asserts/IAssert.java0000644000175000017500000000021312551235562024275 0ustar eugeneeugenepackage org.testng.asserts; public interface IAssert { String getMessage(); void doAssert(); T getActual(); T getExpected(); } testng-testng-6.9.5/src/main/java/org/testng/asserts/Assertion.java0000644000175000017500000005002512551235562024700 0ustar eugeneeugenepackage org.testng.asserts; import java.util.Collection; import java.util.Map; import java.util.Set; /** * An assert class with various hooks allowing its behavior to be modified * by subclasses. */ public class Assertion implements IAssertLifecycle { protected void doAssert(IAssert assertCommand) { onBeforeAssert(assertCommand); try { executeAssert(assertCommand); onAssertSuccess(assertCommand); } catch(AssertionError ex) { onAssertFailure(assertCommand, ex); throw ex; } finally { onAfterAssert(assertCommand); } } /** * Run the assert command in parameter. Meant to be overridden by subclasses. */ @Override public void executeAssert(IAssert assertCommand) { assertCommand.doAssert(); } /** * Invoked when an assert succeeds. Meant to be overridden by subclasses. */ @Override public void onAssertSuccess(IAssert assertCommand) { } /** * Invoked when an assert fails. Meant to be overridden by subclasses. * * @deprecated use onAssertFailure(IAssert assertCommand, AssertionError ex) instead of. */ @Deprecated @Override public void onAssertFailure(IAssert assertCommand) { } @Override public void onAssertFailure(IAssert assertCommand, AssertionError ex) { onAssertFailure(assertCommand); } /** * Invoked before an assert is run. Meant to be overridden by subclasses. */ @Override public void onBeforeAssert(IAssert assertCommand) { } /** * Invoked after an assert is run. Meant to be overridden by subclasses. */ @Override public void onAfterAssert(IAssert assertCommand) { } abstract private static class SimpleAssert implements IAssert { private final T actual; private final T expected; private final String m_message; public SimpleAssert(String message) { this(null, null, message); } public SimpleAssert(T actual, T expected) { this(actual, expected, null); } public SimpleAssert(T actual, T expected, String message) { this.actual = actual; this.expected = expected; m_message = message; } @Override public String getMessage() { return m_message; } @Override public T getActual() { return actual; } @Override public T getExpected() { return expected; } @Override abstract public void doAssert(); } public void assertTrue(final boolean condition, final String message) { doAssert(new SimpleAssert(condition, Boolean.TRUE) { @Override public void doAssert() { org.testng.Assert.assertTrue(condition, message); } }); } public void assertTrue(final boolean condition) { doAssert(new SimpleAssert(condition, Boolean.TRUE) { @Override public void doAssert() { org.testng.Assert.assertTrue(condition); } }); } public void assertFalse(final boolean condition, final String message) { doAssert(new SimpleAssert(condition, Boolean.FALSE, message) { @Override public void doAssert() { org.testng.Assert.assertFalse(condition, message); } }); } public void assertFalse(final boolean condition) { doAssert(new SimpleAssert(condition, Boolean.FALSE) { @Override public void doAssert() { org.testng.Assert.assertFalse(condition); } }); } public void fail(final String message, final Throwable realCause) { doAssert(new SimpleAssert(message) { @Override public void doAssert() { org.testng.Assert.fail(message, realCause); } }); } public void fail(final String message) { doAssert(new SimpleAssert(message) { @Override public void doAssert() { org.testng.Assert.fail(message); } }); } public void fail() { doAssert(new SimpleAssert(null) { @Override public void doAssert() { org.testng.Assert.fail(); } }); } public void assertEquals(final T actual, final T expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, message); } }); } public void assertEquals(final T actual, final T expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected); } }); } public void assertEquals(final String actual, final String expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, message); } }); } public void assertEquals(final String actual, final String expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected); } }); } public void assertEquals(final double actual, final double expected, final double delta, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, delta, message); } }); } public void assertEquals(final double actual, final double expected, final double delta) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, delta); } }); } public void assertEquals(final float actual, final float expected, final float delta, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, delta, message); } }); } public void assertEquals(final float actual, final float expected, final float delta) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, delta); } }); } public void assertEquals(final long actual, final long expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, message); } }); } public void assertEquals(final long actual, final long expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected); } }); } public void assertEquals(final boolean actual, final boolean expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, message); } }); } public void assertEquals(final boolean actual, final boolean expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected); } }); } public void assertEquals(final byte actual, final byte expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, message); } }); } public void assertEquals(final byte actual, final byte expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected); } }); } public void assertEquals(final char actual, final char expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, message); } }); } public void assertEquals(final char actual, final char expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected); } }); } public void assertEquals(final short actual, final short expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, message); } }); } public void assertEquals(final short actual, final short expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected); } }); } public void assertEquals(final int actual, final int expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, message); } }); } public void assertEquals(final int actual, final int expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected); } }); } public void assertNotNull(final Object object) { doAssert(new SimpleAssert(object, null) { @Override public void doAssert() { org.testng.Assert.assertNotNull(object); } }); } public void assertNotNull(final Object object, final String message) { doAssert(new SimpleAssert(object, null, message) { @Override public void doAssert() { org.testng.Assert.assertNotNull(object, message); } }); } public void assertNull(final Object object) { doAssert(new SimpleAssert(object, null) { @Override public void doAssert() { org.testng.Assert.assertNull(object); } }); } public void assertNull(final Object object, final String message) { doAssert(new SimpleAssert(object, null, message) { @Override public void doAssert() { org.testng.Assert.assertNull(object, message); } }); } public void assertSame(final Object actual, final Object expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertSame(actual, expected, message); } }); } public void assertSame(final Object actual, final Object expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertSame(actual, expected); } }); } public void assertNotSame(final Object actual, final Object expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertNotSame(actual, expected, message); } }); } public void assertNotSame(final Object actual, final Object expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertNotSame(actual, expected); } }); } public void assertEquals(final Collection actual, final Collection expected) { doAssert(new SimpleAssert>(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected); } }); } public void assertEquals(final Collection actual, final Collection expected, final String message) { doAssert(new SimpleAssert>(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, message); } }); } public void assertEquals(final Object[] actual, final Object[] expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, message); } }); } public void assertEqualsNoOrder(final Object[] actual, final Object[] expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEqualsNoOrder(actual, expected, message); } }); } public void assertEquals(final Object[] actual, final Object[] expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected); } }); } public void assertEqualsNoOrder(final Object[] actual, final Object[] expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEqualsNoOrder(actual, expected); } }); } public void assertEquals(final byte[] actual, final byte[] expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected); } }); } public void assertEquals(final byte[] actual, final byte[] expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, message); } }); } public void assertEquals(final Set actual, final Set expected) { doAssert(new SimpleAssert>(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected); } }); } public void assertEquals(final Set actual, final Set expected, final String message) { doAssert(new SimpleAssert>(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected, message); } }); } public void assertEquals(final Map actual, final Map expected) { doAssert(new SimpleAssert>(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertEquals(actual, expected); } }); } public void assertNotEquals(final Object actual, final Object expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected, message); } }); } public void assertNotEquals(final Object actual, final Object expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected); } }); } void assertNotEquals(final String actual, final String expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected, message); } }); } void assertNotEquals(final String actual, final String expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected); } }); } void assertNotEquals(final long actual, final long expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected, message); } }); } void assertNotEquals(final long actual, final long expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected); } }); } void assertNotEquals(final boolean actual, final boolean expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected, message); } }); } void assertNotEquals(final boolean actual, final boolean expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected); } }); } void assertNotEquals(final byte actual, final byte expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected, message); } }); } void assertNotEquals(final byte actual, final byte expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected); } }); } void assertNotEquals(final char actual, final char expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected, message); } }); } void assertNotEquals(final char actual, final char expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected); } }); } void assertNotEquals(final short actual, final short expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected, message); } }); } void assertNotEquals(final short actual, final short expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected); } }); } void assertNotEquals(final int actual, final int expected, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected, message); } }); } void assertNotEquals(final int actual, final int expected) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected); } }); } public void assertNotEquals(final float actual, final float expected, final float delta, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected, delta, message); } }); } public void assertNotEquals(final float actual, final float expected, final float delta) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected, delta); } }); } public void assertNotEquals(final double actual, final double expected, final double delta, final String message) { doAssert(new SimpleAssert(actual, expected, message) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected, delta, message); } }); } public void assertNotEquals(final double actual, final double expected, final double delta) { doAssert(new SimpleAssert(actual, expected) { @Override public void doAssert() { org.testng.Assert.assertNotEquals(actual, expected, delta); } }); } } testng-testng-6.9.5/src/main/java/org/testng/annotations/0000755000175000017500000000000012551235562022735 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/org/testng/annotations/TestInstance.java0000755000175000017500000000101612551235562026205 0ustar eugeneeugenepackage org.testng.annotations; import static java.lang.annotation.ElementType.PARAMETER; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** * If this annotation is used on a parameter of a data provider, that parameter is the instance * of the test method which is going to be fed by this data provider. * * This annotation is ignored everywhere else. * * @author cbeust */ @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({PARAMETER}) public @interface TestInstance { } testng-testng-6.9.5/src/main/java/org/testng/annotations/Test.java0000755000175000017500000001336212551235562024527 0ustar eugeneeugenepackage org.testng.annotations; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** * Mark a class or a method as part of the test. * * @author Cedric Beust, Apr 26, 2004 */ @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({METHOD, TYPE, CONSTRUCTOR}) public @interface Test { /** * The list of groups this class/method belongs to. */ public String[] groups() default {}; /** * Whether methods on this class/method are enabled. */ public boolean enabled() default true; /** * The list of variables used to fill the parameters of this method. * These variables must be defined in the property file. * * @deprecated Use @Parameters */ @Deprecated public String[] parameters() default {}; /** * The list of groups this method depends on. Every method * member of one of these groups is guaranteed to have been * invoked before this method. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. */ public String[] dependsOnGroups() default {}; /** * The list of methods this method depends on. There is no guarantee * on the order on which the methods depended upon will be run, but you * are guaranteed that all these methods will be run before the test method * that contains this annotation is run. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. * * If some of these methods have been overloaded, all the overloaded * versions will be run. */ public String[] dependsOnMethods() default {}; /** * The maximum number of milliseconds this test should take. * If it hasn't returned after this time, it will be marked as a FAIL. */ public long timeOut() default 0; /** * The maximum number of milliseconds that the total number of invocations on this test * method should take. This annotation will be ignored if the attribute invocationCount * is not specified on this method. * If it hasn't returned after this time, it will be marked as a FAIL. */ public long invocationTimeOut() default 0; /** * The number of times this method should be invoked. */ public int invocationCount() default 1; /** * The size of the thread pool for this method. The method will be invoked * from multiple threads as specified by invocationCount. * Note: this attribute is ignored if invocationCount is not specified */ public int threadPoolSize() default 0; /** * The percentage of success expected from this method. */ public int successPercentage() default 100; /** * The name of the data provider for this test method. * @see org.testng.annotations.DataProvider */ public String dataProvider() default ""; /** * The class where to look for the data provider. If not * specified, the dataprovider will be looked on the class * of the current test method or one of its super classes. * If this attribute is specified, the data provider method * needs to be static on the specified class. */ public Class dataProviderClass() default Object.class; /** * If set to true, this test method will always be run even if it depends * on a method that failed. This attribute will be ignored if this test * doesn't depend on any method or group. */ public boolean alwaysRun() default false; /** * The description for this method. The string used will appear in the * HTML report and also on standard output if verbose >= 2. */ public String description() default ""; /** * The list of exceptions that a test method is expected to throw. If no * exception or a different than one on this list is thrown, this test will be * marked a failure. */ public Class[] expectedExceptions() default {}; /** * If expectedExceptions was specified, its message must match the regular expression * specified in this attribute. */ public String expectedExceptionsMessageRegExp() default ".*"; /** * The name of the suite this test class should be placed in. This * attribute is ignore if @Test is not at the class level. */ public String suiteName() default ""; /** * The name of the test this test class should be placed in. This * attribute is ignore if @Test is not at the class level. */ public String testName() default ""; /** * @deprecated Use singleThreaded */ public boolean sequential() default false; /** * If set to true, all the methods on this test class are guaranteed to run * in the same thread, even if the tests are currently being run with parallel="true". * * This attribute can only be used at the class level and will be ignored * if used at the method level. */ public boolean singleThreaded() default false; /** * The name of the class that should be called to test if the test * should be retried. * @return String The name of the class that will test if a test method * should be retried. */ public Class retryAnalyzer() default Class.class; /** * If true and invocationCount is specified with a value > 1, * then all invocations after a failure will be marked as a SKIP * instead of a FAIL. */ public boolean skipFailedInvocations() default false; /** * If set to true, this test will run even if the methods * it depends on are missing or excluded. */ public boolean ignoreMissingDependencies() default false; /** * The scheduling priority. Lower priorities will be scheduled first. */ int priority() default 0; } testng-testng-6.9.5/src/main/java/org/testng/annotations/Parameters.java0000755000175000017500000000202412551235562025704 0ustar eugeneeugenepackage org.testng.annotations; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** * Describes how to pass parameters to a @Test method. * * @author Cedric Beust */ @Retention(RUNTIME) @Target({METHOD, CONSTRUCTOR, TYPE }) public @interface Parameters { /** * The list of variables used to fill the parameters of this method. * These variables must be defined in your testng.xml file. * For example *

* * @Parameters({ "xmlPath" })
* @Test
* public void verifyXmlFile(String path) { ... }
*
*

and in testng.xml:

* * <parameter name="xmlPath" value="account.xml" />
*
*/ public String[] value() default {}; } testng-testng-6.9.5/src/main/java/org/testng/annotations/Optional.java0000755000175000017500000000210512551235562025366 0ustar eugeneeugenepackage org.testng.annotations; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.RUNTIME; import org.testng.internal.Parameters; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** * Specifies that the current parameter is optional. TestNG will pass * in a specified default value, or null if none is specified. */ @Retention(RUNTIME) @Target({PARAMETER}) public @interface Optional { /** The default value to pass to this parameter.

The default deserves * a bit of explanation. JSR-175 (which defines annotations) says that * Java annotation parameters can only be ConstantExpressions, which * can be primitive/string literals, but not null.

*

In this case, we use this string as a substitute * for null; in practice, TestNG will pass null * to your code, and not the string "null", if you do not specify * a default value here in this parameter. */ public String value() default Parameters.NULL_VALUE; } testng-testng-6.9.5/src/main/java/org/testng/annotations/ObjectFactory.java0000755000175000017500000000103612551235562026341 0ustar eugeneeugenepackage org.testng.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** * Marks a method as the object factory to use for creating all test instances. * The test classes can only contain one method marked with this annotation, * and the method must return an instance of {@link org.testng.ITestObjectFactory}. * * @author Hani Suleiman * @since 5.6 */ @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(java.lang.annotation.ElementType.METHOD) public @interface ObjectFactory { } testng-testng-6.9.5/src/main/java/org/testng/annotations/NoInjection.java0000644000175000017500000000057212551235562026023 0ustar eugeneeugenepackage org.testng.annotations; import static java.lang.annotation.ElementType.PARAMETER; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** * Turn off TestNG injection for a parameter. * * @author Cedric Beust, July 9th, 2010 */ @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({PARAMETER}) public @interface NoInjection { } testng-testng-6.9.5/src/main/java/org/testng/annotations/Listeners.java0000644000175000017500000000177212551235562025557 0ustar eugeneeugenepackage org.testng.annotations; import static java.lang.annotation.ElementType.TYPE; import org.testng.IAnnotationTransformer; import org.testng.IAnnotationTransformer2; import org.testng.ITestNGListener; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** * This annotation lets you define listeners directly on a test class * instead of doing so in your testng.xml. Any class that implements * the interface {@link org.testng.ITestNGListener} is allowed, * except {@link IAnnotationTransformer} and {@link IAnnotationTransformer2}, * which need to be defined in XML since they have to be known before we even * start looking for annotations. * * Note that listeners specified this way are global to your entire suite, just * like listeners specified in testng.xml. * * @author Cedric Beust, Mar 26, 2010 * */ @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({TYPE}) public @interface Listeners { Class[] value() default {}; } testng-testng-6.9.5/src/main/java/org/testng/annotations/ITestOrConfiguration.java0000755000175000017500000000353212551235562027667 0ustar eugeneeugenepackage org.testng.annotations; /** * This interface captures methods common to @Test and @Configuration * * Created on Dec 20, 2005 * @author Cedric Beust */ public interface ITestOrConfiguration extends IParameterizable { /** * Returns the maximum number of milliseconds this test should take. * If it hasn't returned after this time, it will be marked as a FAIL. * @return the maximum number of milliseconds this test should take. */ public long getTimeOut(); public void setTimeOut(long l); /** * The list of groups this class/method belongs to. */ public String[] getGroups(); public void setGroups(String[] groups); /** * The list of groups this method depends on. Every method * member of one of these groups is guaranteed to have been * invoked before this method. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. */ public String[] getDependsOnGroups(); public void setDependsOnGroups(String[] groups); /** * The list of methods this method depends on. There is no guarantee * on the order on which the methods depended upon will be run, but you * are guaranteed that all these methods will be run before the test method * that contains this annotation is run. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. * * If some of these methods have been overloaded, all the overloaded * versions will be run. */ public String[] getDependsOnMethods(); public void setDependsOnMethods(String[] dependsOnMethods); /** * The description for this method, which will be shown in the reports. */ public String getDescription(); public void setDescription(String description); } testng-testng-6.9.5/src/main/java/org/testng/annotations/ITestAnnotation.java0000755000175000017500000000473612551235562026700 0ustar eugeneeugenepackage org.testng.annotations; import org.testng.IRetryAnalyzer; import org.testng.internal.annotations.IDataProvidable; /** * Encapsulate the @Test / @testng.test annotation. * * Created on Dec 20, 2005 * @author Cedric Beust */ public interface ITestAnnotation extends ITestOrConfiguration, IDataProvidable { /** * Returns the number of times this method should be invoked. * @return the number of times this method should be invoked. */ public int getInvocationCount(); public void setInvocationCount(int l); /** * The size of the thread pool for this method. The method will be invoked * from multiple threads as specified by invocationCount. * Note: this attribute is ignored if invocationCount is not specified */ public int getThreadPoolSize(); public void setThreadPoolSize(int n); /** * The percentage of success expected from this method. */ public int getSuccessPercentage(); public void setSuccessPercentage(int s); /** * If set to true, this test method will always be run even if it depends * on a method that failed. This attribute will be ignored if this test * doesn't depend on any method or group. */ public boolean getAlwaysRun(); public void setAlwaysRun(boolean f); public Class[] getExpectedExceptions(); public void setExpectedExceptions(Class[] e); public String getExpectedExceptionsMessageRegExp(); public void setExpectedExceptionsMessageRegExp(String e); public String getSuiteName(); public void setSuiteName(String s); public String getTestName(); public void setTestName(String s); public boolean getSequential(); public void setSequential(boolean f); public boolean getSingleThreaded(); public void setSingleThreaded(boolean f); public String getDataProvider(); public void setDataProvider(String v); public Class getDataProviderClass(); public void setDataProviderClass(Class v); public IRetryAnalyzer getRetryAnalyzer(); public void setRetryAnalyzer(Class c); public boolean skipFailedInvocations(); public void setSkipFailedInvocations(boolean skip); public long invocationTimeOut(); public void setInvocationTimeOut(long timeOut); public boolean ignoreMissingDependencies(); public void setIgnoreMissingDependencies(boolean ignore); /** * The scheduling priority. Lower priorities get scheduled first. */ public int getPriority(); public void setPriority(int priority); } testng-testng-6.9.5/src/main/java/org/testng/annotations/IParametersAnnotation.java0000755000175000017500000000133312551235562030052 0ustar eugeneeugenepackage org.testng.annotations; /** * Encapsulate the @Parameters / @testng.parameters annotation * * Created on Dec 20, 2005 * @author Cedric Beust */ public interface IParametersAnnotation extends IAnnotation { /** * The list of variables used to fill the parameters of this method. * These variables must be defined in your testng.xml file. * For example *

* * @Parameters({ "xmlPath" })
* @Test
* public void verifyXmlFile(String path) { ... }
*
*

and in testng.xml:

* * <parameter name="xmlPath" value="account.xml" />
*
*/ public String[] getValue(); } testng-testng-6.9.5/src/main/java/org/testng/annotations/IParameterizable.java0000755000175000017500000000114512551235562027024 0ustar eugeneeugenepackage org.testng.annotations; /** * Parent interface for annotations that can receive parameters. * * Created on Dec 20, 2005 * @author Cedric Beust */ public interface IParameterizable extends IAnnotation { /** * The list of variables used to fill the parameters of this method. * These variables must be defined in the property file. * * @deprecated Use @Parameters */ @Deprecated public String[] getParameters(); /** * Whether this annotation is enabled. */ public boolean getEnabled(); public void setEnabled(boolean enabled); } testng-testng-6.9.5/src/main/java/org/testng/annotations/IObjectFactoryAnnotation.java0000755000175000017500000000027512551235562030511 0ustar eugeneeugenepackage org.testng.annotations; /** * @author Hani Suleiman * Date: Mar 6, 2007 * Time: 2:16:13 PM */ public interface IObjectFactoryAnnotation extends IAnnotation { } testng-testng-6.9.5/src/main/java/org/testng/annotations/IFactoryAnnotation.java0000755000175000017500000000051112551235562027353 0ustar eugeneeugenepackage org.testng.annotations; import org.testng.internal.annotations.IDataProvidable; /** * Encapsulate the @Factory / @testng.factory annotation * * Created on Dec 20, 2005 * @author Cedric Beust */ public interface IFactoryAnnotation extends IParameterizable, IDataProvidable { } testng-testng-6.9.5/src/main/java/org/testng/annotations/IExpectedExceptionsAnnotation.java0000755000175000017500000000060512551235562031553 0ustar eugeneeugenepackage org.testng.annotations; /** * Encapsulate the @ExpectedExceptions / @testng.expected-exceptions annotation * Created on Dec 20, 2005 * @author Cedric Beust */ public interface IExpectedExceptionsAnnotation extends IAnnotation { /** * The list of exceptions expected to be thrown by this method. */ public Class[] getValue(); } testng-testng-6.9.5/src/main/java/org/testng/annotations/IDataProviderAnnotation.java0000755000175000017500000000100012551235562030322 0ustar eugeneeugenepackage org.testng.annotations; /** * Encapsulate the @DataProvider / @testng.data-provider annotation * * Created on Dec 20, 2005 * @author Cedric Beust */ public interface IDataProviderAnnotation extends IAnnotation { /** * The name of this DataProvider. */ public String getName(); public void setName(String name); /** * Whether this data provider should be used in parallel. */ boolean isParallel(); void setParallel(boolean parallel); } testng-testng-6.9.5/src/main/java/org/testng/annotations/IConfigurationAnnotation.java0000755000175000017500000000433712551235562030565 0ustar eugeneeugenepackage org.testng.annotations; /** * Encapsulate the @Configuration / @testng.configuration annotation * * Created on Dec 20, 2005 * @author Cedric Beust */ public interface IConfigurationAnnotation extends ITestOrConfiguration { /** * If true, the annotated method will be run after the test class is instantiated * and before the test method is invoked. */ public boolean getBeforeTestClass(); /** * If true, the annotated method will be run after all the tests in the test * class have been run. */ public boolean getAfterTestClass(); /** * If true, the annotated method will be run before any test method is invoked. */ public boolean getBeforeTestMethod(); /** * If true, the annotated method will be run after any test method is invoked. */ public boolean getAfterTestMethod(); /** * If true, the annotated method will be run before this suite starts. */ public boolean getBeforeSuite(); /** * If true, the annotated method will be run after all tests in this suite * have run. */ public boolean getAfterSuite(); /** * If true, the annotated method will be run before every test */ public boolean getBeforeTest(); /** * If true, the annotated method will be run after all every test. */ public boolean getAfterTest(); /** * Used only for after type of configuration methods. If set to true than * the configuration method will be run whatever the status of before * configuration methods was. */ public boolean getAlwaysRun(); /** * If true, this @Configuration method will belong to groups specified in the * \@Test annotation on the class (if any). */ public boolean getInheritGroups(); /** * The list of groups that this configuration method will run before. */ public String[] getBeforeGroups(); /** * The list of groups that this configuration method will run after. */ public String[] getAfterGroups(); /** * Internal use only. * @return true if this configuration annotation is not a "true" configuration * annotation but a @BeforeSuite or similar that is represented as a configuration * annotation. */ public boolean isFakeConfiguration(); } testng-testng-6.9.5/src/main/java/org/testng/annotations/IAnnotation.java0000755000175000017500000000033212551235562026024 0ustar eugeneeugenepackage org.testng.annotations; /** * The parent interface for all the annotations. * * Created on Dec 20, 2005 * * @author Cedric Beust */ public interface IAnnotation { } testng-testng-6.9.5/src/main/java/org/testng/annotations/Guice.java0000644000175000017500000000132312551235562024633 0ustar eugeneeugenepackage org.testng.annotations; import static java.lang.annotation.ElementType.TYPE; import com.google.inject.Module; import org.testng.IModuleFactory; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** * This annotation specifies what Guice modules should be used to instantiate * this test class. * * @author Cedric Beust */ @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(TYPE) public @interface Guice { /** * @return the list of modules to query when trying to create an instance of this test class. */ Class[] modules() default {}; Class moduleFactory() default IModuleFactory.class; } testng-testng-6.9.5/src/main/java/org/testng/annotations/Factory.java0000755000175000017500000000251612551235562025216 0ustar eugeneeugenepackage org.testng.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** * Marks a method as a factory that returns objects that will be used by TestNG * as Test classes. The method must return Object[]. * * @author Cedric Beust */ @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.CONSTRUCTOR}) public @interface Factory { /** * The list of variables used to fill the parameters of this method. * These variables must be defined in the property file. * * @deprecated Use @Parameters */ @Deprecated public String[] parameters() default {}; /** * The name of the data provider for this test method. * @see org.testng.annotations.DataProvider */ public String dataProvider() default ""; /** * The class where to look for the data provider. If not * specified, the dataprovider will be looked on the class * of the current test method or one of its super classes. * If this attribute is specified, the data provider method * needs to be static on the specified class. */ public Class dataProviderClass() default Object.class; /** * Whether this factory is enabled. */ public boolean enabled() default true; } testng-testng-6.9.5/src/main/java/org/testng/annotations/ExpectedExceptions.java0000755000175000017500000000102412551235562027403 0ustar eugeneeugenepackage org.testng.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** * List of exceptions that a test method is expected to throw. * * @deprecated Use @Test(expectedExceptions = "...") * * @author Cedric Beust, Apr 26, 2004 * */ @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(java.lang.annotation.ElementType.METHOD) public @interface ExpectedExceptions { /** * The list of exceptions expected to be thrown by this method. */ public Class[] value(); } testng-testng-6.9.5/src/main/java/org/testng/annotations/DataProvider.java0000755000175000017500000000172612551235562026175 0ustar eugeneeugenepackage org.testng.annotations; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** * Mark a method as supplying data for a test method. The data provider name * defaults to method name. * The annotated method must return an Object[][] where each * Object[] can be assigned the parameter list of the test method. * The @Test method that wants to receive data from this DataProvider * needs to use a dataProvider name equals to the name of this annotation. * * @author cbeust */ @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({METHOD}) public @interface DataProvider { /** * The name of this DataProvider. */ public String name() default ""; /** * Whether this data provider should be run in parallel. */ boolean parallel() default false; /** * Which indices to run from this data provider, default: all. */ int[] indices() default {}; } testng-testng-6.9.5/src/main/java/org/testng/annotations/Configuration.java0000755000175000017500000001054512551235562026417 0ustar eugeneeugenepackage org.testng.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; /** * Configuration information for a TestNG class. * * @deprecated Use @BeforeSuite, @AfterSuite, @BeforeTest, @AfterTest, * \@BeforeGroups, @AfterGroups, @BeforeClass, @AfterClass, @BeforeMethod, * \@AfterMethod * * @author Cedric Beust, Apr 26, 2004 * */ @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(java.lang.annotation.ElementType.METHOD) public @interface Configuration { /** * If true, the annotated method will be run after the test class is instantiated * and before the test method is invoked. */ public boolean beforeTestClass() default false; /** * If true, the annotated method will be run after all the tests in the test * class have been run. */ public boolean afterTestClass() default false; /** * If true, the annotated method will be run before any test method is invoked. */ public boolean beforeTestMethod() default false; /** * If true, the annotated method will be run after any test method is invoked. */ public boolean afterTestMethod() default false; /** * If true, the annotated method will be run before this suite starts. */ public boolean beforeSuite() default false; /** * If true, the annotated method will be run after all tests in this suite * have run. */ public boolean afterSuite() default false; /** * If true, the annotated method will be run before every test. */ public boolean beforeTest() default false; /** * If true, the annotated method will be run after all every test. */ public boolean afterTest() default false; /** * The list of groups that this configuration method will run before. * This method is guaranteed to run shortly before the first test method that * belongs to any of these groups is invoked. */ public String[] beforeGroups() default {}; /** * The list of groups that this configuration method will run after. * This method is guaranteed to run shortly after the last test method that * belongs to any of these groups is invoked. */ public String[] afterGroups() default {}; /** * The list of variables used to fill the parameters of this method. * These variables must be defined in the property file. * * @deprecated Use @Parameters */ @Deprecated public String[] parameters() default {}; /** * Whether methods on this class/method are enabled. */ public boolean enabled() default true; /** * The list of groups this class/method belongs to. */ public String[] groups() default {}; /** * The list of groups this method depends on. Every method * member of one of these groups is guaranteed to have been * invoked before this method. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. */ public String[] dependsOnGroups() default {}; /** * The list of methods this method depends on. There is no guarantee * on the order on which the methods depended upon will be run, but you * are guaranteed that all these methods will be run before the test method * that contains this annotation is run. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. * * If some of these methods have been overloaded, all the overloaded * versions will be run. */ public String[] dependsOnMethods() default {}; /** * For before methods (beforeSuite, beforeTest, beforeTestClass and * beforeTestMethod, but not beforeGroups): * If set to true, this configuration method will be run * regardless of what groups it belongs to. *
* For after methods (afterSuite, afterClass, ...): * If set to true, this configuration method will be run * even if one or more methods invoked previously failed or * was skipped. */ public boolean alwaysRun() default false; /** * If true, this @Configuration method will belong to groups specified in the * @Test annotation on the class (if any). */ public boolean inheritGroups() default true; /** * The description for this method. The string used will appear in the * HTML report and also on standard output if verbose >= 2. */ public String description() default ""; } testng-testng-6.9.5/src/main/java/org/testng/annotations/BeforeTest.java0000755000175000017500000000467712551235562025663 0ustar eugeneeugenepackage org.testng.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(java.lang.annotation.ElementType.METHOD) public @interface BeforeTest { /** * Whether methods on this class/method are enabled. */ public boolean enabled() default true; /** * The list of groups this class/method belongs to. */ public String[] groups() default {}; /** * The list of groups this method depends on. Every method * member of one of these groups is guaranteed to have been * invoked before this method. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. */ public String[] dependsOnGroups() default {}; /** * The list of methods this method depends on. There is no guarantee * on the order on which the methods depended upon will be run, but you * are guaranteed that all these methods will be run before the test method * that contains this annotation is run. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. * * If some of these methods have been overloaded, all the overloaded * versions will be run. */ public String[] dependsOnMethods() default {}; /** * For before methods (beforeSuite, beforeTest, beforeTestClass and * beforeTestMethod, but not beforeGroups): * If set to true, this configuration method will be run * regardless of what groups it belongs to. *
* For after methods (afterSuite, afterClass, ...): * If set to true, this configuration method will be run * even if one or more methods invoked previously failed or * was skipped. */ public boolean alwaysRun() default false; /** * If true, this @Configuration method will belong to groups specified in the * @Test annotation on the class (if any). */ public boolean inheritGroups() default true; /** * The description for this method. The string used will appear in the * HTML report and also on standard output if verbose >= 2. */ public String description() default ""; /** * The maximum number of milliseconds this method should take. * If it hasn't returned after this time, this method will fail and * it will cause test methods depending on it to be skipped. */ public long timeOut() default 0; } testng-testng-6.9.5/src/main/java/org/testng/annotations/BeforeSuite.java0000755000175000017500000000470312551235562026023 0ustar eugeneeugenepackage org.testng.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(java.lang.annotation.ElementType.METHOD) public @interface BeforeSuite { /** * Whether methods on this class/method are enabled. */ public boolean enabled() default true; /** * The list of groups this class/method belongs to. */ public String[] groups() default {}; /** * The list of groups this method depends on. Every method * member of one of these groups is guaranteed to have been * invoked before this method. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. */ public String[] dependsOnGroups() default {}; /** * The list of methods this method depends on. There is no guarantee * on the order on which the methods depended upon will be run, but you * are guaranteed that all these methods will be run before the test method * that contains this annotation is run. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. * * If some of these methods have been overloaded, all the overloaded * versions will be run. */ public String[] dependsOnMethods() default {}; /** * For before methods (beforeSuite, beforeTest, beforeTestClass and * beforeTestMethod, but not beforeGroups): * If set to true, this configuration method will be run * regardless of what groups it belongs to. *
* For after methods (afterSuite, afterClass, ...): * If set to true, this configuration method will be run * even if one or more methods invoked previously failed or * was skipped. */ public boolean alwaysRun() default false; /** * If true, this @Configuration method will belong to groups specified in the * @Test annotation on the class (if any). */ public boolean inheritGroups() default true; /** * The description for this method. The string used will appear in the * HTML report and also on standard output if verbose >= 2. */ public String description() default ""; /** * The maximum number of milliseconds this method should take. * If it hasn't returned after this time, this method will fail and * it will cause test methods depending on it to be skipped. */ public long timeOut() default 0; } testng-testng-6.9.5/src/main/java/org/testng/annotations/BeforeMethod.java0000755000175000017500000000524712551235562026156 0ustar eugeneeugenepackage org.testng.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(java.lang.annotation.ElementType.METHOD) public @interface BeforeMethod { /** * Whether methods on this class/method are enabled. */ public boolean enabled() default true; /** * The list of groups this class/method belongs to. */ public String[] groups() default {}; /** * The list of groups this method depends on. Every method * member of one of these groups is guaranteed to have been * invoked before this method. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. */ public String[] dependsOnGroups() default {}; /** * The list of methods this method depends on. There is no guarantee * on the order on which the methods depended upon will be run, but you * are guaranteed that all these methods will be run before the test method * that contains this annotation is run. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. * * If some of these methods have been overloaded, all the overloaded * versions will be run. */ public String[] dependsOnMethods() default {}; /** * For before methods (beforeSuite, beforeTest, beforeTestClass and * beforeTestMethod, but not beforeGroups): * If set to true, this configuration method will be run * regardless of what groups it belongs to. *
* For after methods (afterSuite, afterClass, ...): * If set to true, this configuration method will be run * even if one or more methods invoked previously failed or * was skipped. */ public boolean alwaysRun() default false; /** * If true, this @Configuration method will belong to groups specified in the * @Test annotation on the class (if any). */ public boolean inheritGroups() default true; /** * The description for this method. The string used will appear in the * 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 * BeforeMethod will only be invoked once (before the first test invocation). */ public boolean firstTimeOnly() default false; /** * The maximum number of milliseconds this method should take. * If it hasn't returned after this time, this method will fail and * it will cause test methods depending on it to be skipped. */ public long timeOut() default 0; } testng-testng-6.9.5/src/main/java/org/testng/annotations/BeforeGroups.java0000755000175000017500000000564312551235562026215 0ustar eugeneeugenepackage org.testng.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(java.lang.annotation.ElementType.METHOD) public @interface BeforeGroups { /** * The list of groups that this configuration method will run before. If specified it overrides the * list of groups provided through {@link #groups()} attribute. * This method is guaranteed to run shortly before the first test method that * belongs to any of these groups is invoked. */ public String[] value() default {}; /** * Whether methods on this class/method are enabled. */ public boolean enabled() default true; /** * The list of groups this class/method belongs to. This list also describes the groups * that this configuration method will run before (if no {@link #value()} attribute is defined). */ public String[] groups() default {}; /** * The list of groups this method depends on. Every method * member of one of these groups is guaranteed to have been * invoked before this method. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. */ public String[] dependsOnGroups() default {}; /** * The list of methods this method depends on. There is no guarantee * on the order on which the methods depended upon will be run, but you * are guaranteed that all these methods will be run before the test method * that contains this annotation is run. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. * * If some of these methods have been overloaded, all the overloaded * versions will be run. */ public String[] dependsOnMethods() default {}; /** * For before methods (beforeSuite, beforeTest, beforeTestClass and * beforeTestMethod, but not beforeGroups): * If set to true, this configuration method will be run * regardless of what groups it belongs to. *
* For after methods (afterSuite, afterClass, ...): * If set to true, this configuration method will be run * even if one or more methods invoked previously failed or * was skipped. */ public boolean alwaysRun() default false; /** * If true, this @Configuration method will belong to groups specified in the * @Test annotation on the class (if any). */ public boolean inheritGroups() default true; /** * The description for this method. The string used will appear in the * HTML report and also on standard output if verbose >= 2. */ public String description() default ""; /** * The maximum number of milliseconds this method should take. * If it hasn't returned after this time, this method will fail and * it will cause test methods depending on it to be skipped. */ public long timeOut() default 0; } testng-testng-6.9.5/src/main/java/org/testng/annotations/BeforeClass.java0000755000175000017500000000470012551235562025774 0ustar eugeneeugenepackage org.testng.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(java.lang.annotation.ElementType.METHOD) public @interface BeforeClass { /** * Whether methods on this class/method are enabled. */ public boolean enabled() default true; /** * The list of groups this class/method belongs to. */ public String[] groups() default {}; /** * The list of groups this method depends on. Every method * member of one of these groups is guaranteed to have been * invoked before this method. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. */ public String[] dependsOnGroups() default {}; /** * The list of methods this method depends on. There is no guarantee * on the order on which the methods depended upon will be run, but you * are guaranteed that all these methods will be run before the test method * that contains this annotation is run. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. * * If some of these methods have been overloaded, all the overloaded * versions will be run. */ public String[] dependsOnMethods() default {}; /** * For before methods (beforeSuite, beforeTest, beforeTestClass and * beforeTestMethod, but not beforeGroups): * If set to true, this configuration method will be run * regardless of what groups it belongs to. *
* For after methods (afterSuite, afterClass, ...): * If set to true, this configuration method will be run * even if one or more methods invoked previously failed or * was skipped. */ public boolean alwaysRun() default false; /** * If true, this @Configuration method will belong to groups specified in the * @Test annotation on the class (if any). */ public boolean inheritGroups() default true; /** * The description for this method. The string used will appear in the * HTML report and also on standard output if verbose >= 2. */ public String description() default ""; /** * The maximum number of milliseconds this method should take. * If it hasn't returned after this time, this method will fail and * it will cause test methods depending on it to be skipped. */ public long timeOut() default 0; } testng-testng-6.9.5/src/main/java/org/testng/annotations/AfterTest.java0000755000175000017500000000467612551235562025521 0ustar eugeneeugenepackage org.testng.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(java.lang.annotation.ElementType.METHOD) public @interface AfterTest { /** * Whether methods on this class/method are enabled. */ public boolean enabled() default true; /** * The list of groups this class/method belongs to. */ public String[] groups() default {}; /** * The list of groups this method depends on. Every method * member of one of these groups is guaranteed to have been * invoked before this method. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. */ public String[] dependsOnGroups() default {}; /** * The list of methods this method depends on. There is no guarantee * on the order on which the methods depended upon will be run, but you * are guaranteed that all these methods will be run before the test method * that contains this annotation is run. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. * * If some of these methods have been overloaded, all the overloaded * versions will be run. */ public String[] dependsOnMethods() default {}; /** * For before methods (beforeSuite, beforeTest, beforeTestClass and * beforeTestMethod, but not beforeGroups): * If set to true, this configuration method will be run * regardless of what groups it belongs to. *
* For after methods (afterSuite, afterClass, ...): * If set to true, this configuration method will be run * even if one or more methods invoked previously failed or * was skipped. */ public boolean alwaysRun() default false; /** * If true, this @Configuration method will belong to groups specified in the * @Test annotation on the class (if any). */ public boolean inheritGroups() default true; /** * The description for this method. The string used will appear in the * HTML report and also on standard output if verbose >= 2. */ public String description() default ""; /** * The maximum number of milliseconds this method should take. * If it hasn't returned after this time, this method will fail and * it will cause test methods depending on it to be skipped. */ public long timeOut() default 0; } testng-testng-6.9.5/src/main/java/org/testng/annotations/AfterSuite.java0000755000175000017500000000467712551235562025674 0ustar eugeneeugenepackage org.testng.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(java.lang.annotation.ElementType.METHOD) public @interface AfterSuite { /** * Whether methods on this class/method are enabled. */ public boolean enabled() default true; /** * The list of groups this class/method belongs to. */ public String[] groups() default {}; /** * The list of groups this method depends on. Every method * member of one of these groups is guaranteed to have been * invoked before this method. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. */ public String[] dependsOnGroups() default {}; /** * The list of methods this method depends on. There is no guarantee * on the order on which the methods depended upon will be run, but you * are guaranteed that all these methods will be run before the test method * that contains this annotation is run. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. * * If some of these methods have been overloaded, all the overloaded * versions will be run. */ public String[] dependsOnMethods() default {}; /** * For before methods (beforeSuite, beforeTest, beforeTestClass and * beforeTestMethod, but not beforeGroups): * If set to true, this configuration method will be run * regardless of what groups it belongs to. *
* For after methods (afterSuite, afterClass, ...): * If set to true, this configuration method will be run * even if one or more methods invoked previously failed or * was skipped. */ public boolean alwaysRun() default false; /** * If true, this @Configuration method will belong to groups specified in the * @Test annotation on the class (if any). */ public boolean inheritGroups() default true; /** * The description for this method. The string used will appear in the * HTML report and also on standard output if verbose >= 2. */ public String description() default ""; /** * The maximum number of milliseconds this method should take. * If it hasn't returned after this time, this method will fail and * it will cause test methods depending on it to be skipped. */ public long timeOut() default 0; } testng-testng-6.9.5/src/main/java/org/testng/annotations/AfterMethod.java0000755000175000017500000000524312551235562026011 0ustar eugeneeugenepackage org.testng.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(java.lang.annotation.ElementType.METHOD) public @interface AfterMethod { /** * Whether methods on this class/method are enabled. */ public boolean enabled() default true; /** * The list of groups this class/method belongs to. */ public String[] groups() default {}; /** * The list of groups this method depends on. Every method * member of one of these groups is guaranteed to have been * invoked before this method. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. */ public String[] dependsOnGroups() default {}; /** * The list of methods this method depends on. There is no guarantee * on the order on which the methods depended upon will be run, but you * are guaranteed that all these methods will be run before the test method * that contains this annotation is run. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. * * If some of these methods have been overloaded, all the overloaded * versions will be run. */ public String[] dependsOnMethods() default {}; /** * For before methods (beforeSuite, beforeTest, beforeTestClass and * beforeTestMethod, but not beforeGroups): * If set to true, this configuration method will be run * regardless of what groups it belongs to. *
* For after methods (afterSuite, afterClass, ...): * If set to true, this configuration method will be run * even if one or more test methods invoked previously failed or * was skipped. */ public boolean alwaysRun() default false; /** * If true, this @Configuration method will belong to groups specified in the * @Test annotation on the class (if any). */ public boolean inheritGroups() default true; /** * The description for this method. The string used will appear in the * HTML report and also on standard output if verbose >= 2. */ public String description() default ""; /** * If true and the @Test method that was just run has an invocationCount > 1, this * AfterMethod will only be invoked once (after the last test invocation). */ public boolean lastTimeOnly() default false; /** * The maximum number of milliseconds this method should take. * If it hasn't returned after this time, this method will fail and * it will cause test methods depending on it to be skipped. */ public long timeOut() default 0; } testng-testng-6.9.5/src/main/java/org/testng/annotations/AfterGroups.java0000755000175000017500000000564512551235562026056 0ustar eugeneeugenepackage org.testng.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(java.lang.annotation.ElementType.METHOD) public @interface AfterGroups { /** * The list of groups that this configuration method will run after. If * specified it overrides the list of groups provided through * {@link #groups()} attribute. This method is guaranteed to run shortly * after the last test method that belongs to any of these groups is * invoked. */ public String[] value() default {}; /** * Whether methods on this class/method are enabled. */ public boolean enabled() default true; /** * The list of groups this class/method belongs to. The list also describes the groups * that this configuration method will be run after (if no {@link #value()} attribute is defined). */ public String[] groups() default {}; /** * The list of groups this method depends on. Every method * member of one of these groups is guaranteed to have been * invoked before this method. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. */ public String[] dependsOnGroups() default {}; /** * The list of methods this method depends on. There is no guarantee * on the order on which the methods depended upon will be run, but you * are guaranteed that all these methods will be run before the test method * that contains this annotation is run. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. * * If some of these methods have been overloaded, all the overloaded * versions will be run. */ public String[] dependsOnMethods() default {}; /** * For before methods (beforeSuite, beforeTest, beforeTestClass and * beforeTestMethod, but not beforeGroups): * If set to true, this configuration method will be run * regardless of what groups it belongs to. *
* For after methods (afterSuite, afterClass, ...): * If set to true, this configuration method will be run * even if one or more methods invoked previously failed or * was skipped. */ public boolean alwaysRun() default false; /** * If true, this @Configuration method will belong to groups specified in the * @Test annotation on the class (if any). */ public boolean inheritGroups() default true; /** * The description for this method. The string used will appear in the * HTML report and also on standard output if verbose >= 2. */ public String description() default ""; /** * The maximum number of milliseconds this method should take. * If it hasn't returned after this time, this method will fail and * it will cause test methods depending on it to be skipped. */ public long timeOut() default 0; } testng-testng-6.9.5/src/main/java/org/testng/annotations/AfterClass.java0000755000175000017500000000467712551235562025650 0ustar eugeneeugenepackage org.testng.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target(java.lang.annotation.ElementType.METHOD) public @interface AfterClass { /** * Whether methods on this class/method are enabled. */ public boolean enabled() default true; /** * The list of groups this class/method belongs to. */ public String[] groups() default {}; /** * The list of groups this method depends on. Every method * member of one of these groups is guaranteed to have been * invoked before this method. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. */ public String[] dependsOnGroups() default {}; /** * The list of methods this method depends on. There is no guarantee * on the order on which the methods depended upon will be run, but you * are guaranteed that all these methods will be run before the test method * that contains this annotation is run. Furthermore, if any of these * methods was not a SUCCESS, this test method will not be * run and will be flagged as a SKIP. * * If some of these methods have been overloaded, all the overloaded * versions will be run. */ public String[] dependsOnMethods() default {}; /** * For before methods (beforeSuite, beforeTest, beforeTestClass and * beforeTestMethod, but not beforeGroups): * If set to true, this configuration method will be run * regardless of what groups it belongs to. *
* For after methods (afterSuite, afterClass, ...): * If set to true, this configuration method will be run * even if one or more methods invoked previously failed or * was skipped. */ public boolean alwaysRun() default false; /** * If true, this @Configuration method will belong to groups specified in the * @Test annotation on the class (if any). */ public boolean inheritGroups() default true; /** * The description for this method. The string used will appear in the * HTML report and also on standard output if verbose >= 2. */ public String description() default ""; /** * The maximum number of milliseconds this method should take. * If it hasn't returned after this time, this method will fail and * it will cause test methods depending on it to be skipped. */ public long timeOut() default 0; } testng-testng-6.9.5/src/main/java/org/testng/TimeBombSkipException.java0000755000175000017500000002070612551235562025457 0ustar eugeneeugenepackage org.testng; import java.io.PrintStream; import java.io.PrintWriter; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * A {@link SkipException} extension that transforms a skipped method * into a failed method based on a time trigger. *

* By default the time format is yyyy/MM/dd (according to {@code SimpleDateFormat}). * You can customize this by using the specialized constructors. Suppported date * formats are according to the {@code SimpleDateFormat}. * * @author Alex Popescu * @since 5.6 */ public class TimeBombSkipException extends SkipException { private static final long serialVersionUID = -8599821478834048537L; private static final SimpleDateFormat SDF= new SimpleDateFormat("yyyy/MM/dd"); private Calendar m_expireDate; private DateFormat m_inFormat= SDF; private DateFormat m_outFormat= SDF; /** * Creates a {@code TimeBombedSkipException} using the expirationDate. * The format used for date comparison is yyyy/MM/dd * @param msg exception message * @param expirationDate time limit after which the SKIP becomes a FAILURE */ public TimeBombSkipException(String msg, Date expirationDate) { super(msg); initExpireDate(expirationDate); } /** * Creates a {@code TimeBombedSkipException} using the expirationDate. * The format parameter wiil be used for performing the time comparison. * @param msg exception message * @param expirationDate time limit after which the SKIP becomes a FAILURE * @param format format for the time comparison */ public TimeBombSkipException(String msg, Date expirationDate, String format) { super(msg); m_inFormat= new SimpleDateFormat(format); m_outFormat= new SimpleDateFormat(format); initExpireDate(expirationDate); } /** * Creates a {@code TimeBombedSkipException} using the date * in the format yyyy/MM/dd. * @param msg exception message * @param date time limit after which the SKIP becomes a FAILURE */ public TimeBombSkipException(String msg, String date) { super(msg); initExpireDate(date); } /** * Creates a {@code TimeBombedSkipException} using the date * in the specified format format. The same format is used * when performing the time comparison. * @param msg exception message * @param date time limit after which the SKIP becomes a FAILURE * @param format format of the passed in date and of the time comparison */ public TimeBombSkipException(String msg, String date, String format) { this(msg, date, format, format); } /** * Creates a {@code TimeBombedSkipException} using the date * in the specified format inFormat. The outFormat will be * used to perform the time comparison and display. * @param msg exception message * @param date time limit after which the SKIP becomes a FAILURE * @param inFormat format of the passed in date * @param outFormat format of the time comparison */ public TimeBombSkipException(String msg, String date, String inFormat, String outFormat) { super(msg); m_inFormat= new SimpleDateFormat(inFormat); m_outFormat= new SimpleDateFormat(outFormat); initExpireDate(date); } /** * Creates a {@code TimeBombedSkipException} using the expirationDate. * The format used for date comparison is yyyy/MM/dd * @param msg exception message * @param expirationDate time limit after which the SKIP becomes a FAILURE * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A null value is * permitted, and indicates that the cause is nonexistent or * unknown.) */ public TimeBombSkipException(String msg, Date expirationDate, Throwable cause) { super(msg, cause); initExpireDate(expirationDate); } /** * Creates a {@code TimeBombedSkipException} using the expirationDate. * The format parameter wiil be used for performing the time comparison. * @param msg exception message * @param expirationDate time limit after which the SKIP becomes a FAILURE * @param format format for the time comparison * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A null value is * permitted, and indicates that the cause is nonexistent or * unknown.) */ public TimeBombSkipException(String msg, Date expirationDate, String format, Throwable cause) { super(msg, cause); m_inFormat= new SimpleDateFormat(format); m_outFormat= new SimpleDateFormat(format); initExpireDate(expirationDate); } /** * Creates a {@code TimeBombedSkipException} using the date * in the format yyyy/MM/dd. * @param msg exception message * @param date time limit after which the SKIP becomes a FAILURE * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A null value is * permitted, and indicates that the cause is nonexistent or * unknown.) */ public TimeBombSkipException(String msg, String date, Throwable cause) { super(msg, cause); initExpireDate(date); } /** * Creates a {@code TimeBombedSkipException} using the date * in the specified format format. The same format is used * when performing the time comparison. * @param msg exception message * @param date time limit after which the SKIP becomes a FAILURE * @param format format of the passed in date and of the time comparison * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A null value is * permitted, and indicates that the cause is nonexistent or * unknown.) */ public TimeBombSkipException(String msg, String date, String format, Throwable cause) { this(msg, date, format, format, cause); } /** * Creates a {@code TimeBombedSkipException} using the date * in the specified format inFormat. The outFormat will be * used to perform the time comparison and display. * @param msg exception message * @param date time limit after which the SKIP becomes a FAILURE * @param inFormat format of the passed in date * @param outFormat format of the time comparison * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A null value is * permitted, and indicates that the cause is nonexistent or * unknown.) */ public TimeBombSkipException(String msg, String date, String inFormat, String outFormat, Throwable cause) { super(msg, cause); m_inFormat= new SimpleDateFormat(inFormat); m_outFormat= new SimpleDateFormat(outFormat); initExpireDate(date); } private void initExpireDate(Date expireDate) { m_expireDate= Calendar.getInstance(); m_expireDate.setTime(expireDate); } private void initExpireDate(String date) { try { // 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); } } @Override public boolean isSkip() { if (null == m_expireDate) { return false; } try { Calendar now= Calendar.getInstance(); Date nowDate= m_inFormat.parse(m_inFormat.format(now.getTime())); now.setTime(nowDate); return !now.after(m_expireDate); } catch(ParseException pex) { throw new TestNGException("Cannot compare dates."); } } @Override public String getMessage() { if(isSkip()) { return super.getMessage(); } else { return super.getMessage() + "; Test must have been enabled by: " + m_outFormat.format(m_expireDate.getTime()); } } @Override public void printStackTrace(PrintStream s) { reduceStackTrace(); super.printStackTrace(s); } @Override public void printStackTrace(PrintWriter s) { reduceStackTrace(); super.printStackTrace(s); } } testng-testng-6.9.5/src/main/java/org/testng/TestRunner.java0000644000175000017500000015536712551235562023375 0ustar eugeneeugenepackage org.testng; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Map; 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; import org.testng.internal.DynamicGraph; import org.testng.internal.DynamicGraph.Status; import org.testng.internal.IConfiguration; import org.testng.internal.IInvoker; import org.testng.internal.ITestResultNotifier; import org.testng.internal.InvokedMethod; import org.testng.internal.Invoker; import org.testng.internal.MethodGroupsHelper; import org.testng.internal.MethodHelper; import org.testng.internal.MethodInstance; import org.testng.internal.ResultMap; import org.testng.internal.RunInfo; import org.testng.internal.TestMethodWorker; 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.thread.ThreadUtil; import org.testng.internal.thread.graph.GraphThreadPoolExecutor; import org.testng.internal.thread.graph.IThreadWorkerFactory; import org.testng.internal.thread.graph.IWorker; import org.testng.junit.IJUnitTestRunner; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlPackage; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import com.google.inject.Injector; import com.google.inject.Module; /** * This class takes care of running one Test. * * @author Cedric Beust, Apr 26, 2004 */ public class TestRunner implements ITestContext, ITestResultNotifier, IThreadWorkerFactory { /* generated */ private static final long serialVersionUID = 4247820024988306670L; private ISuite m_suite; private XmlTest m_xmlTest; private String m_testName; transient private List m_testClassesFromXml= null; transient private List m_packageNamesFromXml= null; transient private IInvoker m_invoker= null; transient private IAnnotationFinder m_annotationFinder= null; /** ITestListeners support. */ transient private List m_testListeners = Lists.newArrayList(); transient private Set m_configurationListeners = Sets.newHashSet(); transient private IConfigurationListener m_confListener= new ConfigurationListener(); transient private boolean m_skipFailedInvocationCounts; transient private List m_invokedMethodListeners = Lists.newArrayList(); /** * All the test methods we found, associated with their respective classes. * Note that these test methods might belong to different classes. * We pick which ones to run at runtime. */ private ITestNGMethod[] m_allTestMethods = new ITestNGMethod[0]; // Information about this test run private Date m_startDate = null; private Date m_endDate = null; /** A map to keep track of Class <-> IClass. */ transient private Map, ITestClass> m_classMap = Maps.newLinkedHashMap(); /** Where the reports will be created. */ private String m_outputDirectory= Constants.getDefaultValueFor(Constants.PROP_OUTPUT_DIR); // The XML method selector (groups/methods included/excluded in XML) private XmlMethodSelector m_xmlMethodSelector = new XmlMethodSelector(); private static int m_verbose = 1; // // These next fields contain all the configuration methods found on this class. // At initialization time, they just contain all the various @Configuration methods // found in all the classes we are going to run. When comes the time to run them, // only a subset of them are run: those that are enabled and belong on the same class as // (or a parent of) the test class. // /** */ private ITestNGMethod[] m_beforeSuiteMethods = {}; private ITestNGMethod[] m_afterSuiteMethods = {}; private ITestNGMethod[] m_beforeXmlTestMethods = {}; private ITestNGMethod[] m_afterXmlTestMethods = {}; private List m_excludedMethods = Lists.newArrayList(); private ConfigurationGroupMethods m_groupMethods = null; // Meta groups private Map> m_metaGroups = Maps.newHashMap(); // All the tests that were run along with their result private IResultMap m_passedTests = new ResultMap(); private IResultMap m_failedTests = new ResultMap(); private IResultMap m_failedButWithinSuccessPercentageTests = new ResultMap(); private IResultMap m_skippedTests = new ResultMap(); private RunInfo m_runInfo= new RunInfo(); // The host where this test was run, or null if run locally private String m_host; // Defined dynamically depending on transient private List m_methodInterceptors; private transient ClassMethodMap m_classMethodMap; private transient TestNGClassFinder m_testClassFinder; private transient IConfiguration m_configuration; private IMethodInterceptor builtinInterceptor; protected TestRunner(IConfiguration configuration, ISuite suite, XmlTest test, String outputDirectory, IAnnotationFinder finder, boolean skipFailedInvocationCounts, List invokedMethodListeners) { init(configuration, suite, test, outputDirectory, finder, skipFailedInvocationCounts, invokedMethodListeners); } public TestRunner(IConfiguration configuration, ISuite suite, XmlTest test, boolean skipFailedInvocationCounts, List listeners) { init(configuration, suite, test, suite.getOutputDirectory(), suite.getAnnotationFinder(), skipFailedInvocationCounts, listeners); } private void init(IConfiguration configuration, ISuite suite, XmlTest test, String outputDirectory, IAnnotationFinder annotationFinder, boolean skipFailedInvocationCounts, List invokedMethodListeners) { m_configuration = configuration; m_xmlTest= test; m_suite = suite; m_testName = test.getName(); m_host = suite.getHost(); m_testClassesFromXml= test.getXmlClasses(); m_skipFailedInvocationCounts = skipFailedInvocationCounts; setVerbose(test.getVerbose()); boolean preserveOrder = "true".equalsIgnoreCase(test.getPreserveOrder()); m_methodInterceptors = new ArrayList(); builtinInterceptor = preserveOrder ? new PreserveOrderMethodInterceptor() : new InstanceOrderingMethodInterceptor(); m_packageNamesFromXml= test.getXmlPackages(); if(null != m_packageNamesFromXml) { for(XmlPackage xp: m_packageNamesFromXml) { m_testClassesFromXml.addAll(xp.getXmlClasses()); } } m_annotationFinder= annotationFinder; m_invokedMethodListeners = invokedMethodListeners; m_invoker = new Invoker(m_configuration, this, this, m_suite.getSuiteState(), m_skipFailedInvocationCounts, invokedMethodListeners); if (suite.getParallel() != null) { log(3, "Running the tests in '" + test.getName() + "' with parallel mode:" + suite.getParallel()); } setOutputDirectory(outputDirectory); // Finish our initialization init(); } public IInvoker getInvoker() { return m_invoker; } public ITestNGMethod[] getBeforeSuiteMethods() { return m_beforeSuiteMethods; } public ITestNGMethod[] getAfterSuiteMethods() { return m_afterSuiteMethods; } public ITestNGMethod[] getBeforeTestConfigurationMethods() { return m_beforeXmlTestMethods; } public ITestNGMethod[] getAfterTestConfigurationMethods() { return m_afterXmlTestMethods; } private void init() { initMetaGroups(m_xmlTest); initRunInfo(m_xmlTest); // Init methods and class map // JUnit behavior is different and doesn't need this initialization step if(!m_xmlTest.isJUnit()) { initMethods(); } initListeners(); addConfigurationListener(m_confListener); } private class ListenerHolder { private List> listenerClasses; private Class listenerFactoryClass; } /** * @return all the @Listeners annotations found in the current class and its * superclasses. */ private ListenerHolder findAllListeners(Class cls) { ListenerHolder result = new ListenerHolder(); result.listenerClasses = Lists.newArrayList(); do { IListeners l = m_annotationFinder.findAnnotation(cls, IListeners.class); if (l != null) { Class[] classes = l.getValue(); for (Class c : classes) { result.listenerClasses.add(c); if (ITestNGListenerFactory.class.isAssignableFrom(c)) { if (result.listenerFactoryClass == null) { result.listenerFactoryClass = (Class) c; } else { throw new TestNGException("Found more than one class implementing" + "ITestNGListenerFactory:" + c + " and " + result.listenerFactoryClass); } } } } cls = cls.getSuperclass(); } while (cls != Object.class); return result; } private void initListeners() { // // Find all the listener factories and collect all the listeners requested in a // @Listeners annotation. // Set> listenerClasses = Sets.newHashSet(); Class listenerFactoryClass = null; for (IClass cls : getTestClasses()) { Class realClass = cls.getRealClass(); ListenerHolder listenerHolder = findAllListeners(realClass); if (listenerFactoryClass == null) { listenerFactoryClass = listenerHolder.listenerFactoryClass; } listenerClasses.addAll(listenerHolder.listenerClasses); } // // Now we have all the listeners collected from @Listeners and at most one // listener factory collected from a class implementing ITestNGListenerFactory. // Instantiate all the requested listeners. // ITestNGListenerFactory listenerFactory = null; // If we found a test listener factory, instantiate it. try { if (m_testClassFinder != null) { IClass ic = m_testClassFinder.getIClass(listenerFactoryClass); if (ic != null) { listenerFactory = (ITestNGListenerFactory) ic.getInstances(false)[0]; } } if (listenerFactory == null) { listenerFactory = listenerFactoryClass != null ? listenerFactoryClass.newInstance() : null; } } catch(Exception ex) { throw new TestNGException("Couldn't instantiate the ITestNGListenerFactory: " + ex); } // Instantiate all the listeners for (Class c : listenerClasses) { Object listener = listenerFactory != null ? listenerFactory.createListener(c) : null; if (listener == null) { listener = ClassHelper.newInstance(c); } if (listener instanceof IMethodInterceptor) { m_methodInterceptors.add((IMethodInterceptor) listener); } if (listener instanceof ISuiteListener) { m_suite.addListener((ISuiteListener) listener); } if (listener instanceof IInvokedMethodListener) { m_suite.addListener((ITestNGListener) listener); } if (listener instanceof ITestListener) { // At this point, the field m_testListeners has already been used in the creation addTestListener((ITestListener) listener); } if (listener instanceof IConfigurationListener) { addConfigurationListener((IConfigurationListener) listener); } if (listener instanceof IReporter) { m_suite.addListener((ITestNGListener) listener); } if (listener instanceof IConfigurable) { m_configuration.setConfigurable((IConfigurable) listener); } if (listener instanceof IHookable) { m_configuration.setHookable((IHookable) listener); } if (listener instanceof IExecutionListener) { IExecutionListener iel = (IExecutionListener) listener; iel.onExecutionStart(); m_configuration.addExecutionListener(iel); } } } /** * Initialize meta groups */ private void initMetaGroups(XmlTest xmlTest) { Map> metaGroups = xmlTest.getMetaGroups(); for (Map.Entry> entry : metaGroups.entrySet()) { addMetaGroup(entry.getKey(), entry.getValue()); } } private void initRunInfo(final XmlTest xmlTest) { // Groups m_xmlMethodSelector.setIncludedGroups(createGroups(m_xmlTest.getIncludedGroups())); m_xmlMethodSelector.setExcludedGroups(createGroups(m_xmlTest.getExcludedGroups())); m_xmlMethodSelector.setExpression(m_xmlTest.getExpression()); // Methods m_xmlMethodSelector.setXmlClasses(m_xmlTest.getXmlClasses()); m_runInfo.addMethodSelector(m_xmlMethodSelector, 10); // Add user-specified method selectors (only class selectors, we can ignore // script selectors here) if (null != xmlTest.getMethodSelectors()) { for (org.testng.xml.XmlMethodSelector selector : xmlTest.getMethodSelectors()) { if (selector.getClassName() != null) { IMethodSelector s = ClassHelper.createSelector(selector); m_runInfo.addMethodSelector(s, selector.getPriority()); } } } } private void initMethods() { // // Calculate all the methods we need to invoke // List beforeClassMethods = Lists.newArrayList(); List testMethods = Lists.newArrayList(); List afterClassMethods = Lists.newArrayList(); List beforeSuiteMethods = Lists.newArrayList(); List afterSuiteMethods = Lists.newArrayList(); List beforeXmlTestMethods = Lists.newArrayList(); List afterXmlTestMethods = Lists.newArrayList(); ClassInfoMap classMap = new ClassInfoMap(m_testClassesFromXml); m_testClassFinder= new TestNGClassFinder(classMap, null, m_xmlTest, m_configuration, this); ITestMethodFinder testMethodFinder = new TestNGMethodFinder(m_runInfo, m_annotationFinder); m_runInfo.setTestMethods(testMethods); // // Initialize TestClasses // IClass[] classes = m_testClassFinder.findTestClasses(); for (IClass ic : classes) { // Create TestClass ITestClass tc = new TestClass(ic, testMethodFinder, m_annotationFinder, m_runInfo, m_xmlTest, classMap.getXmlClass(ic.getRealClass())); m_classMap.put(ic.getRealClass(), tc); } // // Calculate groups methods // Map> beforeGroupMethods = MethodGroupsHelper.findGroupsMethods(m_classMap.values(), true); Map> afterGroupMethods = MethodGroupsHelper.findGroupsMethods(m_classMap.values(), false); // // Walk through all the TestClasses, store their method // and initialize them with the correct ITestClass // for (ITestClass tc : m_classMap.values()) { fixMethodsWithClass(tc.getTestMethods(), tc, testMethods); fixMethodsWithClass(tc.getBeforeClassMethods(), tc, beforeClassMethods); fixMethodsWithClass(tc.getBeforeTestMethods(), tc, null); fixMethodsWithClass(tc.getAfterTestMethods(), tc, null); fixMethodsWithClass(tc.getAfterClassMethods(), tc, afterClassMethods); fixMethodsWithClass(tc.getBeforeSuiteMethods(), tc, beforeSuiteMethods); fixMethodsWithClass(tc.getAfterSuiteMethods(), tc, afterSuiteMethods); fixMethodsWithClass(tc.getBeforeTestConfigurationMethods(), tc, beforeXmlTestMethods); fixMethodsWithClass(tc.getAfterTestConfigurationMethods(), tc, afterXmlTestMethods); fixMethodsWithClass(tc.getBeforeGroupsMethods(), tc, MethodHelper.uniqueMethodList(beforeGroupMethods.values())); fixMethodsWithClass(tc.getAfterGroupsMethods(), tc, MethodHelper.uniqueMethodList(afterGroupMethods.values())); } // // Sort the methods // m_beforeSuiteMethods = MethodHelper.collectAndOrderMethods(beforeSuiteMethods, false /* forTests */, m_runInfo, m_annotationFinder, true /* unique */, m_excludedMethods); m_beforeXmlTestMethods = MethodHelper.collectAndOrderMethods(beforeXmlTestMethods, false /* forTests */, m_runInfo, m_annotationFinder, true /* unique (CQ added by me)*/, m_excludedMethods); m_allTestMethods = MethodHelper.collectAndOrderMethods(testMethods, true /* forTest? */, m_runInfo, m_annotationFinder, false /* unique */, m_excludedMethods); m_classMethodMap = new ClassMethodMap(testMethods, m_xmlMethodSelector); m_afterXmlTestMethods = MethodHelper.collectAndOrderMethods(afterXmlTestMethods, false /* forTests */, m_runInfo, m_annotationFinder, true /* unique (CQ added by me)*/, m_excludedMethods); m_afterSuiteMethods = MethodHelper.collectAndOrderMethods(afterSuiteMethods, false /* forTests */, m_runInfo, m_annotationFinder, true /* unique */, m_excludedMethods); // shared group methods m_groupMethods = new ConfigurationGroupMethods(m_allTestMethods, beforeGroupMethods, afterGroupMethods); } private void fixMethodsWithClass(ITestNGMethod[] methods, ITestClass testCls, List methodList) { for (ITestNGMethod itm : methods) { itm.setTestClass(testCls); if (methodList != null) { methodList.add(itm); } } } public Collection getTestClasses() { return m_classMap.values(); } public void setTestName(String name) { m_testName = name; } public void setOutputDirectory(String od) { m_outputDirectory= od; // FIX: empty directories were created // if (od == null) { m_outputDirectory = null; return; } //for maven2 // File file = new File(od); // file.mkdirs(); // m_outputDirectory= file.getAbsolutePath(); } private void addMetaGroup(String name, List groupNames) { m_metaGroups.put(name, groupNames); } /** * Calculate the transitive closure of all the MetaGroups * * @param groups * @param unfinishedGroups * @param result The transitive closure containing all the groups found */ private void collectGroups(String[] groups, List unfinishedGroups, Map result) { for (String gn : groups) { List subGroups = m_metaGroups.get(gn); if (null != subGroups) { for (String sg : subGroups) { if (null == result.get(sg)) { result.put(sg, sg); unfinishedGroups.add(sg); } } } } } private Map createGroups(List groups) { return createGroups(groups.toArray(new String[groups.size()])); } private Map createGroups(String[] groups) { Map result = Maps.newHashMap(); // Groups that were passed on the command line for (String group : groups) { result.put(group, group); } // See if we have any MetaGroups and // expand them if they match one of the groups // we have just been passed List unfinishedGroups = Lists.newArrayList(); if (m_metaGroups.size() > 0) { collectGroups(groups, unfinishedGroups, result); // Do we need to loop over unfinished groups? while (unfinishedGroups.size() > 0) { String[] uGroups = unfinishedGroups.toArray(new String[unfinishedGroups.size()]); unfinishedGroups = Lists.newArrayList(); collectGroups(uGroups, unfinishedGroups, result); } } // Utils.dumpMap(result); return result; } /** * The main entry method for TestRunner. * * This is where all the hard work is done: * - Invoke configuration methods * - Invoke test methods * - Catch exceptions * - Collect results * - Invoke listeners * - etc... */ public void run() { beforeRun(); try { XmlTest test= getTest(); if(test.isJUnit()) { privateRunJUnit(test); } else { privateRun(test); } } finally { afterRun(); } } /** Before run preparements. */ private void beforeRun() { // // Log the start date // m_startDate = new Date(System.currentTimeMillis()); // Log start logStart(); // Invoke listeners fireEvent(true /*start*/); // invoke @BeforeTest ITestNGMethod[] testConfigurationMethods= getBeforeTestConfigurationMethods(); if(null != testConfigurationMethods && testConfigurationMethods.length > 0) { m_invoker.invokeConfigurations(null, testConfigurationMethods, m_xmlTest.getSuite(), m_xmlTest.getAllParameters(), null, /* no parameter values */ null /* instance */); } } private void privateRunJUnit(XmlTest xmlTest) { final ClassInfoMap cim = new ClassInfoMap(m_testClassesFromXml, false); final Set> classes = cim.getClasses(); final List runMethods = Lists.newArrayList(); List> workers = Lists.newArrayList(); // FIXME: directly referencing JUnitTestRunner which uses JUnit classes // may result in an class resolution exception under different JVMs // The resolution process is not specified in the JVM spec with a specific implementation, // so it can be eager => failure workers.add(new IWorker() { /** * @see org.testng.internal.IMethodWorker#getMaxTimeOut() */ @Override public long getTimeOut() { return 0; } /** * @see java.lang.Runnable#run() */ @Override public void run() { for(Class tc: classes) { List includedMethods = cim.getXmlClass(tc).getIncludedMethods(); List methods = Lists.newArrayList(); for (XmlInclude inc: includedMethods) { methods.add(inc.getName()); } IJUnitTestRunner tr= ClassHelper.createTestRunner(TestRunner.this); tr.setInvokedMethodListeners(m_invokedMethodListeners); try { tr.run(tc, methods.toArray(new String[methods.size()])); } catch(Exception ex) { ex.printStackTrace(); } finally { runMethods.addAll(tr.getTestMethods()); } } } @Override public List getTasks() { throw new TestNGException("JUnit not supported"); } @Override public int getPriority() { if (m_allTestMethods.length == 1) { return m_allTestMethods[0].getPriority(); } else { return 0; } } @Override public int compareTo(IWorker other) { return getPriority() - other.getPriority(); } }); runWorkers(workers, "" /* JUnit does not support parallel */, null); m_allTestMethods= runMethods.toArray(new ITestNGMethod[runMethods.size()]); } /** * Main method that create a graph of methods and then pass it to the * graph executor to run them. */ private void privateRun(XmlTest xmlTest) { String parallelMode = xmlTest.getParallel(); boolean parallel = XmlSuite.PARALLEL_METHODS.equals(parallelMode) || "true".equalsIgnoreCase(parallelMode) || XmlSuite.PARALLEL_CLASSES.equals(parallelMode) || XmlSuite.PARALLEL_INSTANCES.equals(parallelMode); { // parallel int threadCount = parallel ? xmlTest.getThreadCount() : 1; // Make sure we create a graph based on the intercepted methods, otherwise an interceptor // removing methods would cause the graph never to terminate (because it would expect // termination from methods that never get invoked). DynamicGraph graph = createDynamicGraph(intercept(m_allTestMethods)); if (parallel) { if (graph.getNodeCount() > 0) { GraphThreadPoolExecutor executor = new GraphThreadPoolExecutor<>(graph, this, threadCount, threadCount, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); executor.run(); try { long timeOut = m_xmlTest.getTimeOut(XmlTest.DEFAULT_TIMEOUT_MS); Utils.log("TestRunner", 2, "Starting executor for test " + m_xmlTest.getName() + " with time out:" + timeOut + " milliseconds."); executor.awaitTermination(timeOut, TimeUnit.MILLISECONDS); executor.shutdownNow(); } catch (InterruptedException handled) { handled.printStackTrace(); Thread.currentThread().interrupt(); } } } else { boolean debug = false; List freeNodes = graph.getFreeNodes(); if (debug) { System.out.println("Free nodes:" + freeNodes); } if (graph.getNodeCount() > 0 && freeNodes.isEmpty()) { throw new TestNGException("No free nodes found in:" + graph); } while (! freeNodes.isEmpty()) { List> runnables = createWorkers(freeNodes); for (IWorker r : runnables) { r.run(); } graph.setStatus(freeNodes, Status.FINISHED); freeNodes = graph.getFreeNodes(); if (debug) { System.out.println("Free nodes:" + freeNodes); } } } } } /** * Apply the method interceptor (if applicable) to the list of methods. */ private ITestNGMethod[] intercept(ITestNGMethod[] methods) { List methodInstances = methodsToMethodInstances(Arrays.asList(methods)); // add built-in interceptor (PreserveOrderMethodInterceptor or InstanceOrderingMethodInterceptor at the end of the list m_methodInterceptors.add(builtinInterceptor); for (IMethodInterceptor m_methodInterceptor : m_methodInterceptors) { methodInstances = m_methodInterceptor.intercept(methodInstances, this); } List result = Lists.newArrayList(); for (IMethodInstance imi : methodInstances) { result.add(imi.getMethod()); } //Since an interceptor is involved, we would need to ensure that the ClassMethodMap object is in sync with the //output of the interceptor, else @AfterClass doesn't get executed at all when interceptors are involved. //so let's update the current classMethodMap object with the list of methods obtained from the interceptor. this.m_classMethodMap = new ClassMethodMap(result, null); return result.toArray(new ITestNGMethod[result.size()]); } /** * Create a list of workers to run the methods passed in parameter. * Each test method is run in its own worker except in the following cases: * - The method belongs to a class that has @Test(sequential=true) * - The parallel attribute is set to "classes" * In both these cases, all the methods belonging to that class will then * be put in the same worker in order to run in the same thread. */ @Override public List> createWorkers(List methods) { List> result; if (XmlSuite.PARALLEL_INSTANCES.equals(m_xmlTest.getParallel())) { result = createInstanceBasedParallelWorkers(methods); } else { result = createClassBasedParallelWorkers(methods); } return result; } /** * Create workers for parallel="classes" and similar cases. */ private List> createClassBasedParallelWorkers(List methods) { List> result = Lists.newArrayList(); // Methods that belong to classes with a sequential=true or parallel=classes // attribute must all be run in the same worker Set sequentialClasses = Sets.newHashSet(); for (ITestNGMethod m : methods) { Class cls = m.getRealClass(); org.testng.annotations.ITestAnnotation test = m_annotationFinder.findAnnotation(cls, org.testng.annotations.ITestAnnotation.class); // If either sequential=true or parallel=classes, mark this class sequential if (test != null && (test.getSequential() || test.getSingleThreaded()) || XmlSuite.PARALLEL_CLASSES.equals(m_xmlTest.getParallel())) { sequentialClasses.add(cls); } } List methodInstances = Lists.newArrayList(); for (ITestNGMethod tm : methods) { methodInstances.addAll(methodsToMultipleMethodInstances(tm)); } // // Finally, sort the parallel methods by classes // for (IMethodInterceptor m_methodInterceptor : m_methodInterceptors) { methodInstances = m_methodInterceptor.intercept(methodInstances, this); } Map params = m_xmlTest.getAllParameters(); Set> processedClasses = Sets.newHashSet(); for (IMethodInstance im : methodInstances) { Class c = im.getMethod().getTestClass().getRealClass(); if (sequentialClasses.contains(c)) { if (!processedClasses.contains(c)) { processedClasses.add(c); if (System.getProperty("experimental") != null) { List> instances = createInstances(methodInstances); for (List inst : instances) { TestMethodWorker worker = createTestMethodWorker(inst, params, c); result.add(worker); } } else { // Sequential class: all methods in one worker TestMethodWorker worker = createTestMethodWorker(methodInstances, params, c); result.add(worker); } } } else { // Parallel class: each method in its own worker TestMethodWorker worker = createTestMethodWorker(Arrays.asList(im), params, c); result.add(worker); } } // Sort by priorities Collections.sort(result); return result; } /** * Create workers for parallel="instances". */ private List> createInstanceBasedParallelWorkers(List methods) { List> result = Lists.newArrayList(); ListMultiMap lmm = Maps.newListMultiMap(); for (ITestNGMethod m : methods) { lmm.put(m.getInstance(), m); } for (Map.Entry> es : lmm.entrySet()) { List methodInstances = Lists.newArrayList(); for (ITestNGMethod m : es.getValue()) { methodInstances.add(new MethodInstance(m)); } TestMethodWorker tmw = new TestMethodWorker(m_invoker, methodInstances.toArray(new IMethodInstance[methodInstances.size()]), m_xmlTest.getSuite(), m_xmlTest.getAllParameters(), m_groupMethods, m_classMethodMap, this); result.add(tmw); } return result; } private List> createInstances(List methodInstances) { Map> map = Maps.newHashMap(); // MapList map = new MapList(); for (IMethodInstance imi : methodInstances) { for (Object o : imi.getInstances()) { System.out.println(o); List l = map.get(o); if (l == null) { l = Lists.newArrayList(); map.put(o, l); } l.add(imi); } // for (Object instance : imi.getInstances()) { // map.put(imi, instance); // } } // return map.getKeys(); // System.out.println(map); return new ArrayList<>(map.values()); } private TestMethodWorker createTestMethodWorker( List methodInstances, Map params, Class c) { return new TestMethodWorker(m_invoker, findClasses(methodInstances, c), m_xmlTest.getSuite(), params, m_groupMethods, m_classMethodMap, this); } private IMethodInstance[] findClasses(List methodInstances, Class c) { List result = Lists.newArrayList(); for (IMethodInstance mi : methodInstances) { if (mi.getMethod().getTestClass().getRealClass() == c) { result.add(mi); } } return result.toArray(new IMethodInstance[result.size()]); } /** * @@@ remove this */ private List methodsToMultipleMethodInstances(ITestNGMethod... sl) { List vResult = Lists.newArrayList(); for (ITestNGMethod m : sl) { vResult.add(new MethodInstance(m)); } return vResult; } private List methodsToMethodInstances(List sl) { List result = new ArrayList<>(); for (ITestNGMethod iTestNGMethod : sl) { result.add(new MethodInstance(iTestNGMethod)); } return result; } // // Invoke the workers // private void runWorkers(List> workers, String parallelMode, ListMultiMap sequentialWorkers) { if (XmlSuite.PARALLEL_METHODS.equals(parallelMode) || "true".equalsIgnoreCase(parallelMode) || XmlSuite.PARALLEL_CLASSES.equals(parallelMode)) { // // Parallel run // // Default timeout for individual methods: same as the test global-time-out, but // overridden if a method defines its own. long maxTimeOut = m_xmlTest.getTimeOut(XmlTest.DEFAULT_TIMEOUT_MS); for (IWorker tmw : workers) { long mt = tmw.getTimeOut(); if (mt > maxTimeOut) { maxTimeOut= mt; } } ThreadUtil.execute(workers, m_xmlTest.getThreadCount(), maxTimeOut, false); // ThreadUtil.execute(sequentialWorkers); } else { // // Sequential run // for (IWorker tmw : workers) { tmw.run(); } } } private void afterRun() { // invoke @AfterTest ITestNGMethod[] testConfigurationMethods= getAfterTestConfigurationMethods(); if(null != testConfigurationMethods && testConfigurationMethods.length > 0) { m_invoker.invokeConfigurations(null, testConfigurationMethods, m_xmlTest.getSuite(), m_xmlTest.getAllParameters(), null, /* no parameter values */ null /* instance */); } // // Log the end date // m_endDate = new Date(System.currentTimeMillis()); if (getVerbose() >= 3) { dumpInvokedMethods(); } // Invoke listeners fireEvent(false /*stop*/); // Statistics // logResults(); } private DynamicGraph createDynamicGraph(ITestNGMethod[] methods) { DynamicGraph result = new DynamicGraph<>(); result.setComparator(new Comparator() { @Override public int compare(ITestNGMethod o1, ITestNGMethod o2) { return o1.getPriority() - o2.getPriority(); } }); DependencyMap dependencyMap = new DependencyMap(methods); // Keep track of whether we have group dependencies. If we do, preserve-order needs // to be ignored since group dependencies create inter-class dependencies which can // end up creating cycles when combined with preserve-order. boolean hasDependencies = false; for (ITestNGMethod m : methods) { result.addNode(m); // Dependent methods { String[] dependentMethods = m.getMethodsDependedUpon(); if (dependentMethods != null) { for (String d : dependentMethods) { ITestNGMethod dm = dependencyMap.getMethodDependingOn(d, m); if (m != dm){ result.addEdge(m, dm); } } } } // Dependent groups { String[] dependentGroups = m.getGroupsDependedUpon(); for (String d : dependentGroups) { hasDependencies = true; List dg = dependencyMap.getMethodsThatBelongTo(d, m); if (dg == null) { throw new TestNGException("Method \"" + m + "\" depends on nonexistent group \"" + d + "\""); } for (ITestNGMethod ddm : dg) { result.addEdge(m, ddm); } } } } // Preserve order // Don't preserve the ordering if we're running in parallel, otherwise the suite will // create multiple threads but these threads will be created one after the other, // giving the impression of parallelism (multiple thread id's) while still running // sequentially. if (! hasDependencies && ! XmlSuite.isParallel(getCurrentXmlTest().getParallel()) && "true".equalsIgnoreCase(getCurrentXmlTest().getPreserveOrder())) { // If preserve-order was specified and the class order is A, B // create a new set of dependencies where each method of B depends // on all the methods of A ListMultiMap classDependencies = createClassDependencies(methods, getCurrentXmlTest()); for (Map.Entry> es : classDependencies.entrySet()) { for (ITestNGMethod dm : es.getValue()) { result.addEdge(dm, es.getKey()); } } } // Group by instances if (getCurrentXmlTest().getGroupByInstances()) { ListMultiMap instanceDependencies = createInstanceDependencies(methods, getCurrentXmlTest()); for (Map.Entry> es : instanceDependencies.entrySet()) { for (ITestNGMethod dm : es.getValue()) { result.addEdge(dm, es.getKey()); } } } return result; } private ListMultiMap createInstanceDependencies( ITestNGMethod[] methods, XmlTest currentXmlTest) { ListMultiMap instanceMap = Maps.newListMultiMap(); for (ITestNGMethod m : methods) { instanceMap.put(m.getInstance(), m); } ListMultiMap result = Maps.newListMultiMap(); Object previousInstance = null; for (Map.Entry> es : instanceMap.entrySet()) { if (previousInstance == null) { previousInstance = es.getKey(); } else { List previousMethods = instanceMap.get(previousInstance); Object currentInstance = es.getKey(); List currentMethods = instanceMap.get(currentInstance); // Make all the methods from the current instance depend on the methods of // the previous instance for (ITestNGMethod cm : currentMethods) { for (ITestNGMethod pm : previousMethods) { result.put(cm, pm); } } previousInstance = currentInstance; } } return result; } private ListMultiMap createClassDependencies( ITestNGMethod[] methods, XmlTest test) { Map> classes = Maps.newHashMap(); // Note: use a List here to preserve the ordering but make sure // we don't add the same class twice List sortedClasses = Lists.newArrayList(); for (XmlClass c : test.getXmlClasses()) { classes.put(c.getName(), new ArrayList()); if (! sortedClasses.contains(c)) sortedClasses.add(c); } // Sort the classes based on their order of appearance in the XML Collections.sort(sortedClasses, new Comparator() { @Override public int compare(XmlClass arg0, XmlClass arg1) { return arg0.getIndex() - arg1.getIndex(); } }); Map indexedClasses1 = Maps.newHashMap(); Map indexedClasses2 = Maps.newHashMap(); int i = 0; for (XmlClass c : sortedClasses) { indexedClasses1.put(c.getName(), i); indexedClasses2.put(i, c.getName()); i++; } ListMultiMap methodsFromClass = Maps.newListMultiMap(); for (ITestNGMethod m : methods) { methodsFromClass.put(m.getTestClass().getName(), m); } ListMultiMap result = Maps.newListMultiMap(); for (ITestNGMethod m : methods) { String name = m.getTestClass().getName(); Integer index = indexedClasses1.get(name); // The index could be null if the classes listed in the XML are different // from the methods being run (e.g. the .xml only contains a factory that // instantiates methods from a different class). In this case, we cannot // perform any ordering. if (index != null && index > 0) { // Make this method depend on all the methods of the class in the previous // index String classDependedUpon = indexedClasses2.get(index - 1); List methodsDependedUpon = methodsFromClass.get(classDependedUpon); if (methodsDependedUpon != null) { for (ITestNGMethod mdu : methodsDependedUpon) { result.put(mdu, m); } } } } return result; } /** * Logs the beginning of the {@link #beforeRun()} . */ private void logStart() { log(3, "Running test " + m_testName + " on " + m_classMap.size() + " " + " classes, " + " included groups:[" + mapToString(m_xmlMethodSelector.getIncludedGroups()) + "] excluded groups:[" + mapToString(m_xmlMethodSelector.getExcludedGroups()) + "]"); if (getVerbose() >= 3) { for (ITestClass tc : m_classMap.values()) { ((TestClass) tc).dump(); } } } /** * Trigger the start/finish event. * * @param isStart true if the event is for start, false if the * event is for finish */ private void fireEvent(boolean isStart) { for (ITestListener itl : m_testListeners) { if (isStart) { itl.onStart(this); } else { itl.onFinish(this); } } } ///// // ITestContext // @Override public String getName() { return m_testName; } /** * @return Returns the startDate. */ @Override public Date getStartDate() { return m_startDate; } /** * @return Returns the endDate. */ @Override public Date getEndDate() { return m_endDate; } @Override public IResultMap getPassedTests() { return m_passedTests; } @Override public IResultMap getSkippedTests() { return m_skippedTests; } @Override public IResultMap getFailedTests() { return m_failedTests; } @Override public IResultMap getFailedButWithinSuccessPercentageTests() { return m_failedButWithinSuccessPercentageTests; } @Override public String[] getIncludedGroups() { Map ig= m_xmlMethodSelector.getIncludedGroups(); String[] result= ig.values().toArray((new String[ig.size()])); return result; } @Override public String[] getExcludedGroups() { Map eg= m_xmlMethodSelector.getExcludedGroups(); String[] result= eg.values().toArray((new String[eg.size()])); return result; } @Override public String getOutputDirectory() { return m_outputDirectory; } /** * @return Returns the suite. */ @Override public ISuite getSuite() { return m_suite; } @Override public ITestNGMethod[] getAllTestMethods() { return m_allTestMethods; } @Override public String getHost() { return m_host; } @Override public Collection getExcludedMethods() { Map vResult = Maps.newHashMap(); for (ITestNGMethod m : m_excludedMethods) { vResult.put(m, m); } return vResult.keySet(); } /** * @see org.testng.ITestContext#getFailedConfigurations() */ @Override public IResultMap getFailedConfigurations() { return m_failedConfigurations; } /** * @see org.testng.ITestContext#getPassedConfigurations() */ @Override public IResultMap getPassedConfigurations() { return m_passedConfigurations; } /** * @see org.testng.ITestContext#getSkippedConfigurations() */ @Override public IResultMap getSkippedConfigurations() { return m_skippedConfigurations; } // // ITestContext ///// ///// // ITestResultNotifier // @Override public void addPassedTest(ITestNGMethod tm, ITestResult tr) { m_passedTests.addResult(tr, tm); } @Override public Set getPassedTests(ITestNGMethod tm) { return m_passedTests.getResults(tm); } @Override public Set getFailedTests(ITestNGMethod tm) { return m_failedTests.getResults(tm); } @Override public Set getSkippedTests(ITestNGMethod tm) { return m_skippedTests.getResults(tm); } @Override public void addSkippedTest(ITestNGMethod tm, ITestResult tr) { m_skippedTests.addResult(tr, tm); } @Override public void addInvokedMethod(InvokedMethod im) { synchronized(m_invokedMethods) { m_invokedMethods.add(im); } } @Override public void addFailedTest(ITestNGMethod testMethod, ITestResult result) { logFailedTest(testMethod, result, false /* withinSuccessPercentage */); } @Override public void addFailedButWithinSuccessPercentageTest(ITestNGMethod testMethod, ITestResult result) { logFailedTest(testMethod, result, true /* withinSuccessPercentage */); } @Override public XmlTest getTest() { return m_xmlTest; } @Override public List getTestListeners() { return m_testListeners; } @Override public List getConfigurationListeners() { return Lists.newArrayList(m_configurationListeners); } // // ITestResultNotifier ///// private void logFailedTest(ITestNGMethod method, ITestResult tr, boolean withinSuccessPercentage) { /* * We should not remove a passed method from m_passedTests so that we can * account for the passed instances of this test method. */ //m_passedTests.removeResult(method); if (withinSuccessPercentage) { m_failedButWithinSuccessPercentageTests.addResult(tr, method); } else { m_failedTests.addResult(tr, method); } } private String mapToString(Map m) { StringBuffer result= new StringBuffer(); for (Object o : m.values()) { result.append(o.toString()).append(" "); } return result.toString(); } private void log(int level, String s) { Utils.log("TestRunner", level, s); } public static int getVerbose() { return m_verbose; } public void setVerbose(int n) { m_verbose = n; } private void log(String s) { Utils.log("TestRunner", 2, s); } ///// // Listeners // public void addListener(Object listener) { if(listener instanceof ITestListener) { addTestListener((ITestListener) listener); } if(listener instanceof IConfigurationListener) { addConfigurationListener((IConfigurationListener) listener); } } public void addTestListener(ITestListener il) { m_testListeners.add(il); } void addConfigurationListener(IConfigurationListener icl) { m_configurationListeners.add(icl); } // // Listeners ///// private final List m_invokedMethods = Lists.newArrayList(); private void dumpInvokedMethods() { System.out.println("===== Invoked methods"); for (IInvokedMethod im : m_invokedMethods) { if (im.isTestMethod()) { System.out.print(" "); } else if (im.isConfigurationMethod()) { System.out.print(" "); } else { continue; } System.out.println("" + im); } System.out.println("====="); } public List getInvokedMethods() { List result= Lists.newArrayList(); synchronized(m_invokedMethods) { for (IInvokedMethod im : m_invokedMethods) { ITestNGMethod tm= im.getTestMethod(); tm.setDate(im.getDate()); result.add(tm); } } return result; } private IResultMap m_passedConfigurations= new ResultMap(); private IResultMap m_skippedConfigurations= new ResultMap(); private IResultMap m_failedConfigurations= new ResultMap(); private class ConfigurationListener implements IConfigurationListener2 { @Override public void beforeConfiguration(ITestResult tr) { } @Override public void onConfigurationFailure(ITestResult itr) { m_failedConfigurations.addResult(itr, itr.getMethod()); } @Override public void onConfigurationSkip(ITestResult itr) { m_skippedConfigurations.addResult(itr, itr.getMethod()); } @Override public void onConfigurationSuccess(ITestResult itr) { m_passedConfigurations.addResult(itr, itr.getMethod()); } } @Deprecated public void setMethodInterceptor(IMethodInterceptor methodInterceptor){ m_methodInterceptors.add(methodInterceptor); } public void addMethodInterceptor(IMethodInterceptor methodInterceptor){ m_methodInterceptors.add(methodInterceptor); } @Override public XmlTest getCurrentXmlTest() { return m_xmlTest; } private IAttributes m_attributes = new Attributes(); @Override public Object getAttribute(String name) { return m_attributes.getAttribute(name); } @Override public void setAttribute(String name, Object value) { m_attributes.setAttribute(name, value); } @Override public Set getAttributeNames() { return m_attributes.getAttributeNames(); } @Override public Object removeAttribute(String name) { return m_attributes.removeAttribute(name); } private ListMultiMap, Module> m_guiceModules = Maps.newListMultiMap(); @Override public List getGuiceModules(Class cls) { List result = m_guiceModules.get(cls); return result; } private void addGuiceModule(Class cls, Module module) { m_guiceModules.put(cls, module); } private Map, Injector> m_injectors = Maps.newHashMap(); @Override public Injector getInjector(List moduleInstances) { return m_injectors .get(moduleInstances); } @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 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 result = Lists.newArrayList(); for (Class moduleClass : guice.modules()) { List 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 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 moduleInstances, Injector injector) { m_injectors.put(moduleInstances, injector); } } // TestRunner testng-testng-6.9.5/src/main/java/org/testng/TestNGUtils.java0000755000175000017500000000064212551235562023435 0ustar eugeneeugenepackage org.testng; import org.testng.internal.ClonedMethod; import java.lang.reflect.Method; public class TestNGUtils { /** * Create an ITestNGMethod for @code{method} based on @code{existingMethod}, which needs * to belong to the same class. */ public static ITestNGMethod createITestNGMethod(ITestNGMethod existingMethod, Method method) { return new ClonedMethod(existingMethod, method); } } testng-testng-6.9.5/src/main/java/org/testng/TestNGException.java0000755000175000017500000000104412551235562024270 0ustar eugeneeugenepackage org.testng; /** * The base class for all exceptions thrown by TestNG. * * @author Cedric Beust */ public class TestNGException extends RuntimeException { /* generated */ private static final long serialVersionUID = -422675971506425913L; public TestNGException(Throwable t) { super(t); } /** * @param string */ public TestNGException(String string) { super("\n" + string); } public TestNGException(String string, Throwable t) { super("\n" + string, t); } } testng-testng-6.9.5/src/main/java/org/testng/TestNGAntTask.java0000755000175000017500000010354212551235562023705 0ustar eugeneeugenepackage org.testng; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.StringTokenizer; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Project; import org.apache.tools.ant.Target; import org.apache.tools.ant.Task; import org.apache.tools.ant.taskdefs.Execute; import org.apache.tools.ant.taskdefs.ExecuteWatchdog; import org.apache.tools.ant.taskdefs.LogOutputStream; import org.apache.tools.ant.taskdefs.PumpStreamHandler; import org.apache.tools.ant.types.Commandline; import org.apache.tools.ant.types.CommandlineJava; import org.apache.tools.ant.types.Environment; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.PropertySet; import org.apache.tools.ant.types.Reference; import org.apache.tools.ant.types.ResourceCollection; import org.apache.tools.ant.types.resources.FileResource; import org.apache.tools.ant.types.selectors.FilenameSelector; import org.testng.collections.Lists; import org.testng.internal.Utils; import org.testng.reporters.VerboseReporter; import static java.lang.Boolean.TRUE; import static org.testng.internal.Utils.isStringNotBlank; /** * TestNG settings: *

    *
  • classfileset (inner)
  • *
  • classfilesetref (attribute)
  • *
  • xmlfileset (inner)
  • *
  • xmlfilesetref (attribute)
  • *
  • enableAssert (attribute)
  • *
  • excludedGroups (attribute)
  • *
  • groups (attribute)
  • *
  • junit (attribute)
  • *
  • listener (attribute)
  • *
  • outputdir (attribute)
  • *
  • parallel (attribute)
  • *
  • reporter (attribute)
  • *
  • sourcedir (attribute)
  • *
  • sourcedirref (attribute)
  • *
  • suitename (attribute)
  • *
  • suiterunnerclass (attribute)
  • *
  • target (attribute)
  • *
  • testjar (attribute)
  • *
  • testname (attribute)
  • *
  • threadcount (attribute)
  • *
  • dataproviderthreadcount (attribute)
  • *
  • verbose (attribute)
  • *
  • testrunfactory (attribute)
  • *
  • configFailurepolicy (attribute)
  • *
  • randomizeSuites (attribute)
  • *
  • methodselectors (attribute)
  • *
* * Ant settings: *
    *
  • classpath (inner)
  • *
  • classpathref (attribute)
  • *
  • jvm (attribute)
  • *
  • workingDir (attribute)
  • *
  • env (inner)
  • *
  • sysproperty (inner)
  • *
  • propertyset (inner)
  • *
  • jvmarg (inner)
  • *
  • timeout (attribute)
  • *
  • haltonfailure (attribute)
  • *
  • onHaltTarget (attribute)
  • *
  • failureProperty (attribute)
  • *
  • haltonFSP (attribute)
  • *
  • FSPproperty (attribute)
  • *
  • haltonskipped (attribute)
  • *
  • skippedProperty (attribute)
  • *
  • testRunnerFactory (attribute)
  • *
* * Debug information: *
    *
  • dumpCommand (boolean)
  • *
  • dumpEnv (boolean)
  • *
  • dumpSys (boolean)
  • *
* * @author Alexandru Popescu * @author Cedric Beust * @author Lukas Jungmann */ public class TestNGAntTask extends Task { protected CommandlineJava m_javaCommand; protected List m_xmlFilesets= Lists.newArrayList(); protected List m_classFilesets= Lists.newArrayList(); protected File m_outputDir; protected File m_testjar; protected File m_workingDir; private Integer m_timeout; private List m_listeners= Lists.newArrayList(); private List m_methodselectors= Lists.newArrayList(); private String m_objectFactory; protected String m_testRunnerFactory; private boolean m_delegateCommandSystemProperties = false; protected Environment m_environment= new Environment(); /** The suite runner name (defaults to TestNG.class.getName(). */ protected String m_mainClass = TestNG.class.getName(); /** True if the temporary file created by the Ant Task for command line parameters * to TestNG should be preserved after execution. */ protected boolean m_dump; private boolean m_dumpEnv; private boolean m_dumpSys; protected boolean m_assertEnabled= true; protected boolean m_haltOnFailure; protected String m_onHaltTarget; protected String m_failurePropertyName; protected boolean m_haltOnSkipped; protected String m_skippedPropertyName; protected boolean m_haltOnFSP; protected String m_fspPropertyName; protected String m_includedGroups; protected String m_excludedGroups; protected String m_parallelMode; protected String m_threadCount; protected String m_dataproviderthreadCount; protected String m_configFailurePolicy; protected Boolean m_randomizeSuites; public String m_useDefaultListeners; private String m_suiteName="Ant suite"; private String m_testName="Ant test"; private Boolean m_skipFailedInvocationCounts; private String m_methods; private Mode mode = Mode.testng; public enum Mode { //lower-case to better look in build scripts testng, junit, mixed; } /** * The list of report listeners added via <reporter> sub-element of the Ant task */ private List reporterConfigs = Lists.newArrayList(); private String m_testNames = ""; public void setParallel(String parallel) { m_parallelMode= parallel; } public void setThreadCount(String threadCount) { m_threadCount= threadCount; } public void setDataProviderThreadCount(String dataproviderthreadCount) { m_dataproviderthreadCount = dataproviderthreadCount; } public void setUseDefaultListeners(String f) { m_useDefaultListeners= f; } // Ant task settings public void setHaltonfailure(boolean value) { m_haltOnFailure= value; } public void setOnHaltTarget(String targetName) { m_onHaltTarget= targetName; } public void setFailureProperty(String propertyName) { m_failurePropertyName= propertyName; } public void setHaltonskipped(boolean value) { m_haltOnSkipped= value; } public void setSkippedProperty(String propertyName) { m_skippedPropertyName= propertyName; } public void setHaltonFSP(boolean value) { m_haltOnFSP= value; } public void setFSPProperty(String propertyName) { m_fspPropertyName= propertyName; } public void setDelegateCommandSystemProperties(boolean value){ m_delegateCommandSystemProperties = value; } /** * Sets the flag to log the command line. When verbose is set to true * the command line parameters are stored in a temporary file stored * in the user's default temporary file directory. The file created is * prefixed with "testng". */ public void setDumpCommand(boolean verbose) { m_dump = verbose; } /** * Sets the flag to write on System.out the Ant * Environment properties. * * @param verbose true for printing */ public void setDumpEnv(boolean verbose) { m_dumpEnv= verbose; } /** * Sets te flag to write on System.out the system properties. * @param verbose true for dumping the info */ public void setDumpSys(boolean verbose) { m_dumpSys= verbose; } public void setEnableAssert(boolean flag) { m_assertEnabled= flag; } /** * The directory to invoke the VM in. * @param workingDir the directory to invoke the JVM from. */ public void setWorkingDir(File workingDir) { m_workingDir= workingDir; } /** * Sets a particular JVM to be used. Default is 'java' and is solved * by Runtime.exec(). * * @param jvm the new jvm */ public void setJvm(String jvm) { getJavaCommand().setVm(jvm); } /** * Set the timeout value (in milliseconds). * *

If the tests are running for more than this value, the tests * will be canceled. * *

* @param value the maximum time (in milliseconds) allowed before declaring the test as 'timed-out' */ public void setTimeout(Integer value) { m_timeout= value; } public Commandline.Argument createJvmarg() { return getJavaCommand().createVmArgument(); } public void addSysproperty(Environment.Variable sysp) { getJavaCommand().addSysproperty(sysp); } /** * Adds an environment variable; used when forking. */ public void addEnv(Environment.Variable var) { m_environment.addVariable(var); } /** * Adds path to classpath used for tests. * * @return reference to the classpath in the embedded java command line */ public Path createClasspath() { return getJavaCommand().createClasspath(getProject()).createPath(); } /** * Adds a path to the bootclasspath. * @return reference to the bootclasspath in the embedded java command line */ public Path createBootclasspath() { return getJavaCommand().createBootclasspath(getProject()).createPath(); } /** * Set the classpath to be used when running the Java class * * @param s an Ant Path object containing the classpath. */ public void setClasspath(Path s) { createClasspath().append(s); } /** * Classpath to use, by reference. * * @param r a reference to an existing classpath */ public void setClasspathRef(Reference r) { createClasspath().setRefid(r); } public void addXmlfileset(FileSet fs) { m_xmlFilesets.add(fs); } public void setXmlfilesetRef(Reference ref) { m_xmlFilesets.add(createResourceCollection(ref)); } public void addClassfileset(FileSet fs) { m_classFilesets.add(appendClassSelector(fs)); } public void setClassfilesetRef(Reference ref) { m_classFilesets.add(createResourceCollection(ref)); } public void setTestNames(String testNames) { m_testNames = testNames; } /** * Sets the suite runner class to invoke * @param s the name of the suite runner class */ public void setSuiteRunnerClass(String s) { m_mainClass= s; } /** * Sets the suite name * @param s the name of the suite */ public void setSuiteName(String s) { m_suiteName= s; } /** * Sets the test name * @param s the name of the test */ public void setTestName(String s) { m_testName= s; } // TestNG settings public void setJUnit(boolean value) { mode = value ? Mode.junit : Mode.testng; } // TestNG settings public void setMode(Mode mode) { this.mode = mode; } /** * Sets the test output directory * @param dir the name of directory */ public void setOutputDir(File dir) { m_outputDir= dir; } /** * Sets the test jar * @param s the name of test jar */ public void setTestJar(File s) { m_testjar= s; } public void setGroups(String groups) { m_includedGroups= groups; } public void setExcludedGroups(String groups) { m_excludedGroups= groups; } private Integer m_verbose= null; private Integer m_suiteThreadPoolSize; private String m_xmlPathInJar; public void setVerbose(Integer verbose) { m_verbose= verbose; } public void setReporter(String listener) { m_listeners.add(listener); } public void setObjectFactory(String className) { m_objectFactory = className; } public void setTestRunnerFactory(String testRunnerFactory) { m_testRunnerFactory = testRunnerFactory; } public void setSuiteThreadPoolSize(Integer n) { m_suiteThreadPoolSize = n; } /** * @deprecated Use "listeners" */ @Deprecated public void setListener(String listener) { m_listeners.add(listener); } public void setListeners(String listeners) { StringTokenizer st= new StringTokenizer(listeners, " ,"); while(st.hasMoreTokens()) { m_listeners.add(st.nextToken()); } } public void setMethodSelectors(String methodSelectors) { StringTokenizer st= new StringTokenizer(methodSelectors, " ,"); while(st.hasMoreTokens()) { m_methodselectors.add(st.nextToken()); } } public void setConfigFailurePolicy(String failurePolicy) { m_configFailurePolicy = failurePolicy; } public void setRandomizeSuites(Boolean randomizeSuites) { m_randomizeSuites = randomizeSuites; } public void setMethods(String methods) { m_methods = methods; } /** * Launches TestNG in a new JVM. * * {@inheritDoc} */ @Override public void execute() throws BuildException { validateOptions(); CommandlineJava cmd = getJavaCommand(); cmd.setClassname(m_mainClass); if(m_assertEnabled) { cmd.createVmArgument().setValue("-ea"); } if (m_delegateCommandSystemProperties) { delegateCommandSystemProperties(); } List argv = createArguments(); String fileName= ""; FileWriter fw= null; BufferedWriter bw= null; try { File f= File.createTempFile("testng", ""); fileName= f.getAbsolutePath(); // If the user asked to see the command, preserve the file if(!m_dump) { f.deleteOnExit(); } fw= new FileWriter(f); bw= new BufferedWriter(fw); for(String arg : argv) { bw.write(arg); bw.newLine(); } bw.flush(); } catch(IOException e) { e.printStackTrace(); } finally { try { if(bw != null) { bw.close(); } if(fw != null) { fw.close(); } } catch(IOException e) { e.printStackTrace(); } } printDebugInfo(fileName); createClasspath().setLocation(findJar()); cmd.createArgument().setValue("@" + fileName); ExecuteWatchdog watchdog= createWatchdog(); boolean wasKilled= false; int exitValue= executeAsForked(cmd, watchdog); if(null != watchdog) { wasKilled= watchdog.killedProcess(); } actOnResult(exitValue, wasKilled); } private List createArguments() { List argv= Lists.newArrayList(); addBooleanIfTrue(argv, CommandLineArgs.JUNIT, mode == Mode.junit); addBooleanIfTrue(argv, CommandLineArgs.MIXED, mode == Mode.mixed); addBooleanIfTrue(argv, CommandLineArgs.SKIP_FAILED_INVOCATION_COUNTS, m_skipFailedInvocationCounts); addIntegerIfNotNull(argv, CommandLineArgs.LOG, m_verbose); addDefaultListeners(argv); addOutputDir(argv); addFileIfFile(argv, CommandLineArgs.TEST_JAR, m_testjar); addStringIfNotBlank(argv, CommandLineArgs.GROUPS, m_includedGroups); addStringIfNotBlank(argv, CommandLineArgs.EXCLUDED_GROUPS, m_excludedGroups); addFilesOfRCollection(argv, CommandLineArgs.TEST_CLASS, m_classFilesets); addListOfStringIfNotEmpty(argv, CommandLineArgs.LISTENER, m_listeners); addListOfStringIfNotEmpty(argv, CommandLineArgs.METHOD_SELECTORS, m_methodselectors); addStringIfNotNull(argv, CommandLineArgs.OBJECT_FACTORY, m_objectFactory); addStringIfNotNull(argv, CommandLineArgs.TEST_RUNNER_FACTORY, m_testRunnerFactory); addStringIfNotNull(argv, CommandLineArgs.PARALLEL, m_parallelMode); addStringIfNotNull(argv, CommandLineArgs.CONFIG_FAILURE_POLICY, m_configFailurePolicy); addBooleanIfTrue(argv, CommandLineArgs.RANDOMIZE_SUITES, m_randomizeSuites); addStringIfNotNull(argv, CommandLineArgs.THREAD_COUNT, m_threadCount); addStringIfNotNull(argv, CommandLineArgs.DATA_PROVIDER_THREAD_COUNT, m_dataproviderthreadCount); addStringIfNotBlank(argv, CommandLineArgs.SUITE_NAME, m_suiteName); addStringIfNotBlank(argv, CommandLineArgs.TEST_NAME, m_testName); addStringIfNotBlank(argv, CommandLineArgs.TEST_NAMES, m_testNames); addStringIfNotBlank(argv, CommandLineArgs.METHODS, m_methods); addReporterConfigs(argv); addIntegerIfNotNull(argv, CommandLineArgs.SUITE_THREAD_POOL_SIZE, m_suiteThreadPoolSize); addStringIfNotNull(argv, CommandLineArgs.XML_PATH_IN_JAR, m_xmlPathInJar); addXmlFiles(argv); return argv; } private void addDefaultListeners(List argv) { if (m_useDefaultListeners != null) { String useDefaultListeners = "false"; if ("yes".equalsIgnoreCase(m_useDefaultListeners) || "true".equalsIgnoreCase(m_useDefaultListeners)) { useDefaultListeners = "true"; } argv.add(CommandLineArgs.USE_DEFAULT_LISTENERS); argv.add(useDefaultListeners); } } private void addOutputDir(List argv) { if (null != m_outputDir) { if (!m_outputDir.exists()) { m_outputDir.mkdirs(); } if (m_outputDir.isDirectory()) { argv.add(CommandLineArgs.OUTPUT_DIRECTORY); argv.add(m_outputDir.getAbsolutePath()); } else { throw new BuildException("Output directory is not a directory: " + m_outputDir); } } } private void addReporterConfigs(List argv) { for (ReporterConfig reporterConfig : reporterConfigs) { argv.add(CommandLineArgs.REPORTER); argv.add(reporterConfig.serialize()); } } private void addFilesOfRCollection(List argv, String name, List resources) { addArgumentsIfNotEmpty(argv, name, getFiles(resources), ","); } private void addListOfStringIfNotEmpty(List argv, String name, List arguments) { addArgumentsIfNotEmpty(argv, name, arguments, ";"); } private void addArgumentsIfNotEmpty(List argv, String name, List arguments, String separator) { if (arguments != null && !arguments.isEmpty()) { argv.add(name); String value= Utils.join(arguments, separator); argv.add(value); } } private void addFileIfFile(List argv, String name, File file) { if ((null != file) && file.isFile()) { argv.add(name); argv.add(file.getAbsolutePath()); } } private void addBooleanIfTrue(List argv, String name, Boolean value) { if (TRUE.equals(value)) { argv.add(name); } } private void addIntegerIfNotNull(List argv, String name, Integer value) { if (value != null) { argv.add(name); argv.add(value.toString()); } } private void addStringIfNotNull(List argv, String name, String value) { if (value != null) { argv.add(name); argv.add(value); } } private void addStringIfNotBlank(List argv, String name, String value) { if (isStringNotBlank(value)) { argv.add(name); argv.add(value); } } private void addXmlFiles(List argv) { for (String file : getSuiteFileNames()) { argv.add(file); } } /** * @return the list of the XML file names. This method can be overridden by subclasses. */ protected List getSuiteFileNames() { List result = Lists.newArrayList(); for(String file : getFiles(m_xmlFilesets)) { result.add(file); } return result; } private void delegateCommandSystemProperties() { // Iterate over command-line args and pass them through as sysproperty // exclude any built-in properties that start with "ant." for (Object propKey : getProject().getUserProperties().keySet()) { String propName = (String) propKey; String propVal = getProject().getUserProperty(propName); if (propName.startsWith("ant.")) { log("Excluding ant property: " + propName + ": " + propVal, Project.MSG_DEBUG); } else { log("Including user property: " + propName + ": " + propVal, Project.MSG_DEBUG); Environment.Variable var = new Environment.Variable(); var.setKey(propName); var.setValue(propVal); addSysproperty(var); } } } private void printDebugInfo(String fileName) { if(m_dumpSys) { System.out.println("* SYSTEM PROPERTIES *"); Properties props= System.getProperties(); Enumeration en= props.propertyNames(); while(en.hasMoreElements()) { String key= (String) en.nextElement(); System.out.println(key + ": " + props.getProperty(key)); } System.out.println(""); } if(m_dumpEnv) { String[] vars= m_environment.getVariables(); if(null != vars && vars.length > 0) { System.out.println("* ENVIRONMENT *"); for(String v: vars) { System.out.println(v); } System.out.println(""); } } if(m_dump) { dumpCommand(fileName); } } private void ppp(String string) { System.out.println("[TestNGAntTask] " + string); } protected void actOnResult(int exitValue, boolean wasKilled) { if(exitValue == -1) { executeHaltTarget(exitValue); throw new BuildException("an error occured when running TestNG tests"); } if((exitValue & TestNG.HAS_NO_TEST) == TestNG.HAS_NO_TEST) { if(m_haltOnFailure) { executeHaltTarget(exitValue); throw new BuildException("No tests were run"); } else { if(null != m_failurePropertyName) { getProject().setNewProperty(m_failurePropertyName, "true"); } log("TestNG haven't found any tests to be run", Project.MSG_DEBUG); } } boolean failed= ((exitValue & TestNG.HAS_FAILURE) == TestNG.HAS_FAILURE) || wasKilled; if(failed) { final String msg= wasKilled ? "The tests timed out and were killed." : "The tests failed."; if(m_haltOnFailure) { executeHaltTarget(exitValue); throw new BuildException(msg); } else { if(null != m_failurePropertyName) { getProject().setNewProperty(m_failurePropertyName, "true"); } log(msg, Project.MSG_INFO); } } if((exitValue & TestNG.HAS_SKIPPED) == TestNG.HAS_SKIPPED) { if(m_haltOnSkipped) { executeHaltTarget(exitValue); throw new BuildException("There are TestNG SKIPPED tests"); } else { if(null != m_skippedPropertyName) { getProject().setNewProperty(m_skippedPropertyName, "true"); } log("There are TestNG SKIPPED tests", Project.MSG_DEBUG); } } if((exitValue & TestNG.HAS_FSP) == TestNG.HAS_FSP) { if(m_haltOnFSP) { executeHaltTarget(exitValue); throw new BuildException("There are TestNG FAILED WITHIN SUCCESS PERCENTAGE tests"); } else { if(null != m_fspPropertyName) { getProject().setNewProperty(m_fspPropertyName, "true"); } log("There are TestNG FAILED WITHIN SUCCESS PERCENTAGE tests", Project.MSG_DEBUG); } } } /** Executes the target, if any, that user designates executing before failing the test */ private void executeHaltTarget(int exitValue) { if(m_onHaltTarget != null) { if(m_outputDir != null) { getProject().setProperty("testng.outputdir", m_outputDir.getAbsolutePath()); } getProject().setProperty("testng.returncode", String.valueOf(exitValue)); Target t= (Target) getProject().getTargets().get(m_onHaltTarget); if(t != null) { t.execute(); } } } /** * Executes the command line as a new process. * * @param cmd the command to execute * @param watchdog * @return the exit status of the subprocess or INVALID. */ protected int executeAsForked(CommandlineJava cmd, ExecuteWatchdog watchdog) { Execute execute= new Execute(new TestNGLogSH(this, Project.MSG_INFO, Project.MSG_WARN, (m_verbose == null || m_verbose < 5)), watchdog); execute.setCommandline(cmd.getCommandline()); execute.setAntRun(getProject()); if(m_workingDir != null) { if(m_workingDir.exists() && m_workingDir.isDirectory()) { execute.setWorkingDirectory(m_workingDir); } else { log("Ignoring invalid working directory : " + m_workingDir, Project.MSG_WARN); } } String[] environment= m_environment.getVariables(); if(null != environment) { for(String envEntry : environment) { log("Setting environment variable: " + envEntry, Project.MSG_VERBOSE); } } execute.setEnvironment(environment); log(cmd.describeCommand(), Project.MSG_VERBOSE); int retVal; try { retVal= execute.execute(); } catch(IOException e) { throw new BuildException("Process fork failed.", e, getLocation()); } return retVal; } /** * Creates or returns the already created CommandlineJava. */ protected CommandlineJava getJavaCommand() { if(null == m_javaCommand) { m_javaCommand = new CommandlineJava(); } return m_javaCommand; } /** * @return null if there is no timeout value, otherwise the * watchdog instance. * * @throws BuildException under unspecified circumstances * @since Ant 1.2 */ protected ExecuteWatchdog createWatchdog() /*throws BuildException*/ { if(m_timeout == null) { return null; } return new ExecuteWatchdog(m_timeout.longValue()); } protected void validateOptions() throws BuildException { int suiteCount = getSuiteFileNames().size(); if (suiteCount == 0 && m_classFilesets.size() == 0 && Utils.isStringEmpty(m_methods) && ((null == m_testjar) || !m_testjar.isFile())) { throw new BuildException("No suites, classes, methods or jar file was specified."); } if((null != m_includedGroups) && (m_classFilesets.size() == 0 && suiteCount == 0)) { throw new BuildException("No class filesets or xml file sets specified while using groups"); } if(m_onHaltTarget != null) { if(!getProject().getTargets().containsKey(m_onHaltTarget)) { throw new BuildException("Target " + m_onHaltTarget + " not found in this project"); } } } private ResourceCollection createResourceCollection(Reference ref) { Object o = ref.getReferencedObject(); if (!(o instanceof ResourceCollection)) { throw new BuildException("Only File based ResourceCollections are supported."); } ResourceCollection rc = (ResourceCollection) o; if (!rc.isFilesystemOnly()) { throw new BuildException("Only ResourceCollections from local file system are supported."); } return rc; } private FileSet appendClassSelector(FileSet fs) { FilenameSelector selector= new FilenameSelector(); selector.setName("**/*.class"); selector.setProject(getProject()); fs.appendSelector(selector); return fs; } private File findJar() { Class thisClass= getClass(); String resource= thisClass.getName().replace('.', '/') + ".class"; URL url= thisClass.getClassLoader().getResource(resource); if(null != url) { String u= url.toString(); if(u.startsWith("jar:file:")) { int pling= u.indexOf("!"); String jarName= u.substring(4, pling); return new File(fromURI(jarName)); } else if(u.startsWith("file:")) { int tail= u.indexOf(resource); String dirName= u.substring(0, tail); return new File(fromURI(dirName)); } } return null; } private String fromURI(String uri) { URL url= null; try { url= new URL(uri); } catch(MalformedURLException murle) { } if((null == url) || !("file".equals(url.getProtocol()))) { throw new IllegalArgumentException("Can only handle valid file: URIs"); } StringBuffer buf= new StringBuffer(url.getHost()); if(buf.length() > 0) { buf.insert(0, File.separatorChar).insert(0, File.separatorChar); } String file= url.getFile(); int queryPos= file.indexOf('?'); buf.append((queryPos < 0) ? file : file.substring(0, queryPos)); uri= buf.toString().replace('/', File.separatorChar); if((File.pathSeparatorChar == ';') && uri.startsWith("\\") && (uri.length() > 2) && Character.isLetter(uri.charAt(1)) && (uri.lastIndexOf(':') > -1)) { uri= uri.substring(1); } StringBuffer sb= new StringBuffer(); CharacterIterator iter= new StringCharacterIterator(uri); for(char c= iter.first(); c != CharacterIterator.DONE; c= iter.next()) { if(c == '%') { char c1= iter.next(); if(c1 != CharacterIterator.DONE) { int i1= Character.digit(c1, 16); char c2= iter.next(); if(c2 != CharacterIterator.DONE) { int i2= Character.digit(c2, 16); sb.append((char) ((i1 << 4) + i2)); } } } else { sb.append(c); } } return sb.toString(); } /** * Returns the list of files corresponding to the resource collection * * @param resources * @return the list of files corresponding to the resource collection * @throws BuildException */ private List getFiles(List resources) throws BuildException { List files= Lists.newArrayList(); for (ResourceCollection rc : resources) { for (Iterator i = rc.iterator(); i.hasNext();) { Object o = i.next(); if (o instanceof FileResource) { FileResource fr = ((FileResource) o); if (fr.isDirectory()) { throw new BuildException("Directory based FileResources are not supported."); } if (!fr.isExists()) { log("'" + fr.toLongString() + "' does not exist", Project.MSG_VERBOSE); } files.add(fr.getFile().getAbsolutePath()); } else { log("Unsupported Resource type: " + o.toString(), Project.MSG_VERBOSE); } } } return files; } /** * Returns the list of files corresponding to the fileset * * @param filesets * @return the list of files corresponding to the fileset * @throws BuildException */ private List fileset(FileSet fileset) throws BuildException { List files= Lists.newArrayList(); DirectoryScanner ds= fileset.getDirectoryScanner(getProject()); for(String file : ds.getIncludedFiles()) { files.add(ds.getBasedir() + File.separator + file); } return files; } /** * Adds double quotes to the command line argument if it contains spaces. * @param pCommandLineArg the command line argument * @return pCommandLineArg in double quotes if it contains space. * */ private static String doubleQuote(String pCommandLineArg) { if(pCommandLineArg.indexOf(" ") != -1 && !(pCommandLineArg.startsWith("\"") && pCommandLineArg.endsWith("\""))) { return "\"" + pCommandLineArg + '\"'; } return pCommandLineArg; } /** * Creates a string representation of the path. */ private String createPathString(Path path, String sep) { if(path == null) { return null; } final StringBuffer buf= new StringBuffer(); for(int i= 0; i < path.list().length; i++) { File file= getProject().resolveFile(path.list()[i]); if(!file.exists()) { log("Classpath entry not found: " + file, Project.MSG_WARN); } buf.append(file.getAbsolutePath()).append(sep); } if(path.list().length > 0) { // cut the last ; buf.deleteCharAt(buf.length() - 1); } return buf.toString(); } private void dumpCommand(String fileName) { ppp("TESTNG PASSED @" + fileName + " WHICH CONTAINS:"); readAndPrintFile(fileName); } private void readAndPrintFile(String fileName) { File file = new File(fileName); BufferedReader br = null; try { br = new BufferedReader(new FileReader(file)); String line = br.readLine(); while (line != null) { System.out.println(" " + line); line = br.readLine(); } } catch(IOException ex) { ex.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } } public void addConfiguredReporter(ReporterConfig reporterConfig) { reporterConfigs.add(reporterConfig); } public void setSkipFailedInvocationCounts(boolean skip) { m_skipFailedInvocationCounts = skip; } public void setXmlPathInJar(String path) { m_xmlPathInJar = path; } /** * Add the referenced property set as system properties for the TestNG JVM. * * @param sysPropertySet A PropertySet of system properties. */ public void addConfiguredPropertySet(PropertySet sysPropertySet) { Properties properties = sysPropertySet.getProperties(); log(properties.keySet().size() + " properties found in nested propertyset", Project.MSG_VERBOSE); for (Object propKeyObj : properties.keySet()) { String propKey = (String) propKeyObj; Environment.Variable sysProp = new Environment.Variable(); sysProp.setKey(propKey); if (properties.get(propKey) instanceof String) { String propVal = (String) properties.get(propKey); sysProp.setValue(propVal); getJavaCommand().addSysproperty(sysProp); log("Added system property " + propKey + " with value " + propVal, Project.MSG_VERBOSE); } else { log("Ignoring non-String property " + propKey, Project.MSG_WARN); } } } @Override protected void handleOutput(String output) { if (output.startsWith(VerboseReporter.LISTENER_PREFIX)) { //send everything from VerboseReporter to verbose level unless log level is > 4 log(output, m_verbose < 5 ? Project.MSG_VERBOSE : Project.MSG_INFO); } else { super.handleOutput(output); } } private static class TestNGLogOS extends LogOutputStream { private Task task; private boolean verbose; public TestNGLogOS(Task task, int level, boolean verbose) { super(task, level); this.task = task; this.verbose = verbose; } @Override protected void processLine(String line, int level) { if (line.startsWith(VerboseReporter.LISTENER_PREFIX)) { task.log(line, verbose ? Project.MSG_VERBOSE : Project.MSG_INFO); } else { super.processLine(line, level); } } } protected static class TestNGLogSH extends PumpStreamHandler { public TestNGLogSH(Task task, int outlevel, int errlevel, boolean verbose) { super(new TestNGLogOS(task, outlevel, verbose), new LogOutputStream(task, errlevel)); } } } testng-testng-6.9.5/src/main/java/org/testng/TestNG.java0000644000175000017500000016460612551235562022424 0ustar eugeneeugenepackage org.testng; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; 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; import java.util.jar.JarEntry; import java.util.jar.JarFile; 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; import org.testng.internal.IConfiguration; import org.testng.internal.IResultListener2; import org.testng.internal.OverrideProcessor; import org.testng.internal.SuiteRunnerMap; import org.testng.internal.Utils; 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.thread.graph.GraphThreadPoolExecutor; import org.testng.internal.thread.graph.IThreadWorkerFactory; import org.testng.internal.thread.graph.SuiteWorkerFactory; import org.testng.junit.JUnitTestFinder; import org.testng.log4testng.Logger; import org.testng.remote.SuiteDispatcher; import org.testng.remote.SuiteSlave; import org.testng.reporters.EmailableReporter; import org.testng.reporters.EmailableReporter2; import org.testng.reporters.FailedReporter; import org.testng.reporters.JUnitReportReporter; import org.testng.reporters.SuiteHTMLReporter; import org.testng.reporters.VerboseReporter; import org.testng.reporters.XMLReporter; import org.testng.reporters.jq.Main; import org.testng.xml.Parser; import org.testng.xml.XmlClass; import org.testng.xml.XmlInclude; import org.testng.xml.XmlMethodSelector; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; 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 * ways: *
    *
  • On an existing testng.xml *
  • On a synthetic testng.xml, created entirely from Java *
  • By directly setting the test classes *
* You can also define which groups to include or exclude, assign parameters, etc... *

* The command line parameters are: *

    *
  • -d outputdir: specify the output directory
  • *
  • -testclass class_name: specifies one or several class names
  • *
  • -testjar jar_name: specifies the jar containing the tests
  • *
  • -sourcedir src1;src2: ; separated list of source directories * (used only when javadoc annotations are used)
  • *
  • -target
  • *
  • -groups
  • *
  • -testrunfactory
  • *
  • -listener
  • *
*

* Please consult documentation for more details. * * FIXME: should support more than simple paths for suite xmls * * @see #usage() * * @author Cedric Beust * @author Alex Popescu */ public class TestNG { /** This class' log4testng Logger. */ private static final Logger LOGGER = Logger.getLogger(TestNG.class); /** The default name for a suite launched from the command line */ public static final String DEFAULT_COMMAND_LINE_SUITE_NAME = "Command line suite"; /** The default name for a test launched from the command line */ public static final String DEFAULT_COMMAND_LINE_TEST_NAME = "Command line test"; /** The default name of the result's output directory (keep public, used by Eclipse). */ public static final String DEFAULT_OUTPUTDIR = "test-output"; /** System properties */ public static final String SHOW_TESTNG_STACK_FRAMES = "testng.show.stack.frames"; public static final String TEST_CLASSPATH = "testng.test.classpath"; private static TestNG m_instance; private static JCommander m_jCommander; private List m_commandLineMethods; protected List m_suites = Lists.newArrayList(); private List m_cmdlineSuites; private String m_outputDir = DEFAULT_OUTPUTDIR; private String[] m_includedGroups; private String[] m_excludedGroups; private Boolean m_isJUnit = XmlSuite.DEFAULT_JUNIT; private Boolean m_isMixed = XmlSuite.DEFAULT_MIXED; protected boolean m_useDefaultListeners = true; private ITestRunnerFactory m_testRunnerFactory; // These listeners can be overridden from the command line private List m_testListeners = Lists.newArrayList(); private List m_suiteListeners = Lists.newArrayList(); private Set m_reporters = Sets.newHashSet(); protected static final int HAS_FAILURE = 1; protected static final int HAS_SKIPPED = 2; protected static final int HAS_FSP = 4; protected static final int HAS_NO_TEST = 8; public static final Integer DEFAULT_VERBOSE = 1; private int m_status; private boolean m_hasTests= false; private String m_slavefileName = null; private String m_masterfileName = null; // Command line suite parameters private int m_threadCount; private boolean m_useThreadCount; private String m_parallelMode; private boolean m_useParallelMode; private String m_configFailurePolicy; private Class[] m_commandLineTestClasses; private String m_defaultSuiteName=DEFAULT_COMMAND_LINE_SUITE_NAME; private String m_defaultTestName=DEFAULT_COMMAND_LINE_TEST_NAME; private Map m_methodDescriptors = Maps.newHashMap(); private ITestObjectFactory m_objectFactory; private List m_invokedMethodListeners = Lists.newArrayList(); private Integer m_dataProviderThreadCount = null; private String m_jarPath; /** The path of the testng.xml file inside the jar file */ private String m_xmlPathInJar = CommandLineArgs.XML_PATH_IN_JAR_DEFAULT; private List m_stringSuites = Lists.newArrayList(); private IHookable m_hookable; private IConfigurable m_configurable; protected long m_end; protected long m_start; private List m_executionListeners = Lists.newArrayList(); private boolean m_isInitialized = false; /** * Default constructor. Setting also usage of default listeners/reporters. */ public TestNG() { init(true); } /** * Used by maven2 to have 0 output of any kind come out * of testng. * @param useDefaultListeners Whether or not any default reports * should be added to tests. */ public TestNG(boolean useDefaultListeners) { init(useDefaultListeners); } private void init(boolean useDefaultListeners) { m_instance = this; m_useDefaultListeners = useDefaultListeners; m_configuration = new Configuration(); } public int getStatus() { return m_status; } private void setStatus(int status) { m_status |= status; } /** * Sets the output directory where the reports will be created. * @param outputdir The directory. */ public void setOutputDirectory(final String outputdir) { if (isStringNotEmpty(outputdir)) { m_outputDir = outputdir; } } /** * If this method is passed true before run(), the default listeners * will not be used. *

    *
  • org.testng.reporters.TestHTMLReporter *
  • org.testng.reporters.JUnitXMLReporter *
  • org.testng.reporters.XMLReporter *
* * @see org.testng.reporters.TestHTMLReporter * @see org.testng.reporters.JUnitXMLReporter * @see org.testng.reporters.XMLReporter */ public void setUseDefaultListeners(boolean useDefaultListeners) { m_useDefaultListeners = useDefaultListeners; } /** * Sets a jar containing a testng.xml file. * * @param jarPath */ public void setTestJar(String jarPath) { m_jarPath = jarPath; } /** * Sets the path to the XML file in the test jar file. */ public void setXmlPathInJar(String xmlPathInJar) { m_xmlPathInJar = xmlPathInJar; } public void initializeSuitesAndJarFile() { // The Eclipse plug-in (RemoteTestNG) might have invoked this method already // so don't initialize suites twice. if (m_isInitialized) { return; } m_isInitialized = true; if (m_suites.size() > 0) { //to parse the suite files (), if any for (XmlSuite s: m_suites) { for (String suiteFile : s.getSuiteFiles()) { try { Collection childSuites = getParser(suiteFile).parse(); for (XmlSuite cSuite : childSuites){ cSuite.setParentSuite(s); s.getChildSuites().add(cSuite); } } catch (ParserConfigurationException | IOException | SAXException e) { e.printStackTrace(System.out); } } } return; } // // Parse the suites that were passed on the command line // for (String suitePath : m_stringSuites) { if(LOGGER.isDebugEnabled()) { LOGGER.debug("suiteXmlPath: \"" + suitePath + "\""); } try { Collection allSuites = getParser(suitePath).parse(); for (XmlSuite s : allSuites) { // If test names were specified, only run these test names if (m_testNames != null) { m_suites.add(extractTestNames(s, m_testNames)); } else { m_suites.add(s); } } } catch(SAXException | ParserConfigurationException | IOException e) { e.printStackTrace(System.out); } catch(Exception ex) { // Probably a Yaml exception, unnest it Throwable t = ex; while (t.getCause() != null) t = t.getCause(); // t.printStackTrace(); if (t instanceof TestNGException) throw (TestNGException) t; else throw new TestNGException(t); } } // // jar path // // If suites were passed on the command line, they take precedence over the suite file // inside that jar path if (m_jarPath != null && m_stringSuites.size() > 0) { StringBuilder suites = new StringBuilder(); for (String s : m_stringSuites) { suites.append(s); } Utils.log("TestNG", 2, "Ignoring the XML file inside " + m_jarPath + " and using " + suites + " instead"); return; } if (isStringEmpty(m_jarPath)) { return; } // We have a jar file and no XML file was specified: try to find an XML file inside the jar File jarFile = new File(m_jarPath); try { Utils.log("TestNG", 2, "Trying to open jar file:" + jarFile); JarFile jf = new JarFile(jarFile); // System.out.println(" result: " + jf); Enumeration entries = jf.entries(); List classes = Lists.newArrayList(); boolean foundTestngXml = false; while (entries.hasMoreElements()) { JarEntry je = entries.nextElement(); if (je.getName().equals(m_xmlPathInJar)) { Parser parser = getParser(jf.getInputStream(je)); Collection suites = parser.parse(); for (XmlSuite suite : suites) { // If test names were specified, only run these test names if (m_testNames != null) { m_suites.add(extractTestNames(suite, m_testNames)); } else { m_suites.add(suite); } } foundTestngXml = true; break; } else if (je.getName().endsWith(".class")) { int n = je.getName().length() - ".class".length(); classes.add(je.getName().replace("/", ".").substring(0, n)); } } if (! foundTestngXml) { Utils.log("TestNG", 1, "Couldn't find the " + m_xmlPathInJar + " in the jar file, running all the classes"); XmlSuite xmlSuite = new XmlSuite(); xmlSuite.setVerbose(0); xmlSuite.setName("Jar suite"); XmlTest xmlTest = new XmlTest(xmlSuite); List xmlClasses = Lists.newArrayList(); for (String cls : classes) { XmlClass xmlClass = new XmlClass(cls); xmlClasses.add(xmlClass); } xmlTest.setXmlClasses(xmlClasses); m_suites.add(xmlSuite); } } catch(ParserConfigurationException | IOException | SAXException ex) { ex.printStackTrace(); } } private Parser getParser(String path) { Parser result = new Parser(path); initProcessor(result); return result; } private Parser getParser(InputStream is) { Parser result = new Parser(is); initProcessor(result); return result; } private void initProcessor(Parser result) { result.setPostProcessor(new OverrideProcessor(m_includedGroups, m_excludedGroups)); } /** * If the XmlSuite contains at least one test named as testNames, return * an XmlSuite that's made only of these tests, otherwise, return the * original suite. */ private static XmlSuite extractTestNames(XmlSuite s, List testNames) { List tests = Lists.newArrayList(); for (XmlTest xt : s.getTests()) { for (String tn : testNames) { if (xt.getName().equals(tn)) { tests.add(xt); } } } if (tests.size() == 0) { return s; } else { XmlSuite result = (XmlSuite) s.clone(); result.getTests().clear(); result.getTests().addAll(tests); return result; } } /** * Define the number of threads in the thread pool. */ public void setThreadCount(int threadCount) { if(threadCount < 1) { exitWithError("Cannot use a threadCount parameter less than 1; 1 > " + threadCount); } m_threadCount = threadCount; m_useThreadCount = true; } /** * Define whether this run will be run in parallel mode. */ public void setParallel(String parallel) { m_parallelMode = parallel; m_useParallelMode = true; } public void setCommandLineSuite(XmlSuite suite) { m_cmdlineSuites = Lists.newArrayList(); m_cmdlineSuites.add(suite); m_suites.add(suite); } /** * Set the test classes to be run by this TestNG object. This method * will create a dummy suite that will wrap these classes called * "Command Line Test". *

* If used together with threadCount, parallel, groups, excludedGroups than this one must be set first. * * @param classes An array of classes that contain TestNG annotations. */ public void setTestClasses(Class[] classes) { m_suites.clear(); m_commandLineTestClasses = classes; } /** * Given a string com.example.Foo.f1, return an array where [0] is the class and [1] * is the method. */ private String[] splitMethod(String m) { int index = m.lastIndexOf("."); if (index < 0) { throw new TestNGException("Bad format for command line method:" + m + ", expected ."); } return new String[] { m.substring(0, index), m.substring(index + 1).replaceAll("\\*", "\\.\\*") }; } /** * @return a list of XmlSuite objects that represent the list of classes and methods passed * in parameter. * * @param commandLineMethods a string with the form "com.example.Foo.f1,com.example.Bar.f2" */ private List createCommandLineSuitesForMethods(List commandLineMethods) { // // Create the tag // Set classes = Sets.newHashSet(); for (String m : commandLineMethods) { Class c = ClassHelper.forName(splitMethod(m)[0]); if (c != null) { classes.add(c); } } List result = createCommandLineSuitesForClasses(classes.toArray(new Class[0])); // // Add the method tags // List xmlClasses = Lists.newArrayList(); for (XmlSuite s : result) { for (XmlTest t : s.getTests()) { xmlClasses.addAll(t.getClasses()); } } for (XmlClass xc : xmlClasses) { for (String m : commandLineMethods) { String[] split = splitMethod(m); String className = split[0]; if (xc.getName().equals(className)) { XmlInclude includedMethod = new XmlInclude(split[1]); xc.getIncludedMethods().add(includedMethod); } } } return result; } private List createCommandLineSuitesForClasses(Class[] classes) { // // See if any of the classes has an xmlSuite or xmlTest attribute. // If it does, create the appropriate XmlSuite, otherwise, create // the default one // XmlClass[] xmlClasses = Utils.classesToXmlClasses(classes); Map suites = Maps.newHashMap(); IAnnotationFinder finder = m_configuration.getAnnotationFinder(); for (int i = 0; i < classes.length; i++) { Class c = classes[i]; ITestAnnotation test = finder.findAnnotation(c, ITestAnnotation.class); String suiteName = getDefaultSuiteName(); String testName = getDefaultTestName(); boolean isJUnit = false; if (test != null) { suiteName = defaultIfStringEmpty(test.getSuiteName(), suiteName); testName = defaultIfStringEmpty(test.getTestName(), testName); } else { if (m_isMixed && JUnitTestFinder.isJUnitTest(c)) { isJUnit = true; testName = c.getName(); } } XmlSuite xmlSuite = suites.get(suiteName); if (xmlSuite == null) { xmlSuite = new XmlSuite(); xmlSuite.setName(suiteName); suites.put(suiteName, xmlSuite); } if (m_dataProviderThreadCount != null) { xmlSuite.setDataProviderThreadCount(m_dataProviderThreadCount); } XmlTest xmlTest = null; for (XmlTest xt : xmlSuite.getTests()) { if (xt.getName().equals(testName)) { xmlTest = xt; break; } } if (xmlTest == null) { xmlTest = new XmlTest(xmlSuite); xmlTest.setName(testName); xmlTest.setJUnit(isJUnit); } xmlTest.getXmlClasses().add(xmlClasses[i]); } return new ArrayList<>(suites.values()); } public void addMethodSelector(String className, int priority) { m_methodDescriptors.put(className, priority); } /** * Set the suites file names to be run by this TestNG object. This method tries to load and * parse the specified TestNG suite xml files. If a file is missing, it is ignored. * * @param suites A list of paths to one more XML files defining the tests. For example: * *

   * TestNG tng = new TestNG();
   * List suites = Lists.newArrayList();
   * suites.add("c:/tests/testng1.xml");
   * suites.add("c:/tests/testng2.xml");
   * tng.setTestSuites(suites);
   * tng.run();
   * 
*/ public void setTestSuites(List suites) { m_stringSuites = suites; } /** * Specifies the XmlSuite objects to run. * @param suites * @see org.testng.xml.XmlSuite */ public void setXmlSuites(List suites) { m_suites = suites; } /** * Define which groups will be excluded from this run. * * @param groups A list of group names separated by a comma. */ public void setExcludedGroups(String groups) { m_excludedGroups = Utils.split(groups, ","); } /** * Define which groups will be included from this run. * * @param groups A list of group names separated by a comma. */ public void setGroups(String groups) { m_includedGroups = Utils.split(groups, ","); } private void setTestRunnerFactoryClass(Class testRunnerFactoryClass) { setTestRunnerFactory((ITestRunnerFactory) ClassHelper.newInstance(testRunnerFactoryClass)); } protected void setTestRunnerFactory(ITestRunnerFactory itrf) { m_testRunnerFactory= itrf; } public void setObjectFactory(Class c) { m_objectFactory = (ITestObjectFactory) ClassHelper.newInstance(c); } public void setObjectFactory(ITestObjectFactory factory) { m_objectFactory = factory; } /** * Define which listeners to user for this run. * * @param classes A list of classes, which must be either ISuiteListener, * ITestListener or IReporter */ public void setListenerClasses(List classes) { for (Class cls: classes) { addListener(ClassHelper.newInstance(cls)); } } public void addListener(Object listener) { if (! (listener instanceof ITestNGListener)) { exitWithError("Listener " + listener + " must be one of ITestListener, ISuiteListener, IReporter, " + " IAnnotationTransformer, IMethodInterceptor or IInvokedMethodListener"); } else { if (listener instanceof ISuiteListener) { addListener((ISuiteListener) listener); } if (listener instanceof ITestListener) { addListener((ITestListener) listener); } if (listener instanceof IReporter) { addListener((IReporter) listener); } if (listener instanceof IAnnotationTransformer) { setAnnotationTransformer((IAnnotationTransformer) listener); } if (listener instanceof IMethodInterceptor) { m_methodInterceptors.add((IMethodInterceptor) listener); } if (listener instanceof IInvokedMethodListener) { addInvokedMethodListener((IInvokedMethodListener) listener); } if (listener instanceof IHookable) { setHookable((IHookable) listener); } if (listener instanceof IConfigurable) { setConfigurable((IConfigurable) listener); } if (listener instanceof IExecutionListener) { addExecutionListener((IExecutionListener) listener); } if (listener instanceof IConfigurationListener) { getConfiguration().addConfigurationListener((IConfigurationListener) listener); } } } public void addListener(IInvokedMethodListener listener) { m_invokedMethodListeners.add(listener); } public void addListener(ISuiteListener listener) { if (null != listener) { m_suiteListeners.add(listener); } } public void addListener(ITestListener listener) { if (null != listener) { m_testListeners.add(listener); } } public void addListener(IReporter listener) { if (null != listener) { m_reporters.add(listener); } } public void addInvokedMethodListener(IInvokedMethodListener listener) { m_invokedMethodListeners.add(listener); } public Set getReporters() { return m_reporters; } public List getTestListeners() { return m_testListeners; } public List getSuiteListeners() { return m_suiteListeners; } /** If m_verbose gets set, it will override the verbose setting in testng.xml */ private Integer m_verbose = null; private final IAnnotationTransformer m_defaultAnnoProcessor = new DefaultAnnotationTransformer(); private IAnnotationTransformer m_annotationTransformer = m_defaultAnnoProcessor; private Boolean m_skipFailedInvocationCounts = false; private List m_methodInterceptors = new ArrayList(); /** The list of test names to run from the given suite */ private List m_testNames; private Integer m_suiteThreadPoolSize = CommandLineArgs.SUITE_THREAD_POOL_SIZE_DEFAULT; private boolean m_randomizeSuites = Boolean.FALSE; private boolean m_preserveOrder = false; private Boolean m_groupByInstances; private IConfiguration m_configuration; /** * Sets the level of verbosity. This value will override the value specified * in the test suites. * * @param verbose the verbosity level (0 to 10 where 10 is most detailed) * Actually, this is a lie: you can specify -1 and this will put TestNG * in debug mode (no longer slicing off stack traces and all). */ public void setVerbose(int verbose) { m_verbose = verbose; } private void initializeCommandLineSuites() { if (m_commandLineTestClasses != null || m_commandLineMethods != null) { if (null != m_commandLineMethods) { m_cmdlineSuites = createCommandLineSuitesForMethods(m_commandLineMethods); } else { m_cmdlineSuites = createCommandLineSuitesForClasses(m_commandLineTestClasses); } for (XmlSuite s : m_cmdlineSuites) { for (XmlTest t : s.getTests()) { t.setPreserveOrder(String.valueOf(m_preserveOrder)); } m_suites.add(s); if (m_groupByInstances != null) { s.setGroupByInstances(m_groupByInstances); } } } } private void initializeCommandLineSuitesParams() { if(null == m_cmdlineSuites) { return; } for (XmlSuite s : m_cmdlineSuites) { if(m_useThreadCount) { s.setThreadCount(m_threadCount); } if(m_useParallelMode) { s.setParallel(m_parallelMode); } if(m_configFailurePolicy != null) { s.setConfigFailurePolicy(m_configFailurePolicy.toString()); } } } private void initializeCommandLineSuitesGroups() { // If groups were specified on the command line, they should override groups // specified in the XML file boolean hasIncludedGroups = null != m_includedGroups && m_includedGroups.length > 0; boolean hasExcludedGroups = null != m_excludedGroups && m_excludedGroups.length > 0; List suites = m_cmdlineSuites != null ? m_cmdlineSuites : m_suites; if (hasIncludedGroups || hasExcludedGroups) { for (XmlSuite s : suites) { //set on each test, instead of just the first one of the suite for (XmlTest t : s.getTests()) { if(hasIncludedGroups) { t.setIncludedGroups(Arrays.asList(m_includedGroups)); } if(hasExcludedGroups) { t.setExcludedGroups(Arrays.asList(m_excludedGroups)); } } } } } private void addReporter(Class r) { if (! m_reporters.contains(r)) { m_reporters.add(ClassHelper.newInstance(r)); } } private void initializeDefaultListeners() { m_testListeners.add(new ExitCodeListener(this)); if (m_useDefaultListeners) { addReporter(SuiteHTMLReporter.class); addReporter(Main.class); addReporter(FailedReporter.class); addReporter(XMLReporter.class); if (System.getProperty("oldTestngEmailableReporter") != null) { addReporter(EmailableReporter.class); } else if (System.getProperty("noEmailableReporter") == null) { addReporter(EmailableReporter2.class); } addReporter(JUnitReportReporter.class); if (m_verbose != null && m_verbose > 4) { addListener(new VerboseReporter("[TestNG] ")); } } } private void initializeConfiguration() { ITestObjectFactory factory = m_objectFactory; // // Install the listeners found in ServiceLoader (or use the class // loader for tests, if specified). // addServiceLoaderListeners(); // // Install the listeners found in the suites // for (XmlSuite s : m_suites) { for (String listenerName : s.getListeners()) { Class listenerClass = ClassHelper.forName(listenerName); // If specified listener does not exist, a TestNGException will be thrown if(listenerClass == null) { throw new TestNGException("Listener " + listenerName + " was not found in project's classpath"); } Object listener = ClassHelper.newInstance(listenerClass); addListener(listener); } // // Install the method selectors // for (XmlMethodSelector methodSelector : s.getMethodSelectors() ) { addMethodSelector(methodSelector.getClassName(), methodSelector.getPriority()); } // // Find if we have an object factory // if (s.getObjectFactory() != null) { if (factory == null) { factory = s.getObjectFactory(); } else { throw new TestNGException("Found more than one object-factory tag in your suites"); } } } m_configuration.setAnnotationFinder(new JDK15AnnotationFinder(getAnnotationTransformer())); m_configuration.setHookable(m_hookable); m_configuration.setConfigurable(m_configurable); m_configuration.setObjectFactory(factory); } /** * Using reflection to remain Java 5 compliant. */ private void addServiceLoaderListeners() { Iterable loader = m_serviceLoaderClassLoader != null ? ServiceLoader.load(ITestNGListener.class, m_serviceLoaderClassLoader) : ServiceLoader.load(ITestNGListener.class); for (ITestNGListener l : loader) { Utils.log("[TestNG]", 2, "Adding ServiceLoader listener:" + l); addListener(l); addServiceLoaderListener(l); } } /** * Before suites are executed, do a sanity check to ensure all required * conditions are met. If not, throw an exception to stop test execution * * @throws TestNGException if the sanity check fails */ private void sanityCheck() { checkTestNames(m_suites); checkSuiteNames(m_suites); } /** * Ensure that two XmlTest within the same XmlSuite don't have the same name */ private void checkTestNames(List suites) { for (XmlSuite suite : suites) { Set testNames = Sets.newHashSet(); for (XmlTest test : suite.getTests()) { if (testNames.contains(test.getName())) { throw new TestNGException("Two tests in the same suite " + "cannot have the same name: " + test.getName()); } else { testNames.add(test.getName()); } } checkTestNames(suite.getChildSuites()); } } /** * Ensure that two XmlSuite don't have the same name * Otherwise will be clash in SuiteRunnerMap * See issue #302 */ private void checkSuiteNames(List suites) { checkSuiteNamesInternal(suites, Sets.newHashSet()); } private void checkSuiteNamesInternal(List suites, Set names) { for (XmlSuite suite : suites) { final String name = suite.getName(); if (names.contains(name)) { throw new TestNGException("Two suites cannot have the same name: " + name); } names.add(name); checkSuiteNamesInternal(suite.getChildSuites(), names); } } /** * Run TestNG. */ public void run() { initializeSuitesAndJarFile(); initializeConfiguration(); initializeDefaultListeners(); initializeCommandLineSuites(); initializeCommandLineSuitesParams(); initializeCommandLineSuitesGroups(); sanityCheck(); List suiteRunners = null; runExecutionListeners(true /* start */); m_start = System.currentTimeMillis(); // // Slave mode // if (m_slavefileName != null) { SuiteSlave slave = new SuiteSlave( m_slavefileName, this ); slave.waitForSuites(); } // // Regular mode // else if (m_masterfileName == null) { suiteRunners = runSuitesLocally(); } // // Master mode // else { SuiteDispatcher dispatcher = new SuiteDispatcher(m_masterfileName); suiteRunners = dispatcher.dispatch(getConfiguration(), m_suites, getOutputDirectory(), getTestListeners()); } m_end = System.currentTimeMillis(); runExecutionListeners(false /* finish */); if(null != suiteRunners) { generateReports(suiteRunners); } if(!m_hasTests) { setStatus(HAS_NO_TEST); if (TestRunner.getVerbose() > 1) { System.err.println("[TestNG] No tests found. Nothing was run"); usage(); } } } private void p(String string) { System.out.println("[TestNG] " + string); } private void runExecutionListeners(boolean start) { for (List listeners : Arrays.asList(m_executionListeners, m_configuration.getExecutionListeners())) { for (IExecutionListener l : listeners) { if (start) l.onExecutionStart(); else l.onExecutionFinish(); } } } public void addExecutionListener(IExecutionListener l) { m_executionListeners.add(l); } private static void usage() { if (m_jCommander == null) { m_jCommander = new JCommander(new CommandLineArgs()); } m_jCommander.usage(); } private void generateReports(List suiteRunners) { for (IReporter reporter : m_reporters) { try { long start = System.currentTimeMillis(); reporter.generateReport(m_suites, suiteRunners, m_outputDir); Utils.log("TestNG", 2, "Time taken by " + reporter + ": " + (System.currentTimeMillis() - start) + " ms"); } catch(Exception ex) { System.err.println("[TestNG] Reporter " + reporter + " failed"); ex.printStackTrace(System.err); } } } /** * This needs to be public for maven2, for now..At least * until an alternative mechanism is found. */ public List runSuitesLocally() { SuiteRunnerMap suiteRunnerMap = new SuiteRunnerMap(); if (m_suites.size() > 0) { if (m_suites.get(0).getVerbose() >= 2) { Version.displayBanner(); } // First initialize the suite runners to ensure there are no configuration issues. // Create a map with XmlSuite as key and corresponding SuiteRunner as value for (XmlSuite xmlSuite : m_suites) { createSuiteRunners(suiteRunnerMap, xmlSuite); } // // Run suites // if (m_suiteThreadPoolSize == 1 && !m_randomizeSuites) { // Single threaded and not randomized: run the suites in order for (XmlSuite xmlSuite : m_suites) { runSuitesSequentially(xmlSuite, suiteRunnerMap, getVerbose(xmlSuite), getDefaultSuiteName()); } } else { // Multithreaded: generate a dynamic graph that stores the suite hierarchy. This is then // used to run related suites in specific order. Parent suites are run only // once all the child suites have completed execution DynamicGraph suiteGraph = new DynamicGraph<>(); for (XmlSuite xmlSuite : m_suites) { populateSuiteGraph(suiteGraph, suiteRunnerMap, xmlSuite); } IThreadWorkerFactory factory = new SuiteWorkerFactory(suiteRunnerMap, 0 /* verbose hasn't been set yet */, getDefaultSuiteName()); GraphThreadPoolExecutor pooledExecutor = new GraphThreadPoolExecutor<>(suiteGraph, factory, m_suiteThreadPoolSize, m_suiteThreadPoolSize, Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); Utils.log("TestNG", 2, "Starting executor for all suites"); // Run all suites in parallel pooledExecutor.run(); try { pooledExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); pooledExecutor.shutdownNow(); } catch (InterruptedException handled) { Thread.currentThread().interrupt(); error("Error waiting for concurrent executors to finish " + handled.getMessage()); } } } else { setStatus(HAS_NO_TEST); error("No test suite found. Nothing to run"); usage(); } // // Generate the suites report // return Lists.newArrayList(suiteRunnerMap.values()); } private static void error(String s) { LOGGER.error(s); } /** * @return the verbose level, checking in order: the verbose level on * the suite, the verbose level on the TestNG object, or 1. */ private int getVerbose(XmlSuite xmlSuite) { int result = xmlSuite.getVerbose() != null ? xmlSuite.getVerbose() : (m_verbose != null ? m_verbose : DEFAULT_VERBOSE); return result; } /** * Recursively runs suites. Runs the children suites before running the parent * suite. This is done so that the results for parent suite can reflect the * combined results of the children suites. * * @param xmlSuite XML Suite to be executed * @param suiteRunnerMap Maps {@code XmlSuite}s to respective {@code ISuite} * @param verbose verbose level * @param defaultSuiteName default suite name */ private void runSuitesSequentially(XmlSuite xmlSuite, SuiteRunnerMap suiteRunnerMap, int verbose, String defaultSuiteName) { for (XmlSuite childSuite : xmlSuite.getChildSuites()) { runSuitesSequentially(childSuite, suiteRunnerMap, verbose, defaultSuiteName); } SuiteRunnerWorker srw = new SuiteRunnerWorker(suiteRunnerMap.get(xmlSuite), suiteRunnerMap, verbose, defaultSuiteName); srw.run(); } /** * Populates the dynamic graph with the reverse hierarchy of suites. Edges are * added pointing from child suite runners to parent suite runners, hence making * parent suite runners dependent on all the child suite runners * * @param suiteGraph dynamic graph representing the reverse hierarchy of SuiteRunners * @param suiteRunnerMap Map with XMLSuite as key and its respective SuiteRunner as value * @param xmlSuite XML Suite */ private void populateSuiteGraph(DynamicGraph suiteGraph /* OUT */, SuiteRunnerMap suiteRunnerMap, XmlSuite xmlSuite) { ISuite parentSuiteRunner = suiteRunnerMap.get(xmlSuite); if (xmlSuite.getChildSuites().isEmpty()) { suiteGraph.addNode(parentSuiteRunner); } else { for (XmlSuite childSuite : xmlSuite.getChildSuites()) { suiteGraph.addEdge(parentSuiteRunner, suiteRunnerMap.get(childSuite)); populateSuiteGraph(suiteGraph, suiteRunnerMap, childSuite); } } } /** * Creates the {@code SuiteRunner}s and populates the suite runner map with * this information * @param suiteRunnerMap Map with XMLSuite as key and it's respective * SuiteRunner as value. This is updated as part of this method call * @param xmlSuite Xml Suite (and its children) for which {@code SuiteRunner}s are created */ private void createSuiteRunners(SuiteRunnerMap suiteRunnerMap /* OUT */, XmlSuite xmlSuite) { if (null != m_isJUnit && ! m_isJUnit.equals(XmlSuite.DEFAULT_JUNIT)) { xmlSuite.setJUnit(m_isJUnit); } // If the skip flag was invoked on the command line, it // takes precedence if (null != m_skipFailedInvocationCounts) { xmlSuite.setSkipFailedInvocationCounts(m_skipFailedInvocationCounts); } // Override the XmlSuite verbose value with the one from TestNG if (m_verbose != null) { xmlSuite.setVerbose(m_verbose); } if (null != m_configFailurePolicy) { xmlSuite.setConfigFailurePolicy(m_configFailurePolicy); } for (XmlTest t : xmlSuite.getTests()) { for (Map.Entry ms : m_methodDescriptors.entrySet()) { XmlMethodSelector xms = new XmlMethodSelector(); xms.setName(ms.getKey()); xms.setPriority(ms.getValue()); t.getMethodSelectors().add(xms); } } suiteRunnerMap.put(xmlSuite, createSuiteRunner(xmlSuite)); for (XmlSuite childSuite : xmlSuite.getChildSuites()) { createSuiteRunners(suiteRunnerMap, childSuite); } } /** * Creates a suite runner and configures its initial state * @param xmlSuite * @return returns the newly created suite runner */ private SuiteRunner createSuiteRunner(XmlSuite xmlSuite) { SuiteRunner result = new SuiteRunner(getConfiguration(), xmlSuite, m_outputDir, m_testRunnerFactory, m_useDefaultListeners, m_methodInterceptors, m_invokedMethodListeners, m_testListeners); for (ISuiteListener isl : m_suiteListeners) { result.addListener(isl); } for (IReporter r : result.getReporters()) { addListener(r); } for (IConfigurationListener cl : m_configuration.getConfigurationListeners()) { result.addConfigurationListener(cl); } return result; } protected IConfiguration getConfiguration() { return m_configuration; } /** * The TestNG entry point for command line execution. * * @param argv the TestNG command line parameters. * @throws FileNotFoundException */ public static void main(String[] argv) { TestNG testng = privateMain(argv, null); System.exit(testng.getStatus()); } /** * Note: this method is not part of the public API and is meant for internal usage only. */ public static TestNG privateMain(String[] argv, ITestListener listener) { TestNG result = new TestNG(); if (null != listener) { result.addListener(listener); } // // Parse the arguments // try { CommandLineArgs cla = new CommandLineArgs(); m_jCommander = new JCommander(cla, argv); validateCommandLineParameters(cla); result.configure(cla); } catch(ParameterException ex) { exitWithError(ex.getMessage()); } // // Run // try { result.run(); } catch(TestNGException ex) { if (TestRunner.getVerbose() > 1) { ex.printStackTrace(System.out); } else { error(ex.getMessage()); } result.setStatus(HAS_FAILURE); } return result; } /** * Configure the TestNG instance based on the command line parameters. */ protected void configure(CommandLineArgs cla) { if (cla.verbose != null) { setVerbose(cla.verbose); } setOutputDirectory(cla.outputDirectory); String testClasses = cla.testClass; if (null != testClasses) { String[] strClasses = testClasses.split(","); List classes = Lists.newArrayList(); for (String c : strClasses) { classes.add(ClassHelper.fileToClass(c)); } setTestClasses(classes.toArray(new Class[classes.size()])); } setOutputDirectory(cla.outputDirectory); if (cla.testNames != null) { setTestNames(Arrays.asList(cla.testNames.split(","))); } // List testNgXml = (List) cmdLineArgs.get(CommandLineArgs.SUITE_DEF); // if (null != testNgXml) { // setTestSuites(testNgXml); // } // Note: can't use a Boolean field here because we are allowing a boolean // parameter with an arity of 1 ("-usedefaultlisteners false") if (cla.useDefaultListeners != null) { setUseDefaultListeners("true".equalsIgnoreCase(cla.useDefaultListeners)); } setGroups(cla.groups); setExcludedGroups(cla.excludedGroups); setTestJar(cla.testJar); setXmlPathInJar(cla.xmlPathInJar); setJUnit(cla.junit); setMixed(cla.mixed); setMaster(cla.master); setSlave(cla.slave); setSkipFailedInvocationCounts(cla.skipFailedInvocationCounts); if (cla.parallelMode != null) { setParallel(cla.parallelMode); } if (cla.configFailurePolicy != null) { setConfigFailurePolicy(cla.configFailurePolicy); } if (cla.threadCount != null) { setThreadCount(cla.threadCount); } if (cla.dataProviderThreadCount != null) { setDataProviderThreadCount(cla.dataProviderThreadCount); } if (cla.suiteName != null) { setDefaultSuiteName(cla.suiteName); } if (cla.testName != null) { setDefaultTestName(cla.testName); } if (cla.listener != null) { String sep = ";"; if (cla.listener.contains(",")) { sep = ","; } String[] strs = Utils.split(cla.listener, sep); List classes = Lists.newArrayList(); for (String cls : strs) { classes.add(ClassHelper.fileToClass(cls)); } setListenerClasses(classes); } if (null != cla.methodSelectors) { String[] strs = Utils.split(cla.methodSelectors, ","); for (String cls : strs) { String[] sel = Utils.split(cls, ":"); try { if (sel.length == 2) { addMethodSelector(sel[0], Integer.valueOf(sel[1])); } else { error("Method selector value was not in the format org.example.Selector:4"); } } catch (NumberFormatException nfe) { error("Method selector value was not in the format org.example.Selector:4"); } } } if (cla.objectFactory != null) { setObjectFactory(ClassHelper.fileToClass(cla.objectFactory)); } if (cla.testRunnerFactory != null) { setTestRunnerFactoryClass( ClassHelper.fileToClass(cla.testRunnerFactory)); } if (cla.reporter != null) { ReporterConfig reporterConfig = ReporterConfig.deserialize(cla.reporter); addReporter(reporterConfig); } if (cla.commandLineMethods.size() > 0) { m_commandLineMethods = cla.commandLineMethods; } if (cla.suiteFiles != null) { setTestSuites(cla.suiteFiles); } setSuiteThreadPoolSize(cla.suiteThreadPoolSize); setRandomizeSuites(cla.randomizeSuites); } public void setSuiteThreadPoolSize(Integer suiteThreadPoolSize) { m_suiteThreadPoolSize = suiteThreadPoolSize; } public Integer getSuiteThreadPoolSize() { return m_suiteThreadPoolSize; } public void setRandomizeSuites(boolean randomizeSuites) { m_randomizeSuites = randomizeSuites; } /** * This method is invoked by Maven's Surefire, only remove it once * Surefire has been modified to no longer call it. */ public void setSourcePath(String path) { // nop } /** * This method is invoked by Maven's Surefire to configure the runner, * do not remove unless you know for sure that Surefire has been updated * to use the new configure(CommandLineArgs) method. * * @deprecated use new configure(CommandLineArgs) method */ @SuppressWarnings({"unchecked"}) @Deprecated public void configure(Map cmdLineArgs) { CommandLineArgs result = new CommandLineArgs(); Integer verbose = (Integer) cmdLineArgs.get(CommandLineArgs.LOG); if (null != verbose) { result.verbose = verbose; } result.outputDirectory = (String) cmdLineArgs.get(CommandLineArgs.OUTPUT_DIRECTORY); String testClasses = (String) cmdLineArgs.get(CommandLineArgs.TEST_CLASS); if (null != testClasses) { result.testClass = testClasses; } String testNames = (String) cmdLineArgs.get(CommandLineArgs.TEST_NAMES); if (testNames != null) { result.testNames = testNames; } String useDefaultListeners = (String) cmdLineArgs.get(CommandLineArgs.USE_DEFAULT_LISTENERS); if (null != useDefaultListeners) { result.useDefaultListeners = useDefaultListeners; } result.groups = (String) cmdLineArgs.get(CommandLineArgs.GROUPS); result.excludedGroups = (String) cmdLineArgs.get(CommandLineArgs.EXCLUDED_GROUPS); result.testJar = (String) cmdLineArgs.get(CommandLineArgs.TEST_JAR); result.xmlPathInJar = (String) cmdLineArgs.get(CommandLineArgs.XML_PATH_IN_JAR); result.junit = (Boolean) cmdLineArgs.get(CommandLineArgs.JUNIT); result.mixed = (Boolean) cmdLineArgs.get(CommandLineArgs.MIXED); result.master = (String) cmdLineArgs.get(CommandLineArgs.MASTER); result.slave = (String) cmdLineArgs.get(CommandLineArgs.SLAVE); result.skipFailedInvocationCounts = (Boolean) cmdLineArgs.get( CommandLineArgs.SKIP_FAILED_INVOCATION_COUNTS); String parallelMode = (String) cmdLineArgs.get(CommandLineArgs.PARALLEL); if (parallelMode != null) { result.parallelMode = parallelMode; } String threadCount = (String) cmdLineArgs.get(CommandLineArgs.THREAD_COUNT); if (threadCount != null) { result.threadCount = Integer.parseInt(threadCount); } // Not supported by Surefire yet Integer dptc = (Integer) cmdLineArgs.get(CommandLineArgs.DATA_PROVIDER_THREAD_COUNT); if (dptc != null) { result.dataProviderThreadCount = dptc; } String defaultSuiteName = (String) cmdLineArgs.get(CommandLineArgs.SUITE_NAME); if (defaultSuiteName != null) { result.suiteName = defaultSuiteName; } String defaultTestName = (String) cmdLineArgs.get(CommandLineArgs.TEST_NAME); if (defaultTestName != null) { result.testName = defaultTestName; } Object listeners = cmdLineArgs.get(CommandLineArgs.LISTENER); if (listeners instanceof List) { result.listener = Utils.join((List) listeners, ","); } else { result.listener = (String) listeners; } String ms = (String) cmdLineArgs.get(CommandLineArgs.METHOD_SELECTORS); if (null != ms) { result.methodSelectors = ms; } String objectFactory = (String) cmdLineArgs.get(CommandLineArgs.OBJECT_FACTORY); if(null != objectFactory) { result.objectFactory = objectFactory; } String runnerFactory = (String) cmdLineArgs.get(CommandLineArgs.TEST_RUNNER_FACTORY); if (null != runnerFactory) { result.testRunnerFactory = runnerFactory; } String reporterConfigs = (String) cmdLineArgs.get(CommandLineArgs.REPORTER); if (reporterConfigs != null) { result.reporter = reporterConfigs; } String failurePolicy = (String)cmdLineArgs.get(CommandLineArgs.CONFIG_FAILURE_POLICY); if (failurePolicy != null) { result.configFailurePolicy = failurePolicy; } configure(result); } /** * Only run the specified tests from the suite. */ public void setTestNames(List testNames) { m_testNames = testNames; } public void setSkipFailedInvocationCounts(Boolean skip) { m_skipFailedInvocationCounts = skip; } private void addReporter(ReporterConfig reporterConfig) { Object instance = reporterConfig.newReporterInstance(); if (instance != null) { addListener(instance); } else { LOGGER.warn("Could not find reporte class : " + reporterConfig.getClassName()); } } /** * Specify if this run should be in Master-Slave mode as Master * * @param fileName remote.properties path */ public void setMaster(String fileName) { m_masterfileName = fileName; } /** * Specify if this run should be in Master-Slave mode as slave * * @param fileName remote.properties path */ public void setSlave(String fileName) { m_slavefileName = fileName; } /** * Specify if this run should be made in JUnit mode * * @param isJUnit */ public void setJUnit(Boolean isJUnit) { m_isJUnit = isJUnit; } /** * Specify if this run should be made in mixed mode */ public void setMixed(Boolean isMixed) { if(isMixed==null){ return; } m_isMixed = isMixed; } /** * @deprecated The TestNG version is now established at load time. This * method is not required anymore and is now a no-op. */ @Deprecated public static void setTestNGVersion() { LOGGER.info("setTestNGVersion has been deprecated."); } /** * Returns true if this is the JDK 1.4 JAR version of TestNG, false otherwise. * * @return true if this is the JDK 1.4 JAR version of TestNG, false otherwise. */ @Deprecated public static boolean isJdk14() { return false; } /** * Double check that the command line parameters are valid. */ protected static void validateCommandLineParameters(CommandLineArgs args) { String testClasses = args.testClass; List testNgXml = args.suiteFiles; String testJar = args.testJar; String slave = args.slave; List methods = args.commandLineMethods; if (testClasses == null && slave == null && testJar == null && (testNgXml == null || testNgXml.isEmpty()) && (methods == null || methods.isEmpty())) { throw new ParameterException("You need to specify at least one testng.xml, one class" + " or one method"); } String groups = args.groups; String excludedGroups = args.excludedGroups; if (testJar == null && (null != groups || null != excludedGroups) && testClasses == null && (testNgXml == null || testNgXml.isEmpty())) { throw new ParameterException("Groups option should be used with testclass option"); } if (args.slave != null && args.master != null) { throw new ParameterException(CommandLineArgs.SLAVE + " can't be combined with " + CommandLineArgs.MASTER); } Boolean junit = args.junit; Boolean mixed = args.mixed; if (junit && mixed) { throw new ParameterException(CommandLineArgs.MIXED + " can't be combined with " + CommandLineArgs.JUNIT); } } /** * @return true if at least one test failed. */ public boolean hasFailure() { return (getStatus() & HAS_FAILURE) == HAS_FAILURE; } /** * @return true if at least one test failed within success percentage. */ public boolean hasFailureWithinSuccessPercentage() { return (getStatus() & HAS_FSP) == HAS_FSP; } /** * @return true if at least one test was skipped. */ public boolean hasSkip() { return (getStatus() & HAS_SKIPPED) == HAS_SKIPPED; } static void exitWithError(String msg) { System.err.println(msg); usage(); System.exit(1); } public String getOutputDirectory() { return m_outputDir; } public IAnnotationTransformer getAnnotationTransformer() { return m_annotationTransformer; } public void setAnnotationTransformer(IAnnotationTransformer t) { // compare by reference! if (m_annotationTransformer != m_defaultAnnoProcessor && m_annotationTransformer != t) { LOGGER.warn("AnnotationTransformer already set"); } m_annotationTransformer = t; } /** * @return the defaultSuiteName */ public String getDefaultSuiteName() { return m_defaultSuiteName; } /** * @param defaultSuiteName the defaultSuiteName to set */ public void setDefaultSuiteName(String defaultSuiteName) { m_defaultSuiteName = defaultSuiteName; } /** * @return the defaultTestName */ public String getDefaultTestName() { return m_defaultTestName; } /** * @param defaultTestName the defaultTestName to set */ public void setDefaultTestName(String defaultTestName) { m_defaultTestName = defaultTestName; } /** * Sets the policy for whether or not to ever invoke a configuration method again after * it has failed once. Possible values are defined in {@link XmlSuite}. The default * value is {@link XmlSuite#SKIP}. * @param failurePolicy the configuration failure policy */ public void setConfigFailurePolicy(String failurePolicy) { m_configFailurePolicy = failurePolicy; } /** * Returns the configuration failure policy. * @return config failure policy */ public String getConfigFailurePolicy() { return m_configFailurePolicy; } // DEPRECATED: to be removed after a major version change /** * @deprecated since 5.1 */ @Deprecated public static TestNG getDefault() { return m_instance; } /** * @deprecated since 5.1 */ @Deprecated public void setHasFailure(boolean hasFailure) { m_status |= HAS_FAILURE; } /** * @deprecated since 5.1 */ @Deprecated public void setHasFailureWithinSuccessPercentage(boolean hasFailureWithinSuccessPercentage) { m_status |= HAS_FSP; } /** * @deprecated since 5.1 */ @Deprecated public void setHasSkip(boolean hasSkip) { m_status |= HAS_SKIPPED; } public static class ExitCodeListener implements IResultListener2 { private TestNG m_mainRunner; public ExitCodeListener() { m_mainRunner = TestNG.m_instance; } public ExitCodeListener(TestNG runner) { m_mainRunner = runner; } @Override public void beforeConfiguration(ITestResult tr) { } @Override public void onTestFailure(ITestResult result) { setHasRunTests(); m_mainRunner.setStatus(HAS_FAILURE); } @Override public void onTestSkipped(ITestResult result) { setHasRunTests(); if ((m_mainRunner.getStatus() & HAS_FAILURE) != 0) { m_mainRunner.setStatus(HAS_SKIPPED); } } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult result) { setHasRunTests(); m_mainRunner.setStatus(HAS_FSP); } @Override public void onTestSuccess(ITestResult result) { setHasRunTests(); } @Override public void onStart(ITestContext context) { setHasRunTests(); } @Override public void onFinish(ITestContext context) { } @Override public void onTestStart(ITestResult result) { setHasRunTests(); } private void setHasRunTests() { m_mainRunner.m_hasTests= true; } /** * @see org.testng.IConfigurationListener#onConfigurationFailure(org.testng.ITestResult) */ @Override public void onConfigurationFailure(ITestResult itr) { m_mainRunner.setStatus(HAS_FAILURE); } /** * @see org.testng.IConfigurationListener#onConfigurationSkip(org.testng.ITestResult) */ @Override public void onConfigurationSkip(ITestResult itr) { m_mainRunner.setStatus(HAS_SKIPPED); } /** * @see org.testng.IConfigurationListener#onConfigurationSuccess(org.testng.ITestResult) */ @Override public void onConfigurationSuccess(ITestResult itr) { } } private void setConfigurable(IConfigurable c) { // compare by reference! if (m_configurable != null && m_configurable != c) { LOGGER.warn("Configurable already set"); } m_configurable = c; } private void setHookable(IHookable h) { // compare by reference! if (m_hookable != null && m_hookable != h) { LOGGER.warn("Hookable already set"); } m_hookable = h; } public void setMethodInterceptor(IMethodInterceptor methodInterceptor) { m_methodInterceptors.add(methodInterceptor); } public void setDataProviderThreadCount(int count) { m_dataProviderThreadCount = count; } /** Add a class loader to the searchable loaders. */ public void addClassLoader(final ClassLoader loader) { if (loader != null) { ClassHelper.addClassLoader(loader); } } public void setPreserveOrder(boolean b) { m_preserveOrder = b; } protected long getStart() { return m_start; } protected long getEnd() { return m_end; } public void setGroupByInstances(boolean b) { m_groupByInstances = b; } ///// // ServiceLoader testing // private URLClassLoader m_serviceLoaderClassLoader; private List m_serviceLoaderListeners = Lists.newArrayList(); /* * Used to test ServiceClassLoader */ public void setServiceLoaderClassLoader(URLClassLoader ucl) { m_serviceLoaderClassLoader = ucl; } /* * Used to test ServiceClassLoader */ private void addServiceLoaderListener(ITestNGListener l) { m_serviceLoaderListeners.add(l); } /* * Used to test ServiceClassLoader */ public List getServiceLoaderListeners() { return m_serviceLoaderListeners; } // // ServiceLoader testing ///// } testng-testng-6.9.5/src/main/java/org/testng/TestListenerAdapter.java0000755000175000017500000001263612551235562025204 0ustar eugeneeugenepackage org.testng; import org.testng.collections.Lists; import org.testng.collections.Objects; import org.testng.internal.IResultListener2; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * A simple ITestListener adapter that stores all the tests * that were run. You can retrieve these results with the * following methods: * getPassedTests() * getFailedTests() * getSkippedTests() * * If you extend this class in order to override any of these * methods, remember to call their super equivalent if you want * this list of tests to be maintained. * * @author Cedric Beust, Aug 6, 2004 * @author Alexandru Popescu */ public class TestListenerAdapter implements IResultListener2 { private List m_allTestMethods = Collections.synchronizedList(Lists.newArrayList()); private List m_passedTests = Collections.synchronizedList(Lists.newArrayList()); private List m_failedTests = Collections.synchronizedList(Lists.newArrayList()); private List m_skippedTests = Collections.synchronizedList(Lists.newArrayList()); private List m_failedButWSPerTests = Collections.synchronizedList(Lists.newArrayList()); private List m_testContexts= Collections.synchronizedList(new ArrayList()); private List m_failedConfs= Collections.synchronizedList(Lists.newArrayList()); private List m_skippedConfs= Collections.synchronizedList(Lists.newArrayList()); private List m_passedConfs= Collections.synchronizedList(Lists.newArrayList()); @Override public void onTestSuccess(ITestResult tr) { m_allTestMethods.add(tr.getMethod()); m_passedTests.add(tr); } @Override public void onTestFailure(ITestResult tr) { m_allTestMethods.add(tr.getMethod()); m_failedTests.add(tr); } @Override public void onTestSkipped(ITestResult tr) { m_allTestMethods.add(tr.getMethod()); m_skippedTests.add(tr); } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult tr) { m_allTestMethods.add(tr.getMethod()); m_failedButWSPerTests.add(tr); } protected ITestNGMethod[] getAllTestMethods() { return m_allTestMethods.toArray(new ITestNGMethod[m_allTestMethods.size()]); } @Override public void onStart(ITestContext testContext) { m_testContexts.add(testContext); } @Override public void onFinish(ITestContext testContext) { } /** * @return Returns the failedButWithinSuccessPercentageTests. */ public List getFailedButWithinSuccessPercentageTests() { return m_failedButWSPerTests; } /** * @return Returns the failedTests. */ public List getFailedTests() { return m_failedTests; } /** * @return Returns the passedTests. */ public List getPassedTests() { return m_passedTests; } /** * @return Returns the skippedTests. */ public List getSkippedTests() { return m_skippedTests; } private static void ppp(String s) { System.out.println("[TestListenerAdapter] " + s); } /** * @param allTestMethods The allTestMethods to set. */ public void setAllTestMethods(List allTestMethods) { m_allTestMethods = allTestMethods; } /** * @param failedButWithinSuccessPercentageTests The failedButWithinSuccessPercentageTests to set. */ public void setFailedButWithinSuccessPercentageTests( List failedButWithinSuccessPercentageTests) { m_failedButWSPerTests = failedButWithinSuccessPercentageTests; } /** * @param failedTests The failedTests to set. */ public void setFailedTests(List failedTests) { m_failedTests = failedTests; } /** * @param passedTests The passedTests to set. */ public void setPassedTests(List passedTests) { m_passedTests = passedTests; } /** * @param skippedTests The skippedTests to set. */ public void setSkippedTests(List skippedTests) { m_skippedTests = skippedTests; } @Override public void onTestStart(ITestResult result) { } public List getTestContexts() { return m_testContexts; } public List getConfigurationFailures() { return m_failedConfs; } /** * @see org.testng.IConfigurationListener#onConfigurationFailure(org.testng.ITestResult) */ @Override public void onConfigurationFailure(ITestResult itr) { m_failedConfs.add(itr); } public List getConfigurationSkips() { return m_skippedConfs; } @Override public void beforeConfiguration(ITestResult tr) { } /** * @see org.testng.IConfigurationListener#onConfigurationSkip(org.testng.ITestResult) */ @Override public void onConfigurationSkip(ITestResult itr) { m_skippedConfs.add(itr); } /** * @see org.testng.IConfigurationListener#onConfigurationSuccess(org.testng.ITestResult) */ @Override public void onConfigurationSuccess(ITestResult itr) { m_passedConfs.add(itr); } @Override public String toString() { return Objects.toStringHelper(getClass()) .add("passed", getPassedTests().size()) .add("failed", getFailedTests().size()) .add("skipped", getSkippedTests().size()) .toString(); } } testng-testng-6.9.5/src/main/java/org/testng/TestException.java0000755000175000017500000000073012551235562024044 0ustar eugeneeugenepackage org.testng; /** * Exception thrown when an exception happens while running a test * method. * * @author Cedric Beust, Apr 26, 2004 * */ public class TestException extends TestNGException { private static final long serialVersionUID = -7946644025188038804L; public TestException(String s) { super(s); } public TestException(Throwable t) { super(t); } public TestException(String message, Throwable t) { super(message, t); } } testng-testng-6.9.5/src/main/java/org/testng/TestClass.java0000755000175000017500000002113412551235562023154 0ustar eugeneeugenepackage org.testng; import org.testng.collections.Lists; import org.testng.collections.Objects; import org.testng.internal.ConfigurationMethod; import org.testng.internal.NoOpTestClass; import org.testng.internal.RunInfo; import org.testng.internal.TestNGMethod; import org.testng.internal.Utils; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.xml.XmlClass; import org.testng.xml.XmlTest; import java.lang.reflect.Method; import java.util.List; /** * This class represents a test class: * - The test methods * - The configuration methods (test and method) * - The class file * * @author Cedric Beust * @author Alexandru Popescu */ class TestClass extends NoOpTestClass implements ITestClass { /* generated */ private static final long serialVersionUID = -8077917128278361294L; transient private IAnnotationFinder m_annotationFinder = null; // The Strategy used to locate test methods (TestNG, JUnit, etc...) transient private ITestMethodFinder m_testMethodFinder = null; private IClass m_iClass = null; private RunInfo m_runInfo = null; private String m_testName; private XmlTest m_xmlTest; private XmlClass m_xmlClass; protected TestClass(IClass cls, ITestMethodFinder testMethodFinder, IAnnotationFinder annotationFinder, RunInfo runInfo, XmlTest xmlTest, XmlClass xmlClass) { init(cls, testMethodFinder, annotationFinder, runInfo, xmlTest, xmlClass); } /** * @return the name of this test if the class implements org.testng.ITest, null otherwise. */ @Override public String getTestName() { return m_testName; } @Override public XmlTest getXmlTest() { return m_xmlTest; } @Override public XmlClass getXmlClass() { return m_xmlClass; } public IAnnotationFinder getAnnotationFinder() { return m_annotationFinder; } private void init(IClass cls, ITestMethodFinder testMethodFinder, IAnnotationFinder annotationFinder, RunInfo runInfo, XmlTest xmlTest, XmlClass xmlClass) { log(3, "Creating TestClass for " + cls); m_iClass = cls; m_testClass = cls.getRealClass(); m_xmlTest = xmlTest; m_xmlClass = xmlClass; m_runInfo = runInfo; m_testMethodFinder = testMethodFinder; m_annotationFinder = annotationFinder; initTestClassesAndInstances(); initMethods(); } private void initTestClassesAndInstances() { // // TestClasses and instances // Object[] instances = getInstances(false); for (Object instance : instances) { if (instance instanceof ITest) { m_testName = ((ITest) instance).getTestName(); break; } } } @Override public Object[] getInstances(boolean create) { return m_iClass.getInstances(create); } @Override public long[] getInstanceHashCodes() { return m_iClass.getInstanceHashCodes(); } @Override public int getInstanceCount() { return m_iClass.getInstanceCount(); } @Override public void addInstance(Object instance) { m_iClass.addInstance(instance); } private void initMethods() { ITestNGMethod[] methods = m_testMethodFinder.getTestMethods(m_testClass, m_xmlTest); m_testMethods = createTestMethods(methods); for (Object instance : m_iClass.getInstances(false)) { m_beforeSuiteMethods = ConfigurationMethod .createSuiteConfigurationMethods(m_testMethodFinder.getBeforeSuiteMethods(m_testClass), m_annotationFinder, true, instance); m_afterSuiteMethods = ConfigurationMethod .createSuiteConfigurationMethods(m_testMethodFinder.getAfterSuiteMethods(m_testClass), m_annotationFinder, false, instance); m_beforeTestConfMethods = ConfigurationMethod .createTestConfigurationMethods(m_testMethodFinder.getBeforeTestConfigurationMethods(m_testClass), m_annotationFinder, true, instance); m_afterTestConfMethods = ConfigurationMethod .createTestConfigurationMethods(m_testMethodFinder.getAfterTestConfigurationMethods(m_testClass), m_annotationFinder, false, instance); m_beforeClassMethods = ConfigurationMethod .createClassConfigurationMethods(m_testMethodFinder.getBeforeClassMethods(m_testClass), m_annotationFinder, true, instance); m_afterClassMethods = ConfigurationMethod .createClassConfigurationMethods(m_testMethodFinder.getAfterClassMethods(m_testClass), m_annotationFinder, false, instance); m_beforeGroupsMethods = ConfigurationMethod .createBeforeConfigurationMethods(m_testMethodFinder.getBeforeGroupsConfigurationMethods(m_testClass), m_annotationFinder, true, instance); m_afterGroupsMethods = ConfigurationMethod .createAfterConfigurationMethods(m_testMethodFinder.getAfterGroupsConfigurationMethods(m_testClass), m_annotationFinder, false, instance); m_beforeTestMethods = ConfigurationMethod .createTestMethodConfigurationMethods(m_testMethodFinder.getBeforeTestMethods(m_testClass), m_annotationFinder, true, instance); m_afterTestMethods = ConfigurationMethod .createTestMethodConfigurationMethods(m_testMethodFinder.getAfterTestMethods(m_testClass), m_annotationFinder, false, instance); } } /** * Create the test methods that belong to this class (rejects * all those that belong to a different class). */ private ITestNGMethod[] createTestMethods(ITestNGMethod[] methods) { List vResult = Lists.newArrayList(); for (ITestNGMethod tm : methods) { Method m = tm.getMethod(); if (m.getDeclaringClass().isAssignableFrom(m_testClass)) { for (Object o : m_iClass.getInstances(false)) { log(4, "Adding method " + tm + " on TestClass " + m_testClass); vResult.add(new TestNGMethod(/* tm.getRealClass(), */ m, m_annotationFinder, m_xmlTest, o)); } } else { log(4, "Rejecting method " + tm + " for TestClass " + m_testClass); } } ITestNGMethod[] result = vResult.toArray(new ITestNGMethod[vResult.size()]); return result; } private RunInfo getRunInfo() { return m_runInfo; } public ITestMethodFinder getTestMethodFinder() { return m_testMethodFinder; } private void log(int level, String s) { Utils.log("TestClass", level, s); } private static void ppp(String s) { System.out.println("[TestClass] " + s); } protected void dump() { System.out.println("===== Test class\n" + m_testClass.getName()); for (ITestNGMethod m : m_beforeClassMethods) { System.out.println(" @BeforeClass " + m); } for (ITestNGMethod m : m_beforeTestMethods) { System.out.println(" @BeforeMethod " + m); } for (ITestNGMethod m : m_testMethods) { System.out.println(" @Test " + m); } for (ITestNGMethod m : m_afterTestMethods) { System.out.println(" @AfterMethod " + m); } for (ITestNGMethod m : m_afterClassMethods) { System.out.println(" @AfterClass " + m); } System.out.println("======"); } @Override public String toString() { return Objects.toStringHelper(getClass()) .add("name", m_testClass) .toString(); } public IClass getIClass() { return m_iClass; } }testng-testng-6.9.5/src/main/java/org/testng/SuiteRunnerWorker.java0000644000175000017500000001142412551235562024722 0ustar eugeneeugenepackage org.testng; import org.testng.collections.Lists; import org.testng.collections.Objects; import org.testng.internal.SuiteRunnerMap; import org.testng.internal.Utils; import org.testng.internal.thread.graph.IWorker; import org.testng.xml.XmlSuite; import java.util.Collection; import java.util.List; import java.util.Map; /** * An {@code IWorker} that is used to encapsulate and run Suite Runners * * @author cbeust, nullin */ public class SuiteRunnerWorker implements IWorker { private SuiteRunner m_suiteRunner; private Integer m_verbose; private String m_defaultSuiteName; private SuiteRunnerMap m_suiteRunnerMap; public SuiteRunnerWorker(ISuite suiteRunner, SuiteRunnerMap suiteRunnerMap, int verbose, String defaultSuiteName) { m_suiteRunnerMap = suiteRunnerMap; m_suiteRunner = (SuiteRunner) suiteRunner; m_verbose = verbose; m_defaultSuiteName = defaultSuiteName; } /** * Runs a suite * @param suiteRunnerMap map of suiteRunners that are updated with test results * @param xmlSuite XML suites to run */ private void runSuite(SuiteRunnerMap suiteRunnerMap /* OUT */, XmlSuite xmlSuite) { if (m_verbose > 0) { StringBuffer allFiles = new StringBuffer(); allFiles.append(" ").append(xmlSuite.getFileName() != null ? xmlSuite.getFileName() : m_defaultSuiteName).append('\n'); Utils.log("TestNG", 0, "Running:\n" + allFiles.toString()); } SuiteRunner suiteRunner = (SuiteRunner) suiteRunnerMap.get(xmlSuite); suiteRunner.run(); //TODO: this should be handled properly // for (IReporter r : suiteRunner.getReporters()) { // addListener(r); // } // PoolService.getInstance().shutdown(); // // Display the final statistics // if (xmlSuite.getVerbose() > 0) { SuiteResultCounts counts = new SuiteResultCounts(); synchronized (suiteRunnerMap) { counts.calculateResultCounts(xmlSuite, suiteRunnerMap); } StringBuffer bufLog = new StringBuffer("\n===============================================\n") .append(xmlSuite.getName()); bufLog.append("\nTotal tests run: ") .append(counts.m_total).append(", Failures: ").append(counts.m_failed) .append(", Skips: ").append(counts.m_skipped); if(counts.m_confFailures > 0 || counts.m_confSkips > 0) { bufLog.append("\nConfiguration Failures: ").append(counts.m_confFailures) .append(", Skips: ").append(counts.m_confSkips); } bufLog.append("\n===============================================\n"); System.out.println(bufLog.toString()); } } @Override public void run() { runSuite(m_suiteRunnerMap, m_suiteRunner.getXmlSuite()); } @Override public int compareTo(IWorker arg0) { /* * Dummy Implementation * * Used by IWorkers to prioritize execution in parallel. Not required by * this Worker in current implementation */ return 0; } @Override public List getTasks() { List suiteRunnerList = Lists.newArrayList(); suiteRunnerList.add(m_suiteRunner); return suiteRunnerList; } @Override public String toString() { return Objects.toStringHelper(getClass()) .add("name", m_suiteRunner.getName()) .toString(); } @Override public long getTimeOut() { return m_suiteRunner.getXmlSuite().getTimeOut(Long.MAX_VALUE); } @Override public int getPriority() { // this class doesnt support priorities yet return 0; } } /** * Class to help calculate result counts for tests run as part of a suite and * its children suites * * @author nullin * */ class SuiteResultCounts { int m_total = 0; int m_skipped = 0; int m_failed = 0; int m_confFailures = 0; int m_confSkips = 0; public void calculateResultCounts(XmlSuite xmlSuite, SuiteRunnerMap suiteRunnerMap) { ISuite iSuite = suiteRunnerMap.get(xmlSuite); if (iSuite != null) { Map results = iSuite.getResults(); if (results != null) { Collection tempSuiteResult = results.values(); for (ISuiteResult isr : tempSuiteResult) { ITestContext ctx = isr.getTestContext(); int skipped = ctx.getSkippedTests().size(); int failed = ctx.getFailedTests().size() + ctx.getFailedButWithinSuccessPercentageTests().size(); m_skipped += skipped; m_failed += failed; m_confFailures += ctx.getFailedConfigurations().size(); m_confSkips += ctx.getSkippedConfigurations().size(); m_total += ctx.getPassedTests().size() + failed + skipped; } for (XmlSuite childSuite : xmlSuite.getChildSuites()) { calculateResultCounts(childSuite, suiteRunnerMap); } } } } } testng-testng-6.9.5/src/main/java/org/testng/SuiteRunner.java0000644000175000017500000004711512551235562023536 0ustar eugeneeugenepackage org.testng; import static org.testng.internal.Utils.isStringBlank; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.internal.Attributes; import org.testng.internal.IConfiguration; import org.testng.internal.IInvoker; import org.testng.internal.Utils; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.internal.thread.ThreadUtil; import org.testng.reporters.JUnitXMLReporter; import org.testng.reporters.TestHTMLReporter; import org.testng.reporters.TextReporter; import org.testng.xml.XmlSuite; import org.testng.xml.XmlTest; import java.io.File; import java.io.Serializable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import com.google.inject.Injector; /** * SuiteRunner is responsible for running all the tests included in one * suite. The test start is triggered by {@link #run()} method. * * @author Cedric Beust, Apr 26, 2004 */ public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener { /* generated */ private static final long serialVersionUID = 5284208932089503131L; private static final String DEFAULT_OUTPUT_DIR = "test-output"; private Map m_suiteResults = Collections.synchronizedMap(Maps.newLinkedHashMap()); transient private List m_testRunners = Lists.newArrayList(); transient private List m_listeners = Lists.newArrayList(); transient private TestListenerAdapter m_textReporter = new TestListenerAdapter(); private String m_outputDir; // DEFAULT_OUTPUT_DIR; private XmlSuite m_suite; private Injector m_parentInjector; transient private List m_testListeners = Lists.newArrayList(); transient private ITestRunnerFactory m_tmpRunnerFactory; transient private ITestRunnerFactory m_runnerFactory; transient private boolean m_useDefaultListeners = true; // The remote host where this suite was run, or null if run locally private String m_host; // The configuration transient private IConfiguration m_configuration; transient private ITestObjectFactory m_objectFactory; transient private Boolean m_skipFailedInvocationCounts = Boolean.FALSE; transient private List m_methodInterceptors; private List m_invokedMethodListeners; /** The list of all the methods invoked during this run */ private List m_invokedMethods = Collections.synchronizedList(Lists.newArrayList()); private List m_allTestMethods = Lists.newArrayList(); // transient private IAnnotationTransformer m_annotationTransformer = null; public SuiteRunner(IConfiguration configuration, XmlSuite suite, String outputDir) { this(configuration, suite, outputDir, null); } public SuiteRunner(IConfiguration configuration, XmlSuite suite, String outputDir, ITestRunnerFactory runnerFactory) { this(configuration, suite, outputDir, runnerFactory, false); } public SuiteRunner(IConfiguration configuration, XmlSuite suite, String outputDir, ITestRunnerFactory runnerFactory, boolean useDefaultListeners) { this(configuration, suite, outputDir, runnerFactory, useDefaultListeners, new ArrayList() /* method interceptor */, null /* invoked method listeners */, null /* test listeners */); } protected SuiteRunner(IConfiguration configuration, XmlSuite suite, String outputDir, ITestRunnerFactory runnerFactory, boolean useDefaultListeners, List methodInterceptors, List invokedMethodListeners, List testListeners) { init(configuration, suite, outputDir, runnerFactory, useDefaultListeners, methodInterceptors, invokedMethodListeners, testListeners); } private void init(IConfiguration configuration, XmlSuite suite, String outputDir, ITestRunnerFactory runnerFactory, boolean useDefaultListeners, List methodInterceptors, List invokedMethodListener, List testListeners) { m_configuration = configuration; m_suite = suite; m_useDefaultListeners = useDefaultListeners; m_tmpRunnerFactory= runnerFactory; m_methodInterceptors = methodInterceptors != null ? methodInterceptors : new ArrayList(); setOutputDir(outputDir); m_objectFactory = m_configuration.getObjectFactory(); if(m_objectFactory == null) { m_objectFactory = suite.getObjectFactory(); } m_invokedMethodListeners = invokedMethodListener; // Add our own IInvokedMethodListener if (m_invokedMethodListeners == null) { m_invokedMethodListeners = Lists.newArrayList(); } m_invokedMethodListeners.add(this); m_skipFailedInvocationCounts = suite.skipFailedInvocationCounts(); if (null != testListeners) { m_testListeners.addAll(testListeners); } m_runnerFactory = buildRunnerFactory(); // Order the tags based on their order of appearance in testng.xml List xmlTests = m_suite.getTests(); Collections.sort(xmlTests, new Comparator() { @Override public int compare(XmlTest arg0, XmlTest arg1) { return arg0.getIndex() - arg1.getIndex(); } }); for (XmlTest test : xmlTests) { TestRunner tr = m_runnerFactory.newTestRunner(this, test, m_invokedMethodListeners); // // Install the method interceptor, if any was passed // for (IMethodInterceptor methodInterceptor : m_methodInterceptors) { tr.addMethodInterceptor(methodInterceptor); } // Reuse the same text reporter so we can accumulate all the results // (this is used to display the final suite report at the end) tr.addListener(m_textReporter); m_testRunners.add(tr); // Add the methods found in this test to our global count m_allTestMethods.addAll(Arrays.asList(tr.getAllTestMethods())); } } @Override public XmlSuite getXmlSuite() { return m_suite; } @Override public String getName() { return m_suite.getName(); } public void setObjectFactory(ITestObjectFactory objectFactory) { m_objectFactory = objectFactory; } public void setReportResults(boolean reportResults) { m_useDefaultListeners = reportResults; } private void invokeListeners(boolean start) { for (ISuiteListener sl : m_listeners) { if (start) { sl.onStart(this); } else { sl.onFinish(this); } } } private void setOutputDir(String outputdir) { if (isStringBlank(outputdir) && m_useDefaultListeners) { outputdir = DEFAULT_OUTPUT_DIR; } m_outputDir = (null != outputdir) ? new File(outputdir).getAbsolutePath() : null; } private ITestRunnerFactory buildRunnerFactory() { ITestRunnerFactory factory = null; if (null == m_tmpRunnerFactory) { factory = new DefaultTestRunnerFactory(m_configuration, m_testListeners.toArray(new ITestListener[m_testListeners.size()]), m_useDefaultListeners, m_skipFailedInvocationCounts); } else { factory = new ProxyTestRunnerFactory( m_testListeners.toArray(new ITestListener[m_testListeners.size()]), m_tmpRunnerFactory); } return factory; } @Override public String getParallel() { return m_suite.getParallel(); } public String getParentModule() { return m_suite.getParentModule(); } @Override public String getGuiceStage() { return m_suite.getGuiceStage(); } public Injector getParentInjector() { return m_parentInjector; } public void setParentInjector(Injector injector) { m_parentInjector = injector; } @Override public void run() { invokeListeners(true /* start */); try { privateRun(); } finally { invokeListeners(false /* stop */); } } private void privateRun() { // Map for unicity, Linked for guaranteed order Map beforeSuiteMethods= new LinkedHashMap<>(); Map afterSuiteMethods = new LinkedHashMap<>(); IInvoker invoker = null; // Get the invoker and find all the suite level methods for (TestRunner tr: m_testRunners) { // TODO: Code smell. Invoker should belong to SuiteRunner, not TestRunner // -- cbeust invoker = tr.getInvoker(); for (ITestNGMethod m : tr.getBeforeSuiteMethods()) { beforeSuiteMethods.put(m.getMethod(), m); } for (ITestNGMethod m : tr.getAfterSuiteMethods()) { afterSuiteMethods.put(m.getMethod(), m); } } // // Invoke beforeSuite methods (the invoker can be null // if the suite we are currently running only contains // a tag and no real tests) // if (invoker != null) { if(beforeSuiteMethods.values().size() > 0) { invoker.invokeConfigurations(null, beforeSuiteMethods.values().toArray(new ITestNGMethod[beforeSuiteMethods.size()]), m_suite, m_suite.getParameters(), null, /* no parameter values */ null /* instance */ ); } Utils.log("SuiteRunner", 3, "Created " + m_testRunners.size() + " TestRunners"); // // Run all the test runners // boolean testsInParallel = XmlSuite.PARALLEL_TESTS.equals(m_suite.getParallel()); if (!testsInParallel) { runSequentially(); } else { runInParallelTestMode(); } // SuitePlan sp = new SuitePlan(); // for (TestRunner tr : m_testRunners) { // sp.addTestPlan(tr.getTestPlan()); // } // sp.dump(); // // Invoke afterSuite methods // if (afterSuiteMethods.values().size() > 0) { invoker.invokeConfigurations(null, afterSuiteMethods.values().toArray(new ITestNGMethod[afterSuiteMethods.size()]), m_suite, m_suite.getAllParameters(), null, /* no parameter values */ null /* instance */); } } } private List m_reporters = Lists.newArrayList(); private void addReporter(IReporter listener) { m_reporters.add(listener); } void addConfigurationListener(IConfigurationListener listener) { m_configuration.addConfigurationListener(listener); } public List getReporters() { return m_reporters; } private void runSequentially() { for (TestRunner tr : m_testRunners) { runTest(tr); } } private void runTest(TestRunner tr) { tr.run(); ISuiteResult sr = new SuiteResult(m_suite, tr); m_suiteResults.put(tr.getName(), sr); } /** * Implement . * Since this kind of parallelism happens at the suite level, we need a special code path * to execute it. All the other parallelism strategies are implemented at the test level * in TestRunner#createParallelWorkers (but since this method deals with just one * tag, it can't implement , which is why we're doing it here). */ private void runInParallelTestMode() { List tasks= Lists.newArrayList(m_testRunners.size()); for(TestRunner tr: m_testRunners) { tasks.add(new SuiteWorker(tr)); } ThreadUtil.execute(tasks, m_suite.getThreadCount(), m_suite.getTimeOut(XmlTest.DEFAULT_TIMEOUT_MS), false); } private class SuiteWorker implements Runnable { private TestRunner m_testRunner; public SuiteWorker(TestRunner tr) { m_testRunner = tr; } @Override public void run() { Utils.log("[SuiteWorker]", 4, "Running XML Test '" + m_testRunner.getTest().getName() + "' in Parallel"); runTest(m_testRunner); } } /** * Registers ISuiteListeners interested in reporting the result of the current * suite. * * @param reporter */ protected void addListener(ISuiteListener reporter) { m_listeners.add(reporter); } @Override public void addListener(ITestNGListener listener) { if (listener instanceof IInvokedMethodListener) { m_invokedMethodListeners.add((IInvokedMethodListener) listener); } if (listener instanceof ISuiteListener) { addListener((ISuiteListener) listener); } if (listener instanceof IReporter) { addReporter((IReporter) listener); } if (listener instanceof IConfigurationListener) { addConfigurationListener((IConfigurationListener) listener); } } @Override public String getOutputDirectory() { return m_outputDir + File.separatorChar + getName(); } @Override public Map getResults() { return m_suiteResults; } /** * FIXME: should be removed? * * @see org.testng.ISuite#getParameter(java.lang.String) */ @Override public String getParameter(String parameterName) { return m_suite.getParameter(parameterName); } /** * @see org.testng.ISuite#getMethodsByGroups() */ @Override public Map> getMethodsByGroups() { Map> result = Maps.newHashMap(); for (TestRunner tr : m_testRunners) { ITestNGMethod[] methods = tr.getAllTestMethods(); for (ITestNGMethod m : methods) { String[] groups = m.getGroups(); for (String groupName : groups) { Collection testMethods = result.get(groupName); if (null == testMethods) { testMethods = Lists.newArrayList(); result.put(groupName, testMethods); } testMethods.add(m); } } } return result; } /** * @see org.testng.ISuite#getInvokedMethods() */ @Override public Collection getInvokedMethods() { return getIncludedOrExcludedMethods(true /* included */); } /** * @see org.testng.ISuite#getExcludedMethods() */ @Override public Collection getExcludedMethods() { return getIncludedOrExcludedMethods(false/* included */); } private Collection getIncludedOrExcludedMethods(boolean included) { List result= Lists.newArrayList(); for (TestRunner tr : m_testRunners) { Collection methods = included ? tr.getInvokedMethods() : tr.getExcludedMethods(); for (ITestNGMethod m : methods) { result.add(m); } } return result; } @Override public IObjectFactory getObjectFactory() { return m_objectFactory instanceof IObjectFactory ? (IObjectFactory) m_objectFactory : null; } @Override public IObjectFactory2 getObjectFactory2() { return m_objectFactory instanceof IObjectFactory2 ? (IObjectFactory2) m_objectFactory : null; } /** * Returns the annotation finder for the given annotation type. * @return the annotation finder for the given annotation type. */ @Override public IAnnotationFinder getAnnotationFinder() { return m_configuration.getAnnotationFinder(); } public static void ppp(String s) { System.out.println("[SuiteRunner] " + s); } /** * The default implementation of {@link ITestRunnerFactory}. */ private static class DefaultTestRunnerFactory implements ITestRunnerFactory { private ITestListener[] m_failureGenerators; private boolean m_useDefaultListeners; private boolean m_skipFailedInvocationCounts; private IConfiguration m_configuration; public DefaultTestRunnerFactory(IConfiguration configuration, ITestListener[] failureListeners, boolean useDefaultListeners, boolean skipFailedInvocationCounts) { m_configuration = configuration; m_failureGenerators = failureListeners; m_useDefaultListeners = useDefaultListeners; m_skipFailedInvocationCounts = skipFailedInvocationCounts; } @Override public TestRunner newTestRunner(ISuite suite, XmlTest test, List listeners) { boolean skip = m_skipFailedInvocationCounts; if (! skip) { skip = test.skipFailedInvocationCounts(); } TestRunner testRunner = new TestRunner(m_configuration, suite, test, suite.getOutputDirectory(), suite.getAnnotationFinder(), skip, listeners); if (m_useDefaultListeners) { testRunner.addListener(new TestHTMLReporter()); testRunner.addListener(new JUnitXMLReporter()); //TODO: Moved these here because maven2 has output reporters running //already, the output from these causes directories to be created with //files. This is not the desired behaviour of running tests in maven2. //Don't know what to do about this though, are people relying on these //to be added even with defaultListeners set to false? testRunner.addListener(new TextReporter(testRunner.getName(), TestRunner.getVerbose())); } for (ITestListener itl : m_failureGenerators) { testRunner.addListener(itl); } for (IConfigurationListener cl : m_configuration.getConfigurationListeners()) { testRunner.addConfigurationListener(cl); } return testRunner; } } private static class ProxyTestRunnerFactory implements ITestRunnerFactory { private ITestListener[] m_failureGenerators; private ITestRunnerFactory m_target; public ProxyTestRunnerFactory(ITestListener[] failureListeners, ITestRunnerFactory target) { m_failureGenerators = failureListeners; m_target= target; } @Override public TestRunner newTestRunner(ISuite suite, XmlTest test, List listeners) { TestRunner testRunner= m_target.newTestRunner(suite, test, listeners); testRunner.addListener(new TextReporter(testRunner.getName(), TestRunner.getVerbose())); for (ITestListener itl : m_failureGenerators) { testRunner.addListener(itl); } return testRunner; } } public void setHost(String host) { m_host = host; } @Override public String getHost() { return m_host; } private SuiteRunState m_suiteState= new SuiteRunState(); /** * @see org.testng.ISuite#getSuiteState() */ @Override public SuiteRunState getSuiteState() { return m_suiteState; } public void setSkipFailedInvocationCounts(Boolean skipFailedInvocationCounts) { if (skipFailedInvocationCounts != null) { m_skipFailedInvocationCounts = skipFailedInvocationCounts; } } private IAttributes m_attributes = new Attributes(); @Override public Object getAttribute(String name) { return m_attributes.getAttribute(name); } @Override public void setAttribute(String name, Object value) { m_attributes.setAttribute(name, value); } @Override public Set getAttributeNames() { return m_attributes.getAttributeNames(); } @Override public Object removeAttribute(String name) { return m_attributes.removeAttribute(name); } ///// // implements IInvokedMethodListener // @Override public void afterInvocation(IInvokedMethod method, ITestResult testResult) { } @Override public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { if (method == null) { throw new NullPointerException("Method should not be null"); } m_invokedMethods.add(method); } // // implements IInvokedMethodListener ///// @Override public List getAllInvokedMethods() { return m_invokedMethods; } @Override public List getAllMethods() { return m_allTestMethods; } } testng-testng-6.9.5/src/main/java/org/testng/SuiteRunState.java0000755000175000017500000000115012551235562024022 0ustar eugeneeugenepackage org.testng; import java.io.Serializable; /** * A state object that records the status of the suite run. Mainly used to * figure out if there are any @BeforeSuite failures. * * @author Alexandru Popescu */ public class SuiteRunState implements Serializable { /** * */ private static final long serialVersionUID = -2716934905049123874L; private boolean m_hasFailures; public synchronized void failed() { m_hasFailures= true; } public synchronized boolean isFailed() { return m_hasFailures; } } testng-testng-6.9.5/src/main/java/org/testng/SuiteResult.java0000755000175000017500000000310512551235562023535 0ustar eugeneeugenepackage org.testng; import org.testng.collections.Objects; import org.testng.xml.XmlSuite; /** * This class logs the result of an entire Test Suite (defined by a * property file). * * @author Cedric Beust, May 10, 2004 * */ class SuiteResult implements ISuiteResult, Comparable { /* generated */ private static final long serialVersionUID = 6778513869858860756L; //FIXME: Is m_propertyFileName needed? private String m_propertyFileName = null; private XmlSuite m_suite = null; private ITestContext m_testContext = null; protected SuiteResult(XmlSuite suite, ITestContext tr) { m_suite = suite; m_testContext = tr; } /** * @return Returns the propertyFileName. */ @Override public String getPropertyFileName() { return m_propertyFileName; } /** * @return Returns the singleTestRunner. */ @Override public ITestContext getTestContext() { return m_testContext; } /** * @return Returns the suite. */ public XmlSuite getSuite() { return m_suite; } @Override public int compareTo(Object o) { int result = 0; try { SuiteResult other = (SuiteResult) o; String n1 = getTestContext().getName(); String n2 = other.getTestContext().getName(); result = n1.compareTo(n2); } catch(Exception ex) { ex.printStackTrace(); } return result; } /** * Returns the test context name. * {@inheritDoc} */ @Override public String toString() { return Objects.toStringHelper(getClass()) .add("context", getTestContext().getName()) .toString(); } } testng-testng-6.9.5/src/main/java/org/testng/SkipException.java0000755000175000017500000000433412551235562024037 0ustar eugeneeugenepackage org.testng; /** * The root exception for special skip handling. In case a @Test or @Configuration * throws this exception the method will be considered a skip or a failure according to the * return of {@link #isSkip()}. * Users may provide extensions to this mechanism by extending this class. * * @author Alex Popescu * @since 5.6 */ public class SkipException extends RuntimeException { private static final long serialVersionUID = 4052142657885527260L; private StackTraceElement[] m_stackTrace; private volatile boolean m_stackReduced; public SkipException(String skipMessage) { super(skipMessage); } public SkipException(String skipMessage, Throwable cause) { super(skipMessage, cause); } /** * Flag if the current exception marks a skipped method (true) * or a failure (false). By default Subclasses should override this method * in order to provide smarter behavior. * * @return true if the method should be considered a skip, * false if the method should be considered failed. If not * overwritten it returns true */ public boolean isSkip() { return true; } /** * Subclasses may use this method to reduce the printed stack trace. * This method keeps only the last frame. * Important: after calling this method the preserved internally * and can be restored called {@link #restoreStackTrace}. */ protected void reduceStackTrace() { if(!m_stackReduced) { synchronized(this) { StackTraceElement[] newStack= new StackTraceElement[1]; StackTraceElement[] originalStack= getStackTrace(); if(originalStack.length > 0) { m_stackTrace= originalStack; newStack[0]= getStackTrace()[0]; setStackTrace(newStack); } m_stackReduced= true; } } } /** * Restores the original exception stack trace after a * previous call to {@link #reduceStackTrace()}. * */ protected void restoreStackTrace() { if(m_stackReduced && null != m_stackTrace) { synchronized(this) { setStackTrace(m_stackTrace); m_stackReduced= false; } } } } testng-testng-6.9.5/src/main/java/org/testng/ReporterConfig.java0000755000175000017500000000720112551235562024176 0ustar eugeneeugenepackage org.testng; import org.testng.collections.Lists; import org.testng.internal.ClassHelper; import org.testng.internal.PropertyUtils; import org.testng.internal.Utils; import java.util.List; /** * Stores the information regarding the configuration of a pluggable report listener. Used also * in conjunction with the <reporter> sub-element of the Ant task * * NOTE: this class needs to be public. It's used by TestNG Ant task * * @author Cosmin Marginean, Apr 12, 2007 */ public class ReporterConfig { /** * The class name of the reporter listener */ private String m_className; /** * The properties of the reporter listener */ private List m_properties = Lists.newArrayList(); public void addProperty(Property property) { m_properties.add(property); } public List getProperties() { return m_properties; } public String getClassName() { return m_className; } public void setClassName(String className) { this.m_className = className; } public String serialize() { StringBuffer sb = new StringBuffer(); sb.append(m_className); if (!m_properties.isEmpty()) { sb.append(":"); for (int i = 0; i < m_properties.size(); i++) { ReporterConfig.Property property = m_properties.get(i); sb.append(property.getName()); sb.append("="); sb.append(property.getValue()); if (i < m_properties.size() - 1) { sb.append(","); } } } return sb.toString(); } public static ReporterConfig deserialize(String inputString) { ReporterConfig reporterConfig = null; if (!Utils.isStringEmpty(inputString)) { reporterConfig = new ReporterConfig(); int clsNameEndIndex = inputString.indexOf(":"); if (clsNameEndIndex == -1) { reporterConfig.setClassName(inputString); } else { reporterConfig.setClassName(inputString.substring(0, clsNameEndIndex)); String propString = inputString.substring(clsNameEndIndex + 1, inputString.length()); String[] props = propString.split(","); if ((props != null) && (props.length > 0)) { for (String prop : props) { String[] propNameAndVal = prop.split("="); if ((propNameAndVal != null) && (propNameAndVal.length == 2)) { Property property = new Property(); property.setName(propNameAndVal[0]); property.setValue(propNameAndVal[1]); reporterConfig.addProperty(property); } } } } } return reporterConfig; } /** * Creates a reporter based on the current configuration */ public Object newReporterInstance() { Object result = null; Class reporterClass = ClassHelper.forName(m_className); if (reporterClass != null) { result = ClassHelper.newInstance(reporterClass); for (ReporterConfig.Property property : m_properties) { PropertyUtils.setProperty(result, property.getName(), property.getValue()); } } return result; } public static class Property { private String name; private String value; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("\nClass = " + m_className); for (Property prop : m_properties) { buf.append("\n\t " + prop.getName() + "=" + prop.getValue()); } return buf.toString(); } } testng-testng-6.9.5/src/main/java/org/testng/Reporter.java0000755000175000017500000001272512551235562023057 0ustar eugeneeugenepackage org.testng; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Vector; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.util.Strings; /** * This class is used for test methods to log messages that will be * included in the HTML reports generated by TestNG. *
*
* Implementation details. *
*
* The reporter keeps a combined output of strings (in m_output) and also * a record of which method output which line. In order to do this, callers * specify what the current method is with setCurrentTestResult() and the * Reporter maintains a mapping of each test result with a list of integers. * These integers are indices in the combined output (avoids duplicating * the output). * * Created on Nov 2, 2005 * @author cbeust */ public class Reporter { // when tests are run in parallel, each thread may be working with different // 'current test result'. Also, this value should be inherited if the test code // spawns its own thread. private static ThreadLocal m_currentTestResult = new InheritableThreadLocal<>(); /** * All output logged in a sequential order. */ private static List m_output = new Vector<>(); /** The key is the hashCode of the ITestResult */ private static Map> m_methodOutputMap = Maps.newHashMap(); private static boolean m_escapeHtml = false; //This variable is responsible for persisting all output that is yet to be associated with any //valid TestResult objects. private static ThreadLocal> m_orphanedOutput = new InheritableThreadLocal<>(); public static void setCurrentTestResult(ITestResult m) { m_currentTestResult.set(m); } public static List getOutput() { return m_output; } /** * Erase the content of all the output generated so far. */ public static void clear() { m_methodOutputMap.clear(); m_output.clear(); } /** * @param escapeHtml If true, use HTML entities for special HTML characters (<, >, &, ...). */ public static void setEscapeHtml(boolean escapeHtml) { m_escapeHtml = escapeHtml; } private static synchronized void log(String s, ITestResult m) { // Escape for the HTML reports if (m_escapeHtml) { s = Strings.escapeHtml(s); } if (m == null) { //Persist the output temporarily into a Threadlocal String list. if (m_orphanedOutput.get() == null) { m_orphanedOutput.set(new ArrayList()); } m_orphanedOutput.get().add(s); return; } // synchronization needed to ensure the line number and m_output are updated atomically int n = getOutput().size(); List lines = m_methodOutputMap.get(m.hashCode()); if (lines == null) { lines = Lists.newArrayList(); m_methodOutputMap.put(m.hashCode(), lines); } // Check if there was already some orphaned output for the current thread. if (m_orphanedOutput.get() != null) { n = n + m_orphanedOutput.get().size(); getOutput().addAll(m_orphanedOutput.get()); // Since we have already added all of the orphaned output to the current // TestResult, lets clear it off m_orphanedOutput.remove(); } lines.add(n); getOutput().add(s); } /** * Log the passed string to the HTML reports * @param s The message to log */ public static void log(String s) { log(s, getCurrentTestResult()); } /** * Log the passed string to the HTML reports if the current verbosity * is equal or greater than the one passed in parameter. If logToStandardOut * is true, the string will also be printed on standard out. * * @param s The message to log * @param level The verbosity of this message * @param logToStandardOut Whether to print this string on standard * out too */ public static void log(String s, int level, boolean logToStandardOut) { if (TestRunner.getVerbose() >= level) { log(s, getCurrentTestResult()); if (logToStandardOut) { System.out.println(s); } } } /** * Log the passed string to the HTML reports. If logToStandardOut * is true, the string will also be printed on standard out. * * @param s The message to log * @param logToStandardOut Whether to print this string on standard * out too */ public static void log(String s, boolean logToStandardOut) { log(s, getCurrentTestResult()); if (logToStandardOut) { System.out.println(s); } } /** * Log the passed string to the HTML reports if the current verbosity * is equal or greater than the one passed in parameter * * @param s The message to log * @param level The verbosity of this message */ public static void log(String s, int level) { if (TestRunner.getVerbose() >= level) { log(s, getCurrentTestResult()); } } /** * @return the current test result. */ public static ITestResult getCurrentTestResult() { return m_currentTestResult.get(); } public static synchronized List getOutput(ITestResult tr) { List result = Lists.newArrayList(); if (tr == null) { //guard against a possible NPE in scenarios wherein the test result object itself could be a null value. return result; } List lines = m_methodOutputMap.get(tr.hashCode()); if (lines != null) { for (Integer n : lines) { result.add(getOutput().get(n)); } } return result; } } testng-testng-6.9.5/src/main/java/org/testng/PreserveOrderMethodInterceptor.java0000644000175000017500000000160712551235562027416 0ustar eugeneeugenepackage org.testng; import org.testng.internal.MethodInstance; import java.util.Collections; import java.util.List; /** * A method interceptor that preserves the order in which test classes were found in * the <test> tag. * * @author cbeust * */ class PreserveOrderMethodInterceptor implements IMethodInterceptor { private void p(List methods, String s) { System.out.println("[PreserveOrderMethodInterceptor] " + s); for (IMethodInstance mi : methods) { System.out.println(" " + mi.getMethod().getMethodName() + " index:" + mi.getMethod().getTestClass().getXmlClass().getIndex()); } } @Override public List intercept(List methods, ITestContext context) { // p(methods, "Before"); Collections.sort(methods, MethodInstance.SORT_BY_INDEX); // p(methods, "After"); return methods; } } testng-testng-6.9.5/src/main/java/org/testng/InstanceOrderingMethodInterceptor.java0000644000175000017500000000253712551235562030070 0ustar eugeneeugenepackage org.testng; import org.testng.collections.Lists; import org.testng.collections.Maps; import java.util.List; import java.util.Map; /** * A method interceptor that sorts its methods per instances (i.e. per class). * * */ class InstanceOrderingMethodInterceptor implements IMethodInterceptor { @Override public List intercept(List methods, ITestContext context) { return groupMethodsByInstance(methods); } /** * The default method interceptor which sorts methods by instances (i.e. by class). */ private List groupMethodsByInstance(List methods) { List instanceList = Lists.newArrayList(); Map> map = Maps.newHashMap(); for (IMethodInstance mi : methods) { Object[] methodInstances = mi.getInstances(); for (Object instance : methodInstances) { if (!instanceList.contains(instance)) { instanceList.add(instance); } List l = map.get(instance); if (l == null) { l = Lists.newArrayList(); map.put(instance, l); } l.add(mi); } } List result = Lists.newArrayList(); for (Object instance : instanceList) { result.addAll(map.get(instance)); } return result; } } testng-testng-6.9.5/src/main/java/org/testng/ITestRunnerFactory.java0000644000175000017500000000044712551235562025022 0ustar eugeneeugenepackage org.testng; import org.testng.xml.XmlTest; import java.util.List; /** * A factory for TestRunners to be used by SuiteRunners. */ public interface ITestRunnerFactory { TestRunner newTestRunner(final ISuite suite, final XmlTest test, List listeners); } testng-testng-6.9.5/src/main/java/org/testng/ITestResult.java0000755000175000017500000000440112551235562023474 0ustar eugeneeugenepackage org.testng; /** * This class describes the result of a test. * * @author Cedric Beust, May 2, 2004 * @since May 2, 2004 * @version $Revision: 721 $, $Date: 2009-05-23 09:55:46 -0700 (Sat, 23 May 2009) $ * */ public interface ITestResult extends IAttributes, Comparable { // // Test status // public static final int SUCCESS = 1; public static final int FAILURE = 2; public static final int SKIP = 3; public static final int SUCCESS_PERCENTAGE_FAILURE = 4; public static final int STARTED= 16; /** * @return The status of this result, using one of the constants * above. */ public int getStatus(); public void setStatus(int status); /** * @return The test method this result represents. */ public ITestNGMethod getMethod(); /** * @return The parameters this method was invoked with. */ public Object[] getParameters(); public void setParameters(Object[] parameters); /** * @return The test class used this object is a result for. */ public IClass getTestClass(); /** * @return The throwable that was thrown while running the * method, or null if no exception was thrown. */ public Throwable getThrowable(); public void setThrowable(Throwable throwable); /** * @return the start date for this test, in milliseconds. */ public long getStartMillis(); /** * @return the end date for this test, in milliseconds. */ public long getEndMillis(); public void setEndMillis(long millis); /** * @return The name of this TestResult, typically identical to the name * of the method. */ public String getName(); /** * @return true if if this test run is a SUCCESS */ public boolean isSuccess(); /** * @return The host where this suite was run, or null if it was run locally. The * returned string has the form: host:port */ public String getHost(); /** * The instance on which this method was run. */ public Object getInstance(); /** * If this result's related instance implements ITest, returns its test name, otherwise returns null. */ public String getTestName(); public String getInstanceName(); /** * @return the {@link ITestContext} for this test result. */ public ITestContext getTestContext(); } testng-testng-6.9.5/src/main/java/org/testng/ITestObjectFactory.java0000644000175000017500000000033012551235562024746 0ustar eugeneeugenepackage org.testng; import java.io.Serializable; /** * Parent interface of all the object factories. * * @author Cedric Beust */ public interface ITestObjectFactory extends Serializable { } testng-testng-6.9.5/src/main/java/org/testng/ITestNGMethod.java0000755000175000017500000001605312551235562023671 0ustar eugeneeugenepackage org.testng; import org.testng.internal.ConstructorOrMethod; import org.testng.xml.XmlTest; import java.io.Serializable; import java.lang.reflect.Method; import java.util.List; import java.util.Map; /** * Describes a TestNG annotated method and the instance on which it will be invoked. * * This interface is not meant to be implemented by users. * * @author Cedric Beust, May 3, 2004 */ public interface ITestNGMethod extends Comparable, Serializable, Cloneable { /** * @return The real class on which this method was declared * (can be different from getMethod().getDeclaringClass() if * the test method was defined in a superclass). */ Class getRealClass(); ITestClass getTestClass(); /** * Sets the test class having this method. This is not necessarily the declaring class. * * @param cls The test class having this method. */ void setTestClass(ITestClass cls); /** * @return the corresponding Java test method. * @deprecated This method is deprecated and can now return null. Use * getConstructorOrMethod() instead. */ @Deprecated Method getMethod(); /** * Returns the method name. This is needed for serialization because * methods are not Serializable. * @return the method name. */ String getMethodName(); /** * @return All the instances the methods will be invoked upon. * This will typically be an array of one object in the absence * of an @Factory annotation. * * @deprecated Use getInstance(). */ @Deprecated Object[] getInstances(); Object getInstance(); /** * Needed for serialization. */ long[] getInstanceHashCodes(); /** * @return The groups this method belongs to, possibly added to the groups * declared on the class. */ String[] getGroups(); /** * @return The groups this method depends on, possibly added to the groups * declared on the class. */ String[] getGroupsDependedUpon(); /** * If a group was not found. */ String getMissingGroup(); public void setMissingGroup(String group); /** * Before and After groups */ public String[] getBeforeGroups(); public String[] getAfterGroups(); /** * @return The methods this method depends on, possibly added to the methods * declared on the class. */ String[] getMethodsDependedUpon(); void addMethodDependedUpon(String methodName); /** * @return true if this method was annotated with @Test */ boolean isTest(); /** * @return true if this method was annotated with @Configuration * and beforeTestMethod = true */ boolean isBeforeMethodConfiguration(); /** * @return true if this method was annotated with @Configuration * and beforeTestMethod = false */ boolean isAfterMethodConfiguration(); /** * @return true if this method was annotated with @Configuration * and beforeClassMethod = true */ boolean isBeforeClassConfiguration(); /** * @return true if this method was annotated with @Configuration * and beforeClassMethod = false */ boolean isAfterClassConfiguration(); /** * @return true if this method was annotated with @Configuration * and beforeSuite = true */ boolean isBeforeSuiteConfiguration(); /** * @return true if this method was annotated with @Configuration * and afterSuite = true */ boolean isAfterSuiteConfiguration(); /** * @return true if this method is a @BeforeTest (@Configuration beforeTest=true) */ boolean isBeforeTestConfiguration(); /** * @return true if this method is an @AfterTest (@Configuration afterTest=true) */ boolean isAfterTestConfiguration(); boolean isBeforeGroupsConfiguration(); boolean isAfterGroupsConfiguration(); /** * @return The timeout in milliseconds. */ long getTimeOut(); void setTimeOut(long timeOut); /** * @return the number of times this method needs to be invoked. */ int getInvocationCount(); 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(); /** * @return The id of the thread this method was run in. */ String getId(); void setId(String id); long getDate(); void setDate(long date); /** * Returns if this ITestNGMethod can be invoked from within IClass. */ boolean canRunFromClass(IClass testClass); /** * @return true if this method is alwaysRun=true */ boolean isAlwaysRun(); /** * @return the number of threads to be used when invoking the method on parallel */ int getThreadPoolSize(); void setThreadPoolSize(int threadPoolSize); boolean getEnabled(); public String getDescription(); void setDescription(String description); public void incrementCurrentInvocationCount(); public int getCurrentInvocationCount(); public void setParameterInvocationCount(int n); public int getParameterInvocationCount(); public ITestNGMethod clone(); public IRetryAnalyzer getRetryAnalyzer(); public void setRetryAnalyzer(IRetryAnalyzer retryAnalyzer); public boolean skipFailedInvocations(); public void setSkipFailedInvocations(boolean skip); /** * The time under which all invocationCount methods need to complete by. */ public long getInvocationTimeOut(); public boolean ignoreMissingDependencies(); public void setIgnoreMissingDependencies(boolean ignore); /** * Which invocation numbers of this method should be used (only applicable * if it uses a data provider). If this value is an empty list, use all the values * returned from the data provider. These values are read from the XML file in * the tag. */ public List getInvocationNumbers(); public void setInvocationNumbers(List numbers); /** * The list of invocation numbers that failed, which is only applicable for * methods that have a data provider. */ public void addFailedInvocationNumber(int number); public List getFailedInvocationNumbers(); /** * The scheduling priority. Lower priorities get scheduled first. */ public int getPriority(); public void setPriority(int priority); /** * @return the XmlTest this method belongs to. */ public XmlTest getXmlTest(); ConstructorOrMethod getConstructorOrMethod(); /** * @return the parameters found in the include tag, if any * @param test */ Map findMethodParameters(XmlTest test); } testng-testng-6.9.5/src/main/java/org/testng/ITestNGListenerFactory.java0000644000175000017500000000072712551235562025564 0ustar eugeneeugenepackage org.testng; /** * A factory used to create instances of ITestNGListener. Users can implement this interface * in any of their test classes but there can be only one such instance. */ public interface ITestNGListenerFactory { /** * Create and return an instance of the listener class passed in parameter. Return null * if you want to use the default factory. */ ITestNGListener createListener(Class listenerClass); } testng-testng-6.9.5/src/main/java/org/testng/ITestNGListener.java0000755000175000017500000000026412551235562024233 0ustar eugeneeugenepackage org.testng; /** * This is a marker interface for all objects that can be passed * as a -listener argument. * * @author cbeust */ public interface ITestNGListener { } testng-testng-6.9.5/src/main/java/org/testng/ITestMethodFinder.java0000755000175000017500000000364412551235562024576 0ustar eugeneeugenepackage org.testng; import org.testng.xml.XmlTest; /** * This interface allows to modify the strategy used by TestRunner * to find its test methods. At the time of this writing, TestNG * supports two different strategies: TestNG (using annotations to * locate these methods) and JUnit (setUp()/tearDown() and all * methods that start with "test" or have a suite() method). * * @author Cedric Beust, May 3, 2004 * */ public interface ITestMethodFinder { /** * @return All the applicable test methods. */ ITestNGMethod[] getTestMethods(Class cls, XmlTest xmlTest); /** * @return All the methods that should be invoked * before a test method is invoked. */ ITestNGMethod[] getBeforeTestMethods(Class cls); /** * @return All the methods that should be invoked * after a test method completes. */ 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); /** * @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); /** * @return All the methods that should be invoked * before the suite starts running. */ 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[] getBeforeTestConfigurationMethods(Class testClass); ITestNGMethod[] getAfterTestConfigurationMethods(Class testClass); ITestNGMethod[] getBeforeGroupsConfigurationMethods(Class testClass); ITestNGMethod[] getAfterGroupsConfigurationMethods(Class testClass); } testng-testng-6.9.5/src/main/java/org/testng/ITestListener.java0000755000175000017500000000365612551235562024016 0ustar eugeneeugenepackage org.testng; /** * A listener for test running. * * @author Cedric Beust * @author Alexandru Popescu * @author Hani Suleiman */ public interface ITestListener extends ITestNGListener { /** * Invoked each time before a test will be invoked. * The ITestResult is only partially filled with the references to * class, method, start millis and status. * * @param result the partially filled ITestResult * @see ITestResult#STARTED */ void onTestStart(ITestResult result); /** * Invoked each time a test succeeds. * * @param result ITestResult containing information about the run test * @see ITestResult#SUCCESS */ public void onTestSuccess(ITestResult result); /** * Invoked each time a test fails. * * @param result ITestResult containing information about the run test * @see ITestResult#FAILURE */ public void onTestFailure(ITestResult result); /** * Invoked each time a test is skipped. * * @param result ITestResult containing information about the run test * @see ITestResult#SKIP */ public void onTestSkipped(ITestResult result); /** * Invoked each time a method fails but has been annotated with * successPercentage and this failure still keeps it within the * success percentage requested. * * @param result ITestResult containing information about the run test * @see ITestResult#SUCCESS_PERCENTAGE_FAILURE */ public void onTestFailedButWithinSuccessPercentage(ITestResult result); /** * Invoked after the test class is instantiated and before * any configuration method is called. */ public void onStart(ITestContext context); /** * Invoked after all the tests have run and all their * Configuration methods have been called. */ public void onFinish(ITestContext context); } testng-testng-6.9.5/src/main/java/org/testng/ITestContext.java0000644000175000017500000000600012551235562023634 0ustar eugeneeugenepackage 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; import java.util.Date; import java.util.List; /** * This class defines a test context which contains all the information * for a given test run. An instance of this context is passed to the * test listeners so they can query information about their * environment. * * @author Cedric Beust, Aug 6, 2004 * @author Alexandru Popescu */ public interface ITestContext extends IAttributes { /** * The name of this test. */ public String getName(); /** * When this test started running. */ public Date getStartDate(); /** * When this test stopped running. */ public Date getEndDate(); /** * @return A list of all the tests that run successfully. */ public IResultMap getPassedTests(); /** * @return A list of all the tests that were skipped */ public IResultMap getSkippedTests(); /** * @return A list of all the tests that failed but are being ignored because * annotated with a successPercentage. */ public IResultMap getFailedButWithinSuccessPercentageTests(); /** * @return A map of all the tests that passed, indexed by * their ITextMethor. * * @see org.testng.ITestNGMethod */ public IResultMap getFailedTests(); /** * @return All the groups that are included for this test run. */ public String[] getIncludedGroups(); /** * @return All the groups that are excluded for this test run. */ public String[] getExcludedGroups(); /** * @return Where the reports will be generated. */ public String getOutputDirectory(); /** * @return The Suite object that was passed to the runner * at start-up. */ public ISuite getSuite(); /** * @return All the test methods that were run. */ public ITestNGMethod[] getAllTestMethods(); /** * @return The host where this test was run, or null if it was run locally. The * returned string has the form: host:port */ public String getHost(); /** * @return All the methods that were not included in this test run. */ public Collection getExcludedMethods(); /** * Retrieves information about the successful configuration method invocations. */ public IResultMap getPassedConfigurations(); /** * Retrieves information about the skipped configuration method invocations. */ public IResultMap getSkippedConfigurations(); /** * Retrieves information about the failed configuration method invocations. */ public IResultMap getFailedConfigurations(); /** * @return the current XmlTest. */ public XmlTest getCurrentXmlTest(); public List getGuiceModules(Class cls); public Injector getInjector(List moduleInstances); Injector getInjector(IClass iClass); public void addInjector(List moduleInstances, Injector injector); } testng-testng-6.9.5/src/main/java/org/testng/ITestClassFinder.java0000755000175000017500000000121412551235562024412 0ustar eugeneeugenepackage org.testng; /** * This class is used by TestNG to locate the test classes. * * @author Cedric Beust */ public interface ITestClassFinder { /** * @return An array of all the classes that contain test * methods. This method usually returns an array of one * class, which is the class on which TestNG is running, * except in the following cases. * - TestNG: the class contains an @Factory method * - JUnit: the class contains a suite() method */ public IClass[] findTestClasses(); /** * Return the IClass for a given class */ public IClass getIClass(Class cls); } testng-testng-6.9.5/src/main/java/org/testng/ITestClass.java0000755000175000017500000001000112551235562023254 0ustar eugeneeugenepackage org.testng; import java.io.Serializable; /** * This class represents a test class: *
    *
  • The test methods *
  • The configuration methods (test and method) *
  • The class file *
* * Note that the methods returned by instances of this class * are expected to be correct at runtime. In other words, * they might differ from what the ITestMethodFinder returned * since ITestClass will take into account the groups being * included and excluded. * * @author Cedric Beust */ public interface ITestClass extends IClass, Serializable { /** * Returns all the instances the methods will be invoked upon. * This will typically be an array of one object in the absence * of a @Factory annotation. * * @param reuse flag if a new set of instances must be returned * (if set to false) * @return All the instances the methods will be invoked upon. * * {@inheritDoc} */ @Override Object[] getInstances(boolean reuse); /** * TODO cquezel JavaDoc. * * {@inheritDoc} */ @Override long[] getInstanceHashCodes(); /** * @return The number of instances used in this class. This method * is needed for serialization since we don't know ahead of time if the * instances of the test classes will be serializable. */ @Override int getInstanceCount(); /** * Returns all the applicable test methods. * @return All the applicable test methods. */ ITestNGMethod[] getTestMethods(); /** * Returns all the methods that should be invoked * before a test method is invoked. * @return All the methods that should be invoked * before a test method is invoked. */ ITestNGMethod[] getBeforeTestMethods(); /** * Returns all the methods that should be invoked * after a test method completes. * @return All the methods that should be invoked * after a test method completes. */ ITestNGMethod[] getAfterTestMethods(); /** * Return all the methods that should be invoked * after the test class has been created and before * any of its test methods is invoked. * @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(); /** * Returns all the methods that should be invoked * after all the tests have been run on this class. * @return All the methods that should be invoked * after all the tests have been run on this class. */ ITestNGMethod[] getAfterClassMethods(); /** * Returns All the methods that should be invoked * before the suite is run. * @return All the methods that should be invoked * before the suite is run. */ ITestNGMethod[] getBeforeSuiteMethods(); /** * Returns all the methods that should be invoked * after the suite has run. * @return All the methods that should be invoked * after the suite has run. */ ITestNGMethod[] getAfterSuiteMethods(); /** * Returns all @Configuration methods that should be invoked before any others in the * current test. * @return all @Configuration methods that should be invoked before any others in the current test. */ ITestNGMethod[] getBeforeTestConfigurationMethods(); /** * Returns all @Configuration methods that should be invoked last before any others * in the current test. * @return all @Configuration methods that should be invoked last before any others * in the current test. */ ITestNGMethod[] getAfterTestConfigurationMethods(); /** * Returns all @Configuration methods that should be invoked before certain groups. * @return all @Configuration methods that should be invoked before certain groups. */ ITestNGMethod[] getBeforeGroupsMethods(); /** * Returns all @Configuration methods that should be invoked after certain groups. * @return all @Configuration methods that should be invoked after certain groups. */ ITestNGMethod[] getAfterGroupsMethods(); } testng-testng-6.9.5/src/main/java/org/testng/ITest.java0000755000175000017500000000060412551235562022276 0ustar eugeneeugenepackage org.testng; /** * If a test class implements this interface, it will receive a * special treatment, such as having the test name displayed * in the HTML reports. * * @author cbeust * Jun 6, 2006 */ public interface ITest { /** * The name of test instance(s). * @return name associated with a particular instance of a test. */ public String getTestName(); } testng-testng-6.9.5/src/main/java/org/testng/ISuiteResult.java0000755000175000017500000000065212551235562023652 0ustar eugeneeugenepackage org.testng; import java.io.Serializable; /** * This class represents the result of a suite run. * * @author Cedric Beust, Aug 6, 2004 * */ public interface ISuiteResult extends Serializable { /** * @return The name of the property file for these tests. */ public String getPropertyFileName(); /** * @return The testing context for these tests. */ public ITestContext getTestContext(); } testng-testng-6.9.5/src/main/java/org/testng/ISuiteListener.java0000755000175000017500000000062612551235562024162 0ustar eugeneeugenepackage org.testng; /** * Listener for test suites. * * @author Cedric Beust, Aug 6, 2004 * */ public interface ISuiteListener extends ITestNGListener { /** * This method is invoked before the SuiteRunner starts. */ public void onStart(ISuite suite); /** * This method is invoked after the SuiteRunner has run all * the test suites. */ public void onFinish(ISuite suite); } testng-testng-6.9.5/src/main/java/org/testng/ISuite.java0000755000175000017500000000611412551235562022452 0ustar eugeneeugenepackage org.testng; import java.util.Collection; import java.util.List; import java.util.Map; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.xml.XmlSuite; import com.google.inject.Injector; /** * Interface defining a Test Suite. * * @author Cedric Beust, Aug 6, 2004 * */ public interface ISuite extends IAttributes { /** * @return the name of this suite. */ public String getName(); /** * @return The results for this suite. */ public Map getResults(); /** * @return The object factory used to create all test instances. */ public IObjectFactory getObjectFactory(); public IObjectFactory2 getObjectFactory2(); /** * @return The output directory used for the reports. */ public String getOutputDirectory(); /** * @return true if the tests must be run in parallel. */ public String getParallel(); public String getParentModule(); public String getGuiceStage(); /** * @return The value of this parameter, or null if none was specified. */ public String getParameter(String parameterName); /** * Retrieves the map of groups and their associated test methods. * * @return A map where the key is the group and the value is a list * of methods used by this group. */ public Map> getMethodsByGroups(); /** * Retrieves the list of all the methods that were invoked during this run. * @return a collection of ITestNGMethods belonging to all tests included in the suite. * @deprecated Use getAllInvokedMthods(). */ @Deprecated public Collection getInvokedMethods(); /** * @return a list of all the methods that were invoked in this suite. */ public List getAllInvokedMethods(); /** * @return All the methods that were not included in this test run. */ public Collection getExcludedMethods(); /** * Triggers the start of running tests included in the suite. */ public void run(); /** * @return The host where this suite was run, or null if it was run locally. The * returned string has the form: host:port */ public String getHost(); /** * Retrieves the shared state for a suite. * * @return the share state of the current suite. */ public SuiteRunState getSuiteState(); /** * @return the annotation finder used for the specified type (JDK5 or javadoc) */ public IAnnotationFinder getAnnotationFinder(); /** * @return The representation of the current XML suite file. */ public XmlSuite getXmlSuite(); public void addListener(ITestNGListener listener); public Injector getParentInjector(); public void setParentInjector(Injector injector); /** * @return the total number of methods found in this suite. The presence of * factories or data providers might cause the actual number of test methods * run be bigger than this list. */ List getAllMethods(); } testng-testng-6.9.5/src/main/java/org/testng/IRetryAnalyzer.java0000755000175000017500000000073512551235562024177 0ustar eugeneeugenepackage org.testng; /** * Interface to implement to be able to have a chance to retry a failed test. * * @author tocman@gmail.com (Jeremie Lenfant-Engelmann) * */ public interface IRetryAnalyzer { /** * Returns true if the test method has to be retried, false otherwise. * * @param result The result of the test method that just ran. * @return true if the test method has to be retried, false otherwise. */ public boolean retry(ITestResult result); } testng-testng-6.9.5/src/main/java/org/testng/IResultMap.java0000755000175000017500000000075612551235562023303 0ustar eugeneeugenepackage org.testng; import java.io.Serializable; import java.util.Collection; import java.util.Set; public interface IResultMap extends Serializable { public void addResult(ITestResult result, ITestNGMethod method); public Set getResults(ITestNGMethod method); public Set getAllResults(); public void removeResult(ITestNGMethod m); public void removeResult(ITestResult r); public Collection getAllMethods(); public int size(); } testng-testng-6.9.5/src/main/java/org/testng/IReporter.java0000755000175000017500000000111712551235562023161 0ustar eugeneeugenepackage org.testng; import org.testng.xml.XmlSuite; import java.util.List; /** * This interface can be implemented by clients to generate a report. Its method * generateReport() will be invoked after all the suite have run and the parameters * give all the test results that happened during that run. * * @author cbeust * Feb 17, 2006 */ public interface IReporter extends ITestNGListener { /** * Generate a report for the given suites into the specified output directory. */ void generateReport(List xmlSuites, List suites, String outputDirectory); } testng-testng-6.9.5/src/main/java/org/testng/IObjectFactory2.java0000644000175000017500000000052412551235562024175 0ustar eugeneeugenepackage org.testng; /** * Factory used to create all test instances. This object factory only receives the class * in parameter. * * @see org.testng.IObjectFactory * * @author Cedric Beust * * @since 5.14.6 */ public interface IObjectFactory2 extends ITestObjectFactory { Object newInstance(Class cls); } testng-testng-6.9.5/src/main/java/org/testng/IObjectFactory.java0000755000175000017500000000070512551235562024117 0ustar eugeneeugenepackage org.testng; import java.lang.reflect.Constructor; /** * Factory used to create all test instances. This factory is passed the constructor * along with the parameters that TestNG calculated based on the environment * (@Parameters, etc...). * * @see IObjectFactory2 * * @author Hani Suleiman * @since 5.6 */ public interface IObjectFactory extends ITestObjectFactory { Object newInstance(Constructor constructor, Object... params); } testng-testng-6.9.5/src/main/java/org/testng/IModuleFactory.java0000644000175000017500000000111412551235562024126 0ustar eugeneeugenepackage org.testng; import com.google.inject.Module; /** * This interface is used by the moduleFactory attribute of the @Guice * annotation. It allows users to use different Guice modules based on the test * class waiting to be injected. * * @author Cedric Beust */ public interface IModuleFactory { /** * @param context The current test context * @param testClass The test class * * @return The Guice module that should be used to get an instance of this * test class. */ Module createModule(ITestContext context, Class testClass); } testng-testng-6.9.5/src/main/java/org/testng/IMethodSelectorContext.java0000755000175000017500000000165412551235562025653 0ustar eugeneeugenepackage org.testng; import java.util.Map; /** * An implementation of this interface is passed to all the Method Selectors * when their includeMethod() is invoked. Method selectors can invoke * any method of this context at that time. * * Created on Jan 3, 2007 * @author Cedric Beust */ public interface IMethodSelectorContext { /** * @return true if no more Method Selectors should be invoked after * the current one. */ public boolean isStopped(); /** * Indicate that no other Method Selectors should be invoked after the * current one if stopped is false. * @param stopped */ public void setStopped(boolean stopped); /** * @return a Map that can be freely manipulated by the Method Selector. * This can be used to share information among several Method Selectors. */ public Map getUserData(); } testng-testng-6.9.5/src/main/java/org/testng/IMethodSelector.java0000755000175000017500000000235412551235562024304 0ustar eugeneeugenepackage org.testng; import java.io.Serializable; import java.util.List; /** * This interface is used to augment or replace TestNG's algorithm to * decide whether a test method should be included in a test run. * * Created on Sep 26, 2005 * @author cbeust */ public interface IMethodSelector extends Serializable { /** * @param context The selector context. The implementation of this method * can invoke setHalted(true) to indicate that no other Method Selector * should be invoked by TestNG after this one. Additionally, this * implementation can manipulate the Map object returned by * getUserData(). * @param method The test method * @param isTestMethod true if this is a @Test method, false if it's a * configuration method * @return true if this method should be included in the test run, false * otherwise */ public boolean includeMethod(IMethodSelectorContext context, ITestNGMethod method, boolean isTestMethod); /** * Invoked when all the test methods are known so that the method selector * can perform additional work, such as adding the transitive closure of * all the groups being included and depended upon. */ public void setTestMethods(List testMethods); } testng-testng-6.9.5/src/main/java/org/testng/IMethodInterceptor.java0000755000175000017500000000236512551235562025024 0ustar eugeneeugenepackage org.testng; import java.util.List; /** * This class is used to alter the list of test methods that TestNG is about to run. * *

* * An instance of this class will be invoked right before TestNG starts invoking test methods. * Only methods that have no dependents and that don't depend on any other test methods will * be passed in parameter. Implementers of this interface need to return a list of {@link IMethodInstance} * that represents the list of test methods they want run. TestNG will run these methods in the * same order found in the returned value. * *

* * Typically, the returned list will be just the methods passed in parameter but sorted * differently, but it can actually have any size (it can be empty, it can be of the * same size as the original list or it can contain more methods). * *

* * The {@link ITestContext} is passed in the intercept method so that implementers can set user values * (using {@link ITestContext#setAttribute(String, Object)}), which they can then look up * later while generating the reports. * * @author cbeust */ public interface IMethodInterceptor extends ITestNGListener { List intercept(List methods, ITestContext context); } testng-testng-6.9.5/src/main/java/org/testng/IMethodInstance.java0000755000175000017500000000044312551235562024265 0ustar eugeneeugenepackage org.testng; /** * This interface captures a test method along with all the instances it should * be run on. */ public interface IMethodInstance { ITestNGMethod getMethod(); /** * @deprecated Use getInstance() */ Object[] getInstances(); Object getInstance(); } testng-testng-6.9.5/src/main/java/org/testng/IInvokedMethodListener2.java0000644000175000017500000000115712551235562025710 0ustar eugeneeugenepackage org.testng; /** * Implement this interface if you need a handle to {@link ITestContext}. * * @author karthik.krishnan@gmail.com (Karthik Krishnan) */ public interface IInvokedMethodListener2 extends IInvokedMethodListener { /** * To be implemented if the method needs a handle to contextual information. */ void beforeInvocation(IInvokedMethod method, ITestResult testResult, ITestContext context); /** * To be implemented if the method needs a handle to contextual information. */ void afterInvocation(IInvokedMethod method, ITestResult testResult, ITestContext context); } testng-testng-6.9.5/src/main/java/org/testng/IInvokedMethodListener.java0000755000175000017500000000061412551235562025626 0ustar eugeneeugenepackage org.testng; /** * A listener that gets invoked before and after a method is invoked by TestNG. * This listener will only be invoked for configuration and test methods. */ public interface IInvokedMethodListener extends ITestNGListener { void beforeInvocation(IInvokedMethod method, ITestResult testResult); void afterInvocation(IInvokedMethod method, ITestResult testResult); } testng-testng-6.9.5/src/main/java/org/testng/IInvokedMethod.java0000755000175000017500000000121012551235562024111 0ustar eugeneeugenepackage org.testng; /** * An interface representing a method that has been invoked by TestNG. * * This interface is internal. */ public interface IInvokedMethod { /** * @return true if this method is a test method */ public abstract boolean isTestMethod(); /** * @return true if this method is a configuration method (@BeforeXXX or @AfterXXX) */ public abstract boolean isConfigurationMethod(); /** * @return the test method */ public abstract ITestNGMethod getTestMethod(); public ITestResult getTestResult(); /** * @return the date when this method was run */ public abstract long getDate(); }testng-testng-6.9.5/src/main/java/org/testng/IInstanceInfo.java0000755000175000017500000000124012551235562023734 0ustar eugeneeugenepackage org.testng; /** * This class defines a pair of instance/class. A method with @Factory * can return an array of these objects instead of Object[] so that * instances can be dynamic proxies or mock objects and still provide * enough information to TestNG to figure out what classes the * annotations should be looked up in. * * @author Cedric Beust */ public interface IInstanceInfo { /** * @return The instance on which the tests will be invoked. */ public Object getInstance(); /** * @return The class on which the TestNG annotations should be looked for. */ public Class getInstanceClass(); } testng-testng-6.9.5/src/main/java/org/testng/IHookable.java0000755000175000017500000000160112551235562023101 0ustar eugeneeugenepackage org.testng; /** * If a test class implements this interface, its run() method * will be invoked instead of each @Test method found. The invocation of * the test method will then be performed upon invocation of the callBack() * method of the IHookCallBack parameter. * * This is useful to test classes that require JAAS authentication, which can * be implemented as follows: * *

 * public void run(final IHookCallBack icb, ITestResult testResult) {
 *   // Preferably initialized in a @Configuration method
 *   mySubject = authenticateWithJAAs();
 *
 *   Subject.doAs(mySubject, new PrivilegedExceptionAction() {
 *     public Object run() {
 *       icb.callback(testResult);
 *     }
 *   };
 * }
 * 
* * @author cbeust * Jan 28, 2006 */ public interface IHookable extends ITestNGListener { public void run(IHookCallBack callBack, ITestResult testResult); } testng-testng-6.9.5/src/main/java/org/testng/IHookCallBack.java0000755000175000017500000000123612551235562023636 0ustar eugeneeugenepackage org.testng; /** * A parameter of this type will be passed to the run() method of a IHookable. * Invoking runTestMethod() on that parameter will cause the test method currently * being diverted to be invoked. * *

* * This interface is not meant to be implemented by clients, only by TestNG. * * @see org.testng.IHookable * * * @author cbeust * Jan 28, 2006 */ public interface IHookCallBack { /** * Invoke the test method currently being hijacked. */ public void runTestMethod(ITestResult testResult); /** * @return the parameters that will be used to invoke the test method. */ public Object[] getParameters(); } testng-testng-6.9.5/src/main/java/org/testng/IExtraOutput.java0000755000175000017500000000107512551235562023666 0ustar eugeneeugenepackage org.testng; import java.io.Serializable; import java.util.List; /** * This class is used by Reporter to store the extra output to be later * included in the HTML report: * - User-generated report * - Parameter info * * Created on Feb 16, 2006 * @author Cedric Beust */ public interface IExtraOutput extends Serializable { /** * @return a List representing the parameters passed * to this test method, or an empty List if no parameters were used. */ public List getParameterOutput(); } testng-testng-6.9.5/src/main/java/org/testng/IExpectedExceptionsHolder.java0000644000175000017500000000114012551235562026311 0ustar eugeneeugenepackage org.testng; public interface IExpectedExceptionsHolder { /** * Get the message in case the Throwable thrown by the test is not matching. * * @param ite The Throwable thrown by the test * @return The message which will be displayed as test result */ String getWrongExceptionMessage(Throwable ite); /** * Check if the Throwable thrown by the test is matching with the holder logic * * @param ite The Throwable thrown by the test * @return true if the Throwable is matching with the holder logic, false otherwise */ boolean isThrowableMatching(Throwable ite); } testng-testng-6.9.5/src/main/java/org/testng/IExecutionListener.java0000644000175000017500000000057112551235562025030 0ustar eugeneeugenepackage org.testng; /** * A listener used to monitor when a TestNG run starts and ends. * * @author Cedric Beust */ public interface IExecutionListener extends ITestNGListener { /** * Invoked before the TestNG run starts. */ void onExecutionStart(); /** * Invoked once all the suites have been run. */ void onExecutionFinish(); } testng-testng-6.9.5/src/main/java/org/testng/IConfigureCallBack.java0000644000175000017500000000127012551235562024652 0ustar eugeneeugenepackage org.testng; /** * A parameter of this type will be passed to the run() method of a IConfigurable. * Invoking runConfigurationMethod() on that parameter will cause the test method currently * being diverted to be invoked. * * This interface is not meant to be implemented by clients, only by TestNG. * * @see org.testng.IConfigurable * * @author cbeust * Sep 07, 2010 */ public interface IConfigureCallBack { /** * Invoke the test method currently being hijacked. */ public void runConfigurationMethod(ITestResult testResult); /** * @return the parameters that will be used to invoke the configuration method. */ public Object[] getParameters(); } testng-testng-6.9.5/src/main/java/org/testng/IConfigurationListener2.java0000644000175000017500000000032212551235562025750 0ustar eugeneeugenepackage org.testng; public interface IConfigurationListener2 extends IConfigurationListener { /** * Invoked before a configuration method is invoked. */ void beforeConfiguration(ITestResult tr); } testng-testng-6.9.5/src/main/java/org/testng/IConfigurationListener.java0000755000175000017500000000102512551235562025672 0ustar eugeneeugenepackage org.testng; /** * Listener interface for events related to configuration methods. */ public interface IConfigurationListener extends ITestNGListener { /** * Invoked whenever a configuration method succeeded. */ void onConfigurationSuccess(ITestResult itr); /** * Invoked whenever a configuration method failed. */ void onConfigurationFailure(ITestResult itr); /** * Invoked whenever a configuration method was skipped. */ void onConfigurationSkip(ITestResult itr); } testng-testng-6.9.5/src/main/java/org/testng/IConfigurable.java0000644000175000017500000000073212551235562023756 0ustar eugeneeugenepackage org.testng; /** * If a test class implements this interface, its run() method * will be invoked instead of each configuration method found. The invocation of * the configuration method will then be performed upon invocation of the callBack() * method of the IConfigureCallBack parameter. * * @author cbeust * Sep 07, 2010 */ public interface IConfigurable extends ITestNGListener { public void run(IConfigureCallBack callBack, ITestResult testResult); } testng-testng-6.9.5/src/main/java/org/testng/IClass.java0000755000175000017500000000175112551235562022430 0ustar eugeneeugenepackage org.testng; import org.testng.xml.XmlClass; import org.testng.xml.XmlTest; import java.io.Serializable; /** * IClass represents a test class and a collection of its instances. * * @author Cedric Beust */ public interface IClass extends Serializable { /** * @return this test class name. This is the name of the * corresponding Java class. */ String getName(); /** * @return the <test> tag this class was found in. */ XmlTest getXmlTest(); /** * @return the *lt;class> tag this class was found in. */ XmlClass getXmlClass(); /** * If this class implements ITest, returns its test name, otherwise returns null. */ String getTestName(); /** * @return the Java class corresponding to this IClass. */ Class getRealClass(); Object[] getInstances(boolean create); int getInstanceCount(); long[] getInstanceHashCodes(); void addInstance(Object instance); } testng-testng-6.9.5/src/main/java/org/testng/IAttributes.java0000755000175000017500000000125212551235562023505 0ustar eugeneeugenepackage org.testng; import java.io.Serializable; import java.util.Set; /** * A trait that is used by all interfaces that lets the user add or remove their * own attributes. */ public interface IAttributes extends Serializable { /** * @param name The name of the attribute to return */ public Object getAttribute(String name); /** * Set a custom attribute. */ public void setAttribute(String name, Object value); /** * @return all the attributes names. */ public Set getAttributeNames(); /** * Remove the attribute * * @return the attribute value if found, null otherwise */ public Object removeAttribute(String name); } testng-testng-6.9.5/src/main/java/org/testng/IAnnotationTransformer2.java0000755000175000017500000000315712551235562026004 0ustar eugeneeugenepackage org.testng; import org.testng.annotations.IConfigurationAnnotation; import org.testng.annotations.IDataProviderAnnotation; import org.testng.annotations.IFactoryAnnotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; /** * Use this interface instead of IAnnotationTransformer if you want to modify any TestNG * annotation besides @Test. */ public interface IAnnotationTransformer2 extends IAnnotationTransformer { /** * Transform an IConfiguration annotation. * * Note that only one of the three parameters testClass, * testConstructor and testMethod will be non-null. * * @param annotation The annotation that was read from your * test class. * @param testClass If the annotation was found on a class, this * parameter represents this class (null otherwise). * @param testConstructor If the annotation was found on a constructor, * this parameter represents this constructor (null otherwise). * @param testMethod If the annotation was found on a method, * this parameter represents this method (null otherwise). */ public void transform(IConfigurationAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod); /** * Transform an IDataProvider annotation. * * @param method The method annotated with the IDataProvider annotation. */ public void transform(IDataProviderAnnotation annotation, Method method); /** * Transform an IFactory annotation. * * @param method The method annotated with the IFactory annotation. */ public void transform(IFactoryAnnotation annotation, Method method); } testng-testng-6.9.5/src/main/java/org/testng/IAnnotationTransformer.java0000755000175000017500000000221312551235562025712 0ustar eugeneeugenepackage org.testng; import org.testng.annotations.ITestAnnotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public interface IAnnotationTransformer extends ITestNGListener { /** * This method will be invoked by TestNG to give you a chance * to modify a TestNG annotation read from your test classes. * You can change the values you need by calling any of the * setters on the ITest interface. * * Note that only one of the three parameters testClass, * testConstructor and testMethod will be non-null. * * @param annotation The annotation that was read from your * test class. * @param testClass If the annotation was found on a class, this * parameter represents this class (null otherwise). * @param testConstructor If the annotation was found on a constructor, * this parameter represents this constructor (null otherwise). * @param testMethod If the annotation was found on a method, * this parameter represents this method (null otherwise). */ public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod); } testng-testng-6.9.5/src/main/java/org/testng/FileAssert.java0000755000175000017500000002267612551235562023324 0ustar eugeneeugenepackage org.testng; import java.io.File; import java.io.IOException; /** * Assertion tool for File centric assertions. * Conceptually this is an extension of {@link Assert} * Presents assertion methods with a more natural parameter order. * The order is always actualValue, expectedValue [, message]. * * @author Paul Mendelon * @since 5.6 * @version $Revision: 650 $, $Date: 2009-01-05 03:51:54 -0800 (Mon, 05 Jan 2009) $ */ public class FileAssert { /** * Protect constructor since it is a static only class */ private FileAssert() { // hide constructor } /** * Asserts that a {@code tstvalue} is a proper directory. If it isn't, * an AssertionError, with the given message, is thrown. * @param tstvalue the file to evaluate * @param message the assertion error message */ static public void assertDirectory(File tstvalue, String message) { boolean condition=false; try { condition=tstvalue.isDirectory(); } catch(SecurityException e) { failSecurity(e,tstvalue,fileType(tstvalue),"Directory", message); } if(!condition) { failFile(tstvalue,fileType(tstvalue),"Directory", message); } } static public void assertDirectory(File tstvalue) { assertDirectory(tstvalue, null); } /** * Asserts that a {@code tstvalue} is a proper directory. If it isn't, * an AssertionError, with the given message, is thrown. * @param tstvalue the file to evaluate * @param message the assertion error message */ static public void assertFile(File tstvalue, String message) { boolean condition=false; try { condition=tstvalue.isFile(); } catch(SecurityException e) { failSecurity(e,tstvalue,fileType(tstvalue),"File", message); } if(!condition) { failFile(tstvalue,fileType(tstvalue),"File", message); } } /** * @see #assertFile(File, String) */ static public void assertFile(File tstvalue) { assertFile(tstvalue, null); } /** * Asserts that a {@code tstvalue} is a file of exactly {@code expected} characters * or a directory of exactly {@code expected} entries. If it isn't, * an AssertionError, with the given message, is thrown. * @param tstvalue the file to evaluate * @param message the assertion error message */ static public void assertLength(File tstvalue, long expected, String message) { long actual=-1L; try { actual=tstvalue.isDirectory()?tstvalue.list().length:tstvalue.length(); } catch(SecurityException e) { failSecurity(e,tstvalue,String.valueOf(actual),String.valueOf(expected), message); } if(actual!=expected) { failFile(tstvalue,String.valueOf(actual),String.valueOf(expected), message); } } /** * @see #assertLength(File, long, String) */ static public void assertLength(File tstvalue, long expected) { assertLength(tstvalue, expected, null); } /** * Asserts that a {@code tstvalue} is a file of at least {@code expected} characters * or a directory of at least {@code expected} entries. If it isn't, * an AssertionError, with the given message, is thrown. * @param tstvalue the file to evaluate * @param message the assertion error message */ static public void assertMinLength(File tstvalue, long expected, String message) { long actual=-1L; try { actual=tstvalue.isDirectory()?tstvalue.list().length:tstvalue.length(); } catch(SecurityException e) { failSecurity(e,tstvalue,String.valueOf(actual),"at least "+String.valueOf(expected), message); } if(actualexpected) { failFile(tstvalue,String.valueOf(actual),"at most "+String.valueOf(expected), message); } } /** * @see #assertMaxLength(File, long, String) */ static public void assertMaxLength(File tstvalue, long expected) { assertMaxLength(tstvalue, expected, null); } /** * Asserts that a {@code tstvalue} is readable. If it isn't, * an AssertionError, with the given message, is thrown. * @param tstvalue the file to evaluate * @param message the assertion error message */ static public void assertReadable(File tstvalue, String message) { boolean condition=false; try { condition=tstvalue.canRead(); } catch(SecurityException e) { failSecurity(e,tstvalue,fileAccess(tstvalue),"Read Access", message); } if(!condition) { failFile(tstvalue,fileAccess(tstvalue),"Read Access", message); } } /** * @see #assertReadable(File, String) */ static public void assertReadable(File tstvalue) { assertReadable(tstvalue, null); } /** * Asserts that a {@code tstvalue} is writeable. If it isn't, * an AssertionError, with the given message, is thrown. * @param tstvalue the file to evaluate * @param message the assertion error message */ static public void assertWriteable(File tstvalue, String message) { boolean condition=false; try { condition=tstvalue.canWrite(); } catch(SecurityException e) { failSecurity(e,tstvalue,fileAccess(tstvalue),"Write Access", message); } if(!condition) { failFile(tstvalue,fileAccess(tstvalue),"Write Access", message); } } /** * @see #assertWriteable(File, String) */ static public void assertWriteable(File tstvalue) { assertReadable(tstvalue, null); } /** * Asserts that a {@code tstvalue} is readable and writeable. If it isn't, * an AssertionError, with the given message, is thrown. * @param tstvalue the file to evaluate * @param message the assertion error message */ static public void assertReadWrite(File tstvalue, String message) { boolean condition=false; try { condition=tstvalue.canRead() && tstvalue.canWrite(); } catch(SecurityException e) { failSecurity(e,tstvalue,fileAccess(tstvalue),"Read/Write Access", message); } if(!condition) { failFile(tstvalue,fileAccess(tstvalue),"Read/Write Access", message); } } /** * @see #assertReadWrite(File, String) */ static public void assertReadWrite(File tstvalue) { assertReadWrite(tstvalue, null); } /** * Fails a test with the given message and wrapping the original exception. * * @param message the assertion error message * @param realCause the original exception */ static public void fail(String message, Throwable realCause) { AssertionError ae = new AssertionError(message); ae.initCause(realCause); throw ae; } /** * Fails a test with the given message. * @param message the assertion error message */ static public void fail(String message) { throw new AssertionError(message); } /** * Fails a test with no message. */ static public void fail() { fail(null); } /** * Formats failure for file assertions */ private static void failFile(File path, String actual, String expected, String message) { String formatted = ""; if(message != null) { formatted = message + " "; } fail(formatted + "expected <" + expected +"> but was <" + toString(path) + ">" +(expected!=null?"<" + expected +">":"")); } /** * @param tstvalue * @param string * @param string2 * @param message */ private static void failSecurity(Exception e, File path, String actual, String expected, String message) { String formatted = ""; if(message != null) { formatted = message + " "; } fail(formatted + "expected <" + expected +"> but was <" + toString(path) + ">" +"<" + (e!=null && e.getMessage()!=null && e.getMessage().length()>0 ?e.getMessage() :"not authorized by JVM") + ">"); } /** * String representation of what sort of file {@code path} is. */ private static String fileType(File path) { try { if(!path.exists()) { return "Non existant"; } else if (path.isDirectory()) { return "Directory"; } else if (path.isFile()) { return "File"; } else { return "Special File"; } } catch (SecurityException e) { return "Unauthorized"; } } /** * String representation of what sort of file {@code path} is. */ private static String fileAccess(File path) { try { if(!path.exists()) { return "Non existant"; } else if (path.canWrite() && path.canRead()) { return "Read/Write Access"; } else if (path.canRead()) { return "Read only Access"; } else if (path.canWrite()) { return "Write only Access"; } else { return "No Access"; } } catch (SecurityException e) { return "Unauthorized"; } } private static String toString(File path) { try { return path.getCanonicalPath(); } catch(IOException e) { return path.getAbsolutePath(); } } } testng-testng-6.9.5/src/main/java/org/testng/DependencyMap.java0000644000175000017500000000440512551235562023762 0ustar eugeneeugenepackage org.testng; import org.testng.collections.ListMultiMap; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.collections.Sets; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.regex.Pattern; /** * Helper class to keep track of dependencies. * * @author Cedric Beust */ public class DependencyMap { private ListMultiMap m_dependencies = Maps.newListMultiMap(); private ListMultiMap m_groups = Maps.newListMultiMap(); public DependencyMap(ITestNGMethod[] methods) { for (ITestNGMethod m : methods) { m_dependencies.put( m.getRealClass().getName() + "." + m.getMethodName(), m); for (String g : m.getGroups()) { m_groups.put(g, m); } } } public List getMethodsThatBelongTo(String group, ITestNGMethod fromMethod) { Set uniqueKeys = m_groups.keySet(); List result = Lists.newArrayList(); for (String k : uniqueKeys) { if (Pattern.matches(group, k)) { List temp = m_groups.get(k); if (temp != null) result.addAll(m_groups.get(k)); } } if (result.isEmpty() && !fromMethod.ignoreMissingDependencies()) { throw new TestNGException("DependencyMap::Method \"" + fromMethod + "\" depends on nonexistent group \"" + group + "\""); } else { return result; } } public ITestNGMethod getMethodDependingOn(String methodName, ITestNGMethod fromMethod) { List l = m_dependencies.get(methodName); if (l == null && fromMethod.ignoreMissingDependencies()){ return fromMethod; } for (ITestNGMethod m : l) { // If they are in the same class hierarchy, they must belong to the same instance, // otherwise, it's a method depending on a method in a different class so we // don't bother checking the instance if (fromMethod.getRealClass().isAssignableFrom(m.getRealClass())) { if (m.getInstance() == fromMethod.getInstance()) return m; } else { return m; } } throw new TestNGException("Method \"" + fromMethod + "\" depends on nonexistent method \"" + methodName + "\""); } } testng-testng-6.9.5/src/main/java/org/testng/Converter.java0000644000175000017500000000561312551235562023217 0ustar eugeneeugenepackage org.testng; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; import org.testng.collections.Sets; import org.testng.internal.Yaml; import org.testng.xml.Parser; import org.testng.xml.XmlSuite; import org.xml.sax.SAXException; import javax.xml.parsers.ParserConfigurationException; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Set; /** * Convert XML files to YAML and vice versa. * * @author cbeust */ public class Converter { @Parameter(description = "file1 [file2 file3...]", required = true) private List m_files; @Parameter(names = "-d", description = "The directory where the file(s) will be created") private String m_outputDirectory = "."; public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { Converter c = new Converter(); c.run(args); } private void findAllSuites(Collection suites, Set result) { for (XmlSuite s : suites) { result.add(s); for (XmlSuite xs : s.getChildSuites()) { findAllSuites(Arrays.asList(xs), result); } } } private void run(String[] args) throws ParserConfigurationException, SAXException, IOException { JCommander jc = new JCommander(this); try { jc.parse(args); File f = new File(m_outputDirectory); if (! f.exists()) f.mkdir(); for (String file : m_files) { Set allSuites = Sets.newHashSet(); Parser parser = new Parser(file); parser.setLoadClasses(false); // we might not have these classes on the classpath findAllSuites(parser.parse(), allSuites); for (XmlSuite suite : allSuites) { String fileName = suite.getFileName(); int ind = fileName.lastIndexOf("."); String bn = fileName.substring(0, ind); int ind2 = bn.lastIndexOf(File.separatorChar); String baseName = bn.substring(ind2 + 1); if (file.endsWith(".xml")) { File newFile = new File(m_outputDirectory, baseName + ".yaml"); writeFile(newFile, Yaml.toYaml(suite).toString()); } else if (file.endsWith(".yaml")) { File newFile = new File(m_outputDirectory, baseName + ".xml"); writeFile(newFile, suite.toXml()); } else { throw new TestNGException("Unknown file type:" + file); } } } } catch(ParameterException ex) { System.out.println("Error: " + ex.getMessage()); jc.usage(); } } private void writeFile(File newFile, String content) throws IOException { FileWriter bw = new FileWriter(newFile); bw.write(content); bw.close(); System.out.println("Wrote " + newFile); } } testng-testng-6.9.5/src/main/java/org/testng/ConversionUtils.java0000644000175000017500000000247212551235562024416 0ustar eugeneeugenepackage org.testng; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * Helper methods used by the Eclipse plug-in when converting tests from JUnit. * * @author Cedric Beust * */ public class ConversionUtils { /** * Turns the output of a JUnit 4 @Parameters style data provider into * one that is suitable for TestNG's @DataProvider. */ public static Object[] wrapDataProvider(Class cls, Collection data) { List result = new ArrayList(); for (Object o : data) { Object[] parameters = (Object[]) o; Constructor ctor = null; try { for (Constructor c : cls.getConstructors()) { // Just comparing parameter array sizes. Comparing the parameter types // is more error prone since we need to take conversions into account // (int -> Integer, etc...). if (c.getParameterTypes().length == parameters.length) { ctor = c; break; } } if (ctor == null) { throw new TestNGException("Couldn't find a constructor in " + cls); } result.add(ctor.newInstance(parameters)); } catch (Exception ex) { ex.printStackTrace(); } } return result.toArray(); } } testng-testng-6.9.5/src/main/java/org/testng/CommandLineArgs.java0000644000175000017500000001507512551235562024256 0ustar eugeneeugenepackage org.testng; import com.beust.jcommander.Parameter; import com.beust.jcommander.converters.CommaParameterSplitter; import org.testng.collections.Lists; import java.util.ArrayList; import java.util.List; public class CommandLineArgs { @Parameter(description = "The XML suite files to run") public List suiteFiles = Lists.newArrayList(); public static final String LOG = "-log"; public static final String VERBOSE = "-verbose"; @Parameter(names = { LOG, VERBOSE }, description = "Level of verbosity") public Integer verbose; public static final String GROUPS = "-groups"; @Parameter(names = GROUPS, description = "Comma-separated list of group names to be run") public String groups; public static final String EXCLUDED_GROUPS = "-excludegroups"; @Parameter(names = EXCLUDED_GROUPS, description ="Comma-separated list of group names to " + " exclude") public String excludedGroups; public static final String OUTPUT_DIRECTORY = "-d"; @Parameter(names = OUTPUT_DIRECTORY, description ="Output directory") public String outputDirectory; public static final String JUNIT = "-junit"; @Parameter(names = JUNIT, description ="JUnit mode") public Boolean junit = Boolean.FALSE; public static final String MIXED = "-mixed"; @Parameter(names = MIXED, description ="Mixed mode - autodetect the type of current test" + " and run it with appropriate runner") public Boolean mixed = Boolean.FALSE; public static final String LISTENER = "-listener"; @Parameter(names = LISTENER, description = "List of .class files or list of class names" + " implementing ITestListener or ISuiteListener") public String listener; public static final String METHOD_SELECTORS = "-methodselectors"; @Parameter(names = METHOD_SELECTORS, description = "List of .class files or list of class " + "names implementing IMethodSelector") public String methodSelectors; public static final String OBJECT_FACTORY = "-objectfactory"; @Parameter(names = OBJECT_FACTORY, description = "List of .class files or list of class " + "names implementing ITestRunnerFactory") public String objectFactory; public static final String PARALLEL= "-parallel"; @Parameter(names = PARALLEL, description = "Parallel mode (methods, tests or classes)") public String parallelMode; public static final String CONFIG_FAILURE_POLICY = "-configfailurepolicy"; @Parameter(names = CONFIG_FAILURE_POLICY , description = "Configuration failure policy (skip or continue)") public String configFailurePolicy; public static final String THREAD_COUNT = "-threadcount"; @Parameter(names = THREAD_COUNT, description = "Number of threads to use when running tests " + "in parallel") public Integer threadCount; public static final String DATA_PROVIDER_THREAD_COUNT = "-dataproviderthreadcount"; @Parameter(names = DATA_PROVIDER_THREAD_COUNT, description = "Number of threads to use when " + "running data providers") public Integer dataProviderThreadCount; public static final String SUITE_NAME = "-suitename"; @Parameter(names = SUITE_NAME, description = "Default name of test suite, if not specified " + "in suite definition file or source code") public String suiteName; public static final String TEST_NAME = "-testname"; @Parameter(names = TEST_NAME, description = "Default name of test, if not specified in suite" + "definition file or source code") public String testName; public static final String REPORTER = "-reporter"; @Parameter(names = REPORTER, description = "Extended configuration for custom report listener") public String reporter; public static final String USE_DEFAULT_LISTENERS = "-usedefaultlisteners"; @Parameter(names = USE_DEFAULT_LISTENERS, description = "Whether to use the default listeners") public String useDefaultListeners = "true"; public static final String SKIP_FAILED_INVOCATION_COUNTS = "-skipfailedinvocationcounts"; @Parameter(names = SKIP_FAILED_INVOCATION_COUNTS, hidden = true) public Boolean skipFailedInvocationCounts; public static final String TEST_CLASS = "-testclass"; @Parameter(names = TEST_CLASS, description = "The list of test classes") public String testClass; public static final String TEST_NAMES = "-testnames"; @Parameter(names = TEST_NAMES, description = "The list of test names to run") public String testNames; public static final String TEST_JAR = "-testjar"; @Parameter(names = TEST_JAR, description = "A jar file containing the tests") public String testJar; public static final String XML_PATH_IN_JAR = "-xmlpathinjar"; public static final String XML_PATH_IN_JAR_DEFAULT = "testng.xml"; @Parameter(names = XML_PATH_IN_JAR, description = "The full path to the xml file inside the jar file (only valid if -testjar was specified)") public String xmlPathInJar = XML_PATH_IN_JAR_DEFAULT; public static final String TEST_RUNNER_FACTORY = "-testrunfactory"; @Parameter(names = { TEST_RUNNER_FACTORY, "-testRunFactory" }, description = "The factory used to create tests") public String testRunnerFactory; public static final String PORT = "-port"; @Parameter(names = PORT, description = "The port") public Integer port; public static final String HOST = "-host"; @Parameter(names = HOST, description = "The host", hidden = true) public String host; public static final String MASTER = "-master"; @Parameter(names = MASTER, description = "Host where the master is", hidden = true) public String master; public static final String SLAVE = "-slave"; @Parameter(names = SLAVE, description = "Host where the slave is", hidden = true) public String slave; public static final String METHODS = "-methods"; @Parameter(names = METHODS, description = "Comma separated of test methods", splitter = CommaParameterSplitter.class) public List commandLineMethods = new ArrayList<>(); public static final String SUITE_THREAD_POOL_SIZE = "-suitethreadpoolsize"; public static final Integer SUITE_THREAD_POOL_SIZE_DEFAULT = 1; @Parameter(names = SUITE_THREAD_POOL_SIZE, description = "Size of the thread pool to use" + " to run suites") public Integer suiteThreadPoolSize = SUITE_THREAD_POOL_SIZE_DEFAULT; public static final String RANDOMIZE_SUITES = "-randomizesuites"; @Parameter(names = RANDOMIZE_SUITES, hidden = true, description = "Whether to run suites in same order as specified in XML or not") public Boolean randomizeSuites = Boolean.FALSE; public static final String DEBUG = "-debug"; @Parameter(names = DEBUG, hidden = true, description = "Used to debug TestNG") public Boolean debug = Boolean.FALSE; } testng-testng-6.9.5/src/main/java/org/testng/ClassMethodMap.java0000755000175000017500000000551412551235562024117 0ustar eugeneeugenepackage org.testng; import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.internal.XmlMethodSelector; import java.util.List; import java.util.Map; import java.util.Set; /** * This class maintains a map of >. * It is used by TestWorkers to determine if the method they just ran * is the last of its class, in which case it's time to invoke all the * afterClass methods. * * @author Alex Popescu */ public class ClassMethodMap { private Map> m_classMap = Maps.newHashMap(); // These two variables are used throughout the workers to keep track // of what beforeClass/afterClass methods have been invoked private Map> m_beforeClassMethods = Maps.newHashMap(); private Map> m_afterClassMethods = Maps.newHashMap(); public ClassMethodMap(List methods, XmlMethodSelector xmlMethodSelector) { for (ITestNGMethod m : methods) { // Only add to the class map methods that are included in the // method selector. We can pass a null context here since the selector // should already have been initialized if (xmlMethodSelector != null){ if (! xmlMethodSelector.includeMethod(null, m, true)) continue; } Object instance = m.getInstance(); List l = m_classMap.get(instance); if (l == null) { l = Lists.newArrayList(); m_classMap.put(instance, l); } l.add(m); } } /** * Remove the method from this map and returns true if it is the last * of its class. */ public synchronized boolean removeAndCheckIfLast(ITestNGMethod m, Object instance) { List l = m_classMap.get(instance); if (l != null) { l.remove(m); // It's the last method of this class if all the methods remaining in the list belong to a // different class for (ITestNGMethod tm : l) { if (tm.getEnabled() && tm.getTestClass().equals(m.getTestClass())) return false; } return true; } else { throw new AssertionError("l should not be null"); } } private Class getMethodClass(ITestNGMethod m) { return m.getTestClass().getRealClass(); } public Map> getInvokedBeforeClassMethods() { return m_beforeClassMethods; } public Map> getInvokedAfterClassMethods() { return m_afterClassMethods; } public void clear() { for(Set instances: m_beforeClassMethods.values()) { instances.clear(); instances= null; } for(Set instances: m_afterClassMethods.values()) { instances.clear(); instances= null; } m_beforeClassMethods.clear(); m_afterClassMethods.clear(); } } testng-testng-6.9.5/src/main/java/org/testng/AssertJUnit.java0000755000175000017500000002527112551235562023470 0ustar eugeneeugenepackage org.testng; import org.testng.internal.junit.ArrayAsserts; /** * A set of assert methods. Messages are only displayed when an assert fails. * Renamed from junit.framework.Assert. */ public class AssertJUnit extends ArrayAsserts { /** * Protect constructor since it is a static only class */ protected AssertJUnit() { } /** * Asserts that a condition is true. If it isn't it throws * an AssertionFailedError with the given message. */ static public void assertTrue(String message, boolean condition) { if(!condition) { fail(message); } } /** * Asserts that a condition is true. If it isn't it throws * an AssertionFailedError. */ static public void assertTrue(boolean condition) { assertTrue(null, condition); } /** * Asserts that a condition is false. If it isn't it throws * an AssertionFailedError with the given message. */ static public void assertFalse(String message, boolean condition) { assertTrue(message, !condition); } /** * Asserts that a condition is false. If it isn't it throws * an AssertionFailedError. */ static public void assertFalse(boolean condition) { assertFalse(null, condition); } /** * Fails a test with the given message. */ static public void fail(String message) { if (null == message) { message = ""; } throw new AssertionError(message); } /** * Fails a test with no message. */ static public void fail() { fail(null); } /** * Asserts that two objects are equal. If they are not * an AssertionFailedError is thrown with the given message. */ static public void assertEquals(String message, Object expected, Object actual) { if((expected == null) && (actual == null)) { return; } if((expected != null) && expected.equals(actual)) { return; } failNotEquals(message, expected, actual); } /** * Asserts that two objects are equal. If they are not * an AssertionFailedError is thrown. */ static public void assertEquals(Object expected, Object actual) { assertEquals(null, expected, actual); } /** * Asserts that two Strings are equal. */ static public void assertEquals(String message, String expected, String actual) { if((expected == null) && (actual == null)) { return; } if((expected != null) && expected.equals(actual)) { return; } throw new AssertionError(format(message, expected, actual)); } /** * Asserts that two Strings are equal. */ static public void assertEquals(String expected, String actual) { assertEquals(null, expected, actual); } /** * Asserts that two doubles are equal concerning a delta. If they are not * an AssertionFailedError is thrown with the given message. If the expected * value is infinity then the delta value is ignored. */ static public void assertEquals(String message, double expected, double actual, double delta) { // handle infinity specially since subtracting to infinite values gives NaN and the // the following test fails if(Double.isInfinite(expected)) { if(!(expected == actual)) { failNotEquals(message, expected, actual); } } else if(!(Math.abs(expected - actual) <= delta)) { // Because comparison with NaN always returns false failNotEquals(message, expected, actual); } } /** * Asserts that two doubles are equal concerning a delta. If the expected * value is infinity then the delta value is ignored. */ static public void assertEquals(double expected, double actual, double delta) { assertEquals(null, expected, actual, delta); } /** * Asserts that two floats are equal concerning a delta. If they are not * an AssertionFailedError is thrown with the given message. If the expected * value is infinity then the delta value is ignored. */ static public void assertEquals(String message, float expected, float actual, float delta) { // handle infinity specially since subtracting to infinite values gives NaN and the // the following test fails if(Float.isInfinite(expected)) { if(!(expected == actual)) { failNotEquals(message, expected, actual); } } else if(!(Math.abs(expected - actual) <= delta)) { failNotEquals(message, expected, actual); } } /** * Asserts that two floats are equal concerning a delta. If the expected * value is infinity then the delta value is ignored. */ static public void assertEquals(float expected, float actual, float delta) { assertEquals(null, expected, actual, delta); } /** * Asserts that two longs are equal. If they are not * an AssertionFailedError is thrown with the given message. */ static public void assertEquals(String message, long expected, long actual) { assertEquals(message, Long.valueOf(expected), Long.valueOf(actual)); } /** * Asserts that two longs are equal. */ static public void assertEquals(long expected, long actual) { assertEquals(null, expected, actual); } /** * Asserts that two booleans are equal. If they are not * an AssertionFailedError is thrown with the given message. */ static public void assertEquals(String message, boolean expected, boolean actual) { assertEquals(message, Boolean.valueOf(expected), Boolean.valueOf(actual)); } /** * Asserts that two booleans are equal. */ static public void assertEquals(boolean expected, boolean actual) { assertEquals(null, expected, actual); } /** * Asserts that two bytes are equal. If they are not * an AssertionFailedError is thrown with the given message. */ static public void assertEquals(String message, byte expected, byte actual) { assertEquals(message, Byte.valueOf(expected), Byte.valueOf(actual)); } /** * Asserts that two bytes are equal. */ static public void assertEquals(byte expected, byte actual) { assertEquals(null, expected, actual); } /** * Asserts that two chars are equal. If they are not * an AssertionFailedError is thrown with the given message. */ static public void assertEquals(String message, char expected, char actual) { assertEquals(message, Character.valueOf(expected), Character.valueOf(actual)); } /** * Asserts that two chars are equal. */ static public void assertEquals(char expected, char actual) { assertEquals(null, expected, actual); } /** * Asserts that two shorts are equal. If they are not * an AssertionFailedError is thrown with the given message. */ static public void assertEquals(String message, short expected, short actual) { assertEquals(message, Short.valueOf(expected), Short.valueOf(actual)); } /** * Asserts that two shorts are equal. */ static public void assertEquals(short expected, short actual) { assertEquals(null, expected, actual); } /** * Asserts that two ints are equal. If they are not * an AssertionFailedError is thrown with the given message. */ static public void assertEquals(String message, int expected, int actual) { assertEquals(message, Integer.valueOf(expected), Integer.valueOf(actual)); } /** * Asserts that two ints are equal. */ static public void assertEquals(int expected, int actual) { assertEquals(null, expected, actual); } /** * Asserts that an object isn't null. */ static public void assertNotNull(Object object) { assertNotNull(null, object); } /** * Asserts that an object isn't null. If it is * an AssertionFailedError is thrown with the given message. */ static public void assertNotNull(String message, Object object) { assertTrue(message, object != null); } /** * Asserts that an object is null. */ static public void assertNull(Object object) { assertNull(null, object); } /** * Asserts that an object is null. If it is not * an AssertionFailedError is thrown with the given message. */ static public void assertNull(String message, Object object) { assertTrue(message, object == null); } /** * Asserts that two objects refer to the same object. If they are not * an AssertionFailedError is thrown with the given message. */ static public void assertSame(String message, Object expected, Object actual) { if(expected == actual) { return; } failNotSame(message, expected, actual); } /** * Asserts that two objects refer to the same object. If they are not * the same an AssertionFailedError is thrown. */ static public void assertSame(Object expected, Object actual) { assertSame(null, expected, actual); } /** * Asserts that two objects refer to the same object. If they are not * an AssertionFailedError is thrown with the given message. */ static public void assertNotSame(String message, Object expected, Object actual) { if(expected == actual) { failSame(message); } } /** * Asserts that two objects refer to the same object. If they are not * the same an AssertionFailedError is thrown. */ static public void assertNotSame(Object expected, Object actual) { assertNotSame(null, expected, actual); } static public void assertEquals(final byte[] expected, final byte[] actual) { assertEquals("", expected, actual); } static public void assertEquals(final String message, final byte[] expected, final byte[] actual) { if(expected == actual) { return; } if(null == expected) { fail("expected a null array, but not null found. " + message); } if(null == actual) { fail("expected not null array, but null found. " + message); } assertEquals("arrays don't have the same size. " + message, expected.length, actual.length); for(int i= 0; i < expected.length; i++) { if(expected[i] != actual[i]) { fail("arrays differ firstly at element [" + i +"]; " + format(message, expected[i], actual[i])); } } } static private void failSame(String message) { String formatted = ""; if(message != null) { formatted = message + " "; } fail(formatted + "expected not same"); } static private void failNotSame(String message, Object expected, Object actual) { String formatted = ""; if(message != null) { formatted = message + " "; } fail(formatted + "expected same:<" + expected + "> was not:<" + actual + ">"); } static private void failNotEquals(String message, Object expected, Object actual) { fail(format(message, expected, actual)); } static String format(String message, Object expected, Object actual) { String formatted = ""; if(message != null) { formatted = message + " "; } return formatted + "expected:<" + expected + "> but was:<" + actual + ">"; } } testng-testng-6.9.5/src/main/java/org/testng/Assert.java0000644000175000017500000010155112551235562022507 0ustar eugeneeugenepackage org.testng; import static org.testng.internal.EclipseInterface.ASSERT_LEFT; import static org.testng.internal.EclipseInterface.ASSERT_LEFT2; import static org.testng.internal.EclipseInterface.ASSERT_MIDDLE; import static org.testng.internal.EclipseInterface.ASSERT_RIGHT; import org.testng.collections.Lists; import java.lang.reflect.Array; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; /** * Assertion tool class. Presents assertion methods with a more natural parameter order. * The order is always actualValue, expectedValue [, message]. * * @author Alexandru Popescu */ public class Assert { /** * Protect constructor since it is a static only class */ protected Assert() { // hide constructor } /** * Asserts that a condition is true. If it isn't, * an AssertionError, with the given message, is thrown. * @param condition the condition to evaluate * @param message the assertion error message */ static public void assertTrue(boolean condition, String message) { if(!condition) { failNotEquals(condition, Boolean.TRUE, message); } } /** * Asserts that a condition is true. If it isn't, * an AssertionError is thrown. * @param condition the condition to evaluate */ static public void assertTrue(boolean condition) { assertTrue(condition, null); } /** * Asserts that a condition is false. If it isn't, * an AssertionError, with the given message, is thrown. * @param condition the condition to evaluate * @param message the assertion error message */ static public void assertFalse(boolean condition, String message) { if(condition) { failNotEquals(condition, Boolean.FALSE, message); // TESTNG-81 } } /** * Asserts that a condition is false. If it isn't, * an AssertionError is thrown. * @param condition the condition to evaluate */ static public void assertFalse(boolean condition) { assertFalse(condition, null); } /** * Fails a test with the given message and wrapping the original exception. * * @param message the assertion error message * @param realCause the original exception */ static public void fail(String message, Throwable realCause) { AssertionError ae = new AssertionError(message); ae.initCause(realCause); throw ae; } /** * Fails a test with the given message. * @param message the assertion error message */ static public void fail(String message) { throw new AssertionError(message); } /** * Fails a test with no message. */ static public void fail() { fail(null); } /** * Asserts that two objects are equal. If they are not, * an AssertionError, with the given message, is thrown. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertEquals(Object actual, Object expected, String message) { if((expected == null) && (actual == null)) { 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); } /** * Asserts that two objects are equal. It they are not, an AssertionError, * with given message, is thrown. * @param actual the actual value * @param expected the expected value (should be an non-null array value) * @param message the assertion error message */ private static void assertArrayEquals(Object actual, Object expected, String message) { //is called only when expected is an array if (actual.getClass().isArray()) { int expectedLength = Array.getLength(expected); if (expectedLength == Array.getLength(actual)) { for (int i = 0 ; i < expectedLength ; i++) { Object _actual = Array.get(actual, i); Object _expected = Array.get(expected, i); try { assertEquals(_actual, _expected); } catch (AssertionError ae) { failNotEquals(actual, expected, message == null ? "" : message + " (values at index " + i + " are not the same)"); } } //array values matched return; } else { failNotEquals(Array.getLength(actual), expectedLength, message == null ? "" : message + " (Array lengths are not the same)"); } } failNotEquals(actual, expected, message); } /** * Asserts that two objects are equal. If they are not, * an AssertionError is thrown. * @param actual the actual value * @param expected the expected value */ static public void assertEquals(Object actual, Object expected) { assertEquals(actual, expected, null); } /** * Asserts that two Strings are equal. If they are not, * an AssertionError, with the given message, is thrown. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertEquals(String actual, String expected, String message) { assertEquals((Object) actual, (Object) expected, message); } /** * Asserts that two Strings are equal. If they are not, * an AssertionError is thrown. * @param actual the actual value * @param expected the expected value */ static public void assertEquals(String actual, String expected) { assertEquals(actual, expected, null); } /** * Asserts that two doubles are equal concerning a delta. If they are not, * an AssertionError, with the given message, is thrown. If the expected * value is infinity then the delta value is ignored. * @param actual the actual value * @param expected the expected value * @param delta the absolute tolerable difference between the actual and expected values * @param message the assertion error message */ static public void assertEquals(double actual, double expected, double delta, String message) { // handle infinity specially since subtracting to infinite values gives NaN and the // the following test fails if(Double.isInfinite(expected)) { if(!(expected == actual)) { failNotEquals(actual, expected, message); } } else if(!(Math.abs(expected - actual) <= delta)) { // Because comparison with NaN always returns false failNotEquals(actual, expected, message); } } /** * Asserts that two doubles are equal concerning a delta. If they are not, * an AssertionError is thrown. If the expected value is infinity then the * delta value is ignored. * @param actual the actual value * @param expected the expected value * @param delta the absolute tolerable difference between the actual and expected values */ static public void assertEquals(double actual, double expected, double delta) { assertEquals(actual, expected, delta, null); } /** * Asserts that two floats are equal concerning a delta. If they are not, * an AssertionError, with the given message, is thrown. If the expected * value is infinity then the delta value is ignored. * @param actual the actual value * @param expected the expected value * @param delta the absolute tolerable difference between the actual and expected values * @param message the assertion error message */ static public void assertEquals(float actual, float expected, float delta, String message) { // handle infinity specially since subtracting to infinite values gives NaN and the // the following test fails if(Float.isInfinite(expected)) { if(!(expected == actual)) { failNotEquals(actual, expected, message); } } else if(!(Math.abs(expected - actual) <= delta)) { failNotEquals(actual, expected, message); } } /** * Asserts that two floats are equal concerning a delta. If they are not, * an AssertionError is thrown. If the expected * value is infinity then the delta value is ignored. * @param actual the actual value * @param expected the expected value * @param delta the absolute tolerable difference between the actual and expected values */ static public void assertEquals(float actual, float expected, float delta) { assertEquals(actual, expected, delta, null); } /** * Asserts that two longs are equal. If they are not, * an AssertionError, with the given message, is thrown. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertEquals(long actual, long expected, String message) { assertEquals(Long.valueOf(actual), Long.valueOf(expected), message); } /** * Asserts that two longs are equal. If they are not, * an AssertionError is thrown. * @param actual the actual value * @param expected the expected value */ static public void assertEquals(long actual, long expected) { assertEquals(actual, expected, null); } /** * Asserts that two booleans are equal. If they are not, * an AssertionError, with the given message, is thrown. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertEquals(boolean actual, boolean expected, String message) { assertEquals( Boolean.valueOf(actual), Boolean.valueOf(expected), message); } /** * Asserts that two booleans are equal. If they are not, * an AssertionError is thrown. * @param actual the actual value * @param expected the expected value */ static public void assertEquals(boolean actual, boolean expected) { assertEquals(actual, expected, null); } /** * Asserts that two bytes are equal. If they are not, * an AssertionError, with the given message, is thrown. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertEquals(byte actual, byte expected, String message) { assertEquals(Byte.valueOf(actual), Byte.valueOf(expected), message); } /** * Asserts that two bytes are equal. If they are not, * an AssertionError is thrown. * @param actual the actual value * @param expected the expected value */ static public void assertEquals(byte actual, byte expected) { assertEquals(actual, expected, null); } /** * Asserts that two chars are equal. If they are not, * an AssertionFailedError, with the given message, is thrown. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertEquals(char actual, char expected, String message) { assertEquals(Character.valueOf(actual), Character.valueOf(expected), message); } /** * Asserts that two chars are equal. If they are not, * an AssertionError is thrown. * @param actual the actual value * @param expected the expected value */ static public void assertEquals(char actual, char expected) { assertEquals(actual, expected, null); } /** * Asserts that two shorts are equal. If they are not, * an AssertionFailedError, with the given message, is thrown. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertEquals(short actual, short expected, String message) { assertEquals(Short.valueOf(actual), Short.valueOf(expected), message); } /** * Asserts that two shorts are equal. If they are not, * an AssertionError is thrown. * @param actual the actual value * @param expected the expected value */ static public void assertEquals(short actual, short expected) { assertEquals(actual, expected, null); } /** * Asserts that two ints are equal. If they are not, * an AssertionFailedError, with the given message, is thrown. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertEquals(int actual, int expected, String message) { assertEquals(Integer.valueOf(actual), Integer.valueOf(expected), message); } /** * Asserts that two ints are equal. If they are not, * an AssertionError is thrown. * @param actual the actual value * @param expected the expected value */ static public void assertEquals(int actual, int expected) { assertEquals(actual, expected, null); } /** * Asserts that an object isn't null. If it is, * an AssertionError is thrown. * @param object the assertion object */ static public void assertNotNull(Object object) { assertNotNull(object, null); } /** * Asserts that an object isn't null. If it is, * an AssertionFailedError, with the given message, is thrown. * @param object the assertion object * @param message the assertion error message */ static public void assertNotNull(Object object, String message) { if (object == null) { String formatted = ""; if(message != null) { formatted = message + " "; } fail(formatted + "expected object to not be null"); } assertTrue(object != null, message); } /** * Asserts that an object is null. If it is not, * an AssertionError, with the given message, is thrown. * @param object the assertion object */ static public void assertNull(Object object) { assertNull(object, null); } /** * Asserts that an object is null. If it is not, * an AssertionFailedError, with the given message, is thrown. * @param object the assertion object * @param message the assertion error message */ static public void assertNull(Object object, String message) { if (object != null) { failNotSame(object, null, message); } } /** * Asserts that two objects refer to the same object. If they do not, * an AssertionFailedError, with the given message, is thrown. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertSame(Object actual, Object expected, String message) { if(expected == actual) { return; } failNotSame(actual, expected, message); } /** * Asserts that two objects refer to the same object. If they do not, * an AssertionError is thrown. * @param actual the actual value * @param expected the expected value */ static public void assertSame(Object actual, Object expected) { assertSame(actual, expected, null); } /** * Asserts that two objects do not refer to the same objects. If they do, * an AssertionError, with the given message, is thrown. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertNotSame(Object actual, Object expected, String message) { if(expected == actual) { failSame(actual, expected, message); } } /** * Asserts that two objects do not refer to the same object. If they do, * an AssertionError is thrown. * @param actual the actual value * @param expected the expected value */ static public void assertNotSame(Object actual, Object expected) { assertNotSame(actual, expected, null); } static private void failSame(Object actual, Object expected, String message) { String formatted = ""; if(message != null) { formatted = message + " "; } fail(formatted + ASSERT_LEFT2 + expected + ASSERT_MIDDLE + actual + ASSERT_RIGHT); } static private void failNotSame(Object actual, Object expected, String message) { String formatted = ""; if(message != null) { formatted = message + " "; } fail(formatted + ASSERT_LEFT + expected + ASSERT_MIDDLE + actual + ASSERT_RIGHT); } static private void failNotEquals(Object actual , Object expected, String message ) { fail(format(actual, expected, message)); } static String format(Object actual, Object expected, String message) { String formatted = ""; if (null != message) { formatted = message + " "; } return formatted + ASSERT_LEFT + expected + ASSERT_MIDDLE + actual + ASSERT_RIGHT; } /** * Asserts that two collections contain the same elements in the same order. If they do not, * an AssertionError is thrown. * * @param actual the actual value * @param expected the expected value */ static public void assertEquals(Collection actual, Collection expected) { assertEquals(actual, expected, null); } /** * Asserts that two collections contain the same elements in the same order. If they do not, * an AssertionError, with the given message, is thrown. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertEquals(Collection actual, Collection expected, String message) { if(actual == expected) { return; } if (actual == null || expected == null) { if (message != null) { fail(message); } else { fail("Collections not equal: expected: " + expected + " and actual: " + actual); } } assertEquals(actual.size(), expected.size(), (message == null ? "" : message + ": ") + "lists don't have the same size"); Iterator actIt = actual.iterator(); Iterator expIt = expected.iterator(); int i = -1; while(actIt.hasNext() && expIt.hasNext()) { i++; Object e = expIt.next(); Object a = actIt.next(); String explanation = "Lists differ at element [" + i + "]: " + e + " != " + a; String errorMessage = message == null ? explanation : message + ": " + explanation; assertEquals(a, e, errorMessage); } } /** Asserts that two iterators return the same elements in the same order. If they do not, * an AssertionError is thrown. * Please note that this assert iterates over the elements and modifies the state of the iterators. * @param actual the actual value * @param expected the expected value */ static public void assertEquals(Iterator actual, Iterator expected) { assertEquals(actual, expected, null); } /** Asserts that two iterators return the same elements in the same order. If they do not, * an AssertionError, with the given message, is thrown. * Please note that this assert iterates over the elements and modifies the state of the iterators. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertEquals(Iterator actual, Iterator expected, String message) { if(actual == expected) { return; } if(actual == null || expected == null) { if(message != null) { fail(message); } else { fail("Iterators not equal: expected: " + expected + " and actual: " + actual); } } int i = -1; while(actual.hasNext() && expected.hasNext()) { i++; Object e = expected.next(); Object a = actual.next(); String explanation = "Iterators differ at element [" + i + "]: " + e + " != " + a; String errorMessage = message == null ? explanation : message + ": " + explanation; assertEquals(a, e, errorMessage); } if(actual.hasNext()) { String explanation = "Actual iterator returned more elements than the expected iterator."; String errorMessage = message == null ? explanation : message + ": " + explanation; fail(errorMessage); } else if(expected.hasNext()) { String explanation = "Expected iterator returned more elements than the actual iterator."; String errorMessage = message == null ? explanation : message + ": " + explanation; fail(errorMessage); } } /** Asserts that two iterables return iterators with the same elements in the same order. If they do not, * an AssertionError is thrown. * @param actual the actual value * @param expected the expected value */ static public void assertEquals(Iterable actual, Iterable expected) { assertEquals(actual, expected, null); } /** Asserts that two iterables return iterators with the same elements in the same order. If they do not, * an AssertionError, with the given message, is thrown. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertEquals(Iterable actual, Iterable expected, String message) { if(actual == expected) { return; } if(actual == null || expected == null) { if(message != null) { fail(message); } else { fail("Iterables not equal: expected: " + expected + " and actual: " + actual); } } Iterator actIt = actual.iterator(); Iterator expIt = expected.iterator(); assertEquals(actIt, expIt, message); } /** * Asserts that two arrays contain the same elements in the same order. If they do not, * an AssertionError, with the given message, is thrown. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertEquals(Object[] actual, Object[] expected, String message) { if(actual == expected) { return; } if ((actual == null && expected != null) || (actual != null && expected == null)) { if (message != null) { fail(message); } else { fail("Arrays not equal: " + Arrays.toString(expected) + " and " + Arrays.toString(actual)); } } assertEquals(Arrays.asList(actual), Arrays.asList(expected), message); } /** * Asserts that two arrays contain the same elements in no particular order. If they do not, * an AssertionError, with the given message, is thrown. * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertEqualsNoOrder(Object[] actual, Object[] expected, String message) { if(actual == expected) { return; } if ((actual == null && expected != null) || (actual != null && expected == null)) { failAssertNoEqual( "Arrays not equal: " + Arrays.toString(expected) + " and " + Arrays.toString(actual), message); } if (actual.length != expected.length) { failAssertNoEqual( "Arrays do not have the same size:" + actual.length + " != " + expected.length, message); } List actualCollection = Lists.newArrayList(); for (Object a : actual) { actualCollection.add(a); } for (Object o : expected) { actualCollection.remove(o); } if (actualCollection.size() != 0) { failAssertNoEqual( "Arrays not equal: " + Arrays.toString(expected) + " and " + Arrays.toString(actual), message); } } private static void failAssertNoEqual(String defaultMessage, String message) { if (message != null) { fail(message); } else { fail(defaultMessage); } } /** * Asserts that two arrays contain the same elements in the same order. If they do not, * an AssertionError is thrown. * * @param actual the actual value * @param expected the expected value */ static public void assertEquals(Object[] actual, Object[] expected) { assertEquals(actual, expected, null); } /** * Asserts that two arrays contain the same elements in no particular order. If they do not, * an AssertionError is thrown. * @param actual the actual value * @param expected the expected value */ static public void assertEqualsNoOrder(Object[] actual, Object[] expected) { assertEqualsNoOrder(actual, expected, null); } /** * Asserts that two arrays contain the same elements in the same order. If they do not, * an AssertionError is thrown. * * @param actual the actual value * @param expected the expected value */ static public void assertEquals(final byte[] actual, final byte[] expected) { assertEquals(actual, expected, ""); } /** * Asserts that two arrays contain the same elements in the same order. If they do not, * an AssertionError, with the given message, is thrown. * * @param actual the actual value * @param expected the expected value * @param message the assertion error message */ static public void assertEquals(final byte[] actual, final byte[] expected, final String message) { if(expected == actual) { return; } if(null == expected) { fail("expected a null array, but not null found. " + message); } if(null == actual) { fail("expected not null array, but null found. " + message); } assertEquals(actual.length, expected.length, "arrays don't have the same size. " + message); for(int i= 0; i < expected.length; i++) { if(expected[i] != actual[i]) { fail("arrays differ firstly at element [" + i +"]; " + "expected value is <" + expected[i] +"> but was <" + actual[i] + ">. " + message); } } } /** * Asserts that two sets are equal. */ static public void assertEquals(Set actual, Set expected) { assertEquals(actual, expected, null); } /** * Assert set equals */ static public void assertEquals(Set actual, Set expected, String message) { if (actual == expected) { return; } if (actual == null || expected == null) { // Keep the back compatible if (message == null) { fail("Sets not equal: expected: " + expected + " and actual: " + actual); } else { failNotEquals(actual, expected, message); } } if (!actual.equals(expected)) { if (message == null) { fail("Sets differ: expected " + expected + " but got " + actual); } else { failNotEquals(actual, expected, message); } } } /** * Asserts that two maps are equal. */ static public void assertEquals(Map actual, Map expected) { if (actual == expected) { return; } if (actual == null || expected == null) { fail("Maps not equal: expected: " + expected + " and actual: " + actual); } if (actual.size() != expected.size()) { fail("Maps do not have the same size:" + actual.size() + " != " + expected.size()); } Set entrySet = actual.entrySet(); for (Object anEntrySet : entrySet) { Map.Entry entry = (Map.Entry) anEntrySet; Object key = entry.getKey(); Object value = entry.getValue(); Object expectedValue = expected.get(key); assertEquals(value, expectedValue, "Maps do not match for key:" + key + " actual:" + value + " expected:" + expectedValue); } } ///// // assertNotEquals // public static void assertNotEquals(Object actual1, Object actual2, String message) { boolean fail = false; try { Assert.assertEquals(actual1, actual2); fail = true; } catch (AssertionError e) { } if (fail) { Assert.fail(message); } } public static void assertNotEquals(Object actual1, Object actual2) { assertNotEquals(actual1, actual2, null); } static void assertNotEquals(String actual1, String actual2, String message) { assertNotEquals((Object) actual1, (Object) actual2, message); } static void assertNotEquals(String actual1, String actual2) { assertNotEquals(actual1, actual2, null); } static void assertNotEquals(long actual1, long actual2, String message) { assertNotEquals(Long.valueOf(actual1), Long.valueOf(actual2), message); } static void assertNotEquals(long actual1, long actual2) { assertNotEquals(actual1, actual2, null); } static void assertNotEquals(boolean actual1, boolean actual2, String message) { assertNotEquals(Boolean.valueOf(actual1), Boolean.valueOf(actual2), message); } static void assertNotEquals(boolean actual1, boolean actual2) { assertNotEquals(actual1, actual2, null); } static void assertNotEquals(byte actual1, byte actual2, String message) { assertNotEquals(Byte.valueOf(actual1), Byte.valueOf(actual2), message); } static void assertNotEquals(byte actual1, byte actual2) { assertNotEquals(actual1, actual2, null); } static void assertNotEquals(char actual1, char actual2, String message) { assertNotEquals(Character.valueOf(actual1), Character.valueOf(actual2), message); } static void assertNotEquals(char actual1, char actual2) { assertNotEquals(actual1, actual2, null); } static void assertNotEquals(short actual1, short actual2, String message) { assertNotEquals(Short.valueOf(actual1), Short.valueOf(actual2), message); } static void assertNotEquals(short actual1, short actual2) { assertNotEquals(actual1, actual2, null); } static void assertNotEquals(int actual1, int actual2, String message) { assertNotEquals(Integer.valueOf(actual1), Integer.valueOf(actual2), message); } static void assertNotEquals(int actual1, int actual2) { assertNotEquals(actual1, actual2, null); } static public void assertNotEquals(float actual1, float actual2, float delta, String message) { boolean fail = false; try { Assert.assertEquals(actual1, actual2, delta, message); fail = true; } catch (AssertionError e) { } if (fail) { Assert.fail(message); } } static public void assertNotEquals(float actual1, float actual2, float delta) { assertNotEquals(actual1, actual2, delta, null); } static public void assertNotEquals(double actual1, double actual2, double delta, String message) { boolean fail = false; try { Assert.assertEquals(actual1, actual2, delta, message); fail = true; } catch (AssertionError e) { } if (fail) { Assert.fail(message); } } static public void assertNotEquals(double actual1, double actual2, double delta) { assertNotEquals(actual1, actual2, delta, null); } /** * This interface facilitates the use of {@link #expectThrows} from Java 8. It allows * method references to both void and non-void methods to be passed directly into * expectThrows without wrapping, even if they declare checked exceptions. *

* This interface is not meant to be implemented directly. */ public interface ThrowingRunnable { void run() throws Throwable; } /** * Asserts that {@code runnable} throws an exception when invoked. If it does not, an * {@link AssertionError} is thrown. * * @param runnable A function that is expected to throw an exception when invoked */ public static void assertThrows(ThrowingRunnable runnable) { assertThrows(Throwable.class, runnable); } /** * Asserts that {@code runnable} throws an exception of type {@code throwableClass} when * executed. If it does not throw an exception, an {@link AssertionError} is thrown. If it * throws the wrong type of exception, an {@code AssertionError} is thrown describing the * mismatch; the exception that was actually thrown can be obtained by calling {@link * AssertionError#getCause}. * * @param throwableClass the expected type of the exception * @param runnable A function that is expected to throw an exception when invoked */ @SuppressWarnings("ThrowableResultOfMethodCallIgnored") public static void assertThrows(Class throwableClass, ThrowingRunnable runnable) { expectThrows(throwableClass, runnable); } /** * Asserts that {@code runnable} throws an exception of type {@code throwableClass} when * executed and returns the exception. If {@code runnable} does not throw an exception, an * {@link AssertionError} is thrown. If it throws the wrong type of exception, an {@code * AssertionError} is thrown describing the mismatch; the exception that was actually thrown can * be obtained by calling {@link AssertionError#getCause}. * * @param throwableClass the expected type of the exception * @param runnable A function that is expected to throw an exception when invoked * @return The exception thrown by {@code runnable} */ public static T expectThrows(Class throwableClass, ThrowingRunnable runnable) { try { runnable.run(); } catch (Throwable t) { if (throwableClass.isInstance(t)) { return throwableClass.cast(t); } else { String mismatchMessage = String.format("Expected %s to be thrown, but %s was thrown", throwableClass.getSimpleName(), t.getClass().getSimpleName()); throw new AssertionError(mismatchMessage, t); } } String message = String.format("Expected %s to be thrown, but nothing was thrown", throwableClass.getSimpleName()); throw new AssertionError(message); } } testng-testng-6.9.5/src/main/java/com/0000755000175000017500000000000012551235562017063 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/com/beust/0000755000175000017500000000000012551235562020205 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/com/beust/testng/0000755000175000017500000000000012551235562021511 5ustar eugeneeugenetestng-testng-6.9.5/src/main/java/com/beust/testng/TestNGAntTask.java0000755000175000017500000000042612551235562025013 0ustar eugeneeugenepackage com.beust.testng; /** * For backward compatibility. * * Created on Jun 18, 2005 * @author Cedric Beust * @deprecated Use org.testng.TestNGAntTask */ @Deprecated public class TestNGAntTask extends org.testng.TestNGAntTask { } testng-testng-6.9.5/src/main/java/com/beust/testng/TestNG.java0000755000175000017500000000040112551235562023516 0ustar eugeneeugenepackage com.beust.testng; /** * For backward compatibility. * * Created on Jun 18, 2005 * @author Cedric Beust * @deprecated Use org.testng.TestNG */ @Deprecated public class TestNG extends org.testng.TestNG { }testng-testng-6.9.5/src/generated/0000755000175000017500000000000012551235562016376 5ustar eugeneeugenetestng-testng-6.9.5/src/generated/java/0000755000175000017500000000000012551235562017317 5ustar eugeneeugenetestng-testng-6.9.5/src/generated/java/org/0000755000175000017500000000000012551235562020106 5ustar eugeneeugenetestng-testng-6.9.5/src/generated/java/org/testng/0000755000175000017500000000000012551235562021412 5ustar eugeneeugenetestng-testng-6.9.5/src/generated/java/org/testng/internal/0000755000175000017500000000000012551235562023226 5ustar eugeneeugenetestng-testng-6.9.5/src/generated/java/org/testng/internal/VersionTemplateJava0000644000175000017500000000040312551235562027071 0ustar eugeneeugenepackage org.testng.internal; public class Version { public static final String VERSION = "6.9.47-SNAPSHOT"; public static void displayBanner() { System.out.println("...\n... TestNG " + VERSION + " by Cédric Beust (cedric@beust.com)\n...\n"); } } testng-testng-6.9.5/sitemap.xml0000644000175000017500000000221712551235562016037 0ustar eugeneeugene http://testng.org/doc/index.html daily 1.0 http://testng.org/doc/download.html daily http://testng.org/doc/migrating.html daily http://testng.org/javadocs/index.html daily http://testng.org/doc/book.html daily http://testng.org/doc/eclipse.html daily http://testng.org/doc/idea.html daily http://testng.org/doc/maven.html daily http://testng.org/doc/ant.html daily http://testng.org/doc/misc.html daily testng-testng-6.9.5/pom.xml0000644000175000017500000002675712551235562015207 0ustar eugeneeugene 4.0.0 org.testng testng jar TestNG 6.9.5-SNAPSHOT TestNG is a testing framework. http://testng.org Apache License, Version 2.0 http://apache.org/licenses/LICENSE-2.0 repo scm:git:git@github.com:cbeust/testng.git scm:git:git@github.com:cbeust/testng.git git@github.com:cbeust/testng.git Cedric Beust org.sonatype.oss oss-parent 3 bintray https://api.bintray.com/maven/cbeust/maven/testng org.apache.ant ant 1.7.0 true junit junit 4.10 true org.beanshell bsh 2.0b4 com.google.inject guice 4.0 no_aop provided com.beust jcommander 1.48 org.yaml snakeyaml 1.15 true org.assertj assertj-core 2.0.0 test ${project.build.directory}/generated-sources/version src/main/resources **/VersionTemplateJava true ${version.build.directory} src/main/resources com.coderplus.maven.plugins copy-rename-maven-plugin 1.0.1 rename-file process-resources rename ${version.build.directory}/org/testng/internal/VersionTemplateJava ${version.build.directory}/org/testng/internal/Version.java maven-release-plugin false release true org.apache.maven.plugins maven-javadoc-plugin 2.10.3 false *internal attach-javadocs jar org.apache.maven.plugins maven-source-plugin 2.1.1 attach-sources jar org.apache.maven.plugins maven-compiler-plugin 3.1 1.7 1.7 org.apache.maven.plugins maven-resources-plugin 2.4.1 UTF-8 process-sources org.codehaus.mojo build-helper-maven-plugin 1.9.1 generate-sources add-source ${version.build.directory} org.apache.felix maven-bundle-plugin 2.1.0 bundle-manifest process-classes manifest <_versionpolicy>$(@) bsh.*;version="[2.0.0,3.0.0)";resolution:=optional, 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.*, * org.apache.maven.plugins maven-jar-plugin 2.3.1 ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.apache.maven.plugins maven-surefire-plugin 2.14.1 true org.apache.maven.plugins maven-gpg-plugin 1.4 sign-artifacts verify sign bintray maven-source-plugin attach-sources jar org.apache.maven.plugins maven-javadoc-plugin 2.10.3 false *internal attach-javadocs jar snapshot nexus-snapshot-repository https://oss.sonatype.org/content/repositories/snapshots/ org.apache.ant ant 1.7.0 true junit junit 4.11 true org.beanshell bsh 2.0b4 com.google.inject guice 2.0 provided com.beust jcommander 1.48 testng-testng-6.9.5/pictures/0000755000175000017500000000000012551235562015507 5ustar eugeneeugenetestng-testng-6.9.5/pictures/wp-indexit.php0000644000175000017500000000000312551235562020301 0ustar eugeneeugene testng-testng-6.9.5/pictures/view.png0000755000175000017500000020631012551235562017174 0ustar eugeneeugenePNG  IHDRmRˡYiCCPICC ProfilexXy8To,c'=AdߗlYc`%I)*VR)$f"ٲZDJ3[zy|sous,|@?H&j`mlԯ=8kp,o0, )- 7|sORF[QC3`@0G)e[Rp9 xQ Ƒ0$Yk8ƌ]vqzRtGb%y{+M$j}^w $+0 <ïe8f?rhÉ;zV?ܢYA=r;=mo/± - ~!YF.zk P ChBnOSQibisB7cY2e8Zxo^1_~`dTAN"C3򛊴J@Ն#jE4ifi~S[DAaѐɴٺ9!kf6^v'9 dqtvlE?L &'= ':<-uYsߍP{R}\WēSiW_Ξzpܭ쌆oe'u?=7ATWs#B"bز U55j=zjLAM^\imjni+j~ûٙ%۾ץsuPpHh+̯$5c{.v\m|y{l'ON>}7}_TggJ/~&BŋK=?WRW}7fˀH*FA ϣhj [= ]L 9l0k_}yf?B˂B5"bKQRyKq2+H**N+5)g>b*}ȸZ50u' =̓ZZS:zOIc7M>{hfcIr6;k`aaʼnri8(W;󘗁~?~"84F &4> />qTbd(Ѯc<..|=>+J_ISSWQ1^tcԭwbfޗΕyp0ODX#l!O1g {) SRXn)SwIH=3FƟ[R_85K4/ԷƶzyGWM^>ꁔA!ahdlUkbcOƫ'g~Ș̜X9? _gqs__-(~(Ի|qtM|i 11Aa2" ɉ|">QwT}ܳ* [6fC,W''_ 5Vb8zƒc)i.鎃gpr2E˫T(P$(q(T:,wJ5<hs Zz]:XS , 1Ff&,&Wl4/[Y Yg'(lٶ%8su<dW)yE|d~y_{z| Da}*&LBÁynbd/ەkW>:P>hb:6O+t|ԍ-Lfb^4X7g^Xo' QBDMCCyND,'#{ĥ#q $JHɽV(}f@vz=l܉gʋJs+k͟=e}T|5ݪCkw|v8a5qo?BϤ~M7?z/XX Y_w0oIn ;P+0DD oHud(9CYQ]p a*A &jn`~ElZd:vLz=1 3L6~6l~`Zqt2Vc'Ј-W +#@PJE|tĶ$Fj4O&V6SЄ_,R;O8\}ESBvNA+c!gX-r-|3/w8&D|uSr?%B F 4>%tz,Ǟ0 [|HԞKu6-7'3\nOfme߻ϖ{Cr#bB2+*UeˮW|Xz[KN>|`0qTUϛ1w:G&ݦN[}ʙ"8k4=ւ‡X][z/_++U"ɫk^k777\6766ǶTm-llP/Q a4v_ܓ Vbb <H6o-8Bv[G7ƺ a/MIưƇ``cF,~~;=.Er Y" `?2^붐B̭` Ph7"O;6gbp7Y?@ xw &}<^ ڑ#e?ZRc^莎/uϑ`[ہ++}mYxG^ofnt; ûѠx/M8y %Eɣ4ZRXHP(KPnoZ+kZ ^PQEVZ+*P y%@NZsNٙ3o^׬95{^--1'9bOZ@݉t^ǻ<;~ \ r8ܦꑬ<_dec'y'zio|W^)? ȸ:5E˶Mq܉&›+s4fRţFM׈aWV~wOXDKT$[#Puҿ^G>[[ X X m s^t/? 7Sׯ s;|"(ZZķ@N7(-ǣ _:Nѯ?/7dhlƻ2]5o"o{?{ZY{<~wVEgDh^^xkʅ0; o̶m6okkkkd-s6Ͷa6w:˟!&f~v5k*m /GlD^x[1q~mI`K'ּ^VC0l P"V[yo;YY#^X~xLbͶh|4_X T7xɚx0+KmͶ3inmy//>8q-`:`35yAhGìnkؤi}M>Mu^r2&oL(gyq&Zx54놳p]:F_;'le~d .ֶ87^ f[4^xh&|k̊hh7kI[ӂDž`H~Xޖu7/B#m5:qx['6eښ&W͊j$4 m>] ]py'Z['j;Hjţs?~n!r£k OF'[x]K*M*m|\OYlGG s\_Rj׍gO{<~~Ai'a)"/8.[8W|tT#4m-x.~9LGIQʬYi ݫ>N|9ttѽ{oJ8[{ >|x_|ŋ<#ItT!>NqqnL^fZ‚qkxӔ)S\s5?hժ7P[SҭA >ӏ̜9mf7$ xլ/EF`ZL1%w ^jTh#5Jف^Bo:tlh1jB( #>8{n L`02a.&>m2B['̎EI6^'*N: ;rkkkkkga;vNs2ZnNa: 5Ӓ.Xiaf~ū%p-pZ]]ݩ񖉈p{w/-Ž>BUYVyyrYwFC.DZ谸>yr|8pjjkIO@vЧO悧Ad=wށ_ 7}CcÙ>;Uy8,q )%M;׌A@8|s1iֵq Ũp# f^{Wc<;S~fR3 Nб[7g6ڵ(B{ QOmٲ6l@6ѶM[nMϸ)T>Сݻ7a7O }6tNQSSĞ{>\&bĐgVퟮš6=Ч(8%{'.K`͇Mp^ح8cJ8|Ԍ n4 R\Gxex7{6(>T qq;O?կ՟p 3`֭QXXΝ;KXP|g/vld玝#O;4'(xz._q6OkO%e¡rr_AOOZ~WCM͇q*;0ƫW9JU?5 c8ptǫ3o?WzMК`DeV ;c>x.Lt3YM7RLׇ8{X\ٯ!!93\ Ԣ' tr;O~6x3ѩȳ[^&ڹs'v [FFz22СCd#fOo~;A:DmC(ꝋVvgK7.O|͞pm%{.} wUd 9t]Y9ꙍ?qsQ_ԗ#4 5[ߗ`I7l@ h'/!Of3Z m%рա8Dj1 &,xa/h-ːeɶuhv-#4ˢq X q(h35>T+F Ud7/ldU|{9µU89ܦZ_ on#Xf蛼2_~sBl=DN<;Vmx3p/S>}N]Xy8 xQV>wFMCը=Fk?>cƳsh2z`_8wS̹rYY\,_v.'5pMuM=AA"~Th\dP:E41OH`]3,ǝ!9P.!gB.9,zAmd=B3設A*zcw ﳳ`NM"n0/f3kpѶmkdpmɁTӒWuV-:\s{&LƿdM!t݁7OƧY!_}܂?J3 rAyZm3ߏpBTlgV`3§חuK>@M~a|}EU[.SpUx }QQMe@:-峿<{/~gUi~sD+]錽鄗Gb?>u J}F3Y*&&3ϔl&a00Hm^AiεCR3M`]~N;eUfq;aCΙnhmYߩDVQUN+GC1ׯL3V[  (2MUTx:9Ȉ'KMU{Wpf?{ 74:T»/}?`)\MS?Dè)?]{/V~m\rDpmtk7Cr, p_CU09w6_[gYWC_M͢oOCQx+a\F*c.kLe` NF#ڣj/i\$(q7Z\K<"B jHG2anˡ58j9x12۷G:v``@ rO_8RD:UgjVC^Qe]:tE#eBkŴͤҡláJ-Tl&LÁ0:_p;\5+[8ψJ<;kg4.4.gOЀy)^8w 9b||!C!M9H{9ee!LwU_wW<ӠM7tP.2;`^{Fk`h6 fQ@Ȏ\t/b:l?uo^ Ƞ;M_b}y79m>Y^B6GDw< cW9}3zeг!*dTU["L[~Z<"6y>-*;!YoDq*Ty;'^_qS ck1_&8߾=>th\x+~ӻ3#(08=*(; ? z#Il}[}!8v\?Dnsμ\Z;ʀ 倂׵ s9 4|0iZx90 ^;wD, З?E=[Age}|e+h((f'h3x"j?o]A«6ᝍF.vjJ3v¶_g,zk-ꉮYam@hwዝJ&]~rNGWzLkgO;nCsmm+r\s:ש= >2Qԫ'fTOm(jC6c=ݫ;>ö2~u"9tQ^Ejvztāg4V| vk'Nΐ(;k;0Cn5̃PQf)݊uav\0r8zZWG}v hoI"f y}?-}|s Pp 21xE2t*h)^0>Emڿ>IwHj9ئu))8SnumEy^MlґED!et.Y 5Wmw{!_?Xa5G < sѰ/t KF݊Txf~:80]5*?۵kʲqQ{!/+{?e~̯Kg< `΅,lofYA=.$=4s/S"aRp֢oBRY8ƪpY@kN_As~P|e-EsG$oe&@8V\Ix#0,1>#g>Sgv8~vL 2+p0o>2E' fs;%Z X />3|'/Xj52.g1p A55L LO&J+-xaΊ?d-h.T|"tx/^@N܊fu-Νq~ks?Ok`sى#'كИ pbXx|qKbW^̣e?zc-"JԷ`"u+-'p/|ҏZoc83ܵ_԰i-k\ۉnJqEqG $߸f-`-`-В,N|Sp|K-nP 5p[[o֢ =I߶8Auai> &'JJhZ@>9+h-`-`-pZ@77gli"ԌgT1 04aQa1u}۶@K׍IOOKfj| 9Z/aXYFyL0kkkפsc^&x'WmшO҇[2u[ฃ32X`m~5'ӵ6n Yyӏ8p`q&+6&M3c-`-`-Ђ- ~OA`?_gh-}p1TٺOy''"x!4t2nL_~%y|gNjJ`/;[[wJBNO?{.vT㘾&0#2y]dّb#' c7'I~G/A MRlF IDAT59'-~]9 'JଳUW]'&Mj6vN̅GdnpID(4qx\ּr"'9!΂ \^{-:wg !-Im!C)//Ν;ՆG}ƍsq%a qiXܵƙۂ2,i'/ Ȁ܁BұiXey,ZFn8< w!C)&C晁 DkkeIծ];'w;}>{ mOeΗK2lY޷ ^N5( tM4K4K͸eѢEN6l33Ȝ hNJ ݻwm۶Lo,9(*e˖}ͨQJjXcYZkb. \آ܍ ̵"oZܾ};;<'̀`X&MK(ݫxckYZZXX_@Yv-l,쀗>s_wvVx } 9 6O5Hi5if;4 +$+5м誛P Xnwɷ5sf HÌhJvx,^qTX X Xشi:B3[`:-cװIq1AM7D΍Ӄx2)9(&bƵ3,,É}GhӦMt4ڮ^14{Mߝdpi86c\uTiΊh~̣0ѴR~-ASN-}4,ѳ?0>x3%\⼙ ~Cۼ|agKcװI3jXkRkpN7 ^|z< ~Eq-xך_ԩyA%A?,^&`ʖhLBɌ\cQb ]W7fOv5P&Z?3qF \s[K*k$XLf;cX|'8l0vIsiNBxr/ht.3l\~bpL'DF<4~.˱)xy6, ݃C2'`Ce!?oj*,^˱|1bٓp,cv+>`:Zkz/:r 6z"Ș{tp.36Wl%Oy+iX$@8Ean47%]GgAKvB$.ݐ+EXN|gTl"c~;n|UQ?Lx|ZjZN VO!BDѩ4*.DNȦ{w4; @N()=:N Z͞OR댯h+ݻ 3.DP<} >,)rx>c-pZ&\xHf\stIhp'.ʀw~47%:9X> ezNC`yb4Lxj5:?v^#ﴎk0ᱸb8" ܵThI'v;L +0Ǝ]ȴ"gaZ,`-pY n$ H0Сs3@0L|3f zܨ,ZD;v^*`q@` iB1%(nM>yᅞp!/5Ϩo3^h3M,KS]nvs.ױcG3оEyBWaL YWFdBބVpʑhtמH`e]+QN*!_Ih&çj̡s"^7ÝbN }D2 W_99q~._OoESxZh*rp[ &h.1 nAȘmsoM'iXxzȶ^B^֜ w^] ϧ`VBٹ[7ZF}%6?Qօ_tQ.<e-pX2gdA﹙L|$~O^,/Oa($ EIϥPݺu#;3,r_}B}b#Uق'؏2xV-> ;(/h:/jhy " b^ 3h&owva 3BzVW&$(Q},`-`-,A_PُGi oIa1}E¤ah@p*>MAIhL4 j'd g X X X Y@fD_Omb_(ݘHӅq>I $J\' '\DX X X 祊8 {!xvܚ+ x3LhZ|&-HHী> ͧFWkP%}=EFTVZZZiLG^6i Żv4ޏ/:H2@%}jeEFpRk#Nx <`p`PX X X 4IGv?Y êA!_?)|R 휄Gp 'x7p&JL5Iyf<. Ʊ@Z 7;rf!+ijkj~ cp\v|cEr`--/'qzQ\L`?)kkk@%yΪ{WIBOxN)&1? 1/|ppLxEL;hrn=sx9, n|VNs#[Iavg"!!DѾMEJת0q/z`q&M)y`?`\B|=W@)2iý6$?OBJqb-Ђ-7\fgϳIC`XՅ菤'68N- zfΝN:Mv< \ /51 {&f`*h2zplxQ׬Y?^z) Ĺ8E:K}z^oiK|KFŋ`fva zMS0|"cۯD\;=#9hk-p"[@<N8\ .Fݻ7$U$h{nb#&xBgygj vk&A*MqƠrG ʫ+~&{dT @aHx>cӲ XafKDÈ/LJ?L #=^M5wQk(`Ry,jq?x/̒f#CŊ1T{rX X 8;}^&_?+k:`cTDn^+Dfv!c5>‹;KG=zHM'~6izq6ԯU|&&NyoO< A5{PX\wkkg q))ܴ'&=s选~5(ƇNm` z+AF|]L0N0!xn\t OП*;D+nF.ơGo0\]]&LV~틿K}׮ƞ{[Z$/4uDZ"],tF]n ٴiZoa[m6XLta>/Ҏ[{4y0S/y)Koy睸 ](@2Cp W%qGP/bJLϛ-ZgE݇gvnZfDp$2}0yz)ٍ='`]C0{M92z:2k-pXh }ܦF :hZoqrm׶ uN]ԁW̜R3L3:eHG5qmg$ !m=/vp]Ya'//~ \qۗn㔇*i= 1ꆑѾM>LA(;uCrT>x~yr<,ZDO?߼.V<w+> }6-!}kP\?/.Z}:vsqfV8(˩BKNutp^N^(0k1^y`́Bsv:g)񖌄/^EpRKa>2G.mI}?qRsSu>F:J>I"u'iߨ"Zu*>VH+lDa#8[[ X X ] tlCEi"w t6RFf%D:?k/y© ڹܔ4x,ZZZ eh1\[<#ao&R|Q$ۘGAx⪛CeCi&m,æImkkkZ.g!z# GhEطA6IyZ摾4>.Ԁ䓶~)NR ''c;H4AYDoeQPȤ@2uq͑|r^x'\95SAoP_RǓO)%᳠':olgM@hQJfeRiB5T0ܴOd7żмrgLޤڒ 硇¦MLsWrBLY=36t!Տ.߄9SJmi5n_xY bEU `Po1[Y u B<̫HGi\k6o8!ZLZ@h@p*f 覠W`7ϵM5n9[OL;PP]珧Y,^3vר48/J})'X8v.RNv&_cہh&@g6^FLBA83yxOe$08'UH :E5N`O>09|fǪ r6+,{nC~_Fª<+*(,;pȋRdp@_,ik jv6iP/g u{k4m<')--E=&yb1DO pL- ؍?I+BG]xnF?ߍP) Mʌ6~H6+c`.nkkkTX>GN#_(eоE;_*S i<^L{y]Ө^*UA++ Njm [M.. pXN1wNS6?2}1;_\LԋJD]m4rrJHyR@ҫiK@-@ވ, IDATN|Af|]1-\mƦ޵ Ov׎b_qml9 ,АN{CiCx~OZo]ʔr!*Af;#Fq,a 稔.AN{Pv;~5θpƀvAc~kE)P sAT=?9*a Xv $bЎi\{^4 3𣙼 9A<˗&_TQ$d]} 1q8bS9xlQ QH޼װ`*Q>|ǂٹ'Ԫ}!z ]"{a+桤~&Vrnڠcr7#uP;ť 0^7+T7fOn`LL&VY۲h!P/8vnN\p+ڏ9@V~)ށ)=6hقi݆˖.ͯ= ˖lwMm*De#@un8gw>MFEqۆ]X͸9g9i+S1|X b(V2rkh䴠|)v%#vމ:e/_L; rř#.`xf6B2[ޥR_;l"+g>O+E[nSohm);4mQRDg9!?(mtť}JϓҪJ"uvgasd~Q%L^>~~)u5/ds^9Cz^ >\#CH(VggxjC [Z!D-cdɝcW%6J*ޒb(8INx w ܩx.ʶZl>zs1NZ;vi8y7%\J/A O^ɍ d:;Kryy2srr߱?E]'(#jRSP g uKk ul>8ƇᤇKHkBhMuZ-84ϦE&I*!z-~ߔeay=4eXMѤx*֍iY \Mq^2x6 _&RlwkEE^쥙H.w+qKXqlh>zۨQ>!SV RqL5i2[":lhhȇ@3;UiWT;w3F5x,ZZZ edu &m͋jʛt۶Hl>q|Җ:vf-`-`-lmśxv7-uA|o+ڴX׸{qLѰ[[4B1KSOCNBt+,DdWΣ)Md7虮x`fʍж9($y0.hut·vA)!5^AbG:_GjCxEO Ѵ@pTX3G򣙼G?Avi]0S6*wcˀS)DjF +rVg_a Qhʷcݧq3A-͇@td9D">g 6}EVۤSa>h@p*>MAIhL4͗ r>c\z6l494Bv+p]-׼iZ^ tvn' i0?w'osCab[L,3k-`-b |-*&$^Kf E^IK; r6\Lz`'VwazUK~uFdZ X ͇x@l\b%!lc '7z?lhN |)}l:wـy95IkMl[ X WHG2m`!*jLp*fakkk[Ch/c6/)omZZZ l>lg-tj!Ŀ~]َ׃/m[@[C6C0o̶P ,f~,l-`-`-pt-@)#}A+|gjual-+9Gr v]x4M5N4ώ zp 3l&>M9)_U>C\a>bX>8|ƛ"< B/hIky b 7żмrgL@c r*G3tcT7xX"йY&kk-͇@q>ʃpCML A\ 7Lyk?K> rd9x~r~ oCpQgdJlTͻfڔ8 ]`l-l>Z/bډ ,XVXZ QSW5.9gS!hBt9{ 899?s8p0e䯎;_lxgW;oƀĤy+*1 2slUח`YFL0 [J0fL J&-7V@c 9! [c:p/y){K)|44(Igľ/ɘue+qxUpOkbw5~F˯V/ÁƧ?mP=.K6#^Ceo;T@N|1%#=׎_iXuTfMw&=eǢ6&_s^!Tm=cfFqs/tdl|kJ;{\8JYzl͇{ Nj'nu7p͙ A!)(UL߉e:҆cފ.}8Tx 94t@KP)9m[;@t !D|Ik.?wI_Rk9^z)  ʟj#L#7nMh{??_~1@+?8/3QSӹ4IkN{Rl)8p k.+s5}Ĕq^ỏ"GuW5-`-`- '{>zov)iMO9erz!7WWv`-pY@!T4w䄫k_5j_*QGMN!oc[E nX+(n>!:5;XX X xXCHiʠ䓶fm-`-`-pt-@Cor}wf;^&'on! 7Bi'/mѵy=B YNnm3@$:H[ | 6.*gzEӟ Ѵ@pS* XPEIƙJL z;^|-}Xiq-͇@o5·vV rНGtj֖攤`Evծ'PڵEZ X h!&Is 2f_)%tI4zOStƛ!EyXhQe\ <.bc !TE/J eBg@[MC> 2i3-;P^(%KViK;n/ $28f*%|B3e£q)9A컹]4A݅5:'_ߢV:Yv쯊䌤.ocM r<;zl5~z5&ҩ7ǢShd-pC󯍌jWbOÍln$ypUWgϞC~ӕ;bqDv;)rfkT8m2gTO ¼a[lw{v.ĔRqwuHh+Ѷ͇ !8Ax9JF8DfZF9F@&d96 $uѭ͇@aA@vڱNɻ/5n9 aK1Su{@$ 't93_Xn۲H6BNZ˻D_JxVV*kE8sA Gx,GZZZ 1 |7N$p':C] 9t')--E=&yb1FIݲ1;gLka9=(A6s̕ë\=iDЃ*#(YB'YNZCHxԦsw Ǥ5[X$yՅ,[Ÿ'uˢ9= 쫈Me@Rm>L*b;4΂ŵ9U+P>eN [ X 46BL{9nXF1MR&I햙 'PқꐍMVZ6BBPmI[jKd)f@2 oke:d:R&miIx4hYEjvl^x'\95SAoP_RǓtkkkf͇`!4`-`-B,@6BjhG12C0f-`-`-6kSc@q'Mxlm-`-`-d D!gj!C~Ɛd=6=4ݫh@p*Qb2c^ߔ<~4>zW4vkkhEC0}jFxDE5N`)O+.a\ȧ7\ CLቑ+tmX X `gc!_ q\ TӁ{3Lx4.iw8GΝ$JuϏQs6*WqŗifnCnǻb-`-p\ZCQ"OvOnr)åӔ.+W^ye 9 'lJ3{\.g'9b7FڭQ\OiҜdl'EYc0fVC0)_5ƾ-xQI@9۸g-`-k|555fjkQ]]CPM{QفF{2=^>^kA z<'> [MW\\} 4z$A'ɉs%v:VlC޷9ryA Nk*/MCOÜw(_޷g/=ZZZhȇxڴtTPvGϯ>v£in8Mwc]Ybر#JJJꫯFeG¸h\t3۵rRdO 3]u䆿7-EYOcDbJ<kf#x2?:..@1>t"f!qG˩!C_yˮ n@1x f{OēTO<a-;~*}G݆ 'tB̽cohݱPkk@4Bjkk#az@BYB/#7Oqa4^Fv -:UXӹkM(ywTj~ ݫ ٭ aќ?4$ȡ7uF hhP*ť,A ŸkDi(n31ododJyj=&/Ðy(wS@C>rРp-2K< tF+Gy7KzdWAu L5ap;%'ֱƝq8q"N9Wc-m$kh8T)CEq/N?Z Υa|~gNflMa)$v'x:͇3wi|LZaSޤ}晔ҧv̝ }އ+B8{},Ofb`ߐz^cţP6Է(B<[Chz@M>iK F>"t[Png-`-p,-@C̻x_RǓtkkkf͇-#.l oMGl>Ԛ\ly>ۈ֔qmcxlZZYC1tAv"q ͯ <~ǔ9Xo~?(膝{ J2vcW^w]^ijolu޵ %E"Zݎ[`vl!,^9pf D ũRBi?.4]iث6%28K x3L O% IDATx4E &\;/[ԥŲM_ҏtB14t(DBtAfdJqN__}֨=i%_?UrxW=@_UOYr_(j;Y-pCHrbH(N^֎_iXxOg'?& aa_[^!~Gy협ӊw%UW@HA& ED TD@D)b eQQ@ .6`VQ'A"[@y} 013g9s9w;ih_/hPC!3#nFTwC#&*1\d\9<iͭW|=;]g-qw{4VZCd+Z)1ܮuly6 +<\U*wBcW`N7Føj֨Sdl6@4] ]o栭'NHd|rZoiշtSƟ _¬mv6o}C9E4FڴXdfijH{:ǧoÍu g~j x4!kU~+pQ8)DW"؉|wjwb >|%1g`o;Q|KPSrOX4 S9 r!g`w*#!'oX홒f~e9Fy.n;[c VS4mn30 ݇hyWi M:7˦]0i8]tK#_WgL::m[нYMKYMR=]qˍ7Fq7E;gݸ䷐d)vq 7 _!(ͱ5w`I{ -vk |CeS"y⅄DZj@C(7 Uzq \Vi̸*Uwyn6(fO૵(Hs+WH Hّo!X>8^& w`ko?#oL+nQ@@S UR,6ҒRg٦<:|[+=:aWoy.@@q<6B6Yq/sP=3e'Ƕ g~͟C5 q0FĨ1wcÑ6Rgs,u=.2bF>_n"G}gYAY(BV.qP76Rzg۹#п|{RdG㪆Qu#%F '|:}ؿDz3&Vu~Ce7 ;sY9'R^u<$3%wFᷔ%9<bytz"t/x6e}S^;$v;@@tKwڔVigPR{4@HCk(A\ׂ^x'Ubi-~p}4"/4{0?ś*j,S62n "~t"!ZH5Z.O!.2Nd|ʑ|q,溕B x˼$sj٪.B)nKk@k@ktꄿ?{Wa&>\NZZ xY2RP jU:U%P0u|::g:ۏ7/όئ1!$J:,_פbth%3K1{>e=*t<KFNH $W *wBcwA &3sa!}{%7Y)quX"_Z 0#+Yi8j^ &D\UDh !iհ}Ty+%J#JOo\6}oaPSHc1JQqqBèD1'?6~CuIYg(ڲhLX03 _^/(^a`SΚ?-{%ct:ơkHj*wy=c֬%pƢW6/Zc5wL2Z?ݍtR| 3m5p N2Ulk$?۳,EO`QS&ᦲzmʡ!kU~+Pd?W _yS [ҬsRZ @ 4ې38}RCޚX]!>u!`s3q3ݔZ2u1/%Ϗu+I?+6FqS0s(Gg"h91ldGj2Cr9 sNHalTrWWR!1LM!\q})$G߻KkZI$hCԃWgf&(%ɧc|U'qy_>>7>{;t9kGp6UoѭY'oo9 v*x2Ld۶+pd{Wڍ|  8ZE^֮؈LJ]T\:F%QJ3ʯP74ߐfDBh3.Edz*u8_"Zњn~9ͧNz¢0zxTTV܏ ~+~*ObnB'4RyA9HtœE7\uۇ& &VR&>tZQ{@jo) uFปOOإxd:t1t.t:c3&G'/1l,&7)8'ܠ6Lz-"c{ UXm]7zcn:BjIz|x'9TXl@s{0|ᬄ >߰c}&iԿ]_Ί%"cb)Xv6';xu<+JOqohxaHHH@•E>Ik#̊p9q< J:q=ۣv~7Y1`z:Ժz?C3626BvV썮ЖqEei/)nJ#b:օi T6_v[ụ1N꒛5^h;-wsqˋT*ނqGb0hۀ ;/MR Ds>u<)SSq0$!~N_~yq˯5K059M[iI,f':- ٓXd (Z[#ҵ sWtнJ,9g"aO<>xf͝FK+(AiȌܑ0j#-b1g#}![$F[$Brl(tIk|hC`nM.*39:SsxY Sp˞|3,j?oNmȡn^;> 01oU Zt<ۙ߆ją_IYptBô\ \ucp/ٴ ZZ'U|VC J|K9ycI]*^ Svm\7Lt g:yTFUw^waہ*8ZUU]-FFn P@g : a 2b<3;~;z3[F/Atj٦nc4E,p' SF=N W !r]idm͹sEB^"uV|&.S#oeD"9O2`ͮ_JL3!8_ٸOfg?iqW" M7\m~y)]P/Wӫl1>,Mߠ#qY @;|'ЙO#5纔jtW:"c腎i:$Yxjm-ͪ!Z$B-|GLnl,3O#9mL9L#<,f{:V<*~L7?Jl4 lO/uO.Aqv9XN•rXW}si.NkOz.MĽ& AxZ@ xҲ6.r{Rg;:;*Jvl~NO9fnrPٔއ xSo-yuډ:$G&?CiYKLۻ"c]05@ֈ!Pd[TNrtC WVxfuq T%JPY}tcdUe^8>etY긥Uk|s8Ӹ[,Q9-An!E4 )8ٸӀ7%7ј;W':ր씑 5oY5Rzs W۩岜2 \!~xttaM:Y- 4@bdȷ&FyԲU RӖQtn6VC(sr`\fJ7ۅђqg4^wO+Bl3ٞ *ʯf%* P|̴^,*h#ɕ@\-Eo<L|)nʗXT[Wy0f6N"Sq\ܾhTzG`pV i,ι/JWi2;NZZt<oM5¯¤,8_m:ůqZZZ4Ɔ^A|hK(g:yFրր@5!Yp/~N-WݚրրրS xAV_`_`Bk;asێUf /("bJhnPзC_Nvv4\yKO4,/'Yk|i8۠]Tf#v|Ty+%J#JGs#n@FxߺϦ~#\b9tk#|8`ftvAЦnj8s!-V훠nt$}@g9F A75pAkC)yPuCsɃ"DM^ne J-%$2ዥshil^xt@Nwq'f I49+_OuƪYsP^?=zCUS IA]K[?"6k2VO Rlk$?񼖔˰pżk*t:D^ӆ. Ec݅D4xkj vNƂW`Tv$y0n.܂ 9CrcFНCD%p}GOǂ0.%ߞŠ~HrCp_}]H'*l“ӠTG'4~)#_2(jBLa@w|OaD+'C"вm3l-6w=*! pkQȚmXy$wxm^msvaf:İ~]ђ;J ]ѿcsB;~Co,JwZm qláLkՀC7!! I~Cݖ~!u:Rc%Hnxͣ#tEh\ X8~P1])'<4:t-G^}55d-9M|j4^E.S qF"bѰ ӄ2| Wi5PY4!=L'u+or^4U$)8E>Er~=uGoA&w[i4Ga#;Zà CQ;?,-Pvߘ,|jBk'M8d{>ypMqu$vnMT+>8a qIa,d{f#Hp@Lj&*RB[҃C Fvr߆jqe|pbۘF^I{TpB[7B1\.e3vG˫K,EKpim ')~jyv;?œ~6ja'=x7ZztR5j{PZQri+'91ͧQ9fr>}09Tʐ=7ӛDɈ@jRzs W۩2e>jU= jm[BY'c&UQ^@ F B!4 A mw ml0xaa֭1B,֛ZaiкYzc>Ɖq3 a!<讫`' M ,":CsɃ"HFZ9ߍŮ']YjgǏlDτ88]G5+z'C:)'c5DW=! t;7}5 ZeՀpO.mW CPB0AI=\^4o&>n~&8r (7g!uh20|Kf}&^Ug&S-~n_kiTGmgcU`:_2(jB+ $BT8DEKXq/ݷܵ알wg W`S$gc<#b,v}f-Bu[>\.ώAK2[Wunhw4&KT{Pʵ(';ӦbGˑxjDG7k>k&`L8;Ǯn0' 3k([MFr418tM7IM˱uKHYAbS=kSRyHcIk4Ķ1J~2H:VBtN7p#Lao NBPCX@hdLhODBED7vϖ%gܟLꃜ pSxX}kbs_ h@0 /o^K2#3'4Q"+6-M0{yӯdϺ eT<S=0{z ^ 7mlN]ܒBΠxϸ'_#?n꺃1 @Ej@m]>4vtvpUfTry*tRom~16'~2_P޲`zڶ+pdV>۾?Kn,ēѧt˗d##?Ghe;y[zM:uB,9N7}-M/c,6U 9ȆFhІ7чȉ=3[Jj-D{$lbP%x *+ >%ut41toy7u3h7)6Y5S?*p:.d#t1:Q4NZQfu+Cn8wX@c+}ulx4OuGl e>meS%Lj'#E >L+5w_ɻ;,&d I4%^r'n):8tS6{N;iɧ)I$ yqZ*e$66;w~Cv׳=jgyu-V06qsg"wsRF& ysڌYCk'nS2'(e53bѴC͸k#!! W6BT ' 5‰s R})1` n#?9.I?sGt0fW\@m6EWٴc/M'Ѵ5(vKs?a\Hs溓TI1)rtʈ`-j^]Sٴ5F1ov?LyCQ6Kg >K~!#MG?ڷ3nH,zm̟"6u;[M>R;qbs0wraG|r8zl]=g /$Muۀ vC1 /(2rBqӸ 5c.YZJdojǼt ]hy?m*ONƑNNV' @l#좝TVU㲹fdlyf052j 8 JL >S09EV "EF2p2Uv>9e`Z0ڬn}wƒxԧ+ 1<6eQ¹l$6M<ܜƴR39S*e9`o5{QN8ۤe;d#H++?^ 9>)PG9!g%9%ߵT쟊2meSK!p"OAU9'4/(:;&=_tlUPx:)ܶ9G( ^0a<4vBx*L-۵!pᗺܟCs,? ̣ -4*Lϧh>zv;i(+ <3`;5`&p`*Z,- Qv6᪝TeWv*}fNUIB`Bk;)`555`=0gN JhTL[u܉``*NTi̸JUO yIrjsI(Uր@@T;LcYJrY]2Rh/H0 T6/A4ݧAW @u"jsGv6 .j'B L,~iF^<+g'-y z3?mm9m:i h \$PUEb? 8uPRrbb|\z/d5ib:2ҹj!Xei %ƾn@WQ=P<|))̂"!0N~]G"g{t1zXa|BLl  +N5ƀA˺x\a0qm?/<կjQ_#y!huYMt/M556QOˀ= v`RΉf<p*~:gjNҥ-c1ڈ)p!#!o6oE!p̻.ëX"GӨqY<^휅QߥOC\ e&Rr#\k@k M܄ԙƎ4Җ [v[+dpD0I]r_w©Kq=k\AW"jywdz#p{{K=0mk5L>O)"sbc]oBlޝWv.R?W[Yp?%dSY鹈W $$^4mzxOߚ3hݞ608 r.<ZwCNgLI̻x2y8\|îNZUGW x4ANl#Q4ׅNL[`NQ!<*܁/]z^VwAL?a!.t׽l]!.;m42y+@tL8/p`6xv~yGom?$g Z&Hg=X %gP:krQҲ.xy/hrט8IĴ2BԲ]~9@:3gv3;v(lƍ"?&vR$UB`*޲CNSq",Jcրր@P4\0'pmӧO#22k8G]SJ/'ӘqV03_zATc* @9hBh h h O<hذ!g<誙(:*Ύg 2+v5A IDATAj{OY$uMTm%b/%fA <-R`з~k,CP̀Ѯ];#ϡ+TGF.]V t XŒ~F` I^_KuEk@krj7h#++p TfMaim۶5fPI5PvS JoYC5_8+28|qƴϊ [RF AJ6_acr`U/yoKKJs/Dԧ1S(]5KF%f͚VZ1^jqbۘFsb?Fx$X:P*?7(h {#6ָ0ڒeףϔ ;Ix{̩3U#%`.l3#KJN4ؙdoMA)t>K Kd۽ .Sݺ_G4w]`1g y˟msO o9ɋnĀ$vfbk){"le?DM?iw.]jc0p7ڷmI|<{pn ׀8y8ߺOeQ/9)׭7Ivp;qfu.? Ɂ5k( /`Ϟ=O\t1Ϗ{BPn^q(:(&aݰ.1 u{߀:G!~?{4-&lZy @ıj{v{63㫽U`bc G s_7}oh[ݷ l}7&,d/HIpյppK &-냽E=>-k8a2=W{gkccU1LøUarYD ̓[IkЀjSQqxII82\'F@N@jRzs W9ÇW^~;csIpguq{ R,׮[+ل' 7RTH|%>r'6tHNLXxắ1lU">~qչccHIo1.mv5:%G-WpذYG|`gt!0D0;N@xmgtDz!n/>j`cp+X*ظX:&P."yN[0$]h O (8|>e_K.82ݳb8) _/͝8[f (lU!tV<  ͛,/]B11WNÖ%53̡=qx,LNp[螴x`&:l$Œԏ18.mvJKF1z[$'"~x&(7#ËzՔ"^;7_[otMv  GImm΢9O3xF 0Sn DS,l ε~Q 3`!{C֭K\iQ`vvl'N^WN5f%J+Taf>_83m|zo߾?~|)g N0l goH#jvQMLvPٸV}ƠQ?v8!+r4wy獨3Ҙ2)gmmJa-0x80E8xs& FD-5Zy-o¤Ib<'đ6w+x;Dv.Յ ,J '[uxk Tߜ e˖yg\excܜv!thTzG`8L:P`L+e7 s_8Le>eco66}9B2ffu#ickh><:݇s݀*'(zi;1S[4,BsyAtÆ a{u*^ S,pɪ1pv\`ˡnayǽG Jn)KY&.ڶoNB{0IHIâ YO\2aCp`C1Hr^AE OV&oz!\ֲ3F1әRg~K$: tjqG!T|'2N&nO" ÝoȥRэQ/E%=_Fb~`СjѣG;5>u$41\j7*p9XAV&V+> 5@:NZ5B'&4* -˼HJXI,Jcրր@eԀvR$籊4[LpyL(28րրE;hXPCs#GHVk@k@k2k@}8Vm YW1%;AfnOL*&5h ݔ{?DtNL]ⶥ uPf vb@xz"YF]Nejv ),f:pdS,S3%_a "Ez }G٥-G$!Eеm=h(F c2¹IHJ^nqڞN|3?_quHzhuxko*VXGv>߽3(*.-6R缷xwtŃKk_]NZ4\k@NY@s]H\Boj;|]8u8}g{S@iX& oC0l^W>vY2hMUۻ7jمiocմIp(t-6hqQ7EY_}xw4&)DO/Z7&ۨEuN` 3R"BcVAe{Эd Cgcղ ?06ܸQ8p<3GP{ 񫷌1n1ZL+i`R-Zzk܁tNZAр=F2NBoKg^%#sjju'4_aeZfFSqVOODˌnnؔvh<kU9rg;[Խc$Zq[FyL8vw~ |FW.ڕrqo;{|6 '/M{n|qTR\jo(n|`-C?#lza/4% O ׵ϭxַhWxh'3:Zδ6?hNyƨACW4 ZEjjq$//Dn-Xw٩hKp`8YX;df3Ӗ^rAugʥ 'eZ%{2-Ur5hZ- KCɌ3_쾐ػErJ1xkhηS(U^iiOAs rvmܽ]v'Sg`XbA08i ʫn\XkA{ZW ܇0H{aaG`H@+4G+ PfЭ[7제NAڝZVbTZVoY50Kٜ#ajag,pzeØNho\WZ۟E0tAȱQʦdgru$tXy6=zנ IƸȻ iS޾1#-'^1Xef~stC12NO/2220fL6͈3~q-44bZ -);T8292ì>¹l$B(g`X(I*Z|5@NFIp|1!^»#5}Pi:/<HfӻJgf>4[rJViL?C3|Ƴ˧Zy Wڅ E\CP!& UƊ/Lp2qځ?+07 O ݸQТGYYbDQh@ l;t`8YVgyɡ5B'gS@wb%/!`fU3vFYpL/p94٩^_rg^n5Ϊb?2g3Z~ I.>Ue*Lt555p^4@M\g'M'd&w1Lrv\rA6 .P^A `ucZZZf a'~?Oƙ3gx 7r.TۨE tXhuf:()) Agu6 OLZZUHԿk.?~Ool,>u'$&2bg!K6mQژTsB[| J0ǃ^ kTCtd5!x/SO]555D D8*f(:$~߿vy!Al$'iT:'iGr$)CX9_Rj04sQ ٮspi^*Rd4n EJEf:ծFR~up:3I]r_>q5CP?:xQ7]vzSg55P~ 2NԯZ`[`23pʐ;Ν8PJ`_./^pVjeiBs/ J~ZZxπxf΀m83ӛ މC0 hKYu3\m'2|MP̀ZZZ{V=d\/x^\-wilU!t[x.SՊF9*!X f׹J+«03/V׵*6N"ÌS&thTzG`8L:P`L+e7 s_8N*?/Oees' |i h h \Hg'Բ]~9@:3_'NĒ?uX+Lj;pN}p;~Le3 $W!0ʝXQ4 j0[OOIKN v {LCK[ꫯտj{m*w_r–L9xdI,vؼqiev,ஃ`C*/[ v{V]l_HBͼНsZ-Ft3__Pro Yoe>5(?&vR$UB`*޲CJXI,JcƕlJpqWgUQ>.PO|i>>|y X^'0DoD'pJHV7п`wEA#I!;=ZQ)Aش?`?]Fk `S1k3?7 !z:v{`Вy߽3VߧKĮ:ɹ_fTYgԉһ/Sa iOg$SxIl!@Sz$'P6jӇ^p=MHmAO k&߈XfHV<;Hf',dN¸-l9K_ƖC520mDYWQ A @gT>vO3zTW_Gu3p>$Ϯlʦ2\DainSyhc_/^Ore7 ~L~~Sٻ`Nrm(-[\r/V7˗j:$kŃF_Na_"-Z)JʨOdzһy),zr(Kל%YS;2Z0eGλU*1ÎJ?=䄶8s#d_cNGji+9&Ȯ.Mqm3i1(bt4n\W+xnmCbg]4LD oαP#w8IwB/u ΁eԿv@4R︿'n[!/_srE~.X}<ٖhij8~ʲ;v奙_v4ǟ=X']e\L: &fG^yk;͒tC=TwruXORv{)r^5v~맍wzm7[郆~BkDY9C*rPFV,w ?uqxdYrGzwWSsȠү?D8OF5~&GWd}Hwγ'.Ы5ߚ{*!fdɕ2嵒_!ĦB,n,[['κTnGZjH xurE]}6{L9Dz+UWg T??'WN=FgĮ[L .N+oZ$w 8tY3٭^m@[(>yN췮˕sʹ'hgn.s%{g/]"S&.cOwCs}-_ʹygjَ+ik68!^[!Ѧ,9}JOng&ȯ:TMv0;}^G9IͼF=$~tߜ4W+Ym=P_=կlo R)S0Nf?ѩB|GpL駗-yNNf B9o_9g1]E֗p7sK d5cˤQ HEr~3S3O{hd'#0B̶E2D8{Wn'GF CBZ;XyN-p2o-9ln^3OM ̼j}W$ܔ\H ޼Kllŏk3/79bUfɵǏ|鷯 e/Tj>1@/LO>tLuAΝ\*HMIxyUo ^⋟7e#Fn2dBxb.w_KF關}\,ٷy~2"i?9M_딷.WM.oOY9xҭ)\}!C`)qX-`:|V8}~Wүq\FRǷ;ɮLe1Sϗy=p> rc)PSX^ L缞ڢųey=9nxz=3摼)1s 5 K/|.n/ܒ&oK/|Y q+l45"=MQ'ߵ]qUS?5ƟuZjo()%[2kt#ٹ@Ϟ&֫F|0]l3P0JN7eV[Wdcfא{anVKCxU^a6O -/ob Oo}*}t޹Wź5>vxXbA,qt wλ+]Vq TJf(DQCFBC2wׁ!]ɻྗ[@wWpHK&zҪ`@rl}|D2+ -xXN'm⼵%o 5u3p}vV_ct\/qvL7>3332Zȹ鳘9EԆf0;A[:}L)}111)9Y?Ŭ8i6r`BIc j "'8M.^1$f f fMe T:iePWCH۩,cQE#'p|qh(UX'ɣ$[9ì߫!M%&xNr\_cbbb5I(VOwݖC/(*Čn8jTcbb>QDN *wC(gRFPSx333Ж3`/mm8XVsC ]'l9ĢgP9Jñ|^ ||G,f f f`f Mm4n`'mnyѦx혁[G/\XK-hSh$ |2?R]}!e kӦ,111 {nw]*/el]NN|vqOcbb>`5>vxOL!qkY}4cbb>@ Pp9֗JƆr9y}h 5up}vmX~*'}$.ux|RY,fuԆfP;A[:}L)}111)9Y?Ŭ8i6r`BIc j "!6jboP|g[!v!FiA\LE,f f ffT]c$o]X~^7Yb};Aq}юhHSP'ɣZY?u[}>,wCh3,fQDe T}8& KMA)N9En@@@[΀8\bY .v}2f f f[C( z ,b>hUYU?[n-[͛WGؾ}{]vNmֈģ+X=Xi>N<{X}֟Jo.4wS-&or=Ȋ+d͚5GmIvygc=d}N;Mvmd@ re|aCf[ K79ᄾ2n!z|mUXm.kx!N ezK7;b<ڔbf`ӦM2k,Yp|3o~2p@km=Se˖c=&?OdСrgH:L&#M{V~{< s|ҹcUuaFYmydi3sJoW]; -}#N,>g:|VG >]~WҫΟ?Vr- _eH+JES#~}Gj,>%;\qUsvW}mn׊Ix͗|VW(Y0,=i({`lwmg\83Xz?ݻ 6zڊQԶn-[d}\zLrAf1ٽr׎ƦPF"wm߱ -IO!4S(L{D:uHgm`o/Ol8TNwQ>;[6]Ad#~'G}>>W~Gn\t[m'wqHmұ:7CU_ r`ج-;I~Jn rҷomyუ#[<^&N64X̍+shll.}v#񍙝3G<՚ɘG^7>J=hVgW7>(\6LC=ӟ/ƱTz56 1.N΍O볼o }oˈ#]vgիW JM8#/'˘kMNS2/J.Z6rJ-:VRp`ƍ СF: wܹP//_63 ҫ즯kwKrR~웲ߗ ϓ:Ⱥ%+N dQ{NSdHG[dWnSDn(E`3hh]IީH>nk߾ڿ,| -x_ӫR}Eoؘe?2M.?2gם-oQ_g-'ϐ޿4~YdE$'\.SDV;@ GH޻ʥ]v+_gC}g<풲ԆP̝@(<;ir,|V~z45< VEeKqq{X %9yoϐSzHxl=dI؋_wrY͇'fާdnmtY#:C:1Y5ǹyziavZX}(Rj`EΠ#+6BaWn÷u},v5n:.Jֲ~ۭK[@Ig^t>^{)"㟥KCw<(G] 2MvPu/cVlIvV`>:\W+;u\߳ ? r> c CSr [ճR7 !:>urhr7/]:(,(?h~>&f醐jzL^x  h = G?k.!,AZXRυ΃O[gw_7ݰ.W?!}vz'G?_+(eG夡vP;i–dC}GsگGc5a:kn>q}>̍+ :Kx.b)Y;￟ڼMŦ~ȌҢY!2rϯO=], 䐗&П~yIt}fNV]M9x{WɥNsOtWl@Tn\"Ǖ>3hg~ks;Hs_N@:xal.~?? igS~qą򽟾#dg);l( 8ftiic<+E hq-0WJtW~l8 ~W?]Ii-mÆ 'rOOWS]¶gf{^#k76 i\_K*]QDFZ2d_ZK6uЫq C ֯/9v_~KI,*SxwGES$IDAT̙3'[PvX~'iڟ_}>']j;'(i|[W6Fm_LA{4~QVlzA9JV8|7^! >`߾A:6 !}/pICVàٳg9ĢlA7ސZSAΪYiO$I5㚦ηK q TO,xIyvU->^7\+]vK*T|a4 [|R;.-r=Tic^+b>Ī8_<ߑ?cGI闿R*\gu̙3ﶟxInJ53e44>ό*] ll6/~^}ak$U_奩0ځ 8uW1pxȧcc#iCZ>:49V'|2SGqGH_?Z#xgE% 9昦_L+΋歷J=eCd!RH7jX_/oBG_{Q=xP;AKg<2ڤ6G1|D6uHK&zP+QЁ[8un mㆠl ߗ?|ryW?zboʹ99f߾}? #9-y.[>?Zc|^VܥV\/ [rfGr6nVRfJ!:7965MTC >;]J|ڔ⣿fW^m4a|̯N鶚)lmoPg0(`k2">(- |}[[xZDvRuZĹ|׶}i6wm'aNk'm xM7>[U) N< z M7,Fl3 o2Q'ߵKӏx 4B0Ჺ$] m+ּ4mXRZ\mvk~5x񬿥7PZ̍+sюhkpk"+ƱTz56N&H \!,/111m!YX/9UY{ <͠vuS,>bbbZSXBs~?Y=q.)Km ύ&bQhSXbox<۷C񖓧)btl_8Wuέξ x|\ !4#F Vchfp}%~ ѴP5M8>e;o!b;iyps]oc333j2`ܹr&ڴ98tXOv8IR`֦^lk_~>}Q 6(7a~wj5pc<,V  MÕ"333*3t҂;lN!7qFf$ 0O:m+i5|rbz3333bڥ u4HnAG翘lA>ZHO(۪aCFİlhHMz $7܌qU$ v qʗ>Ѭ|[Y)SmnS_Hb87m\ n0ie;;1ˇMAm?uJQ<`39a5̍qv]Is?\k5g=_\;?c 2p`ɢOQZ |Tm:|h!p77 0O'FЂk 1tb(Yol,:\6ZFτsh3Ѻ{gu׽ |购`Vx6F)ys6t4ġQf?}w,ܶ;r Y'N :}C/?P'ncC\7ƾV3?|hz c|_<sĬYWg_/CZtfz8cȠ8$1P6q|BS+sHⴉ1SG1ξaߪ&~04r,蟛t,/ sʙc;khVB <4H^G8p4lp瓨e RBA,,c!ga'8[:qG<806cd1#aLJqHYGC|%xSQƆ14JX 0p.6}\l >%1XHO6~ضY>h PG>C6(ɣDM8e2m6G@>úѸ~3gmr}iH7%heOn,wCD pmP9Yaq,ή6,d4q.ĸ)x6bVbqmĬٌ1'1|e?_Q֛ϡXcXI~Q`9>-'O/gC@LJ(&YqdqTwҬ9Brn!`<ġGܳVOCGXc.7g|'|Nlk}r|`.mNawOgk/lENEt|F৴wЧË/U6n]8|/g3P,G|11Ȁ9æiuYInG?uVBzƆIM|H 5Ř( 7Hz1sB_hQ1A2\/ʼnl-o xG'!jnAv%9V醀"j899N>g\mlĬD f%Vøh1>/?{bbjţVa,ШGuŠ/El4[ꈡSa?^Ɇxs`bxRw'jm,ڌQ)c2 d_.GK|Ż `W0v4{cWiA t!bɅΗC1TwS? ǃN :SvvC@7.[>'F ?l }W 9i.N,gCh (*' c"N% 1,ƾF'Μ>bVھ,V"m,//e{^=G5bVGM6thCR'וÍ}gmh XY+!3_. 1c jc!z9 0s\Ģ&Y, ?bb> ,mCctA¶O[㨻 \4[߈e=67 b+!i,.~C_cg`C~H×֗йӞ?v > } }:F:_Y?1T !)&n'd9by@ȧ.J$|N}c?61ȣD}6ٗr|61i~=֚?ň\H4X\mHcB N+lq m,+˃8p(0,tpyJp %|f`961[n >C><-cҞ+>^<J?ț͓Y0`:yCҶ6ꔘ3Dz~Ai\6<.ĉcu[G`ccŠ!` #ib D(-c?$M@զ񡻍w1.ƅvo΀/7.хvo΀/7.хvkǼ87H6h8Hm+ ~0d)*i[ 4@"X<,m)1&FcnJ?/uΐ 6}VBw96%.uJbYOb|fΪdC`GX(-Ǘ\/lHŬ8h6NH9n<9!iЦ wy) IG2GѦ$/$]mPqGty)Cq]mJBѦ wy) IG2GѦ$/$]mPqGty)Cq]mJ(A'pC'ϧG7,N>a,ڌN-Km>ڜ ll u `3Ww6疵ǀK#mĂccecmάIrf:1Y`@>8?S_jCT0 #>$hfN a#OHYF3vh|r]ywm!];G6y!];G6y!];G6y!];G6y!];G6y!];G6y!];G6y!];\o?9Xoy@Yꮏ6$ni1˱6tkkynw9}c! l~Ogum|2gVڜY=/=yCravAFP<˱~o1-Çجo<0.6%Bd8t؟s%9.Ĺ>ӶϟB^[y`Ѧϧ##ׇs1k[Cs,j~=]S{VR6^$Qfmhn%-ƻ46C}Oky\ 5}:1!a\K>ڮJWZ]J'-fuL61Ť:M>q6>탶w8>#ߕ>sh>|W>̍0]07w8>#ߕ>sh>|W>̍06tbx awyN<-|ܐ] C6%p<ZB/>1XS {ԹWK QӁ8mW)c1k9?O^$9 >B:Iq Xh#/i›Y- 1>?<OˋOܼ)32 ጣ B8(C8ȳ|֦Ni*vtXE||MnhSĭtukxCGsY4(?, !q>ⴭFemi[żOI{XYaͮ,E6xvVg̀À^Ob!77ʇrb<3QZrB=>c|~IrFbFO'FӶlLnps1k[][:6gYt4Oixz3+aR+=kϦxwllvK[ݵEs9YO;"W(˱-7ۉXp&7e@@@ 6xqEliŧJq\)]wȏ2f fV\ٮck8! xVÇks.b82f f fZi]̵9'wPp]TV򡲯PqK"K|rd}byI͔W,ٗP|G>_ZsK%!p0_/|1>X~Hc}1}licfz_916i}Q|>X~x(>#i or4}T+g3332P`W܋œZ+;)BL8vO$ږF1INs>4خ?-ߟf4M?2e PGq J t9qp˙{wGЖDD#f f fhioi|EKiE5ΩƠ!?4C8!t|"33ж2Ъ |J]m@@@@@@@@@@@@@@@@@@@@@@kޔfwIENDB`testng-testng-6.9.5/pictures/testNG-run.png0000644000175000017500000003765012551235562020236 0ustar eugeneeugenePNG  IHDR;DLWiCCPICC ProfilexYgT˲ّ9nr$MNE69猀$HN " A7}ff%bHH0+m#`3RKtѲ0}@⇺WAd<am[0}$:"ƨ0 Cb_%cc "1LG{zp`h<|"XF,00Xx&I$z? X7<$ ׯn)}D]c!|@AGa! r33{[ YDhbA^!6|t`Lkc^QE*>0p/i;Ա"p hp$ d|P*@5Mn^0o`|a!D@\?$ @J:@V yCAP$tJҡ-zBih  =!D(!17"8(BT!^b 1XDl"ɈF#:Hs# LD! U&dr9\Bn0(:%ǩ!(JDeJPuvT?jGhQ G{gtz =`1E!㇉d`.a1=Q fŲ`EjXs,=-6bacg[$$\$2$$$A$H H%yN2GKJMOBjNAKEz,.  Y2YYwd<'ɋ[OoSRPP8SDR\xMp8G\wEIG)AIL,l|NLEJOEBGU@JjZZHH]J}zzFƜ&&#yZ,ij3tH:^::w+tf1z?t r 1 w,ƛ;LLZLLLMLϙ~01k2{21731YXY.tLXEX-YYY.ѳd{Î`abgf¾aQqcSӏ3.:/W=/x>_ǯrsrGrWrs93Kƫśǻgw ?)! A;ŝ8wB8! P*a%aK#"yRgQQ_Kbh1e * q q-(i F S˒|%%H6>%%MFD]T,NV_6ISvMNTS\<9> a M |eJJJJIʷUT"Tn^S?"xȕ#3jn}MۣBG#R:ӵ˱Or`uut::8n:9;:;u?&x,#V;ǩ]\͉UM7[۪{Gǂg眗W׼wOϒo_sZ@@[AAA1!!gCBUBCWÌj¡cIP(Ҩh'"sqqWQ}'O$NJLxN'͞48YLԩS)v)]9N<=sLYʳag'Ω8:{~8U68u?#qTzA^{L̢̃ ^ʳ1A5.6?*+($+,*2),+.+)+.m.c/K-qr ˾_UTW TTc?_2xUj} kMzڠک:zkײ ΍#uw67U636Ȗ/7\o4ת_emtmiP{ljOTC-[}]]mݵoaum,z{{~PG*n=Vz10DISm u(t\y / /FǏpzju7Qovߞ|~6I=Y}S Swu|v}fSӟq eo//|q2t+ײeV4Wگή|XgYݐ۴|=-m=^O]Ba_{$"V p0Y@ 9@ #/ȋ(=4}5&!E.͓P,~RS+Ҹ^bgJ`a%a#q}TtGOg>_7YBenq`eU꧵oYAon;۫ٻ?up١| i*E[b1\_Rc2Ir6 J % ZƘ֛.aY%}mco+`".$.Y@D[hؚ% ĺdԦt̶U9+- CB%Myle)GdVKQW֨ f^-׋ӷ3P4d1%|03542s57PbZo,ׁ&Jc.g'cb=Nz{կz@+|3E#gp+!<19)S})/OϟyKjqhIڅЬLBO~IPZ1MLMY̥򁊵J*3WnaUpYVwqK䍊[uu#xpϯ|վ<ͣCOzvxvmh/qWR=u}ԇ鑏۟f>"趔uto-]~/3*!|ȓ(T  $ "}DVN@3ԣRUӡ7gg$21QFdZp t  "<"-#bpL$I$%$ۥ^HIɜ+o&^!HaWV~7y̅;wss7JsKJW/V].vMMad=5ߚOD6qkԝyݯxOGG+_<.=u]SF3Ǿ|]h9 Q(vp=ĺjM 2@ig~ )\"@0JB (s X ^H ¡,X  nAJ#]{o(a5Db11kXS 6Rq:87#'0EPRSIQR[R ٢=CGMWBOʠ0_D2a`DZ7rq|<ՍwFq78{;| BB+"Abb.%3XsFrr -YJA&*ªh#]jښ,Zڝ:-zW/ sMM3YL2^8z6юho (rم8U(-[*(dz=?uRJtz8\bRҏS?N'ŜNeMPʜ*__]]N╙k;)ozEt܊>u^_F@!֧^F_g0:bs.xqqrMhC>+jk.5 |( AH$BeP7BLITC!+(j *MvBcJT$T8S.%!K~ENAYKuz6N yE9B&s '+;Ev3rǜi\&x* bW^a  .RB$B·E E$$%jIs(+(.*M*

rSzFfVvNez,g0ilL̄,-<]l:wwtu:\t񗮋nwVO ~apv)7#&v1^ĉ$n7RmԞ9oz=6#:}A||LAR^qb)B9meIUkM-7[eut.t]mw޻޺Ea??:Bx~qw,|؛w2?M ?|2i2|YXU[;.=?/? &U @hO< ]:]u+@D b) Wm.#?QިhFat0R^!rQ(J}*6ԯih[721>`zǼf?%&X$t];MqJ !I-)'HlFauE6%}H:j4)utr'L9|,Ve6_l99SvisU!xxyTn.˅$SEGVG^;80)ÔgzYtj y}[o궶vou}p=~A ÖǺC&<y<%؝ W onL21C)xvpfz!K˥ԯƬmnqnkj?:dyv;;3{<{i{+?v'?P?8 m`]l?ح:8 /?+1SV~tN^/̏8&n pHYs   IDATx]\kp F슉Q@`GĂb,F5jQTl**v ;hPKᄃ;of(Xv>;͛w}v-/;x<NJJ%R* rX]I`rG#ٳ5k:|$Y⢟ +++!D% @B[]Is_ZZn`-J$`IC`7\NeZŸ `UsQBcH'Cq&O. ?YQp$P(C0Vr\Ɓm  j4\O0)S-l僤_GS5Ts[3)⒜*Flız gp ײ|I&JB31Z|J(K$r$DBY ,%YR$Y(d@-@)+FLj+'MvsQc#輶E|.IK%@r*q8L ܡ,h S-\tilE&BoEzg8T;;;U'pY/ӠY#<ހ&;QsCMWזy"j5ԀPDijݛ.4xOdN*UJQwF(vvZf[ܷjyQ^fm_Ȓ k/2QB٥ #5-Ǵie -uƨ`XqMA[N{_ll,t׿){ER(,]{ӌ.GZ^ ѫS]{,((@oKw}f7߷!fbߗa@(a@Ϥq(Bv!?zX^ܹtj_ɴ8DHHy~ ;gݍZ67@NvROb-P[k^@&Ϣr酨&&k.\`q0':ѭo;ގdA ]^I-)Ű%ֈr Wvo;TQܤeTckUfF*ncW^8#=D/p8:UqCͪϽ /6BcBh I[\Ux Oheh&+˳T'iܿd0O$yeGTt@ ǁ11)AHXŮǴ4te%gG>B]|sJLDo6Ain68-B:ٹLaJ\"` Ʀd+) h1)oFU >~^9 h6'.vP.}?sY^:-Z\Yȕun8~B8;HT`SxvqvCtV\[JNM=+;-p\WVP 0,.߰,{n3Ӑs 1 z kū,#ynN[ D#-9ڠmmC'O{.NZj9FgnTʤPK:_6yI0 3tV@㥋xB-b3ӳ13sEqCP<(kBT͜Dk.HO)Vx_9$|=|7x0G1B-姵,mK2,Xha_Ӂh\B\ 9͝!tN-ᾊ$1Im !a_63A\_0i *BBoV)k;+s.*.l]uҢLj*eL%UQCx"{x#^haZ.h hzӊ_nC6W9t!h H Kj%սʑk/AO*z}hצ"/yw1|o[oX^qNo,݇ XbNqqAw0BmHCwb'XvvAS ?b*M(n{˪{%xm_b]Q> i8 Y؎!5Zqb-ӝ avS2J^ ^0#UOzjC9Y6ٳn }7L6lgGsDTIʎJǫhn e\]U xE2VMR"p=}jzbRuIP.VnlUjF\x@+,xz T3%Zչ4<=G}{T, ְ2kW'v{;_L8feɅb1f)\H2fV78'ȁD.Ėu,H%aC8lqΘt4L?L p'N` c*BV`kh.)zmխz I^ZFWUB_BB5LD_.T;-.B] ppV]ԉ#EGP4`0̧w/'Fh%[b zlYU'vE ۴iӯ_qRd3TIhY~#`X{*`ۂ\'5܂rI4 huTZ$AL),ڪcW|^H6=!]4S|T=6.p$f n o3Wr%@LMb§Rm¾kUx31Y9f͚sμ<{0#w>k ѹ`H7rX/zis\:H!NsSKCp$P{ҥE%Jp8$`0%C׸n3!_ e krs^:a?Ldߴbq :|68 ݉bxh|g;a7ӡa>5֚\SnDxĦM)ܕ2FfCE]ˀqhL@선&ε0招SE̴1hZZ شN w`+F| m>; AYsQɕo:"E 2O򆼂"RiN ף wo`]lWlyWkL׵6aXBn&rdȦ? 0l=.Mn/4JH,1:z Q1щ;fòvsOv\Sh"69:::TYԫXBLu.1WӐ܌@ kRȥ$(Ӫݜǫd`l`mYkW +n*UTYc6?yY떐51P!X; ~eW2W%D(ܡ<`.(JB+Q\ۏLE5H PcRY]L̲~F28W,j, >DZaΕBpX6Id&FDK[UFE$x:Y&HixaH@tHyHqJ@e(&&&}ҵ+<EHf׃N9-U+80k-@/a>W&ُ[sM jfJ [#66b%?q!qH{8 B_|˗W#'}'ShjMl8:XЎS!eT~ߢXgPY3b%B@Il_qɤҏ[tX,X̜<>*'9ި)_[; #9Ptaɤ]]}Qͳ̝=Y Fͳqɺ!xB k -y MM!Nqmly;q5 Esu{Vl;sk zxhy3ѧt E w%-xΪݶxqhyQZE\SLVpΝ70r6yg84?:1MnrK)9JeN;n#E~g6]ߦ}.nB#o?twv*͉2U;|K,8Avb.|`S]ռ%'߿Ba垓o0ɓ}sssmw`ĖH"zŋO>}\8gϞ,f55.IJ&,;vYj uȅBN;aY1I68/a/Z4!zS,fF}/xQstI0_YzUw1'YlK!ÅtIrOS0.\`mmm0B~u|cP{yL-.u҅a2܉-mq[4+@J8 p(*w Eqq=utysTf́ c=?aȹ&F,%— cdg\JfS.<}R*!ϰJȀEV|DB|j@rޭٹ \{YEc6vI:uԨQDijݛZbg^V[uJc'xo5b{)@zc8Ň\9'G͞ ꑜ3W8y14-v!I$ zJwMOY)KE]Oٰs*emXz'N{ ݴ|Sb旯m=T|9Jqn ?ӑ}ӨyɭRzЊPxUun/ӺQVn^r^bq?7XYT޺AaA}tMf-vߚbrn 8 + P^/5=JՏǃy~u{n8yxi$gEGPU a $ gl3ˊ×h]]\\2p6e *^aKO\6Ǵ}Av.sT3uuプLv=]EK&Q"<^M3p{{ :ٹLIfu dlܰ8)7n;6Mh.{ $PޫuE٥`WKy:qpKa1yBkqIIMTWσPu1/ ҂>=gOLܱxICBiᶰZ-)O){vcK4kUO(K/VVMǔ7Y9xiQZ i̹솜M]5Yq g^R\W_CqXCVK,VJςmEIp !637QK+ppA_xf6RJbn{)0fM˫M=|Sdat`e?dNM$9c1f%(B@%w4F؝KoסPI@ǃ'mC[Ԭ-s{6in6<w=lK%~9Pc=PV#2L;Oۂ4ɸ ;bp{1 s~iXiZkg%쵪>)k+pyJT4 zfTѴ5|^g(\vX_C5k]ĎoX+$YpQrr%,6; ^O\)xԲ?l  ꀜGz ͋*Z+_I z[a5~DYo( ^^^gdOQĺL "1铒DžĻw֋T_CY\ W^D'8:<[j2y]'8fj꾒ze~ ڽ|}Yt8 B'v^?8O8jǧO7 vK:fVٖWx_t]:Ӥ$&AIX}W٪-bUWDVq6&FQ 5P?_9ȹp5>g+8Hӓ`Uj SQlo܎+NIDAT3@pBiCL\=}Jnqq~sHcG#+bGW.$$ҮY 7OP&/m,[a唝lux7ZOΝu7fBqw/Wu1-Jꃌob@r[8 0v2_t h_pE)c8&&L0iPzCmݰ's"zks.m ~ڎ;|9xķڵ u)>xADR`;h  so3Ӵ!@G7hށU/ȸ#ZdU11}b7&&U!`]K)qAOש۬-`a'݌_mO^^`9"M}WW/Fs<=wwPp(~/fjs(@Íشs'ƍ .JqUQa}kW1Ȭ(E"=^#P0-Ae82UEfmwL]dȄv7lܬsQVxz1rFCkm=x^w{RDc= gq .Mwih/iik{QGQf;+Pv+|:K [ zٵu5s dִOV? {"2=>~Ըu˞lN9؁X c~YRI‚;4lh31c!A/B]q[P~{[fca-${DPrwvޑ;yk3;cb.\LIH໯}$$-)4%4wcT ICRim _QfÆb&Fzx 32;= {+Zs mB_tNb74t!eef[Sn?F Y%jD 7ffdhacn^躌WΕ?{%|L/ GÐ78.+Wj%'n O:s﯇y\$̆|~Zx; ICEXȁձ)ܹԫ2N lFxS{5! x ЉA0 ; "8jש 2K+$-5)$wkXG bH% 0jp&ƥ> Xm!%q]z?dŶ!IENDB`testng-testng-6.9.5/pictures/testNG-exec.png0000644000175000017500000012511312551235562020346 0ustar eugeneeugenePNG  IHDRO%CWiCCPICC ProfilexYgT˲ّ9nr$MNE69猀$HN " A7}ff%bHH0+m#`3RKtѲ0}@⇺WAd<am[0}$:"ƨ0 Cb_%cc "1LG{zp`h<|"XF,00Xx&I$z? X7<$ ׯn)}D]c!|@AGa! r33{[ YDhbA^!6|t`Lkc^QE*>0p/i;Ա"p hp$ d|P*@5Mn^0o`|a!D@\?$ @J:@V yCAP$tJҡ-zBih  =!D(!17"8(BT!^b 1XDl"ɈF#:Hs# LD! U&dr9\Bn0(:%ǩ!(JDeJPuvT?jGhQ G{gtz =`1E!㇉d`.a1=Q fŲ`EjXs,=-6bacg[$$\$2$$$A$H H%yN2GKJMOBjNAKEz,.  Y2YYwd<'ɋ[OoSRPP8SDR\xMp8G\wEIG)AIL,l|NLEJOEBGU@JjZZHH]J}zzFƜ&&#yZ,ij3tH:^::w+tf1z?t r 1 w,ƛ;LLZLLLMLϙ~01k2{21731YXY.tLXEX-YYY.ѳd{Î`abgf¾aQqcSӏ3.:/W=/x>_ǯrsrGrWrs93Kƫśǻgw ?)! A;ŝ8wB8! P*a%aK#"yRgQQ_Kbh1e * q q-(i F S˒|%%H6>%%MFD]T,NV_6ISvMNTS\<9> a M |eJJJJIʷUT"Tn^S?"xȕ#3jn}MۣBG#R:ӵ˱Or`uut::8n:9;:;u?&x,#V;ǩ]\͉UM7[۪{Gǂg眗W׼wOϒo_sZ@@[AAA1!!gCBUBCWÌj¡cIP(Ҩh'"sqqWQ}'O$NJLxN'͞48YLԩS)v)]9N<=sLYʳag'Ω8:{~8U68u?#qTzA^{L̢̃ ^ʳ1A5.6?*+($+,*2),+.+)+.m.c/K-qr ˾_UTW TTc?_2xUj} kMzڠک:zkײ ΍#uw67U636Ȗ/7\o4ת_emtmiP{ljOTC-[}]]mݵoaum,z{{~PG*n=Vz10DISm u(t\y / /FǏpzju7Qovߞ|~6I=Y}S Swu|v}fSӟq eo//|q2t+ײeV4Wگή|XgYݐ۴|=-m=^O]Ba_{$"V p0Y@ 9@ #/ȋ(=4}5&!E.͓P,~RS+Ҹ^bgJ`a%a#q}TtGOg>_7YBenq`eU꧵oYAon;۫ٻ?up١| i*E[b1\_Rc2Ir6 J % ZƘ֛.aY%}mco+`".$.Y@D[hؚ% ĺdԦt̶U9+- CB%Myle)GdVKQW֨ f^-׋ӷ3P4d1%|03542s57PbZo,ׁ&Jc.g'cb=Nz{կz@+|3E#gp+!<19)S})/OϟyKjqhIڅЬLBO~IPZ1MLMY̥򁊵J*3WnaUpYVwqK䍊[uu#xpϯ|վ<ͣCOzvxvmh/qWR=u}ԇ鑏۟f>"趔uto-]~/3*!|ȓ(T  $ "}DVN@3ԣRUӡ7gg$21QFdZp t  "<"-#bpL$I$%$ۥ^HIɜ+o&^!HaWV~7y̅;wss7JsKJW/V].vMMad=5ߚOD6qkԝyݯxOGG+_<.=u]SF3Ǿ|]h9 Q(vp=ĺjM 2@ig~ )\"@0JB (s X ^H ¡,X  nAJ#]{o(a5Db11kXS 6Rq:87#'0EPRSIQR[R ٢=CGMWBOʠ0_D2a`DZ7rq|<ՍwFq78{;| BB+"Abb.%3XsFrr -YJA&*ªh#]jښ,Zڝ:-zW/ sMM3YL2^8z6юho (rم8U(-[*(dz=?uRJtz8\bRҏS?N'ŜNeMPʜ*__]]N╙k;)ozEt܊>u^_F@!֧^F_g0:bs.xqqrMhC>+jk.5 |( AH$BeP7BLITC!+(j *MvBcJT$T8S.%!K~ENAYKuz6N yE9B&s '+;Ev3rǜi\&x* bW^a  .RB$B·E E$$%jIs(+(.*M*

rSzFfVvNez,g0ilL̄,-<]l:wwtu:\t񗮋nwVO ~apv)7#&v1^ĉ$n7RmԞ9oz=6#:}A||LAR^qb)B9meIUkM-7[eut.t]mw޻޺Ea??:Bx~qw,|؛w2?M ?|2i2|YXU[;.=?/? &U @hO< ]:]u+@D b) Wm.#?QިhFat0R^!rQ(J}*6ԯih[721>`zǼf?%&X$t];MqJ !I-)'HlFauE6%}H:j4)utr'L9|,Ve6_l99SvisU!xxyTn.˅$SEGVG^;80)ÔgzYtj y}[o궶vou}p=~A ÖǺC&<y<%؝ W onL21C)xvpfz!K˥ԯƬmnqnkj?:dyv;;3{<{i{+?v'?P?8 m`]l?ح:8 /?+1SV~tN^/̏8&n pHYs   IDATx] \M߷nuKOIJBySyUR&154kbo!W3bd2jBEQCnӽϹv+ESk=u@$A")))A P#0A#@]@A @@\9 ϝ;' H 7fo~.)) ,qqq~sMjYdfGrG/-3Yjj;)]ܱG'6ol_F^|JyyիWjll2yMdv$3;-/rxWv9s& oC-B8'0ܪ22YrhX5==P Mn3Yvo ̎dKnX1d\pD"l^Sc|#YYWCd)lDȫGF9Vw!)2oO#[x俅&*raweINCxU&R͔f1,1J f!x c h]_:y"!̉ QfoÓ3Ir҄kɸπ.OnZ"$Plg: Z;v)W ԆtgSӋOЂ dLlҨ5 AI\Qr + uZ0f.N! v`h T> P{ОzO䤴xִqDml]A'nVX.;ty1_xLyXFQW9TNө䂟lxor2V`ѮI<ՇKt6N`b;i{ }yOPɌz9uUz響w:&nQ:  tQܜx;fъ@s7?T]"aziz|~Yh}zS fJ9,.@TWPPt׮]přnkjiӆnt#z71Gx# "N@C eN<;Dl*im`,*˶xCo{LoiwGY)_1v) y&}#{Τ)gj0vLArj: .E"u 7z{Or}N*D4!ZF3.tFO"MuZ`TUSӵ+2&8cg7G +Rp'A&"G Yc+JͬG1 }S‚}nV iA ]m[:rd :hb7_ )9kۓ>mKDɉ#9QC'8Pn| #ţ@p`m՜ WsR%!C1 rdť] s%=%C\ISxtv}54P5w.hv#v e}31AfK WtXwZzD$9cy,>T'jrj=zF 0Ca!OQs]p Y#F+ݨSnCElP*O(A_ٱ>g'IK`ht.^3|~.My}{3&sLb:vAPp7Rtopxɓq;=iкķDS!:oS:v<5Ԡ;mP'K]~K {Bf@usV'r7/^)+vQ)g'?Sn׵R2ƒx0ɡ?lT4 \f!8o=0B,s;x)y'C |T&+utLOfށҟ, G`:+:M:[]@xamp 2\39qOQౣ>x#kF.ưCO%2Lf~xhf'm$!~[PEC CSw;їoI@(vB߮3a w@4¤jMO|G_exZӄ;`?e9I+ #N1==7yRڨ6jhd ?\!uخI7//B'8 G2:!~#~HVx>KSqN םqZ{'S(eS:#ҤQp6?l!ϪgS*軭c&7vQheCV7c3(_tC]Fs󅃎A=J`5uNl8!m H*"nU֥Gm)4i-{\_G<]CRP{Rf"y(z3ьgS`uy&:vTI\O.&L` tl' qBYo Սbتs| בpNϋ(ӂ }W}dm(8paT9׆cm̥yC`y'%yAY\*yk3syVG+xcbꬡV>ݽV5Ħ =e=b1g+i͛c[1zB aA]z'pH#A^ ˦u#ZG6!́T`}F~u"1x-W4PՄB?p}jrB}rx7O<Ύ\jcc9lByF4=xf_|/j?f G62J.Bj/Gy>#%'8syUVCȔ@aThM#,_;<w+MBc2=-k"%8榕kWr6--`Oto45shG~8#;ٵ7j>Gv=Ϧ!v"N)^`c'31R~ӻEfu][PX^-pZ{^ =/ΰ_)Uvo8S Qʇls&-%B=+bvTYbd|rrl\gn۵% o[w!0xk-k/L[5?,5'7pukW5M5Z:%|w\)ɀ-3$)⺓ӏmp𲧁G8R7&4a(FO%]u+`4f t%p5ypl dLz% d¢H(~h/FҳtE<[NLf-Z~4G?ZOSmVtz٠!>εgj c6-)-hޗQLS&@T3xB`nS3{Ǡ~hlqzF8n[u(U2Wڕ1#[47|F)4 Ӻ0$(0_35µ `|D:bm`)W'8HRe)N6%6 5M#?pcI<}z&}r{ SI &$_e<?m.0dYZ6?[|!3ӭߣNѴfb$=DDDT/_*;}ˡCG2Kz65k-_[=DI:ïGxY\į$Q|V_˧X%Lv?7TU|N杵?qem4h O(L߅Y ?S \Y$V(W4+'YΖ_M_ :yILFX͎ yrLiN/ 6D+\;Tq5g3@"Xق)мu AE`z<γDRukfF   ~Qhu>M -ZȤODHC][GK;nvn=mWxKa T#rYG[G d;$Io`cePT 'm0wKJQCٽN*Uڪ>sOp单H&wK[beNwHf-Ԫ5vK+o5ˍ]غ|Ʌc1U::בИu;8LLcȐg1L"vx0IAF.!.ۄ]- .)Jp y IH/KJu:P$no fbo@.>u{d0럶B[ ,8!vJz#Ri'oB͏c-v;:`$A#мnb ~N$A @ t<Hl) @  NR&voA@!eA @xo) @  NR&voA@!eA @xo) @  NR&voA@d\xBHA#!`mmmoo_WWב"(E@Wl !@ y~:l 22> @ :u([&H/^ןMzS݃mk.u-$W52`54Q JX/'XHcݓAI#\Q' o*g2_ D%+&ޗj^9l4Sse=n8=H ow.A-(X~~򉻎#6E'|}2ոYӫɍP&Ck|ֶ7b-.;iNK\6c {ŬfqAZ͹z͟oPӱ߉{k?Tn*y09ZaϠ1z֗͝_8eQ3͹3lf M'Cg.(>l}}iE "q%=T3qmmCO Ea ޮMX?p'μ<(ʭ!uh'Is7}Uq(EeܬngMbL%##?A^t"k6}=K4]^zTw*ғ hZ(af8U5CfRih%!.¥?5/* bԴPao:kMO3f9"|@ф罾&`qx+zF# ΔNkn;~TMMTu:.vD?pf|`V9VICu6r7PV-i<:ǿȝM_莤W~4.y("XZPmo,mgwqD3VSIvp ]+J'سPЀ iikE<~'~rf$EQiOw ->; 0'76ҵq$1 VߩJ}"a%_``uS# $tTsfVM%?~ );j-L:5t99bIk(H5'$׋d5г22e`]z-,/ZM[:Ky,Iw!x':r能tu1TƳ2Wu`5 P7 Z`Spu@45EI=c2SR!KtU҂e3>Ð&E~>Sz#k[yT>]tXOp@(pRS:E+HTs)C L/N E=HJYQ*csoY1>l#9 q@B#/KW93o^ԏ.!L sM]{Iakȴ_z[h]̼9q7d;ѰЄcvP<,mr0_غ!Ja N]ΈAzQUxyI~>SiTF$4߿z٦C<(,},&Ն_ eW{93gxHBS:P9t4i*<~gkdF{~SLnR8ص%+dGeE25;/Z8YFdݍ//PpN7[uQ> ) F3b 1Ȋ}Bsόp,q@ 2rnJ@SDFomoM)Tqo@OBgV^{Cu1TWGZf0rlhFqҠW^ݬ$T4]M<ʄAwY5^FíPVݺSs,t5%AxA*_D ;an4R}yʂ f TWWUPN!2:z=Fx ӱ Jm?d^;x/Q ,D>bzEhC'sfS"^| 5G/0GxfݰnUx-gmڴTT~3tnY"JjRAe4z:Y# א ےWa2EI%%%[zqQmvy7t;a`f`d sؔڧ #9ꮟM ) !򄄔)>xF\ĂHRxpTVEh툀-J-:36C9a'nc?UQ74<5Txc'Oʛ Q?_tT1xAca.*j O4ag#[iV դ}[|8/e0̭ܣ ä>r +AzѥB+s.S^^JaS߮1vP'&sӑLqu+}{IZ9'!\N{T&q9x*4YZ2"8sfD QU9u]g.ߵ w 63nuD %,B=cf5dyz1`BjBVn5mZLd5a~='O7VJ|1ʹoPאcvvo l@)@!mA[dӬ"dem2 *3 G*>o.(sx%ՐӘxPgapM?tp1;f;PS#^͋Ԙ-837q+p`4zAAK7+ C\ѳH$Td.i(s2MiQayeplVJ)JԴ+CV렭NVf`UᱦZzCFյ׍<ܻ+fcH]<-%Ɏ,YDo&7ɀflM~g gҩ-_ f'/{" СPW0Vb A @P@A6]zB v AG@L[  @ :u}I,!Uo B'vg_KA@۩B A @]ٗA @Pv!tA @8oq% @ T!@*d @ :u}I,!Uo B'vg_KA@۩B A @]ٗA @Pv!tA @8oq% @ T!5:{jjj˓O$foHPV8))wܹs x xXD <4ȿBMHA -;}/8Ng] *r-q4!o'LooL y;3#mHӬ T*b?ۋ*zLYxX_ELS/U|:R^/b+yxhQeRI  &8",8bsYZL+ ~[GOvqsKoh\ 3cX ^3g#foW9a.G_bqwbL4VyO̥%u/ĿOg5.ذ?ø%v|`[YC"i$)/K 7>CZY_Ė<_O k@;PW9R۝ Tfqҹq;0@a;qՠCEy0l89&T6of_nyu15NB hjq:sEOK/<| !*5)xk#S0Tv>zWwem@Ae,d諒*v@i9c7+ t'B5LI S,NdVTE/^TRpK+Yz[s+Rn:͚w#E67)n77io?C⹆&TZ#`FA^V3M q^Hr@Xڹ4R#o۹mSB~sFOߒ8K%}dC0py,^PqQ2ڂȵ Fݼ\e\LW:biWtXw_xfr@|HfY93!GL*@+b.JEG޻)lx֢YE0q]peȁa+%9A`.=ڬR68n'5=)3=HN'tnܰ9ٹ kjdʤf*tM#F E| KtMk` tiK(_I۱*wk/Ph_6&kU{!~ef ‹wJc^QTo@x}{Q{W_}JMm4Mպ؈xvRcWM4-rAi!޾NH鹶Ň]#E(5Ei_vM1{vO} 2l~;5{.I>[3l},6Y{B1#5 -*7wN]~kI5qH4H e 18WNḶCAXD=N7[@jۚsDv_%j E䃎n-~.U2౼SVgnqy[/KUgjo< mQniv[7Bk'OtVF;dwLZ^Q E-rx4 3ZPr +%@R뭱5BDReSTUJW v2a(l^obЪœǺ63nuD %ݭʪgœm-i2I @xx]uhbOz@ xd@Zo<уWOyg*'`S31xD6ŏ)e25TZױpPf4cV7?kz̾ ;&K[_7PMBxNm[a t(J'0),n}p٩P#Iݝ!yf.-Iq?h9N|Li'~bFœ0#՛=nywDWf>4.baMN`S0 q]u+i8 Zk8B v9~ IDAT`Sҏs2_Ks p^9 çd pd&v:/{ Fvgv zanhiLͯ=+8nhIkpZ䭑^3l2\] ^>P(nylWs,o:x*z\yd}Lq}Po󧗖bvDDDM{H+ ۿYdPOO `uڧ!'lHGzE'_S/Ѓ:Ip>]Yc^tLq#]]X{xpPlVQ\SUt9rrshxX,]ʱR\\V 27F(Uh6ָWSP#2F4ű-3sO ژкk(ܰь-ZQVU^ؤ$DU|_ć>*A/Փ}c{:-ijw1;p,(GSԳ@oIJo6\Օl$G ^ޓFoX$ekA(*^dd6VfaE v6otEiZUy㳀o']*~x)lڛ A] @n{%@v+AtJ "PZZN/7N T}'gXA  :4"eAO v( @ 8-3=g2) bC:""vMT(|:Ny HMYo{rw w𚀀5ቬ7|:ۨ ^ US"UaY ~cwK){Y\ ) zx"Vy;PxhR.w {ĭW]9i8Agw\ |L-Ζń\T3}F|B%c 帆3ceAN-zХs8뙏\̻]e*ڽP_xks'{!wtʹW%q4WĻj蛛wp 3m?saP^Cyg -:-UkW^5@rk@ƌsEǎ+%v_5qS+G; RiF~%>ҽwD'CU}@ںU~s23)˼[JߜL~߶bh]~gILY4ˑhY5#D2 > Zɳk븠hSA%EW~=E\32wWf'E ,o@Z[v9&i7 ‡[-ݭe&|u\RiC}nnaz^v>-75l@T{W&`PyIMM^bKUguIœ`u9O4ps*C`6(="&xeNEg/MjcIii沘G*oS!d&ϲ֎2}qLn:cA%ŔEй,c]ȡP 9?ko[V0|\΂?>U?^QT}*tl4?X__V/>rzHQ ajʃSoApbE=>-u2SC)}ls_5w$Ail15WSGp/sTcTS8~@Gұ3tA4)L]7}A'.BX,!!d{ +{H/A ֨a``r Й zmjԁO\a`bM Hu; 8K pnY~4ϔ] ~ʲu)Μn._xeꡂgN=<]?>7c ]Y7:>g5ZyI=2= #D=b}V cwgb`q#sg&}NAX.TtZ S*SQȟ^8?Bt:;Gh6oc>:x@JT*L\/y#{6%A#W;wMLLlm[ѱJF" +yAG7&j~oq]Qz<:҃ r:Q#O62uvqҒ%lq˙ Jj%_L%A]t Lb5`$5ETæ ,t cs:IŰvflbƍsGBgNçύ9)&r$ +==u2f ڻݮM^EmY9M,"]ID.<%bq m2gJLcӣkls><Θ?i0o<^0ךAC_]|pi@}7sq@P1ɣݺJ$!3Q|&)Ulgۀ?^ vynmj[]' / s9tɄ=B7~N'9}x$&'%*H273J}âwnsP෿cj[5=LiSw;_;(92BzpMWi8|7J ?~*wNDcwJܾ-C164ŵJnntV1*oݪ:Y,7sP*>|Ka⎹yIJw" jg勒(NE|B;oA͙'x&FI뾷~.Len!yxV%IQ?`v14ϙÓ 8MZ,3uINC=dbdK ہ={2ۮ3xY9G3w aZY= U1Yvj5,7.BXfĄxxe;CsIFWz )ӷX}t,}ݝg كh67xѐfihtpSfNo 1n4\<0¤8iηsUv} #ir6"OD,{7)fLf_$jg)D*/8=87&ѻ/`3;T~sKU^Q|{Uwܘ}9!̜-?y!>#mY} 9,i&%is!^1=? '}S1_'(UO)/g_IU#asMPpcE9Z2z`b}(Bzn`$9ZaVC0C}!+NB,j5eC2y>F2)-h %xAgI IRZK/ WoK>yֹ0P(9LL=m{gl`Ҷ^|=g3kry:gxͭe> g$AsgꙘ0>4\'eCD} WK \&9A5C =^P7OE g{>ȹu]U74pu|9% o u1ڞa $YK v| @ @3{n[ T& !"Zx;PZg`ȿEZZA2A @hL&%4GKC+l!,A @Pv?ڤդ&GkP  > u+MZOJ[Iq))a^;Oڪ)'/EZW9I&Tӈ_BTDVuS4T|t[~\ΚDijJL6#eieTÞ|O[*OnI2C~A %혯*5W)C^Ä"QuEI;֟۹п|}a/Wl@Hd砽)9А*^ B)~h`_snG™OYK|m3*7w]~@泱־ِٙr\ݚ9;0s3 }?3#V:rG>G[`_;>uOZK>|*UD说| $oGGߏGA @xh7ɽĉeٳ_t9{aoƉܣsO0pCqZ ^KWAV.=zt;34>עC5z\"<y墈r g;&~A "ݲA)xU&?C,!.sΖ6>lQшetCRTCeEɼ+;&{w:"TEP*D^ai Vr֗!,Bh1deG lIC:UoI 3")@9;E[ >e*w#4i5Y!$ @Pa%e Rb;f@_+_Ni̅-hf Qd`(Bp{sTՇ`~:.l;&;_ىVCmR;y&Op76PҰHISlILh@dQ*SfGn>&%#_R ""YlS!Kqr\"H ~{G3 #ܹ~{Ow$i܉s'gZ  A_?mS00arv|/ope_xoc.C*5mi&b~hpD9덶ZV-h{hE7!_0lB.3L(T(y9OPT \7t|M7?7'$fBrb;_[93ml/檚y!ffU}oQ鑚rT/L{֙܇^SH?y󈉬zw~?gO z^S]"3w.\ *.'½>K[+e׺]J̞ S?,Ndu@RPT*+Ӄ(* ׋Az%md*z!&.U3nޤY[EgPjk wyH'bI.4%/pEs*7ͮE^U(kD1~:|`_)tVy*@f^y"ÖRf=w)*p(p dB뮀:1vB(+\;W]Dn‰8| I)]?wC΢Sn:اeYSDl/Z%0\J5ߺ㤜)9 'ĽReJH[#;yb~D:KFUbVZS䱄 >k:</* ["M3\d@4?`ӡrYPP qgyRiC6XCanc&qplط2V$C>G&|*ӂ+{y#Tn]7$q TAݤtkk ɔ6M UڮɜbQT@'9At -* (@Ez; DT@&* K k܎z˄4U]+.|'r`'0TQ@nט^i If YH*51æ_ƕ :0U%heRjZff̴TAʤ$y{,!4d:u{cɊiPTvc ^N.) Zo8.ooy遅+*a|;3YzKQݜЊLWF0p F7${,p,[Dz3)8,Z5{ut3S * \fd.Ȑ}U_~mwvWig΢M5EIIԻpVzdr5س hXYȦ@{3wQQ@;oP 8hi!"Q[T3@4qmoܬm'ƢG~Q0 #[!lrUpD \ / Z76&Nk9g*aQ]'kUܾ͔4ߍ7 *[( IDAT Lî(OK|1|PPiAz}!7iPz`sÖ, q\|[o [y>3՚^nwfx&nh]PeM6IwV yplnsBl -l-s2c7á73Y]o`1ޚVUl//~/pB!kTa*&@.Zn,?Pk~kȳ32 uۜ l[MBrIɱwsK7[߮Km|UM­WؙRmXvp^ZrGL{ AGgr@o ᣐUuv/|Yz)IKeŽfGjՑzFlK> 2,5MOm&5wfؠ[WMip)w4Ü3I۵Y$̂$}'~j2:^ˢ_ X aٚC{K %ZGdzA(hЁ]x9Y&CT@&@y;Ņ9{GQQp8*&^ʁ|` ѧ9E=u&>?=Ѵe'r]>\+}RDw-3Ȁ/C:ZY)|Mj3Taf쳷·nq;PYelڜ1GwmN[/k(2@Ɖ)_Ŗ UYz_-XbhE]$ t XI.>isRA D;n7* #5 WЯ5*ƣ\ÃΏk쮇xtb.u u5aOWueuZcY&;aT6EoJ4&Ux|!iNiܭj9NV5w?|ȳ)y6tb=u/Y70suc^ڧ Jt| ?ݼ $NJLndކwv:Ht)늉i|hP_ t 1*0 (uڜsO#UgC#\/龜T9ztUv,Z (p !%T Qk48,ͅ.yj?3;Nwϱe'y8Ԝ5p\)|f:b֟6{ ( Ǭ&&.3%m{G/mHIJ K[`NU(<{*H>Z *tL8Klzˆ%mMTs:hLJz`zd+H6fsbF!hfUmd! +Q+SlYoRzfh^Jhi+ֲ_:?,2ˊT@&D$WLQa?R%Ap;5 Q^0إMO-\!5싫(q4j5p2ZBXQk]0Vg'tVr=Yad`WA'I-5@Ϥt__GD&37e*zJԵ˜ Ucj/QJk|dNE/a@P)"\'~ ?RHdo(;R25~bQbN$kL|]Uח~7gM566_6of0Ș)@nxķH|ZW>_cV ( j4%zAyPGL xPoj(E`u µQ[6pAS\ <= F,6.S1Zm{L ztz!.n32s9cYjGH!w)+ ,W mP\m&+57PfQB =R !W54`Yl6VF ":{/XjcWjЕ@V}COekzPirwxy(,B.+t;0& ]<b$qExUh]mp5?%BCV#Ɉ Ӡ?PQ3 <=6c`Xᎀ^)U Y. @fWVKݪ 6:t=Q a8_'' T`@o7)=@@i*-MPӻxqUF%6z尻dz]IwYSZs7*csv RC8CLmǶ, 9ҺsUR /:φ{ )ZB`pRR݁ƚ3& Aw 5)ە UD+K#|e Tb (I4בi0S%Z,u!%҅!"G7m9^<=(6 Nl߱[+%:(E%>d ذnv)oh+KJ[.%/‡h] |%uOh2/ |h.z{JD* LnRV;Eki#\UsIsuColm%7Uᖐ; IxqI{1|c09{peV^aF"?\=)޺П)6L/%rn?k: ?QXlKΙM}+~{Z A1TT@aicIսuiLV~#Ld!!J,@nzb/bW5֭):USfJʼYCH VEb2k6, ̒pzTva鞻jsZ4yMZ5om7K/{tO>gBڂ*0@k>:ƛ ohѭ3“hwXhQbd@Q35Y;<^ߐss+q.U)g< `ŔetXj˼/mSc#Av,Lڡ=c5Y||biu A ԂCCmedO`𵁘!)U_~ZX=VtY?afuurz@o7)7@sVgoK=g?"ۛ~w]ٙwrkfvZw)UQSOȇ ꎟe/mNl< ŐH֖B݃p~ΑTo_h6G1Z,d]Se[}_Nrrƃ7VQ::lge,\W0ʎ)HO'۵LJN1Pm,5 P^wR 뚜C}'P`R`wΐb{vnp⠁6 Dv3c~YZ(?JFg6iԪ<^e٘53NkH3V.;7c]@e}uqp@Ph$#4WB>U[[&C|2H}Pxu?^XXp RwiFdn/__5k/D*t^3@*f؃K32޿.<.TF[SWʢ'iq^.:Yi?XX{bW%ę)7+Y. .^Aj+nǩOYz ,TR@acQ.nr0 j(DYj承 0P8RsN-aN.XdYW3K&DPT:U@aTS,T@P[%$%*I* cQ@4ױ.APTPL *0.:NN@xGSPEz;^;ʤ ص9)is]X^mA8.I 6wL,yFCnEׅ}sԘ@n,zn/,7 a' ]oIo5gwy=KT+] XW8y܎7~eۋ\DKË*p*t`50ݔc-/BxPƛ+Pp-Qkrik] )PlX8vRrT"RQBj≩@ON/dmF'$g0kЩ>Y/TM !Y/2Im!EY:z}#paB_C.X;RbE5 MϽYӺ2]DsOh a4&8twF5_:7kL@vLDHtV9@tT=Hs@4DD֐zEoت?R_2UQopmcT90Fk ZgYff0Pi698PT@ ("4*?Fkf(TX[5h^9PLО54(z 'dY'7frJMJ4W >{|h&E;PYelJ//&b4nkm=7#'nku߷WmtB>LH| m}\i%.Z/wXaVZ(@֖t5Mк_zqi[af^x!7>"tgo[$Е7m7y2M6מ3A)\0#r,T bPirtjxz͖:RA*aOWueu׀jQ:w/M*oV}Ӡz_Ͷ6̡MD|xox_nϧ -:틄\kV4wC@-Ca"-еx?D.OsY4i;KJ/=@ZRb'4ya9otB7kZ~<#o5fe֏?jD~s ݆WA D ZrK^{ωWpP9Ĭ~f(xMϸ᳼ap OF5eL0a /S+K3[E1@t/ACX1$ˎ˄cL"Tct_0M%UL7<ot5#&[/`>Ы,\B J8,:Agf<#3Ut.{5&.6PM`4 ?_Eؼ_ m؃}q1\`LR s5G)"7qPܦ^Vy;:(=ֈ%`iԺfnlf1tJ.5@:ehi;x*vbe # 5i B(yBk-G'rl"3.*Jer412owMd⪼gh/[,^@H'.^zQ48tj4uY"7r_O)ę(];1+Q$^qoQ^LIx 7 rwKsW2>FJH|cPTvW)eyr)ױ%TDd%x]DH EO*p t%`* vHsT@P(Ho CXzӠ*  (M&\EPTvHsW'_ѩkՐ|ذ@W}΁+.3TS@iw~bIJ*[p`L-o3ޤlqYM2 ٕ[>0 * (!un/p>MP%؆idnΒo^MV'H9Rl|\|[|뵆冑A#قPT`*)Ho7#sFT7/k+*4OC ln\ꢢFx>פXjIDAT,b#N! Y5bR꺥 gY>MB V.,8%{;ٛ=g΢M5EII?Rm[gΝڢ{vRXYȦ@{3wQQy\B BgiHη[@-/l%xliFZrIIEk"u:봢`;m?(-B $=geNϘ]Ua0zfF6j~U?'}fU'* \Ve @gp /=(lpab x((4M*% #fc+Lf 1>Y2 \8%F<vx! yle>֔9ܞ;ݼhlcZ]om^\Lwfк({=^qɣQZUyl(Pk6df-Ҙ-&'v|ݻie٪Lo(vmal'&R/r|BKyP\$KmT:WwRi*P^wp~٘]/GIJc{ s2ҥ=$ا` {H]/YFosr9rLBDlտhurµ4M.fu1*h`ƨfʹ"M8w'h*0J;Bs͸g$8Ȍ2iuOh2/ |Vxmd?voiS Yɝ<w"=tI@5 Ԥuˋ֒aB!(K@/.-T@FV@ac;zy8**9dy0fkOc9#iF([*c%b~aR=_bkjo*vW5쫈^ALϽo+sU~S(.Bz4$V+#T@PּE+i#QX #W9Xgs/kN[+ ųU=\MZalD\xn,:]n[ZvӖIJNVz5 ըwyFAJ8H'U̖[>$ Y]3EbcI@xw5ڙn[.Ok!öki]\QuϸhaY,T@I gRzKavHs^5榓O 0$0ie7'GxlKEJccȰm_O}6'-Չ"7* vmQ.ƫ=Ƃ 0;+CaNL SۍSIr[¾i {Jc S5T@ak2X4* vR/ UPT@Ƣ"4 ic]L * (7Hs@PT`\ (!u\i:GNCM2u`켒 SDEz;N`;1Y=fF7v50!at$Vk\DaA }]x{W+h:~S@iyCG%+;6hnhy ĪRcM}iԗ ȕ,5QT`(Ho4פhrSQM;`0.ZTuη9xÕlMW$ bA@]Z.k ,Yz=nبY fx&;ݻYLVAE [5i¡3{ u =)\0kg\Yk)&'a۽8 !}qdoF_I@>}nF]؋O!sQylK U|G&99b}C$'^A"Hk(i/ >T (: ͕Pi 0TfvыUs&{L38J m5Jgń`Tgԙj. RHk b\@R x SI*ǜl]o-+skNQ2: _"Zv`pe(4N3Z!hENoޚ-/Wr M*,$=sr2+˂j2#i}n8;Jo~6t7~!idϫg5] SCe^st+t:.֘ltmgU:ҼN'yȼ]a*NzK\}0Ʀ =opüH2N_}XaQ&+O-mkLP ̮M08*ȍׁ8o7)0\0.J#d0.iUwp899=_}SkJtfձ^^COZ\c\}u!=ڱPkĉ*=]9<͕'_ Ț/IC"zy<1mh}O?Rcyrĵ=AL5%6b,* p (llrwך #pr.^!C!R+ڠ<pl7)}r[®c%Lvő0RDY#Ẍ  [9l8* cV@c[4XE@PT`DEHs["* @|4ר>T@PPChz+w駻Ƃ~+9p`FT" (!Zܝ]IIe[@u umfЖ7va͒9,aɐ]='=c6tu72Y'ZwnIw@ M 23= ?ruQvg@ ;od<l.Fr(u%}fUc *0vF+)Î^> x=>!kڠypt!sv:3+grܾ*/Oegx}jbC.+)%Vc`'-7Vfd~ej]pJc]o[-XEp[Gm5Y5=^0!iiډ]'6CiŅ&b{ d~t(U9B)5FX؞9YlY YdVzvFRiqDX8sߵ7m{=bKbY* hgo}7}_TggJ/~&BŋK=?WRW}7fˀH*FA ϣhj [= ]L 9l0k_}yf?B˂B5"bKQRyKq2+H**N+5)g>b*}ȸZ50u' =̓ZZS:zOIc7M>{hfcIr6;k`aaʼnri8(W;󘗁~?~"84F &4> />qTbd(Ѯc<..|=>+J_ISSWQ1^tcԭwbfޗΕyp0ODX#l!O1g {) SRXn)SwIH=3FƟ[R_85K4/ԷƶzyGWM^>ꁔA!ahdlUkbcOƫ'g~Ș̜X9? _gqs__-(~(Ի|qtM|i 11Aa2" ɉ|">QwT}ܳ* [6fC,W''_ 5Vb8zƒc)i.鎃gpr2E˫T(P$(q(T:,wJ5<hs Zz]:XS , 1Ff&,&Wl4/[Y Yg'(lٶ%8su<dW)yE|d~y_{z| Da}*&LBÁynbd/ەkW>:P>hb:6O+t|ԍ-Lfb^4X7g^Xo' QBDMCCyND,'#{ĥ#q $JHɽV(}f@vz=l܉gʋJs+k͟=e}T|5ݪCkw|v8a5qo?BϤ~M7?z/XX Y_w0oIn ;P+0DD oHud(9CYQ]p a*A &jn`~ElZd:vLz=1 3L6~6l~`Zqt2Vc'Ј-W +#@PJE|tĶ$Fj4O&V6SЄ_,R;O8\}ESBvNA+c!gX-r-|3/w8&D|uSr?%B F 4>%tz,Ǟ0 [|HԞKu6-7'3\nOfme߻ϖ{Cr#bB2+*UeˮW|Xz[KN>|`0qTUϛ1w:G&ݦN[}ʙ"8k4=ւ‡X][z/_++U"ɫk^k777\6766ǶTm-llP/Q a4v_ܓ Vbb <H6o-8Bv[G7ƺ a/MIưƇ``cF,~~;=.Er Y" `?2^붐B̭` Ph7"O;6gbp7Y?@ xw &}<^ ڑ#e?ZRc^莎/uϑ`[ہ++}mYxG^ofnt; ûѠx/M8y %Eɣ4ZRXHP(^1T\~7mډouOkE@PE@P~TPkfc̼g~ k,Wdj1c("(@(b:}^^z>X_6uIbmݖIzvn:7-x}e}gn%\}mu/6I`1Pm;f({0K-qjW է)~<珞?^z}SQnvoB͜m[/lR!Wmzfn z_kE@PE@P$HۂGf?.X f[d(dEԱE?_6k0 2~@޴c۶ݶmom{mmnv۶۶ݶmom{mmnv۶۶ݶmom{mmnv۶۶ݶmom{mmnv۶۶ݶmom{mmnv۶۶ݶmom{mmnv۶۶ݶmom{mmnv۶۶ݶmom{mmnv۶۶ݶmom{msmnm嶽zk"K-BٳϯzM*r0BXPxz/øNj`lctocqbnԿ;LOs{_H0Y=  ާ$w6Ϳخ:Jm`vlŴkBC ]sʶn˴DoزVE@PELE8:/>:\ΖiMbŠFmUDzƚ:6}L/mٖk+{kx8{)~OqG@?{#yEMj^icƳT a{C߭vl}(ϲY8.1;peW RN?OE}6 |^I &άMjcjJ]EZ,:%K'zW}mSVgMԇ+7`)~npG=}TϏ/ߏ9Wۋ-dۗ^ďkN줟kљv'؋îmv0Yj/륏'cMYgc{L;/Yj/S':K[Իδ֭1n~3du|LL;/Ylj/S':K[Իδ֭1n~3du|LL;/Ylj/S':K[Իδ֭1n~3du|LL;/Ylj/S':K[Իδ֭1n~3du|LL;/Ylj/S':K[G\Թٱζf)sWfv->>lq۵de1,}\,~S6DvctTE?=1}ojOM?|\6eљ5kY6r1mLlKKXapɮԋ,q[tfm-5OM鵅cO$&1:_n:k7[7'm7[7۵NMgIM'vf릳f{vu~vuӉ]ٺl?iٺޮltltbonn:Onn:k7[7'm7[7۵NMgIM'vf릳f{vu~vuӉ]ٺl?iٺޮltltbonn:Onn:k7[7'm7[7۵mm7qY=':is-p.n̶f1l/~M6cئ.٭h)$YQK`٤#)tE⊿W-fͲ3}ujW7U?y9QZ=;άbdљ5\@G.EzcƵp,?r=,>ikMȮ$e<>whQE@PE@8n/Y{n eC_rLN ѳ)f[ံӮ=֛mMY۲yb\hxGګN<}QE@PE@8DFFx|>o֟4^:䆪9K!t--[mlەJMVv9W%X1Ev,bS/C~RP+ZE@PE@PN&XZZzݗzg?BT2YRf.gʬ6Hb+5.5%6Yj!DzMz6lxyqq1kQE@PE@8E`~֠A(t0c6ʼOHؑ*PزiCvy@H۬Ef;s_d[ںp1@NYE+]V2tO~q5dd &&2c1yܼ.^/2t+^]N-ۈu@+|^3Z'%!UK7`ξfk-š~pl2^DwѸqc4iM aCeȡU9Vj!^19Ͼ7iеG;ѿ`_}1l8O&K"`"Pewqh<} ǚvQIừ"(&wcuR3IR:g?7ipɮ8I2Re-f-6\ uә`92z+t~MlZun˲hs'~Cvډ!-1 [m֥35k.޽M6DDEF<(ޣx$$$8iiiG[&JΥvI8m\9Gq4ڧ A3,DZԮ e4 zE@#>'Cp?c`f BZ~-|SGDFa׎}(0PIP3 oBnyLXo\n39e߯*R-YGd#6ɫ̓>vT(qߐF$d;o! ǣǐ~="Kc }~ ]&͈_^=RPȻhp)M"!lÅ}(W䟋w  lxĐjg(9ZHHAT$ò}nfWH+@X-o/0|P;D^|W,w! H,^-O5VE4E/H.'D*$Udc[y&&dWsx"\}YN7ѿ 1wϸ5cӰg4}("P;1o\|p?[YgBj:E\sٕ>iK-DV\ }!Wvr##&iqH!bKEQQtpXDӪlGKːA?9Oc/KOjs]r?|vGK&HNNDLtCvQ(6أhڮ6 \_E e#D9鱗MxwRODZ,~bݐWM c.o}.0x )z 翘GuFD=hd}=^Ie9x1O/OcÏ#c3J9> SgOǦG>^[>5==t9 Pw>3= h4+ُG6dpE .@`t ny Gg`P@E9~y;ٖ7PB}(>~{_O6REd!~}DɍHHW_k!÷ ۔6hD]&+0۔>X P1cF">'n1hVKPDc斠 cjQP!WWFbJKݡJgc>ؓٱx8~8|X}r,"='a?H. n_Fְ}"lߵ E2wGB$t>W႟w@(EjZH\~q+,нIC?2{O3.CZ oIጨ/"8T?Yܲ,:F\J1eXl:\k:L;D6kCr[Kϖ~*]2Dȝ1ôZIA KznнB|V"5 U].˶,m~U[?}QHEX"Q_+"")CC+tE@|ZtV #bWrA>&f Ij?l^@ctAү:{>=s)ωj˥ON=3ر|\g;v9FQϰ|/R[}y^wځ\QEIx_Waƿc7"J" o-+^ֱ\N(z֕:}"ޫpv]{?۫HTf;ypљ2ε~Ov-E_(}FAu/oe`Rӥ@:=pOq~J*5޽{˷cˇ\ʱJ?«8r۾߭څKzw@ld b"c[1P11+/_ۜ{}iQ ЧYGϚV/Ý܍=~(˧irLAPm!cĶ鉡x{$D=y-nܽP-]aTJ[x#GK 7.Z{Z:>53("P3 begl+ėϬ踖b>d]ˉpk[y2XRkm_g|9Hp>B-_ Km!\ .IHWc;98,.?o#vR.Q Dmؖ},-:{NspnV(<(Zq(w]ع ~q0,E F~T٢Pv 23 /_:[f^0kۮJ݊ږ͇Lki5>Fd;+,}5iz+ÝcQ/DѓΘ#Lj龽LfَWwSh<͌-?.LvثH;oÿ)h޲!RSkE&;î<\ak2OT(&1h޾-|{9AW=λE 4.A^Q#;ضu'JY,BYg5vs?zhՒx{SJb Ҭ6=[-[ X1vj# su' }&ҔB؎}@"(@`᷑;?.?Pab$:߬ ǬM=z[ׁ¤ԭެMI)̵ֱLRE>`IfIӟY0lH!]}rd>ݫ6Ydb?O7ѕ<r W/##"ѕgJ$|ofD6"e% HO: ?yD|Sbk((^E n)%tYR]{ Cۙ"藝=A$mrVV;=Q|p$.("Py(z:2yr+2$,D\s"̲؈l,;%m LP݊ZϴYb5!n/5O~Hq݌s31=DwcF 潵ēLfyeWora,[x7؊:xߦ7ymJo^)>ՙR RE@8`$Ip>FBH*X{lnRw¶\M8K8d7`L f$aыOŎk؈ 29ݱcG`-Q g5 <\ԶO3ؘڧ("(qD@x_PuR^eajYc%\kjǵ)Dox皋FVPV?\K^E@PE@P U$3IpA{'mMȤv8M;s-]ۙsڔeR`;_ڕ7|ckQE@PE@85`>+U;SS 3'W"̃m-bEϵlEPE@PEDyݸ%\'vRm. i1n $2mK-5QE@PE@P/p,Kg"}PlX6U2^eg_F&K"("('I[j dz2K۬m_U];6y\D'mI^okIQ)>T-èEkb#h#Cm-"(s82dn'p@w\ԉ^lÚԄ I%1I[؀6u,7m8gp18Q+'1E ?zz1t*=sO"(y8sQ4!ҶcZlwM.'V8 !/ Kr'zxNdsJCEغ2 /iQ^]&MbѮqՏsVzux"(?-:!ebcrFı_إ&dKR\K1eqFm[nA*"D7kvE+{Py5~r=GF'$ōQP¢eJxD(݄ a6Գ[OtmP9+  dHBf2:!ڴeٵDw:R]ožЬa"ڵLCzxtk U*a"GG:{v k&4nIq砿( N5SE@8}&5όer[! (lc?Odvڍ첓 &u0<.f -ߢk7"Dwz5Rb1h"h%ֵBnii) P>6gÿearFl%**"Md5\D'56^mĞ}"1D_֍a 'IYK"&)~ƌy?.oY 2-/v-!^2bbb 600*AG_8!]Lx;ih( g6:`dPJElq1Hջ4!gNSP3 >LHV>n6ajBv%yA$9O칖 r؊Ng,;WuO ^ڶ \oR*#""DW|СCسg8|$''~hܸCxy zp7ںh[ߩ-A"(gBLg:-ClK>mH$g$6q-):[.^,@A[.sEW }0/>> }1t)6/yv *v#//?7b޽ί,>\sM>G\բ("A`id=~-mr77|Sll*RsM-RN3`~b'dۜ8VN,;o3]_Aigj\iEWlOV}`7n:^r9D"ƚ_=p .f:Y긡ŶmPPPjʫMsE>'s3c߾}Α33Љ+?6vcUM%qˏ3kI^Sd{.v:ӗ\ 6l[Rǒ^lvsd4~` вb4ٺmĤ.㿪z8nF{ҧVgmRb;Po5te[g."Ni]İBwv-$~]v|6o9r䈳_"|nQ8 @Fc:<lgcAE|s0lѢ==\8hq0:REa{]*BB ~9GT5#w3S;>dϮeN,65ee;&DMz#hwGK0- q!NXIV^gpӥ?|0 Ӷ߈ǯS%0Q }%܈dֽ5Ar&xc\R,R ǽ)3qi(:2X<]+Ύq_u'7}s$4~^VODŽ6+I_ͷG1+ƀ]83+ޣ˄˖-[pYg92ܖ"v|򹈣sWgbHI ?u7B{:7JJKլ}X8aF脥SX?nL"L3$x G_dlq3p@Y[Xp4ys,~w+&Y3q|nC\s $ c⥢;z %U|Ƕ2C݋&)8yNNRNBtyب';a#y=FDw #u=x{!8$&j43݄݂ _ށͪƨ)6)[nuD!f%os`Rl'fn*z\9*#-;`;n=sK_v3FoRV9ŷib07:ǥV"BTu-To~jr֥fBשY_Z6/fՎ:c:cSY`gZf"ʍ7~6 YMep]wU^'Ň]ʑ 6w0i@X?c< !㰈{I[W`s?6ѓtvUhB-۬F֬l[igѭVIPS _LE};V8ӓ ◌3Yh6mڠ-8(GNOd-شb*L; W7[ [1r]1!^& =F|x -~qy^x{}LcGAaKʐ@&gQZzYؿeLـy٩"[^i8bҎ!D4qzcp%}I,L2 V\2&g{Ѡu wP)A!Ԥa}@UcH!---@vʊ.EnЀږB |N+?G\=eÂay BX3V,¿"]a9͡qeyݯ `Ţcg8%KQx[4nG#etAi6M۶Arm?q\FP"(5A~0@4tHK/Evv!^vĠq"Qelنe'WӁkZ]STZZd/ o$n&&~R[qzU] T1VSќDCǶO;[Mg+=_j4N?|Vge&رK\4V`#H|&yǎߓȡhjjy <۟ (꧚W V>~>cxvf4i$j-@nrKb"gx|.9g7_ ڊnB2jKrg{6j!}?,T?gX|.i۟hf(">^E?kC%E@@b?"^-Qic$s[ctο^tEx\s;XfLǑ9WTw\۟ oz uԒrhk߄q-Xb:z(\ Y3i ʘ[*y%E#^,]K" ;cgej>nōCp+ Xt3n&|'1&'N]ū b1݈nsl#%FQ}^1Z{q ^yyLR3o[ iOL=ohf||XUbXciM~po_)TsE>'sՓ[1ڪ; d8+9ɛacv%^}bc7e;&ԚBq })%S;>Kۋ/q+Ll!HnVG"(/W\ܸ|!萚نw+|N:9wq7u2Ĭ4rcVg\3] sZYjӶrMVgP3i7uaUbТAdHgED:"㵚.wB4:޿% ix[BЗwwGpx?ҕ@lRn[?ŋx)]20`Vո/Ư+M{m!\}?>x7Ehkt |h.{Ϛ( *2poڇۓUcTX+>>x?A 1o_w9F'!9197sd3y09ۿ'b.+[iD_E:I{@#ԚH1~|LZO-4Z,{z F<1s.?[Z(IE˜܊]>v!.V9-r}֒1#˜ҡZLǦ8*zo܃'B2.9v8L`^_]lwL̿x&ɸoq1PQHӦ"J"7TЙ~r. ;n#xWm/w'#^/n( q39qe -9IHK۬ek[5Dћ2q>X/}vݑC>E cNχm4}(;Mѩu:5HDR\T%!@Y(D\9@)E!Ů.I &Y;MSp.F_v8 󑐒Ѷq- _|{/Aǧ"?4E񴗌dRJO|󁦂d`_>rW$litFB|2RDT"(' *vO<x%aKŹ\>X-}e>Dږ^dR,;aFIHaEtR[m\DCV|HǶs0-%!mkHqnŷZS*?˗{L/D㣰s {o> K#X/ SbjDt=c5훥UKC~+ETNnF'#=#EE@8,+>KaD'++w7S\drK:sO2!@ WCمu+< JU(@.~x_QY5օVch5UE@P~,f_uv JFgn&ፍH:= 3+Ѣ1|/EӴX UkBE@Pp:l'^tn^:˯.ȮMM] ፋt6I-㋝J\nv`5T<}tq.FcE@PE D@8MfUm}]];srgNFL](i3H5VHqLWv]Se'Mx߸ZAΊ"(fcrP#7ٵ'g&oUI\MWHo*I"("( A _cL(Ǔ>jwW8q suUkRj("("pBonOyڴ15~YƶCmڒ9)Kl{^dE@PE@PN}Nn1TL*5]ٵvnUS"("()@ζI[lvәՖ׮]oC^}LGM&Wǧ4B^ lh\v ++?ưۈLG.? 1H ,z70O>kzkx̑GSѫ ZNEv}*9)"("I?if٭I2ANVM]&sqq1.\g}۶m eѣY@UIع" y/~Kɤ-}~߼kA 37Lii~ ^qǎ gPi|m("("p # +E_a5Y>JLK;ٺ2ipwSN@EL0J~؊>#w#>Gs0옃D}GP*'W"t_|󲰍E@PE@P~ xqCɝ d/cx5Y fNԖ_m;TmV;##w}G 3½>zrwzЍrM2YĶZ_fRP>IA'Fgbbb>ZPE@P7':\+ډDUԢ}6|bcc1p@<h۶m6-jڟ8 k&R^7o?BA޽;:i‹b\2Oٗf1w݉^a5؏*("("p" PtRwbo–% MDtR]uپF0n8ݻiN՘Xo2' "" M]HY'zñПF=;ZO|5q9{6k!&K_E@PE@ `r|1{lo_r_94X:jlZe^c+ƠMٚ;^XnzrÒgGr7=ztDg30vnS-X߃ YɁOئ ;s!fU*ֹ;<m }=5K/0%عDi鬒Mӥ9_ah};DmX8vf.^ t}Sa7c)nߩEY>E6g6fM0x,=@g3kh}4p+Ͽ|YE9i3 mlb60vynZ<5@ "p& aBћicmk|B2۸mIԔ%=yS/֊"P rNƠqiXKGb̀&|9+pӤxld}-fLwqmdzJ 1sX 29uVye7_0rlӥYlo^ [yd}Y|Yy6#;kZ7_\Ps?7|: >,pƬ=76;/z| ,8٘mZo1rMNCQ#MFlL6SĪYW^As1X μ ~uExl<\*| 0(C&x,Yw`PoA뺝5vWg`*Z?; K'^q !tv {::͹|Zaoa@;:o۠qxhUr6/107#ecI8UkȶZELC@_y{ىލ3_Ŷ+v"vN;Jru9EgPޫxe#Ivn܉d^GV@t4MOEWG _-YmX|)SA|bոmd,z{5Ƭq|;-.mLO<y8gyxt`wJ6/aէ#h8f"=nhX˘x ?-\<-YrzCšV3҃1{Qd@rt6')' gһGz͙W継#ѣ HOF֪N~_Cg=' 5gxf*:X_EL@ \em&~nf\Sk'bLmWko=?7n /o#FmMZZ)8t< : Vh.ټ2K{}&ȳ0>h3yz9b.`}w<:9)IFzbcOa_+w _ߏ+ƫv:ė3 ɍ9j3X6epx̡nVɀ u,v:4,^r"]cUnEhZ.e$KW}rG%v=Y-xbȃKt`$k> ~kƀ|x,Yi4,,}c$s[LֻE0\Z3`k&Q;}mHK5PN<`-!.)m-;?fcӾd僘:?Dn2qsB|'L3̟t78NgAYZ/RRqC[ѿ LOv1 ||8VCW (h&ĂyXZ~?#le 2%mc?h\J>Ѹr^^̱4n_Am+$@,AGoq^ps3Áo)op>-`HsD!V^}f<5rð49+(|l9ܒVIUMS_N!g(jQP|}Җ6b[ɮ$斴$gmk׮Ŕ)SgLXp1'1hD k@üI:OWv 6җy1|LҏZp`©@FGFԍnFh?1wٳ.h#9oЍla5}EoDʔcS \o{U㰫x55_Û)FF^+X1bX:yCcbct 㞿 ڛ|eXsZPspڇhhWCsU 1;_1NϖآVǯT *7pپ*pLofڰ̮r^*LInwl33^@siu+ z%V{ ;P;\/Mqē h[P~_6`} K'Mc։^df:m|Don6#Ϯk5~]Kh۶m˷q:ƚOqpټ;qy k_̻?375ƙhƟoyWIjU88OP+h 2>ۄ sz˩;SJch$Ŵ WKwv=5+k4!Vwh3lsW#W/Be}S7cDZg&rƼfU ׎=}.q*sW۪)FPN3W1j">jذ,m7IE u@ϲSpVp&RI siӦa糇nDCo`h||9u@LV4=ZH0)IDt9O&6e=L"ptaDɷ9&\۲U&ϽzzBBNr4YqµcONun2u9wmՔU(f&ĔMg^5U~T1JLK`oWx+}Qy]hzjyr_"̦*tMREF ò6E@PNSL d/cx5!^̉ڲuVw[gj E@PE@P~Jznn:X5ٵ0'}dԅ("("prN畅Brplƪ?dמW%rE86^WE@PE@8k74y٘AAvltA'"("('/$QެMSo^;kۖAMYۓ7"׺>BCU P͚ZjE@PE@P8c/Ulkz7N ꖘoʜ}j(--O?c4K\p>Zs%]߄ßGJ>4s1ҩ E@PE@8"ѣGQVV'zx->"##k{pymg>3ٛrMɮ633eۦ_̙34hׯ0iJJ]<ѱM("P}Q8_0n2Ѿ ~aebɓ'jJLn8{YYYAqqqbd٦MuָkРA[a#rI;ؘI޴"הV TpKv]x^Ak׮ŷ~`qIIڹl:.!y++1}XJ@捺 ;߀p#o㥉CШQF֦"O~>ƫ(BF?F^&j5̟?+Ve] :t@rrrشi>s<ٳ' ( f>i?۸'캮i$,9nsxaO(!.\UVah۶mIw;'۰=4' 4XꝏY 1[^^уWg Uxfrh(7oN:!!җ={j<{n1c}wbҤIh߾}],_|~Lnݺ!33}K1rȠw5o.&n_X&2$-ms':i-n:V21m4q4"`={MkKG"ď1q Λ|[1[dP_EAWMɋJvPhu`%сNVtwڅ'"-- |uā!˱c(Zj|N믯%>)smlkUjBvkLSWIT9##.ٽO?Z?PﭸИ~*2^dtzZY&V,Ne^83/3דּ 'xnvvD;eDߵ'xZ4(;ZFq}WpEUVn5S_a5!^Ixɜa'[[Cׯ_?WT;W<z {5Jr-[\CͿ.m]AZZ8*(}ȧ8~:O=fM[+ ``5qWE@PdtM26Y ,A4uAK;vo_BzMR ʩ+k͜k >D|IIIL LN%s^!?9Q[6v¡m{v1ܸ8]OG˚ctϯ>;Cvd 6R,OX"p߄¤E?m ] $H; ňCd`Ts`c=pWIH$ 7 :L}ѡS&gG޽{EȨHgniY)iu2"#t$\Jxѫ ]6_{];=/t#i% EEE[@b ukb;IKxf6M[OaÆ1by1w_/.G#ݧ*ۺ8F+Fa1rf=P s; kPugڡLnxܜngՂ)x~8;DLm=7 ] h{ =a%!':ixRXt䫤yIjhzknE_2bmxVwkwj^%uOۧ/LvN׷YfbK̡  (8#5-2s,*E0[/8?[v}S짱U1__6oﴷ,=~O+Ξwb}{Ų{s4 (_ƊI.8cɘlXW9N`NlatfP.ȮWnԜ\uN??;]5kG;ƌZ*ۍ )HK9CE LZ߃6E۱䉞1-Pޛ=BwL4Y c cca⅘7t6y!9v*(|0Xa#@a0OŇ/fueǭ@Zh6aBv0@/h.}_3y?&9{k9_b`F`?M0x,ݡe [(990{(i|ړִ]j#4Z̄l(K)"~6+U+?]A|G|6]]qA9By^!c;J0oaD@zBV+/aǟbtG/5&0>o? _R ѶSsNc{}w}K~XХ.el⷟_W9 ndj<_;c{ajoH\#Gs4&qWyB&r!\df$3㏢# +;`4rñ*fNńPB|sSGq&ohO._Hxx1H߂҄1l#U@ Ԕ- 3%o-<. <俽Q6 ZJ/i );ൂqě).y"_`셩\]0!~:N`i~ K?|Sc3Zk9>c^;>|+X71y#0W M^?,Ұ/G3ţ#fX@p9W ŹYxl| RI49'KCߙln_ox ©qrs.3KA@*nXY8C+ moᵥk%,0_QQ]`7ȿ|{nsp|i(|j= Ob`RƑGqFW"wyhQ6muDrçף];W!*ľ@;/f}Fm@+!2۬9 f w9176GLo<zзh]tm+7GfĂwNv l7VN׮6ަ2!7y O-o+TVtkU˰km WqxI43-vlǦ~*mqe|.H$_Vo==/i?f` -)E3 􆟯'K* njl7G|-bǖ87NGbظ٣bF6<žŷ9sJۃO#۳6O % V_" E5U˶`ZwA?9y̒;:f}\!@'&r~37e3w|?~هQL&MBF_<ЄaP)RC"{ ,(5@RM;ͼSd)ym9Қ]ZPID+ 8t醟04umЏBkmlUxҕ(a$(˥*zS*y<ÈEhoja.r zL><m+wc9_ GM5_{А{5bi-:ϨF4>HGDiYm:i |2M#|i%/S,חَ|$r8n33bUǿU6;Y"3ϗۨ)5EttczBv0C(_5•+W4bD /o/nѫ!?@zaqtZL4tػo~}ۢ'N܊Pmǘ.TGߍdv~ÿ"m) _cn<$nE;qx|#nDM]E85Ii9so';~tˌA]5~fOktd} fNztd.'᪱\ٺ6 |D{!onhH2؉PJC HC\a6b=cKhsyK[-ys)M&f31)܂+]$6qOMX;5W[qU` ۇtAШNB/B\DvAqwmt'랔;|cY0KF9f/IGfk;_XG'po BބKRi,;Q9 W:ՎP/*Vt>љx'Ҧ}zZoo4{4im)DGg޴fJ|+A>hnYռSYF<|#qHs$͊,:os8EˎOvaEW:OңhGJn{ݕB"cҤIny2#fHY@,D h]hRT;`UPPJ'6X(cp,΋N-1hA(+ M]Md[?Yurg?l=|;sC N},';vL?Hl PRJ(9Y-qPGrxzhu5nJd]mDÛMiЏJ߬F(?>E$*jj**y 妥{50?rsv<{it cg5h@%"%*-#()9>NDa¨'1/̆`ۅ4q ~W;67Z0wUIKu)!ZMNL.˛agU=4DwͰ]D$ljM֯Bt53||[(IvlS!^gS{cg>5e"|;=u91b"$''k9c2n&wy^O_QvH_n7,זd2r:-gee!>>^(``9it仩t^$9|)jIvd " ey&%}tGUjz *ج`X;y%$c4O"m,˹tԐϾiĂT<Ψq`N%Ov$p8!3Hgym:?|0*?h2y|LC C{ |N'1q7Gqys?}6زe  ֭[pB c)6W<'td7\zUu:DŽSRȞ\"/Qepq䖟#** m۶nuR@Ө?E.w圾M_gLs{B(bx*v{^ҰFDN˵Iȯ 0C;ʒ_ճ,A=HLi}ݽ36+'_%UYD/;Cj:ұCPP#{k;Hvptf$P&/N jfxSاF]ʣITPT?2ꫯuT^oQ]~zRپPe1.˵+&c2YG/c-ڐ8!&Ί&ng~Ow.I_t$Jt¨q=mV,Ȯ|F/?A=zw3qQ5٨\gl ]HtݚNDJOk=h2Wt_ǀR|BS=ΉHn,]0>X=ױf4eTV@גG;}S`>DZ%B@!PV<7|v#?lWEQw;53d'vV8mMB~ ˃ٗ?wΚV3"s0~A4VmEz}qpdi;#b\& YX[_8rg6'xοl@9KBNXHgfy!MJ}h,$ۜ=G#B֏^F>Fx,/fAVP( B@!`C |݌ɜЬvCu â.Lι,e\(|Ʈ(\Xļ9UψxHW:[)MXp2*WfЙ'Q!t7h :NGM99[–x.tABSA.٭B@!P(nZGG3u:9g,윉1'!ZdWU jtK/EE k'IYiK#TV9glMxYK >:@]DgqJXjipY5sR%M.\2* B@!`Ǔ2wBǨ,s,)#]6I~Lujh?c}N?k]5Y+ B@!0D@d(Մq?n )U縙3B.7uT5 Qx L+B@!P( 7H],2f2V?^W[Iv\ؕeSB.D+ B@!PNgtdfj,kw@ɓmvUW( B@!q U61I^dW?9y1\&ըP( BVpט?Y. 3ӑ]9Ŏ75Y#=tRmj#p&n^>R®)Kensx}t#c7M\>LMԼjP( B@!SBy'td\zUu}Jku 'y=vB^/"BCCuFptf$[+:ݮC0 SEXO®p|vR#cϺD?٪L]9a~0:u ۶mCYY6Cm۶.TB@!P(j@u|MD] aԟu䢏y]]+m:;/džrGpFLL ڴi^Xn(]{ S8˩%FFh6DF.#toiV"c04<8lSI8n:=<ˑ:7b5Fb>){ÝF,FtP:U^DV¯^]UQ(~$_ Wm7閬3.zEH&תܰaCӦM3$ji!l|aw<Gj)u|f2"wG]X;-R~."LMSPp|`k׮|5jH>ɒ05{.}$>oڭ& ׿S&AyM:)]s:#ց*( h]\:\TwgdEY掍[ԩO஻6ox4E}7@֠p9m(&B<5,F%}+UW#e8G{LI#0O?ۣ0m1pyic1|:gEڂ.ɯq$yǒhgraVebl/<5e Lޒ/_Hxx1H߂҄1O-)9|ٱi~Z˾9c p)uǪPXx6"~.B! H?6g(2'ȉϐ;QeB@!p;"`5+\p^D.\gWF}d4yĀq1y0tm-ȭjPܶp0u:f9"}`އcP\{4F!hڴ=Dkzv*^K=)m9z_ s1W}ctD` >7Ik6)|8g ?Hx;P7g-񡑃{al=+VYj<}_p&uFFS9s(I>zߠ qBalHz44ڎv lJ5E}Aٺ1ip B@!=L.șOv.ȮF25ĔB]zyy|$eHJ R֡KH^CtOV9~+,m ڞZȇBWn#WkaEDWZ}0"BHKKN^*Q9f$pLc~ޕOj5gyG*X3stxqDthS kEY^/'M%P(?$2q ȅs}C[ IDATuĎ?>.ȮF2v@TA!p;Y]/ S1z!RSSydd'$ii="{^3,Ƈ> rs]Ek}Wp_*B70bЭ S;yf7ۤnB?Pba%/tGՔTAxx8\"#y JIo[Q-sh=P7Z 4k_ZF!RC:^p9pĸWXK>ǹ)sHcGCl ( ,ԱZcٲUUV(?*9yBW Q3LGٕ0XɓrY&ReBMx}[/>~9]{v`D^+S#CKx|0:ӦCkHgG܂C/FXEGp'aBdmU1_!ܶ@)h?|~c0B$׋hI=yxjdLDpHw|k(G0.ξɎV7enqjzDf};r8zȸ>chYn?m3]ph]cmsy=I(H BD@p:1egk$3Ucq (s&,\_gB9׍^?k|:sv]Yû>D~G:m <7:_&Mw}W1T'C=FNN}1Lkx+whq +]+PFY/YǾ&UHm+<ۤ'fOrͤ gtQvz(>rS۸0\'2l.c^OzVf*ZG7=|ZQh[{,c @"U+V[nغuv+===ѧOm}+=6&/DTDđ[IYhӱtl a"`fq"d_4<mTɹlH m+qQb{MFzn9Ŏ`̭)]t IIIK%ڵw aj :|SxOМLX)C+؛8Gxg4ڽwgѥuCm:Xf'13}31ϛ0ܹ3ڷo}7;Cpb3[ݾ!?Ek>˽醏ۃ<P(~b7#'B.cf[cٞuɎe1 ]!H&תx]e,?_3Xwm~tËi(~r3smG{!O 1AH;r} EelySw0o_O̷kL|Vh$V?Ds"_Z=6 q\NWT z-%. ms)@UDI49'RЊLC%`i9집nX4#<\f}]Woe>Vixj΋ =y]g#էSGJښ'< ̴yxi)fwt5tAv+{h!~`F?O0MGpI[rz>Ħqhz|ː>o6p瑉l96x~m;S%v2;D#G83ACֶ'ӮW~O899^sg4rA+9PԼN~( B@!POH(z' ermɮ!y"kbLm9DLL ڴieG.#YL$D%md`J7m5)@n`+o*&-t/1Ln!

KE4g1d #ݓmV\49.cGij iR{zwLѶ2Yk#=G&*) B@!#`dOԅQ1>n~v׊yWuAȄ=ףڰaC<ݻv܍-U˩hF5)y 1),}C۲-:Qֽd ;^•RXigyڨоDX:" /,C4Y/u Q/+^z k5A"='Yx#AMWu,f-ʹ -%#4=~Y!P( :C݌ɜЬv1Lڐ]3cDey/rNu>ޓG[*/˥t mulOvKkP(  e2codqvP?9&F`WF}~4GF A5T_B@!P(~`Ǔ2wBǨ,s\,2rڕLn3O@q{BJQ!sDԩSضm\Nߗd:m۶u B@!PKMr[M٭q3g\ojP(MXnFGyX.=t6n܈Zvr_m;mt]m}8R vٽ8(6mNF>52%nkz1 ;>:W/fOtJu>tX5* ;錼<+˅̨ՏOF$;.2)!eOL~ BƻHN?SC#߃Ͻ(k׮|5jH>Nɒt _"^1_á|{'WzV/ȩcp^;Y~,FNtfs#1yfzFcG~Zw0emCf5ا4YUR]'ծP(L3^&cFF23[55; OɈ6YV]}:=tRFq[ ? ;QW1*$fب#tt.idNF9'xJ@X##U`K#0h0KEh]&cJvrz5|X1HKNEn ʍP(no3Rz wtr7ONv^nsr.pGǬ&t~z\bWa*@JgbY5:e[\TP)];Oum^  9d;,L=rDx#A%@UDTR:L͞xGpHWL\wc廳}F|k [({xUy p*yxgf61£:3f.qbRaN>la!j2.r [F ͥ_H&nȁ D;ھLZLJ=l)w M\W ؚSY_~C,}c(˕0LȒ"$( [sHh8݉Q78>}w' 5bA ?㪮P(C_cgd>#\.yVm }kl7YNCTl ]'׍Clb6f MDjB{Tx =t2I0Yہ"#Nohٺ#ĭ.̜7-Z,z:#pYFsĺi ao}($fI8,sD/j@t< J'UGLd/\%Ȯ KB0dQos< \~% qBt[ x/&=}*=1"aLXs+>;-s0i¢%:30o?M퇭zk"DEY;g|H5]gmn9Ń># A"n~Zpx@yW)3SH'0`{թl-}/ioOXA! ~If~H 8x)l<2Ðd?9bS0rlV8xa>fJP(E?aS \eY/tWպpJT. rQƍؽ{7/_ӧOWҞ72RaL]][qi ҵ\d>**Jkx<yb]L0Gk_9$DƮV QAk03F?ljJZ!s &b-Οy6-2&Ī3P\ f<"~(23+BwuDKxhWVkcAw^z d8uN+TJpj1L3%ZӦ@?ox 6Z:Lr' ld (@Qd3ow}/^-))|V4 }sC+}5 TyJSs5FEבK+, B>:>ZOܹ)Z4[ܠٺ1iK8\'fA;pX @fzBnnm#zGuz/GrV^G`ŲIhENutU: gߙZÃl$)ZmCgo)fƛv6eG0wHW4k(R 4r0V KE\xS}YJND.GmF9W/.-R!v9κ^J>Ҷũ5CPb-ـ=O̶VxxU#a6lFgi|شnXU32\]?*o]%R( .<3ڒ]#<\f}]Woei>a:8K7v~#ˈ:YQjOY99nб)=EGh5a'O"҆ -=pFAfp;f۫cdXҧۗOzxs-H:TF"CIzTnAl؅b}0p )k1rs 49uUg2e~mEYO?9vS,BWx]KVaz饗:uBtt4g[t@nYqcz =a(_F²!ZNҬ HZ5+! -x\Wqb-)=]ћ$CyhW?к]JR!?q WᙻR _sёT2z#gD˘5R1OӰbW VnwnTp UQx1i$|wR'|=KtLj#hId۬^U׬2>.jkg?yLKY1>.l5uӊָhџ2mUcN_V,4Y2`^n޾;Z";"w'\!P=1g9"ǻ%"vǹ,g+d,:reF/;\R}Ė墬Y&Q? u$WDWkA@:7 IDAT@ML5;ժV(LڞOӘo| 00P;gP( :B@p;3s.tdR& /n!fN1/lmofTe!VuC֖kQN?OVh[]R&>Hnc B@!BIr9Ycu|˲arյU]E|X4Dza}Pd'v( N&f[¡>e'Ž Ť&:ڍ(B@!P( xB&rWNen9MDDz5*) B@!Pܞ=d'd"rImF23(8 F!;fs!]$ыU]!P( OyBW Q3LGٕ0XɓrY&ۺ2tRC/ADD O* =FйjsMduMvŠiQ'(ڄLԅ.F2ݭ^z[ Ë}DTFǖQTS}-+MBAUVڞoS\ EϟQ&k֬Yp!ڵkWkϝԑ tሌD;qstDlF.su2RmbߞI}k0TM^5M-'y1x/ۙBGr٬v^kYr*EB@!S@@}E5D6'xnAA^D"Yk5{6Jt'gh4vZ<ø][/#'ʌYnsj{Qy<znuz}UW(~0ڽG `#@Gj Xi$k!c7dʦB@b`ڵ+ 9[A]~o^˹hܸ5(qnW=68p@ôl#'d<lV?e8+_ H?smݝweK/` KƔOaZ(1LBι>:HfEG^dWvh`#; rcuQ7oҥ8y9Koӫs{m|~O<of\lżyؗ1ZTrUiv}1/=x7.:E;-8j} ؀BұD)HZ aFM7j2r=EI0BLN^S֦آ@> "6=~aH!~Q g7J n"A5ђa$-QWB൹|6?dW\#Eb`?ө~Ft /8[})FwG_cܯ6%m;5[:4vGxطK]:R,~)|9|f?A63s80,g텵s#Ar+.R??? cڍ$8 ]Y.dFdr3M^dWh`Y&OFelNʗ.]BRR֯_+W8 F:@$±72JXvpvQs'%Q-Ft\"/m,\&r|}x F>~oN|1) ^m )328[P0S{|_/; ^! 4'^H[q3Q@! Wb8q1`ŊąAI2ÚE4v{ Bq0}sx"Bi{pDa1:>o?M퇭ohL¹(oB L8(5ֈJ.-jѦ @΁}{4 _P׋ 7w{? lGD[GQ#;30b\_$ӗh ϡzދn0jJ||.Gdl";] S %˘1)c3n$Tegk$3Ucy]]Mhe׷]B||<<]!XّξJ,{v@4 lqog;zzq5°Ĵix7eh19wFt1@!ӟ`sb$(? Kb5ů"">SqVDUh>9g.ڭ-k'd;^lz?-Si#nKڒ̿E !' kSoY#!|w! 踶c5^ℍ"p{WhӪTM!Wz[q\MOx/~̀2n@̦O(/~MoRc:+[QߣAX`6e-Ɵ_~c7=*ad7Y|s۟sa)}-Ax~A><j37^r8k7tf2׫Nmc6ܭ8r_ffNr>xzX|9N>n$82 D^MdNqR{GnB }|d%֌+2wN@tXr<.>xΟ=fbq8k%{*dh:cW --w8-1]\d\J̗~ŅѦHx76! \Cǐc[#+ۣ`7zO؈xmΗ4J4 Ϗ Cax~c<ϑ_׻Ѥ}Y=5rA?Xah+{ tH!oNׯ_3YS$:FQ y8NUo/"wQw.RVU)9(^Q! Xb ix׼奄 EU7D)/' R+o%W4MP+hJ9A{=ga͞yfΌg^k;?̌{5w'~Gz$0cĚ^Ƒ _s$^8K>0.^L>gOAqѭ=}֬Ycm47^nfE`ab?T p> ڼk#Wzg.;Lr a䌰;ҥ~8]ߡ8~c1tTu$aܖcWܝ0{s:'YC&iZY]ţ9v={,B.g\]7lvovkI-w^/Ʈ}.náі_S_qkukӆ˫g . @ gJ嫁U>}oO&7 uyS q><V3ݑnw7w|uX{ϟ|~Wh\f:S:v88{ܡCtm?*FKk\y#< AcvH`vX`W1bZ+?"GsX[ۗ#X=$}˗uɧ17uK0b :4|[ ?l:v-g[^hn\aK)9):8jg޵;sшvEKp.%"G`3f -ZT5M-w5jݖ÷~{Muش8H{ڔm'|ykm\ ]W%w[>Lfjms8]ܯ"SO%C/Y"O:,3f`]w- 3|0y`-HHf?|~cn"BsݏYC~k%'xXc_K8Ժtk^%KͰ:tsvN9眓x?I4o9߱x=wh 従30xݚ-.)X}O~۰ aWkpM5[NFCӱ zGqH$'}jŵIH4|^{'x?7vɛQu^ںjB y3<< ,-*fn|ߧc"4_jBqUi?2ʻ 17uaumɹ0hWMb_Y窱rF(vU}(}b޽nxWח7]K^qrVST:m]n%]@Цi,CkfU0"51kg/̨XH$_ksi[0(fvi%L/O0rR?>-~'Uٕozrܗc4OؾƏIMW9fz@mMd X\j%ٳg&oAaۓbf L 3+6ǵz kqm9f7&̊E̷bBh ^$Pk>֚$! O 5nmCUƼ./0֗ubuh[1Vռ-9&   M!1Q4ͺ5*^cj<ԤCs,[^tu[Tn)[_LJ'  O*x6iMheWnHDcJ])󥾲תp;c!7m۵[||Y8uk7v/'t?_mv>THHHH`"`=1m5.ͅb1sZJٵBb"@v~i;Lx15as8˗᤿N7A'|ADa<_{8AnLƠg}qr|18߾`Œxq|/   yBB}6XLgW;Vq4nc:#l;`]ѵ؍򡹛~\L*KemvY6 N IDAT&6Uxߺu'ᗿ߃&lfŝX>YnvBv쎞ݻY'c];__+f-wv?X.%/-)"   'Cb5>_ %}P,LŇ/?|C{ܙ-.|z:~q|f!4Ľfv8a%]nO^ΥHHH 1z jܶ~lT(86vn;s۱A&۠_~خwfeƼ%`F O>=sm?Iӎ8f8=^t.9Xe9+OC"   bjcuybkJ^Ԗkv}!/W {ߌㇻsO6pUC'/h:jD > w2ƵomIuj t|hG\$0[bk5 @ ίDzzC JL[1 KK_UK_N}wZ_5V=P&Ƅ [фMZmU +t>֚tK%Io&PO<cƌEj\G$@$@![n8~w؇iN~/%.V~4}+m#SYK6/1zio5﷡d}Yᗚ sƴ-ʏt@C @(|ߧc=YhԄ:'s+wX+y4q~zȵHHHH*G@i,CkfUήnul9Xk l>    49Xjtsgz@mMd    v#.&@Zcj\8s[ٍ "b}&m>X 7T? c}YWA[-X$"/~}}CAf,}~ p|{3݌[E&2M$@$@$ $~PUBTV\KMZ>4'/܌K/s͋ uWcS`BU5Ξ 6 *igAGt=O׮"oz#O< EЄ~ f,XYe:\HHH dz5mӚ|ܯ hL[+eԗt-^/q 7w-i.fmK/ƜwN{LĂ4=sq3Sf'Z*s cc[Xv'  6d/yV\(:ٵBb"@v~JwfϞ'Ě59ٯƹw㸁;Mm:&7)',6>r:ٹ >"zv7N :==1ڻ }/-1ph n9?,}͓snCޕ7/x ;1 "M ne0pTy)N۳i.> ;/   $.yZk ͏XMٵ61{ۘ]>sJ̛7/xtH8>v.n$:'3;bSn2͜kG_Y 1>xlj\7K5Y/s܍{Wb1U{8U>4#;w=8>w?_88fz3(ֻ/4w^{N%k8oUrp48 asI)a&F7?ikۮNYd-zb[̖={[֘ܮ5ۭZ0cm~q'G_u}sd73^p^rG/.qʭg`6-&W+l]lO'=#  h7zjYj2wvY6qܺpƩ: ?Zwuыϻf;%kt5>ҕгsrWqt=#X0C;wqtQrjgko|6 O?= 'r?b{ÝEEzѺa?nnU@G=uk #7; <4V'w7ts6*- @u5~1gV]/VcS01Q" R5FgmvݴF3ZZ 8 Qf>͡spu7b]؈OzqaCcbkUsGgggSqW\nһ=.`}`Mdnf1mlDsSOJ{`/pD)vp[pLc6n0``nÂڴUL{xp;ϕN5#F*;ӟ[r]` 9h8muS0{#܈82 +aHHH#"o!|_qQ 즶۸+s{ot[w\0&,':'ogNխČq}]c'Awhxv}'űf`H浺p+`+1h]2*8{nyVǮGu>I'%lQ_^6ti-@vݹck}_9c$}[gܣ]:ߖ':&<;_p:7L=};{مu7ȖHHH] +&"Vg,u~Am(!1k?ԊQYX}#X})ĥ._%|0vi k4/TX:Q:+WwDC,l.܄FUK uhrwdZOX>h:fWɼ6wEŚ`շRW|Rw/wzfE+K2MJj/=.G3f -E$@$@xN\#w%"0k,qieq֜\fX:tsvNEuuu7n\rG2ۂ|g7xϭ eӺ'4qϩ]qI[3"$$%ZܻezvJ]u>3Ñ2;cHHH@i9ԇ⒋^؂! R֋YUî_%Wrб76oq F$@$@$@ ;[ ͗P\dn+mvi?2& nqˇkՄ"    jP-OZ.Кbl5.kjNc:ZiC1gHHHH7ͩ/c~Ůr̮/,+^X5XC$@$@$@$P{ŔI^k\|gn11aVD/dg[[x涛-ז{X]|fHHHH ļJ|YO:н rn"x)׼.7bA` n0/Ao?3.$FfW&u.}]s]s}/. BOcrXMX52|hN=}]j˗%kɘ5L|.]fWvsf}oGt~SZSç 9uqN!   v# ИiNkBm,sf7$J1mR_p_|-n~K1}P@Cxo131q,˚Mܖo Η Txɘr5vI]{ZkƤ?Av+(.œQ}--x >q&vx|3tnkǎ]ߞ3:zbHHHHӅ}ڸBc1;?Vī9vS+F6f}ݏɹcƣɴˀ3}Y/J;u =/єxZU[uqp㰍|N#pz+SndUbh7}ZOv_Sܲt܌fSΝ_dSбxK?w `g.Ӯx7wRf~³7b v]b1˓*!6Y~l37s5VzlHHHH#"P̯YWV$g|j]pVg-1 #/>w;={޿fϭ3'6=V/ƬbÀwk1MJ6;ݣg>Cw0  lk`{W=<N{]ghc7zw_c   4&/l܊jl}jf7&JCX!*fq8-vMC֕ 8v 951IW߀nŰkAώ.0jdcbֹ1Źmt{Jdwk.]_ƀƶ8ua{ǶNʹl6$@$@$@$Pu1*q?|$+J~+&Yb&&~Lk/9Xwڵ9{57}LnC܈hq.7gij4tkHL-mjth[Vs÷lruvAk'OƘ1chѢO$@$$[s'~ָ ״Vrχm/?bbB?.~rqlZVbvټK]ޟ_;z-W]Pssu ²'<%ٻ흒o GJ ==H}Z vM+y >4(}yZcOVoݼE̠0fnhHHHHڕ@1>|FkKn+mvUXHsX4\$@$@$@$@E@\53*mvuSc{@iLZ+m(f 49e5үUec|˲FY5ʚI$@$@$@$@3[lF:X]AfE"@|Jݗ:\z饘;wnʒ͸L|XFrꎺU4Ξrࠫd.yI|3M:LW |ļ]1g=a/C*h1V߷\~_Xޯ//^/q 7w-}L8kZ Ąpa۹/kj^?N*8y{y Ƥ<,=TIjטXj9ٳ1qD\vwnj1\n zzii~1B5/! |"dz՘iNkBm,sf7$J1mR_{W^y孳́q)0sq]wcjwgwe~I?\a.é#gHHHHZX'yV\(:ٵBb"@v~jv.\ks7/YAt{bg,}?w t2e&G$@$@$@(B}ڸBc1;?V+avmF6fתZ}3N=T۷uWoï=7]=qn{ܳ [4q=y=ݼNgHHH>o^6UrM01ue7h#1CE֭kq8j4y?j9hHMj_ĄwFνum2{MMXRި]/   X(׬+V+dZm/Ί,5ycȑlRL9v 8cu=7k{'G\:ˍS>ANY$CN5ȖHHH>nxqDӜ6_Rf7&J[R J:-ѣ>`N6l0jZ2l>[b'}6P~Oiƞ>5yA1a*oyzy +b~}:Vѡ~֖V쪰hiLӹlIHHHj5o!ui,CkfU*ZӘVP'   -iMsDXk_ "Ɗ6e ֐ v1el?6W:_ǙrnL0oŲHHHHļ |YO:н rn"x)׼.9&   M!1Q44kTUƴո?WRaHHHHdz 4mӚ|ܯ hL[+e"   MByV\(:ٵBb"@v~0vHHHH Bb}6XΏ$J]AhcѸٵ'   }bJ ՆbJW$g9+6sL$@$@$@$оTXWVR۫ ^mΊa@\IHHHO ͯ?*z[گٍPm(z&IHHHڕ@̿ }mkklG5̮ھogK$@$@$@$PSx3[S:\ P}8HHHHj@V_c9C6kv}!nfپc;}    'Et6Okm]^\", W @(|ߧchmmͮ Vq~Kt=˖HHHH_SR2?fXͮnul9Xk l}    "4O۾F1,bxocY` @PoS&ycs5u* 4 IDAT-ƄY6Y, IHHHj@PSlݫ-, X~ߊrqbyc    $ű~NSI FUkL[se,5iHHHHڏz<@cڦ; ͷJݐ(:ƴRK=/    $`=(1m5.ͅb1sZJ]+ q(&4n cHHHH` .$yZk ͏XMٵ61{ۘ]}    '.zPm([xͮ/Nr0b<$@$@$@$@K@=]Lzje,5 6x+ deHHHHxqҮjݘ(Նb`HHHH] [Pjܶ~lT(86}$@$@$@$@O@_1:To~ffVK?'   }i>P~Oiƞ>5yA1a*oyzy +b~}:Vѡ~֖V쪰hiLӹlIHHHj5o!ui,CkfU*ZӘVP'   -iMsDXk_ "Ɗ6e ֐ v1el?6W:_ǙrnL0oŲHHHHļ |YO:н rn"x)׼.9&   M!1Q44kTUƴո?WRaHHHHdz 4mӚ|ܯ hL[+e"   MByV\(:ٵBb"@v~0vHHHH Bb}6XΏ$J]AhcѸٵ'   }bJ ՆbJW$g9+6sL$@$@$@$оTXWVR۫ ^mΊa@\IHHHO ͯ?*z[گٍPm(z&IHHHڕ@̿ }mkklG5̮ھogK$@$@$@$PSx3[S:\ P}8HHHHj@V_c9C6kv}!nfپc;}    'Et6Okm]^\", W @(|ߧchmmͮ Vq~Kt=˖HHHH_SR2?fXͮnul9Xk l}    "4O۾F1,bxocY` @PoS&ycs5u-ƄY6Y, IHHHj@PSlݫ-, X~ߊrqbyc    $ű~NSI FUkL[se,5iHHHHڏz<@cڦ; ͷJݐ(:ƴRK=/    $`=(1m5.ͅb1sZJ]+ q(&4n cHHHH` .$yZk ͏XMٵ61{ۘ]}    '.zPm([xͮ/Nr0b<$@$@$@$@K@=]Lzje,5 6x+ deHHHHxqҮjݘ(Նb`HHHH] [Pjܶ~lT(86}$@$@$@$@O@_1:To~ffVK?'   }i>P~Oiƞ>5yA1a*oyzy +b~}:Vѡ~֖V쪰hiLӹlIHHHj5o!ui,CkfU*ZӘVP'   -iMsDXk_ "Ɗ6e ֐ v1el?6W:_ǙrnL0oŲHHHHļ |YO:н rn"x)׼.9&   M!1Q44kTUƴո?WRaHHHHdz 4mӚ|ܯ hL[+e"   MByV\(:ٵBb"@v~0vHHHH Bb}6XΏ$J]AhcѸٵ'   }bJ ՆbJW$g9+6sL$@$@$@$оTXWVR۫ ^mΊa@\IHHHO ͯ?*z[گٍPm(z&IHHHڕ@̿ }mkklG5̮ھogK$@$@$@$PSx3[S:\ P}8HHHHj@V_c9C6kv}!nfپc;}    'Et6Okm]^\", W @(|ߧchmmͮ Vq~Kt=˖HHHH_SR2?fXͮnul9Xk l}    "4O۾F1,bxocY` @PoS&ycs5u-ƄY6Y, IHHHj@PSlݫ-, X~ߊrqbyc    $ű~NSI FUkL[se,5iHHHHڏz<@cڦ; ͷJݐ(:ƴRK=/    $`=(1m5.ͅb1sZJ]+ q(&4n cHHHH` .$yZk ͏XMٵ61{ۘ]}    '.zPm([xͮ/Nr0b<$@$@$@$@K@=]Lzje,5 6x+ deHHHHxqҮjݘ(Նb`HHHH] [Pjܶ~lT(86}$@$@$@$@O@_1:To~ffVK?'   }i>P~Oiƞ>5yA1a*oyzy +b~}:Vѡ~֖V쪰hiLӹlIHHHj5o!ui,CkfU*ZӘVP'   -iMsDXk_ "Ɗ6e ֐ v1el?6W:_ǙrnL0oŲHHHHļ |YO:н rn"x)׼.9&   M!1Q44kTUƴո?WRaHHHHdz 4mӚ|ܯ hL[+e"   MByV\(:ٵBb"@v~0vHHHH Bb}6XΏ$J]AhcѸٵ'   }bJ ՆbJW$g9+6sL$@$@$@$оTXWVR۫ ^mΊa@\IHHHO ͯ?*z[گٍPm(z&IHHHڕ@̿ }mkklG5̮ھogK$@$@$@$PSx3[S:\ P}8HHHHj@V_c9C6kv}!nfپc;}    'Et6Okm]^\", W @(|ߧchmmͮ Vq~Kt=˖HHHH_SR2?fXͮnul9Xk l}    "4O۾F1,bxocY` @PoS&ycs5u-ƄY6Y, IHHHj@PSlݫ-, X~ߊrqbyc    $ű~NSI FUkL[se,5iHHHHڏz<@cڦ; ͷJݐ(:ƴRK=/    $`=(1m5.ͅb1sZJ]+ q(&4n cHHHH` .$yZk ͏XMٵ61{ۘ]}    '.zPm([xͮ/Nr0b<$@$@$@$@K@=]Lzje,5 6x+ deHHHHxqҮjݘ(Նb`HHHH] [Pjܶ~lT(86}$@$@$@$@O@_1:To~ffVK?'   }i>P~Oiƞ>5yA1a*oyzy +b~}:Vѡ~֖V쪰hiLӹlIHHHj5o!ui,CkfU*ZӘVP'   -iMsDXk_ "Ɗ6e ֐ v1el?6W:_ǙrnL0oŲHHHHļ |YO:н rn"x)׼.9&   M!1Q44kTUƴո?WRaHHHHdz 4mӚ|ܯ hL[+e"   MByV\(:ٵBb"@v~0vHHHH Bb}6XΏ$J]AhcѸٵ'   }bJ ՆbJW$g9+6sL$@$@$@$оTXWVR۫ ^mΊa@\IHHHO ͯ?*z[گٍPm(z&IHHHڕ@̿ }mkklG5̮ھogK$@$@$@$PSx3[S:\ P}8HHHHj@V_c9C6kv}!nfپc;}    'Et6Okm]^\", W @(|ߧchmmͮ Vq~Kt=˖HHHH_SR2?fXͮnul9Xk l}    "4O۾F1,bxocY` @PoS&ycs5u-ƄY6Y, IHHHj@PSlݫ-, X~ߊrqbyc    $ű~NSI FUkL[se,5iHHHHڏz<@cڦ; ͷJݐ(:ƴRK=/    $`=(1m5.ͅb1sZJ]+ q(&4n cHHHH` .$yZk ͏XMٵ61{ۘ]}    '.zPm([xͮ/Nr0b<$@$@$@$@K@=]Lzje,5 6x+ deHHHHxqҮjݘ(Նb`HHHH] [Pjܶ~lT(86}$@$@$@$@O@_1:To~ffVK?'   }i>P~Oiƞ>5yA1a*oyzy +b~}:Vѡ~֖V쪰hiLӹlIHHHj5o!ui,CkfU*ZӘVP'   -iMsDXk_ "Ɗ6e ֐ v1el?6W:_ǙrnL0oŲHHHHļ |YO:н rn"x)׼.9&   M!1Q44kTUƴո?WRaHHHHdz 4mӚ|ܯ hL[+e"   MByV\(:ٵBb"@v~0vHHHH Bb}6XΏ$J]AhcѸٵ'   }bJ ՆbJW$g9+6sL$@$@$@$оTXWVR۫ ^mΊa@\IHHHO ͯ?*z[گٍPm(z&IHHHڕ@̿ }mkklG5̮ھogK$@$@$@$PSx3[S:\ P}8HHHHj@V_c9C6kv}!nfپc;}    'Et6Okm]^\", W @(|ߧchmmͮ Vq~Kt=˖HHHH_SR2?fXͮnul9Xk l}    "4O۾F1,bxocY` @PoS&ycs5u-ƄY6Y, IHHHj@PSlݫ-, X~ߊrqbyc    $ű~NSI FUkL[se,5iHHHHڏz<@cڦ; ͷJݐ(:ƴRK=/    $`DE IDAT=(1m5.ͅb1sZJ]+ q(&4n cHHHH` .$yZk ͏XMٵ61{ۘ]}    '.zPm([xͮ/Nr0b<$@$@$@$@K@=]Lzje,5 6x+ deHHHHxqҮjݘ(Նb`HHHH] [Pjܶ~lT(86}$@$@$@$@O@_1:To~ffVK?'   }i>P~Oiƞ>5yA1a*oyzy +b~}:Vѡ~֖V쪰hiLӹlIHHHj5o!ui,CkfU*ZӘVP'   -iMsDXk_ "Ɗ6e ֐ v1el?6W:_ǙrnL0oŲHHHHļ |YO:н rn"x)׼.9&   M!1Q44kTUƴո?WRaHHHHdz 4mӚ|ܯ hL[+e"   MByV\(:ٵBb"@v~0vHHHH Bb}6XΏ$J]AhcѸٵ'   }bJ ՆbJW$g9+6sL$@$@$@$оTXWVR۫ ^mΊa@\IHHHO ͯ?*z[گK͖Pm(V" DXv->CY&Dz=9d ?n!6ڀsko!"#Zs0fx>[  sd}ݘ?>.\> ZGO`6V[mmx wJ+ៅ҉VQWLHNCؚrͮټ틠Py @&Wƴi裏b=ѣ;K.!|rxC a;VL,MV_c9B6ƵĤL\R'Zҗ9N}ݯ#.uc^$%0yd3-؞#J^{-V\o~?_W,}_uukr b[/Y(`^-rS1q?́>H+}i/q1qko]i'J^K~y pL$@$ "w㢋.Bn,+3 ;ڵ<̳%\;rHB_ 6t͗P\dn+mvU|8?Etb! Ǘpc]v[l ݽή]Ӽ&i_)X]L{?u{iM4͠?'!g1*`QlqcfScEMM+z<x5,r,ј~>?~`a| _s"|sy*5k4O^vۗHbW9wv}aYX:Ʋ  O0 w#a gv4-pC%׋3.;Χ~+3qgwRbᅧw6kV&jA;07ČL܄`-ļvm=ֈ)kz }Y~Z;kjժGtX~_ X |r w˻{ꅺ_Q>pwwWXIX_׍Ɨ>xdվ:} Œ:sស$>EX<^7w zu]lx[vxqqx6NL9ͭ=j UNm߮i ;qx~ex|.)t:~=g O}?=yHӦLǻrO!afr,Kαr +W,-g;-ڣvc?meuԔ9V 6brgk'AM-j9c[~=+|=d1[[N; Wq go~iXނx5rF Oj[FVyC}Y%ŏeb{^m9f`\Vkޏk |L 3tM&]1PrP3Y:6̜+.cRx:pxkX_f?/7X&dp(l<4vӦXD'_=vtBuX-X=}1!KaYv1ɞX8#w{w>NpMa%bӺz|xy̹b4xٝZ̛3vƴn{䴲?8; $,x CDM/wsOeT^R6YXh.?7xeޘIXO/2xowbUObC7aFGrro}<~Exv9>_B"J=CR_צ~e<Ɛ⺬5*^cj|ݬu=I˯dHHcO@ބ&I;{j䛹۹R^!Uu?_\ c'?xNiFۿv1g NA&lѳЯ'>Ef3uw}ػM ?{݃]U5N#r?Fgc:q?l 3=q1N{9'02`_]h9lW[| =zbϮ݄7o>ITvh1U[%5o[!}L{6ظs5uz=[=Zsѽ]6{չyh,|^"7h =p=rp/7_B:];t\+g%Xɝݤnmiz.rL7v:vLP;,z|l/յ\bR3J`&)])W,W{1IbS9c7xO},M^FCupن quG`nWuuk+Qa5^o'\)O8?]e ѸށQ  O<1bpNo5lbĜs[6hf=?x;쾿{ ^[9 A?{[ot3|I8ngW`u/_ ~enas-Cw gb߬rP|k{É E΋-㕷'(9yw}h\%k5bW~%~GHL_#3Z2_m׫m38|t4Μ9;Kqc;ge_"9m\{v8`4x |{1q~a֘l|mӅ^Cik,4?c5I_ֻ19~l)Ycŷbc5\#1%ƏaPoR/ۿ#q ϞYo9?woR׹x#r9fd$^c>͵Q{#GE2ɸ&`ga؎Xr>i5ܖX%|y4N8C~䯇[;4.ɱwd7@ sl~|/]p]psnף=:G-r\#wG˖-K^;yMS_Q,Z&: ǣGCtMغdɽνw|g<5ɽfN?!8b-\HF=]LzP,VӸVKLZ/_qieܕ ;2E[K˃Ug|m;wn5m޲ +WcwTWkvwVz1ɹZy6w575bn庘 ^UE-{]Vd/Utg;;-M.lOn'7)u³E1T믿~ދvLp2[q@)7.}]Z,esSw}ߚ;OV|}]N{"uDyNF[y[ciGj K_[ۗXDž[O.1ռ4*J9m$@$@Sr'3Lbpg>x_k $jѕH]}C6RYWٯ=S,+gFsfd]'[  # ^x'MeeX<ʫv3~ȒcGmil"cK) (*fi֬YsxR㬊EJlpl.];lx֖ψk1:zSM]~q]936 [?v3_+\ H) 04p'zvwt0Fۏ(t.tV}&ž19zpr8k:nv\xbQ H) <Hᖧ:6k~[nuNssvOch. s9R@ H) O\OU2of7.ųc!R@ H) S]ieȓ?jqǶf0;^R@ H) NRoȅ"_|OX1O}p_l/IŃ|X H) R`t*a%DGf7.7\<1Z18u\0) R@ H{<bu9zu- 1Z_C H) R`t*{<}1Zqxs9?ivð⾾09R@ H) r}'/aĩ~4~{ qK) R@ ~ӕV{7w90y]}+R@ H) ظ +zNi_~xp~>@_V l !ޔxrc}Ŏ03c͘UOR@ H)  o5K,kTk扩Ҽ]H$k1ߩkH) R@ lZ tE^qԱgJ>@/#.$~N0c_'_ H) R`+Pbc\WG?:6-¸h-nn) R@ H@~-}\}۵w˅\#X++R@ H)0`-\'9;r\4ccL.lyR@ H) K9Xof7.ųc!R@ H) S]ieȓ?jqǶf0;^R@ H) NRoȅ"_|OX1O}p_l/IŃ|X H) R`t*a%DGf7.7\<1Z18u\0) R@ H{<bu9zu- 1Z_C H) R`t*{<}1Zqxs9?ivð⾾09R@ H) r}'/aĩ~4~{ qK) R@ ~ӕV{7w90y]}+R@ H) ظ +zNi_ƃa :jK) R@ 5~~~kޒEaq9nm%5U7ux"߶ve{szm @ H) ,֭[gk׮5kTۖuq رcm_}wtkÁ pzz q d/8,8~fn}4ܑ_xw{sjrxٵγCuM2<خ'/tw͜) @stRK%K/pĉ;ڮjo{l̙U;)hr.}ɾ;_>f?X> Ĕicm޼mcxZ`gI~13Ҽ,рv2n0E>ߐC xɜ}_uݵp}߷W1I? .yjٳfT?.]]^?I}ٿ&R@ Hѭի/k֎֭կCX IDATk<=z6ugsWyҮv-{xA}{}fϞIߤmMj,r]eY6lto.݇}#ﴉٳϽhWfÝ\?[Oۅ߹Y?jxH{{ڊ+쬳β=sZ~S… KI[om{ w}1~~evهIHj1e4cO#x,g}ba#fڽicoѰƦjƆ8_Ѧf jTmhVzVl|as[lncw{~m]s{Ι6aتׯ]j+W-5yD{;j;n?jx?K8CR@ H)0:@#uE]weglƌ_GGǪ֭kmmڞY}N>7Tx}Nlg1@ׁvV5k\ZHϢ~v.؜eC_6&14~ ~nQi\QG>>/ U~hGzM4~~]v쥕첫m9->>f?4k)R@ l ŋWH`KY5e쳫ͦL1n~;] aم]vM;jrmܹ=?Ëaɒm`{qZ^wew#/ vuCS 9㗼ݾ/O; ޯkv?aSJ6쮳U}6v69im6iЛG9؍1#4,Ųc#:[~ȎLwnKOeóhxqbxlȡ _m8=i )  xc=Ʀۅxfw`@K7&MVUqv3뿼޶v6E;m6%J߬fmߵc/76]nqbqL0z?qԩSwʻ8@s]ٶ{m+^Nvov'T'bRk>r}oy?VLpRzlȮX֞GchcRb{ؒV딞7n͜]wo*f|,{Ґ'_L/g=m/nia~% Cw^hjuқwu1+~}_WcvL~#!fM8>5xl6GM{|c ) ش@O;S> |"z9QĆ5s~F;fjߘsּ[23ϰK_2f^;ت>{~i;W~/]qt؉Ʊd~TįgbIs{m+V ڗW4]ՌKkmz~@CXh7Amݶfᇏ'_d{&Nk߬XgRז>7lʇcL{r@ٶ ._߳'vο؎e+VMaxC `b3a{Il~}Eȗ^(|]o-M4~g>qv/iH 4n>%?kJg+⧝fDh/G H) F /ǯ)<#$\ЮӇI9vn/S섿rG+l%e V]wv{/}k퉟]jtd|ٯ}gsOi>Gΰ:ľzҞYԼEӘY%u.,~xf-n>#!>%c|zyڴI6%=0)5Ǐi~Q3v~v*'xw/M#tlk[}s;Us6ǣ{u=}H^Sli^rs0%D޺.h<8户V6"p,!|EW\W(~QʦTwxqhH) f3hШEn&~x<;VsVl~ {hq/pX[3ͳmva>Gؾ&W]?_V5[m ,/KoN2ձKǖר~恖)*R_P)SڤqclJ#9nzd|j$Ev뽳M^4uM8{ҝgu~S0K7{'~Ԧ12kz`z4k@O}y͑NuFn"bu9~99k~4X@nuϕsj.9mDLL9<^ZF1ګmj7>]o>eR`*.>}z.~b7;D:v_/]vܜg_) ~; 4Qd]jƤkOߦ1nMO7_J>$*4ۨذQBc ~>&lUs9)EË'(}m/;sمW؋k>`s GnLVlźm#?e v{b' oV^6n{q`L<}u㢰hv-⾾^cv>s<˱ˎۦ;e"e/>sȕR@ l E7UWxYlv̍x_N;l;_?xMD୿gf}{znbEG{7E =vbe?`W^!g˅j/4=q@#lhv߆!!;vۮHIktHMnWmK-q8' ߶s>vmn._vmV clUܷ_IɎ+H?T"ns5^vR?{ܺbGljK;GNc~Q=ƚCnsWV\<ޘ7SR`VwK˖-OQx+-q:1׿r-65a0Pxϳxō6o&͟Ύ{˫{ꄴum 6_9c3s@>Z~KmGMj'۽qsXvM8h#07X!moc~Pؾ<=)}vÞZ>ns_3'ڇWfe1f?|7^V ) \X|~՟=lwO'L)q=w['69GSMLnntտj ݱNt5! W+xW/<#vW^{ex`ϟ7-ZȾ^q6ytg8fcm ?[}Isk6:jw;\[yOoN{i {遫7zFg jOcR A r[8j.eӌEctp'>tZua}ii?{o`m?kk5-(R@ l N{a>]Gdss>f ]h|zĢ:Vs!hNh;x|ZN4ƽ<;_赶z3&x#a[_Ǧ,}c W ؊e/Ǯ{L#u/A]\n`>hs]f/Ea^ rMQY[4}-0|~wN&OX}5 .n7ŵs)xT {衇5\c_|vin>ygѥY]|s=g]tQ٭GuT-4u@<+Vmۙ'ۤWlcM/2%.}ԥǨmMcҟY^9[r%IC+m]&Ľ4kr 0i 68&~|XdɒR]_?^xIRk}쬓>q$|+V炾}OEyM" ?p կ>`öW#x+ĝ܇zn馛_ukQ~ _OVqol=>vk>)NYCwزݻa$c8'PHA (>64WM-cX6'-XX 6&94&x_ݴ?oIBx;Clkk?~~ÝvOoβ8iH) K<`-^xg> 74+X1bܹ;T/T;..\6hVQ }6|Z3mߛݴ/{{_v=񅹀Ow>uٺE H) &+ o\ƏrH]:lha냦Fy`eZ hxn&Owv^XlryopqEbZMwv\s`q~qn>z;v:j;;p>glogzWR@ H)+& <ˋht0!4]/lмOkt@?ܰvZs\=895~7\|b.X<1uCjH)  q[ Bܥ.kӥ`~[nOuNssvq1h9bɅa>/_ H) R`t)P׿1+>brmƅux{9đR@ H) } + yr|R-q3Q0|NjQ H) R`)P PK K>ik6 }xЙx]>K) R@ l~na~Zlv[&NoTxb}-rryϕ/R@ H)@{eŽG#ϑ|G}H31K88>!R@ H)_C7bCsX!zưXGx 9\R@ H) H ѽ˫F@dpgm|~s/q*|.;;F|#_C H) R`*?]nxǸS^6~R.[y1#s} !R@ H)Xh]q;]z(t˭= k]a jq‘A$60G!R@ H)@{UWٙgixtl6`{87/e61Ljv'Ɯ;) 8Oi.)+R@ H)5Qݢ_ _ z<6q'/-6-E\|cKWR@ H) zV`…wxr r~/?\Y?,Mw}LA-E^C H) R`)G,XF`S{7a8bx}_}泶fpc>ȡWC H) R`=+F7;̇ocO8!IwA>"OF<CLK<#&71>1ڽ,YkH) R@ BfϞѴi[`qC/cXư~CM3qeRj\#sDcK<$ch~G>qR >q766T\X}`>}=} xM/}u~O?>-W `*b6ȓZ ocϘycGn bG5p?hqCL 5\SXCI!-y?C'uuG]?}|L70<>-hc0_81XK(}eCuHlТdL89M7r<`p^yܒ\|C,Zk/Ӗx%u%^ gmWYG[pіx%u%^ gmWYG[pіx%u%^ gmWYG[pіx%u%^ gmWYG[pіx%u%^ gmWYG[pіx%u%^ gmWYG[pіx%u%^ gmWYG[pіx%u%^ gmWYG[pіx%u%^ g-xaO M*# <ߜs3OiC\Ryl𫑻\;ĀEC-}cÂєbxhكqEX ✏q|9qغ +JpVڢfBsDz1Rc?K??^=C:?]zztm*?N?c+5lHaO M1C wri#ww9'<\_/M 9173 &17lR@YG sxj`q1~x>G9ȵokccqXngCf9--q[yg9u9-jO 6n jbQu98u97Ө.';Gr:tS=.7ڿ`8eP{1-eg;i#A'\3b(}naBѨdžU`}.1:?b|{z~]:N]N 4I?.vIDATΑ?:t}ˍX7{*ưgz`lh=j\G!(0 @ȁ9assZXl5s=ȩ˩@Fu9'@9RG珮u)3 9`06b 5y^], _ycφ1RZԷ;@9hQZܬMpZ[LP8EWUߪ@IZ=tNvwPC\ҩ9JVJ:j~%JkUS oWҩC?aފ80a,v#ѫ9'cX қi&;qziv#bgL[̑' ̅ 5hh1K9__pK??=G׏IGOy06GM-ɏ1k<>-A>cڊ4%0f{|̝F|~"x"j1?jOp_yƯ \ܝU6Xz-э\'x-+g^?xm@L>-xуCqam4rr<}rssm) 3ZM(0lq [j,\q-a&;G# K,66#p 룏9c>=ƪځ'_7km6}Nsr7C9| >"|\c6"}R@ H) " F4_1<,WGacʘ<0qRys^c Z|L!@EB^<8ֲe-<ױi溘R@ H) 6WGaТ/BSA{,#Ǎy&jqc-8a1719ӲqvE1,Sb *-\3|9c qOC H) }bkD8^<`ry Maq1` =f)9sgs E9rTq'<xsy0:x~SLΟNϕOΟy)g9r}^?uז1,1>\8r6뱮RL,vG#ϹИbx ¼6ԓ<}Xõ''MSDS\tɝb:ttzx:6쟈1xW#1-pc>98W'w=1Ⱥ) Bl>=Fq8b_ 9`~.\, y·# 5XU?@Nx:D~U?@NxZ紉Xߐ9m"j9m"c7@Nxz8xa1?/F9 "O,krXc/#;I6x ~'y`Fsq~p1sG BNA sGo(VH)~C? G6u?y]6β֞ ӘG6p{ZlYZf'co#r,6Aߔbnro5?ѯqp<}7~:Gg?:k  5뇽?~9lgY-ac|!z`Q^C %y_  ,sEf-06 -k,eL,(8ǘPք#1mXp"1m Gc&DcBY<ƴMb<ƴ&yiĂyi eM86'ʚp1m N1-5cL$cL[(k‘ǘI,8ǘPք#1mXp"1m Gc&DcBY<ƴMb<ƴ&yiĂyi eM86'ʚp1m N1-5cL$cL[(k‘ǘI,8ǘPք#1mXp"1m,G)fż| \}L1J.DE 16%Ⲗ<ྙy"ym(~mK;Jk_[䒾RԺE.k(~mK;Jk_[䒾RԺE.k(~mK;Jk_[䒾RԺE.k(~mK;Jk_[䒾RԺE.k(~mK;JkBgo#~x.8|ߟcخGfK)8ƻⲞs 0_xb}^W[+pU?t.~>zq"?ƪW _l^#o&|`fxis%+]; IFTbaD17Yûcn6cD1UϹszC/:tsNGqWM_]Q1%/ZG7Ĭ'-8qkQ#ϼ[0-DcZbQl:\ 8aYa1<4XWpK??+3L׏]?]+9]?\?8O`L\F1X{9bb\u9 1E\9hs9hs9hs9hs9hs9hs9hs9hs9hs9hs9hs9hs9hs9hs9hs9hs9hs/Q\G{scAyo$]yXo}.Ŵ>-khcڐjK9SgsuSpFu~;_bN?1Y) R@ l f:Di#8sZ̅:".a0Ǐs~bE%mJU8$`qsXi7>@Nο֪~Jiȏ6aqȏ6aqȏ6aqȏ6aqȏ6aqȏ6aqȏ6aqȏ6aqȏ6aqȏ6aqȏ6aqȏ6ayo#s\G-}8_ 'ᱬ?.փy$cG>Ʊy3b3 z܈1^/5UF~#Q@H/?:F:X<<AۈbFcoY7-6A.b>>1}ژ\.VqOR@ H) 6erMcx".$9}Z#x"M%1%yY) R@ l ȈǘyuIZ;F0W ֎x;/+R@ HMQ\/>#o;1pYA]zUR|}sӇqrxr:A-7y݋a-4%NǽԨ~H7E/E7E/E7E/EZ? :'N;T:ql쨰@9ˮv3wi¥R@ H)*m ?aЮuh:IډzUR|}\?8K竫'c;;I'ɜ/_ H) RnkNN~qromȦ}ukCR@ H) t:iPsuS 7t#H R@ H) *Fڜa46qM=") R@ l lRb#ۥP}_Fү[ZүUn#׭b|תGVVHCm7[I) R@ H) R@ H) R@ H) R@ H) R@ H)Y+1uŷIENDB`testng-testng-6.9.5/pictures/summary2.png0000644000175000017500000004661712551235562020012 0ustar eugeneeugenePNG  IHDR:ZNiCCPICC ProfilexYgXͲM%Er$HHZҒsJR ""`D `}>ϝ癞wkzm-8 0fFa9f3Dae`AwEZ#QЛX?6_=E>08gd s0Dxp,p%TZA w=08xd YA+ BP<eAP tBm!4=fE3F0# R2 6acT8.+M< Px3%RFQ(/T(**DUQQci2jEѼhIdGۢIt":]ED36H`T1FoL&SŌc1߱X,3VݏubسFl7v;p8u9 Kǝ]ƍqx  Y  G@dBK](6)((U))=(c(s)))SSnRSPSPR*Bu%<ϏW[#b|~A@-NKDAC} L"8 9:B/aNCKcDADSJsf#-%63m,m!5Ǵttttntttmtt2/0<Rz(QH"wXFF#F_,!&&y&;hRNif0?s.s3.mO +,,kZ?xZ^-٣/s0rq8299sœVqU߸ pr-s3skqrpwq/y4x<%` E Y==*{TԖ˼toޖKmK+HKWKa1Ii,+.K-}"G3Kk[/@T8pLG᧢bE%A%W2IeFe l*$ UEpfOjj~jWoN_M9iM>M7JY--wbھڗ?HYUMCe 3Ox*v7ٟ҈ˈdTgbd`gBmbmRb2k*nj~>`|ԁfBff-+ [XK R˷V2VV.֗ڼs[׳Ϸ>(u0١hXӇҝ&>Й߹Ӆ+떛[7w#2.QK+k[O2Y\B^[gwo޿1"5-!//;(:h$X"8=x:D5tJIhMv85y9HԈ,\M=#. B:4~&A;|"ؓ$4HQ~G%K''MOiOJ=:fVN>yLXqq 3ۙYYY[٤2'Ox *斟Ğ <9WO?w_O~X(_XQDUQ4]lZzF3[%>%:eeekg=Ύk_Ȫq|y7++ UUo_PPW^UbZھ:KrNZH^9ܘ"_u:lsMڕBnodބn\iinuhi3niWkqkוֹ|L]T]];co^}gǥE'}}CwM>gptVz:2>okTsΘؽ'FOG&l'N:MN?x/ļ|EpsiYs7aoSyW бh8>~I՝_ؾ\*ŷ72k77n3j USg˝`P_(|yOp@ja,rBll텖(g=[ ԧRKQ%H(ӚйG0&10Sh5/qqr7>&JLAIJ*m'vyvhqe9}4~hYi_3/1X/oge 25oVM;gm^CmNk\N&;L=<^k3>fdrEBKZXH}hRy8OȜ(h1%qxlXbEɌ)tit)3;YN<=9דvJA39E)qgbJKn.X>r~rS j..Ծ4W@E1ě<- mF;;o^A@NhA4-5<VF<g8;Yⳝ/b_ʽ\~0z4vztlkNfnͽT/v^_[^pc'j/׿}Z{`svί @M12a_QdSSb4BtR D;@T*>%vz N2W 2">bK{B%oݐ֔9*{_`4BTPׯԊԮyW5p7_o4`h `11PTfܮ۾`C!%'ó}.5nZ$NҚLjgW{ۯ?0@?=CPŰՈ]QIZ1', EuHъ䔔T4tc|ǩeff>wxNhᓦy /,b)?CU.*Ztv|bUK54lu]6h0y5Z-P+]_-C]K4T ksO>Ob mca裱'E Iϸc/x֫㧃gf$̧{Wpa}R/>Vu}VßsB'`Qx@`u\'1J*9< ~!M9 XHb c Ss:K.YF> <:|)UwEhDel$*I.JK+8ɕVRVPQQR#KTӨҼա}W_wPo@mk+2MLLyMgVdNPYNX]Ѳ>uv,9.t3W[ N=yzx>J!Os'dAACDBS {^9\Yft]],w(ߔp(ؔ|dTc~ǵ3X2>d*:C3z2?/4B[7EŧD8#xs'ΧWVUp&bBm@KjL57_͛-­,۽o%vq~w=w{umw~Ã+ f?JJy67R;plukh2i峡/_YO從!ϱܻzj]p7=@ {Z TPmXQ_T&4D86ޔqA>XDEvH2caXG*,~@T  tz #Y fª`Y' 7JAOaIqb҅#2U 0fC Diizӎi]aah$]2`g` feae ag8 u;ǒ_@`PDɌRғ2e?ʽЫxS%:KjMZ446thu a35?jbkQnb†V. >;vLpqrs[&qyhz{xi&Sx|2#5G2EGDz9&$IvKy>~!c+k!''l{qqpIqYkйh.ՙG77q7Wސh)opu7GFzbchFyԅ%+_ؾV~X{Q5k %dUA *#Ё\Dꂦ p0\woQt(U'*u͉>TWo0l3LHp^ZEE'%҂,{*U,xy| &YW]I"Z m$nޝ=C xѐq)Y9K:<[Rv:Qb.wn)3-`,(#!L!)Uؖa^W 6r Y*g! aM-/: F&̦v ,h, mv:bY8UbZdS|~\!#CË"\bY% $eYOMyf{\)!?$%"O5CAkaQqrIHK9Jj ;?׽j۵;7j[Eۣw^̃OGtL\~zycSI1Qo-D? yo,,6xi]'X{gA~K>  }0 v .hty$ ϣ(mBM)v1}=c&[ |qp crry DM%:ii.ЖqU#E Fmτc"Ͳz-݈cwהO_\OGOXLDQHE2Z^m׍os[#[[䭮??)-_?KNvwB?N|ϼʝUH|bpev:>IA pHYs   IDATx] XSG  hVl-ZP[KESkq~V~PljlUPBe0& ܛPFy=s̙w̜ AI#A  JAAKTDQ1W/ \_">@xi`頦*WW J5$*t\VPWWQR(A@9syyՃbc% SҿΙ+L/*V U R0A@9s*0L;fuοΙ+-1UK.{P/A=pHB@U 622RS^BAv^zՔC(Q-UJxTJ9Z*7B_[BI"k\[L"EߊNO)(˺Ӷq͐% .&cZ"KOoW8@MsA|B,=^RD[JSI.,c5g~}2D>aD=mw'soYs9؈ F(81ST( ypfwpfG(|f呂 P\{,pTD'5\ȧ׮Iۧ1O+Ⱥ0 Ld :G|}\Js~M vZf'u7db/`caJ j4r ΍I!ʆg5c$]*U] g\Ȕ"9IN V-K9RH?=Hz'Rw0AyWhW^VFФ{bxa׮H:k@MsEOethӑ ~`2Yj|8Bwm{"1"裬N}8r#JBK?ߵ{9Z4kɒ <!Գ(dN˲wqoحiSܼqpQ+x4fqLB$\pĪtPq\%fDn`_@. ؒvvN 1&[2 ?Nz1x94 /y='WHKJTw68bl\핺G@)?<Bص'"Ue.2:ёyr {M9mor$Mp=)F+rɘ"YvEm !˝/]` yN"tЦ;ڃбgR9B>teM ʜsjĢجg0z,agB #/xh %CvXEaaLEhEяݬviȁ 24 aFr;ڷo?%$Jy=|}7+迏R 7y^m5X=!G#ie2DI`32 jh!t@t#L+Q+ so0sM`oό$]l9ޛq $}li]9S/QX0H@xߐ{gl >q ~ uc]oLeHhIt=oâR2TL$x<<|O@cWKb)b6f 8RY+N`܄XrԜ][Bf`q4,廞LQB2JdPj1k&8AxU >hkX.G<.̶9!蜹Yxq(gXE8dlzQuH}L^F sjdLb~^YQ-6$'91y1:g<#}K.LjWVQC$^ t\9,=vp5mab@ބjt2RB@̕m3Bl=ypK2 s Ų V$Լ Q#D Bnц \$t bD@smD-V{m @̵pHA@ [A!41!IBnц \$t bD@smD-V{m @̵pHA@ [A!4.>ހOȰo_2{m//ծ.Ds{nD/7[p9ڵ Eo̵BQer7w.qʈTiӝ#7IF27vukF_8mJ׆n9zM8Qi l^Zws{OgPt`]-lǮoHwYkk)j'W>^O,Ec@rb>>v.h‡Յ4+ҨɄ4v|emUj_膃 d=J^ L5,Y]^z!Xnē(gכǽԴg\vemw?<]GˆIhddXxOk}w Xo8˶,dfo&1eI%f)ˆa%sie ' GjR8&(M"~@}c;_81;S6> CkcWdJرlyNx!]+^z/w.`uVve?l s tG11WrbТqf\3(2Ԓ9CekN9$'$Hv6%5l]ל I>w$Ǫ['Tz|P~-תbuQnK#U㸬 K9^ 䄀DOY2! }% ]46\RjǤ%O*..o@sGF2lzoIzoxBzؼsZu{zmIJWKiN)q]Ytr._̭;]11 l!/= h-IkI((U^#zEp'|tLv)*z/ 88|&Z8ED@9VPTB&LXU&I߄!dkpc _qe=єL+w2 gߞzD1gС[=@i ˶ؑ\'-P!3<`5f"tPd(jy#L2**XA;ɀOk' .xҥ}˪Ѐ%U3_7(kiR{>+.*7#m,J!Kr3nswYTZ1遌Kn Ӈ WVkdwt4*+S}7+@twW|> 7ލ;ۡ{bR _~;۠ZF)y'cS̭i֦3ChM߃*X4nkǩN2Z(]i5׽pƮC%9V냦.\? +ڵ{ET`l/%+\=4iڀLj' A K ;I'х Њ [Q<M dvm9,$@+#@̵& -$A@6!aKoW3\m%)Dyra\x֋~!p7 ) P7,;,1'v$$@9B%Yf #B ԉ ։!tH:]uUz1׺ "4  r!Gg(B@dZ?B$ 3w:D#@֮ \u!GcD8:1WiA  -_僾QI2sٺ2%KolM\^#~A:W䵋+Ixm~M֣T#_6m _''S~.8cN#lhsDlĈ֭?ë q>>蜏*vYY|מU~Ԧo3\ yi'>cU!AcB^%mVݿgɮ5uOJu!Ss*6܇J6תk{]\]hZD*++Xz*;{p KLR.|hɮ,00"=xqN6Oy˻vhޚFgpe͊Lv7:tl\y!YK25t'jUſf`By΅Y.|(]$<< Bo遯2T߾' A|fd^/Bw3Ckn /nR6JmX .Μ鼔 yEvK/򻿳7@&MMb**.>1e,Fs; c |p|* \U*+HSY5?qJ[ODێr.8`_|l$͝xz㴝Sn2VO97>y.!w&|7k%ɾWx~g5ln8!VdsNԭѾvJQ_ M*aRE`t *_@&hiG,䆘g'`ޘ=c`C?:Y^z I=/x#z=T?q@fo℟ZR` {:Sz,Jj`<Ў7:jU0FgW\ÿSB d~8Ш#>Ca+)oY3n\_.70,,۷3PhJKQrm̰LNʼnG=z`T.gQϐCHv]&Ɇ: 1o~yp% (,9``We E%RPHhWZ*Js͹W>i(u Q~;$C@I AF}ιM9ɳck Ι/2QD_FhƬ,\٬?8kmn8oaqܣEoWJEhZ)Du4aPhKc R IuQkp0l:`A.+G(gKmZ^yC($fcaeŌH3n5:ӱ)irĖ]:&cscg88p(8{M2}nzz>Ix&jֻUiRp 8lZJ#vi8܄ i+51Sl؋ Zԫ .>}q60t .pD,}C zqQw,zA*PIDATǐG6v$8+֌vr'x]M KqAsSE?g :YuJ8l#,>M4d*7tk3"O[ ./A0p9vq:1U(UA.(0hЖ͕Ge`qGL^f]=wDVf|v:[ŵ=X{X-H%K5%,8VgCV"`! ޙ̨ҕ+0141cB0Ҡm!9ˀg<*=@4qa>/nB<}#Ȧ2 7PSLʋ_ pl&a4!{;zz$RcM (CN<'Zfuٝx420r7xl- h{$fFC^OԩK0ےm1kgw8uPF7XX2l;T̈́;y8LÖ1̗aiaVU`9jǽ7y;v8k,k|N^U.+`Ԥڮn$ \W~XM@ijh`lY8z7p&`4]DcC0Wc* mxN ù0[Kt?`ZoI@q}{LSx3D+As* ]s;Ǐ>{bs-Q‡:oof_}`ڡ8o<{_8aMbVt7ꩈ7Ƽm&#C05EX7=$U&N0FQKJJ6 Άxj$:UDF&Xr9dPZ"˫KuC-TmJB%ڡG63\"dqL4R&+ 4I#v 3s1jvj IJ'1러h/-xlnݥw<fI31 ,E#V[> 4AK㚩hH#2HT:^_QKylzvoG᲌B61E!\50lZtCCPZ9t`ݶS3̲sցjlIɃ=-ڮNn+n_l>l2#2멖0)-#?CJ lFR#m]RG8Xx)D`+! ~^Y~cٕ<tG ,sڨYUbu"-<ΤDt(U>(qQ)\Yko]ŏn-_bovZL OXTBh^ZTOeYY~v(XUvnb̝Ҷ.=]M*2+f۴# c- p').6^J˺yعInNzlcOAQY[ml:w%) Y./= Ǵ{T{tKNJ==6pO3E19|zC0Yu,F@󚔻<#&Q.*AGQR:!;9>> rQW&c>Q"0KpdBL0) 23,:YIh6-مyy%tGDž4fWxpV6<#R9G pzLuL)r0?lYz"FWH&8=ΗyEC8ar &e)VFФ{bxa׮tZ`?ͼ+B0OuYE v[:,=b 8*#!wƓ³s0μ.vώba;0' -Ϸekֶ cbPsv],Hcg9/~BArfI;/2$f%!FB6Y Co JYK KO 󡴤P bA(Bbe"x(@#XX(I7) O Aw&\B<%*TZ*:da>RaElJ _cq"h ձ1E$k.'/1X\}ѭ"C r < \i`w>,ZbZ!,{b!OD)b!cr(@ AOT*A Ut&09_fcC37PQb::4B\=b#p@>Ʌj<8Y%Z-(K%A ϝ"~s#``nMolR5w& }`779Ikvf6`.Lã\T(PqET09 )AZP&.㧻넽\8ViJדi3iLyJLɠb4KL VAenU{1" 8zϨ5Xv%bx[Ϧp\-@f%A ^vs$Y`$2;Speŏ%ZDJRZ^AIB[#@1ZTA\e;07-mK-yeM+R9ж$J9HhȻ-1)TNdS;\7wLͬ]<We]=gCO*هUu7-ّT@#?pk+<@geiõ8~8%+qx1=< r 9=e}?9 $kH;>?,)Dң81ԗəI@Vxe[ud$uݪU 3~9g(aJ"IGdcܪ:plO|gk:,4 8=OFt_w |ʬ-Gn| ?HvRD( 'tUZscGn2`}%3>,(`8+GJ.>ԇ1ܜ-}ox*~߁E<96/='gmAӢmP)*J8aɍ=t=?@ro=ϷgמIkSGzY½~ogPto('RIF__V/vlۣNǢ#BebPEr̵3g/g ̚ EmOADda9w-e>j,pDg6jiztB\طuϢ>~}"cw"s *?((q1x,߮Pt0вK,-h<N4eݱ{IZ჌:+Ѳv{z~w4IV^םÎem~nd&Alȧqpq" Bny?cl#?@7y֔#ыt I} P=@GΓGrAwݳvtUwEQCMshu|wTQX@Wѕ<9vDJ$ԅ@уǸ6X | qFyGzƂG~]zw/;:;`uYsD9xYk5 UܡkN4bi3l t6Aʳw45e!]ҽgXKG'48W{g`A|+t*A:5_v*(x WFêiEw$>}qXm`ږ|.1ɿ=ml*.7@o >r ^@~Cà~ED\ EA'ۗ*YuޯZ7ny7yFu֚P֮;f+Q7{k]֓uã:=ovP*w 5jܻh8oG?z^Z9: s ;oga@u:ctg~af}5 1OCG0|8Z.ϝ癞wkzm-8 0fFa9f3Dae`AwEZ#QЛX?6_=E>08gd s0Dxp,p%TZA w=08xd YA+ BP<eAP tBm!4=fE3F0# R2 6acT8.+M< Px3%RFQ(/T(**DUQQci2jEѼhIdGۢIt":]ED36H`T1FoL&SŌc1߱X,3VݏubسFl7v;p8u9 Kǝ]ƍqx  Y  G@dBK](6)((U))=(c(s)))SSnRSPSPR*Bu%<ϏW[#b|~A@-NKDAC} L"8 9:B/aNCKcDADSJsf#-%63m,m!5Ǵttttntttmtt2/0<Rz(QH"wXFF#F_,!&&y&;hRNif0?s.s3.mO +,,kZ?xZ^-٣/s0rq8299sœVqU߸ pr-s3skqrpwq/y4x<%` E Y==*{TԖ˼toޖKmK+HKWKa1Ii,+.K-}"G3Kk[/@T8pLG᧢bE%A%W2IeFe l*$ UEpfOjj~jWoN_M9iM>M7JY--wbھڗ?HYUMCe 3Ox*v7ٟ҈ˈdTgbd`gBmbmRb2k*nj~>`|ԁfBff-+ [XK R˷V2VV.֗ڼs[׳Ϸ>(u0١hXӇҝ&>Й߹Ӆ+떛[7w#2.QK+k[O2Y\B^[gwo޿1"5-!//;(:h$X"8=x:D5tJIhMv85y9HԈ,\M=#. B:4~&A;|"ؓ$4HQ~G%K''MOiOJ=:fVN>yLXqq 3ۙYYY[٤2'Ox *斟Ğ <9WO?w_O~X(_XQDUQ4]lZzF3[%>%:eeekg=Ύk_Ȫq|y7++ UUo_PPW^UbZھ:KrNZH^9ܘ"_u:lsMڕBnodބn\iinuhi3niWkqkוֹ|L]T]];co^}gǥE'}}CwM>gptVz:2>okTsΘؽ'FOG&l'N:MN?x/ļ|EpsiYs7aoSyW бh8>~I՝_ؾ\*ŷ72k77n3j USg˝`P_(|yOp@ja,rBll텖(g=[ ԧRKQ%H(ӚйG0&10Sh5/qqr7>&JLAIJ*m'vyvhqe9}4~hYi_3/1X/oge 25oVM;gm^CmNk\N&;L=<^k3>fdrEBKZXH}hRy8OȜ(h1%qxlXbEɌ)tit)3;YN<=9דvJA39E)qgbJKn.X>r~rS j..Ծ4W@E1ě<- mF;;o^A@NhA4-5<VF<g8;Yⳝ/b_ʽ\~0z4vztlkNfnͽT/v^_[^pc'j/׿}Z{`svί @M12a_QdSSb4BtR D;@T*>%vz N2W 2">bK{B%oݐ֔9*{_`4BTPׯԊԮyW5p7_o4`h `11PTfܮ۾`C!%'ó}.5nZ$NҚLjgW{ۯ?0@?=CPŰՈ]QIZ1', EuHъ䔔T4tc|ǩeff>wxNhᓦy /,b)?CU.*Ztv|bUK54lu]6h0y5Z-P+]_-C]K4T ksO>Ob mca裱'E Iϸc/x֫㧃gf$̧{Wpa}R/>Vu}VßsB'`Qx@`u\'1J*9< ~!M9 XHb c Ss:K.YF> <:|)UwEhDel$*I.JK+8ɕVRVPQQR#KTӨҼա}W_wPo@mk+2MLLyMgVdNPYNX]Ѳ>uv,9.t3W[ N=yzx>J!Os'dAACDBS {^9\Yft]],w(ߔp(ؔ|dTc~ǵ3X2>d*:C3z2?/4B[7EŧD8#xs'ΧWVUp&bBm@KjL57_͛-­,۽o%vq~w=w{umw~Ã+ f?JJy67R;plukh2i峡/_YO從!ϱܻzj]p7=@ {Z TPmXQ_T&4D86ޔqA>XDEvH2caXG*,~@T  tz #Y fª`Y' 7JAOaIqb҅#2U 0fC Diizӎi]aah$]2`g` feae ag8 u;ǒ_@`PDɌRғ2e?ʽЫxS%:KjMZ446thu a35?jbkQnb†V. >;vLpqrs[&qyhz{xi&Sx|2#5G2EGDz9&$IvKy>~!c+k!''l{qqpIqYkйh.ՙG77q7Wސh)opu7GFzbchFyԅ%+_ؾV~X{Q5k %dUA *#Ё\Dꂦ p0\woQt(U'*u͉>TWo0l3LHp^ZEE'%҂,{*U,xy| &YW]I"Z m$nޝ=C xѐq)Y9K:<[Rv:Qb.wn)3-`,(#!L!)Uؖa^W 6r Y*g! aM-/: F&̦v ,h, mv:bY8UbZdS|~\!#CË"\bY% $eYOMyf{\)!?$%"O5CAkaQqrIHK9Jj ;?׽j۵;7j[Eۣw^̃OGtL\~zycSI1Qo-D? yo,,6xi]'X{gA~K>  }0 v .hty$ ϣ(mBM)v1}=c&[ |qp crry DM%:ii.ЖqU#E Fmτc"Ͳz-݈cwהO_\OGOXLDQHE2Z^m׍os[#[[䭮??)-_?KNvwB?N|ϼʝUH|bpev:>IA pHYs   IDATx] \?ս CL)faSNJ52H6&{PhW1nSME%=ros|o)y~?s>ssݿG u_A @ 0͢N7v<3, ~_`ȹAU̷u*eH:Xゔ7%3w˪˾!aҪhG`\66=Cwvx}< RE߁ƽ#sMDTO*x`2*=^;6RbáP\)ת2Q8It*VsЂYA]">3-,`kE7#bЬYA?: ˅ ~t_}`(M7G;-TpbPX3aߠC(/g- ӹt9斯 n&\حNO:{G|^UpF,3Q-?@X8sRwCM`gg\$baWx$ Ф3<4eպ1?/Z5-N v8A%@@mҧJ<#p__L1)V d^BNFj3E"{O;K.Oٜ~@QmO݅;]Pq75k7Ɋ1[B~>B>ޜ9owe ݆|kkF4xB16$J-u=;'q0\R~6Y9uQB .*4iˡkvRβW`ȹ c$`>ՑygC \lc:8J.[,B&ؐag>}>ڷ+&fFil`/A O?һ___3jԳPxzIoIII9p (+b'L+]=- I!t![d Znn.g-?y!w_+vEX:nn{K"U#T_$up«Qq(`7@ ]{"\T/di ЉҰ#aPN\rAڿ9i9%2?fpq!*Jћi1QZ&h Ԧr/C(0p,V?#rºhK"AEP35ASA:ϻ_RCkxD|砓{]K Zs?Xj$k[㼰adx}ro1KI.RHW;ߔ Q@y^flVVM|D+-+v-߳`Moo)~u\j-F.ݻNݲOuy{u.{+5-=n1^56st%a\>W3v av0G@9q\>ZdhʕE`}J q`4*#Im3v-;@=ʘE=$$A \>EJ*>=GK/ПKK-_6h8?f?iDj)5V@3-76PmG 6JkåCaaT X4 uun EZmAah(a#B@FJ(0҄n޶S׊2BKU{|_< @xP3Z6QvZ]v*!ALx9P3-z9j-v2" @h6fpmXmékI#泘$E>'H#G-98h$BA =@ CE @{B$Amlmp(H 4pl 7S>VhI^ ̈́lY{h&|X@#縮w #8 8iwl=W;GL.@!ݱkvvpօj\(ԯ}IiɥVMDBY܃v׸h_!FDXAq8FB٩\1Qi*sll?d|PDP\(m7|LJ[Ldt>]BY2Fmtے:Z=<,$ hK/e5UPVu&&E&#4 :.վFWBY6^DhF=%k+ʮ ey_/ݑp/;v~ mFB٩.6=}8so?f#4~慲[ktn?ӜD 5љ @ 4;d!&ֈ11׈A !&ֈ11׈A !&ֈ11׈A};dȐfDМumNDv"Pp捃H'4y :t [!H?AH+yT6Zlb;N5\'g~~P_љj>vk)DE Af_emuyүƋܿ㡍SX4Y&=Q6E)U#Rwܹf:Jt{n־Y&0 "L>C n,%O~9o"O^=Q)t2xz%<5Vq,OEu5B<{՝q1!QkF=tbY|}޸=Ns`q6_Ojt`ߡ<^=y=կ-=_bG,(`0Qj wv2J_^M!áVS8j*7iփ,khhƕ"S1~e>"us>Էh ̇.8RXCCpWքtpssiynLE?_B !N "Foa9^XDp[N*mcS1\n-274_;<,p|`xts'^aVFMyɁA/xY۸ T4u 3 V%yJy1_aV$\cB ];l4>*&_$yy߷ Wr ϟ` :MjZߏq!JIڷcC7v]Fd>3HcLr=B,?IѝU:Jl`raBëLղ Mҫ}T*} *)y8ly_ͩ\\繺 51qB.UQ 059{Ϣy?gă9tSUkg(rO&y4 f}# {f3U'dQ?|".6ѪN%g+k s>\䶈%5v]17K=w*X5ZyPk^_Yt>phыM[sЍlW&Ygʯ|3PvEǿ-?}#:uȢcJOeq Ӆc]rgT8,[ٯ93qF HTF *>Ucײqq Uq_X5wxƔᕋU(>9dJn彺{_.z bNt[ 68-8:6eI!' UDz?ٺO]x})QT$ms :Wmc9 -5 (x(C~^y#zYfS#m7&O&|}qÿqч 톦7{͛= ^Vt(H!AjqyNjo.BqV-zؿ)~|NNj 8FP6zvGV {W>vH^IƊQH$* J"$L_#{ UA(J+~͘՟x H Lz"3. $B.mL̎.}I{wݩ,@X$!Z.H6ymfį; DWq'w|us:9J5Џ8W>{"EOBz zD*>Bm)wjRLNEtCiGta!Ƞc__iN mDZ}y1o~bD+zzC:6dٽʾ~у FuOWU:S)SPkzTTJ ~u@LjIn}2O(1|ĴSWo!]U)3\:yGTp VWu.gO@'WBgw55PWWWdHxԔhܩ{_|cvj3EJ&HDԭ>1GG)xÈq{/vr81@zt^0ҩ:J֮Bxke*c m.&fpe.[PUE(̓S3pѣௗϻ3^Gw3i GcXtxpB({=?&=c7z]  y N,CG k!,L ᄏʪ#N ,,6BR}}בmga"m͌8(6WBě>Fcf}(׃͏lmYw"3?Plłzةk%.q{wc1$ȼR,mgҊ&t;Bdibz;r Scfm4@,*\חq@5(Nt}L#T~[ :"C@+8wG` G^Y'SnM~%}簽Ƚ6t274M:JӦrg'v/&㭵ysMw]|ӹl_:@qW;~&ll_7/ZKN؛;'FNU`6 )1Wj\GO8{oC^(\ݐw,MOd^KJ2Q˸Vi3#ьO>qٞ7uC4󌄝ۑeta2 ƭ{ӼWGatm/o ~w@G0fca4jW8M_L륻3q5_KgZ*Agwy뤧gƁ톪C!9tRMMlj]Z9k9cԒ_ Ѭe~ @>^2t_f1rif_Y_mqܸxu41`rk$ߡITUQe s>I0M߈kwR~v_X dnrڵכ(M O󨻚ۆpO|8 /%,N'Z2h2#ERtRA&~ħ8FjZVƯhV/1nfuU封m5tT ~rXP/Z 9&J*\pJng(ZkT  4q 8Ԇv"A|h VB,#B2 #ŰA=B];8)SGz RԱގ/9wqu4ՊݩMKPAWv'dk8foofl/kWl OzXtv@ \QuKW+8 'M,k\o+V&h`UvjҍLW4# /Ȩ+?5% XiVG68{ `IԌ1r3 Nml QU `4֌׈o4N6yr`4U `\{ p7SU6GOj _!=JhAi<lӼ]όRW@8?NO-ϋ88$9.x-GfL_8Vre%2ztHgcla7#FuSO(YtU_Xi׎zA$9qEvHضâB&˾_1ꮐ2W=?>(. i;32򲓼ޥ. ˊ ?v9,Ő*o|HYX? m&$%arhO mu'eLL]9_YIǨSDrlK[>9KQNݱA1ЭJ8S;W>~ q;0SIbt8qNF]^GƖ̆Um<<'ƙiv~w4sפv}l-vLYtAǑ:@Ed qI^h|#Hs;u(:5tfv' )ؖJ̃Tă.T^R4<̏zq"< Z" GǃB*19GH :BJ$-0AޱRYʪӴb8{ V d1z$@hǃwF$h|#2@ҺU2$iBRzO5[pEgࡕ̉x AFW~3'~׺tU@*-K8׈kTs)2EjdWq:@ךvTaCA )>9 gCZ)]dzyn`jaՈ"W<xt8G(Ka 1!8mֺ031@̎ł|Eg9SL zp~s2L(0Dʼnl$C uL 0B#nV4j~+ QۤÈj˯̀mPlnny\Aܘٓ>+)\9.??ޛlNYXӤ}?QQ+4ۉtM;_3ixPdw*Nt1XȯS:zKhB#=Z{~H"łűI<"!|<]!s#Ra%ٸ#vJRU]i^ɥB<:OϋaËpc&=xoȕ}4%%~6RX/KC a3iA_;FUf5_|:/BSSTWCG@-łr݄X5trAȬe(~V,jq_TL;ShB 51ĭ2ӉA(CPlv#@r%ΜFrA0LJw p@[E@9zhRrbs-,Ȃ["zVUyWTT!QK^~˄_҇|n pу8ӏooض͹ g&!nat嗟l_޺ E]yB{s7\[) ,0P&^9#?wL3Q~#ր%ǾcbyM(@~ >HQQ̰@_7F9#er>"$U`q-@ťL+.m| y&'ah8 +xp|'Xp;ߺ {O#$vlDݹ<ㆿ oC'\" Nq)$jK##´n FFK[y:Tr\&g|;N@ζ*$gֿ6y͖ng qfkVYĿQ4<4b+ЕuT)# /5yYdPhBs*4ύQ`jF# $.@G SߙsPԽ2n6LzQ*n~mobOÀõiXxU 3uIIy-Y?\0Bh^CNwGTy*hqH !fQ F w|z(lC16J5hB!J K"Zh X88m*O{uyf9#k`5ur.ل޿<{c σgZbX}cYW\XuƊSSoL=W쐣 +cU䋟QYg,[sfدj= u@f*/XܦoNfɽ;(V m°ӻL~L/v֔]]zio| ʇ7}w+?q-!6[vq8w=[[@< aa LMQ]^D)PXXXۢTc 8[#[7TsLݿ(jLnֺo"&R%CjxV!dDj3Gxt3y9alr& @h4lrBRL 9<@O t#\23BHSGuBA҂N‹`EFuJ<@{Fm`<ʕ9WvJ:qyyI@H 1 SI0-\O/Q ~0`8b0?C[pXKϮ+1+.c:dj #ӨQݹ:D(%{ Juݓ(mB:π6=lwԕ`'p9(Hs;:ԅ3:y5-9fuHhɰd{yDw[$ט %Qe|D"²\E6A4sz1{g"tGvz;;JRƇK,HEUSza/O؁M 9/ J8%A]>++Xr8P }(?ʈ}*!Tjue q.J8d@a]S1P5DݿMIkڎQ.sGO]bvR),dA*BP>ZHEH$Pp12_wHaUwv$B|)CbTRxy:"i,rÝ6Ň:cO鹡ۦA@ysyf'5mP!{ڮLJ-U,8_*ưӦBR2a32vx97pzER&\`s+8 4k'e$kP " w&:Aчo2իLGF edF>)Àz\# C.Ze6m9t )@؆6 3ůŬK^TxF>pՐWfݍDrCnPciV5QWV7-`%[>h,jq_TL;S(,.WGMHdj1zE5q/,)1/A>saԐb(oH$klW'/A Ъx^~ײȠUA'UJ(U ϭ.4&9H=zznt\M^ A"=ķ$Sb1p1BczJj!Eq,-YZ^&`H>d@}CF@OBP8ܴοuD/~]oVpPE1A͹ޏ)dmcӼok[KgtмLg35 m*ړ IDAT&XՍ͋[>BhőEnfp[ ?7$}xEߡrL\~c]yU۬mW#z6Cok<yTpJ?3ri )Xf!Ybp`. e>C2}owm3ncB#`z 3:xދO>4}K"9Kkqh (uT0f<1&R whl1+~(C7*[ P}܂m W]~I(qAc6cd`qR-u_.,vG"*ik.?C'W_Տ7hǎs7:W#=v̄zTedm8DdC!b~OTwׄnQf?#wٿR Q|Rt8ZhKϬ7ooOgʑ/0.LoG=):и,~sǸ+؍<]y#BGbs7\[) ,0PB?f*xx(ڧձn=,|޾YAzt w %6NcE`D}hUdZ[yx&gB :g<SII7Mq/WGګ#΀oNdEKe.Ik?R$|rpiv7_0aZ\mv檩\lBj"*n~mo0MG mHڈUeHciRp*8o^pu*HdǽKV_(?03vyɣy/5`nw ><}l%7NcrZ0Bކo`zW.`vT9tQAMӔQ~enjHrŨ yŝ>ӯҨXNؗ`0iV@ N|d hvl9)oӇToš\M8t4T.K$-F\0 (pnLFϥU&D Ȱ5m^kC*ϹX(0TU^Ag~ qU+Mm^p3wQ&~P0r,Lצa3Ē4bidP\=09"Xjb b)w7*rvRQ=8Ŏi@MeҖ¯,׍j 1PYW2àx#@{BA桩L F AOCcJ L M<5D"?A#!9 Tl8JΥGL8 A"ߛ%f}[EI-DK6;Auyuu*0Q޴sP\ VM2Gei~zJ>9y99gx=C"TIrpOׁTzO1;¸`c3+333c`=6P/`nv6{oe0۬@3"H&e'ȣ#fVXq: phGq`$ۡFSt8'z#X.|uz/#cK|L -c vNq5yrpPV)ilJ]9x+6DX&aQ(JxG*]{P$3ExP]`P$㌨oDtaYv"%Ga(ƽ<xF+.CꌎDR^J$g>𐩮+ wV&B}S%)C%K)!2 <.FȢ3Tc$zxW3<3~Q +<3:IHj`O/ t lZA$Q~'XUis(z.~1ӧ -/uu={{)Hǣ֭;bAZwy!V(vUtu+}+7Gp 7޺ۆZ\Ggsd)>ebY>,_Wa9pz8jec ~??]nF\vA~ܮ@#/%~}{z6_V}%yuH&fE*U3Yc}مWE9G0QP}'+NKD{/{J^J zI\PGd!ɳfYI$Ӧ}m]dPoDeg M]!rC%ATU{3q(bBFX$Q xG'2?4QB0Bvcm\,i06+řo`n/8-qוCM83q4OAOsC~_dZ<ܯ5'm9EGLU Ü8qYؙ:MZgrg9pnG:F|<|PEQrlDd7|"Bn=0ι GOMA摭ӹ'PX@Ϛi$#B3 Цu\VFoq9\@o5`-6U[ 8NQS)Nx> P{y1~m_]N{W<6h ;8gқD:uaӅMs8`7ӯD:0l]fO7Ur 5GJˤ,OJ`A*82JS/&;{{3Dx &lmy\|UCeKɄ0:RhyT("v"H,0 ㉤@`Q:5lQgʉx*rqlԟRiYb*g7"@*Vru`"22^'klWV AybX_8[$a2'f }j(%OIV %ljQPyS=zVT*!#suump(qLMl[25T$/@Cr 1T˷5~&V P,:?z"PKxpX(8IW;jRd Qh)x7$:Ĵ[2 h8e$R!̳+K IpoyPOHiUҭqF :P*T?!Hҭ)AݸtXت;B%1m4)Ar!>(x"B]KϩFVyՏ!ԭ9Wr0TQ\?#`}BnwNyvqgmk:&V.~]oVJވM>Ʀyֶ鎌P~pʜ Ѵ Խ/&67o.8̹%|sV `g"eYV.r؎ÖΠ]60.a`Jwo+R4y{WH۽XM'\g[wӳ 32}o~SszǦ'qW9jJЇ pv9cj)@H3rqBsm (eA&I%'&:2ߟo cfn߻dra ޕͳ3 KN ԭ{~+a"Q's: y̝@|$ 9}KMF䙸"9ؚˮ[=m{tod݄,Tz]j-W {a+-y+s7)fY89_8-U Pyw?N~3'$v~s+eʦ~6Y-N;>O݂d%|==z>>cخuH${茫1 r(|}'fKcx]9śo;yOAp`<Ŷ\}*8NJ͓w&c?9h|ck] -y楩btZ=mX`[{Xw{`ȫ;"ԏ/:q!uwEÈN #!+ #eC_~iX=oW=:Y~;rm#yߺU_Ö́~p{ʢ vJ'Ats.py0=;k.Wt=vn!FO{ڄ" V؍Ap 16}G?'7~?tsݍ9C&9rU&y:Q6SO@> ZNׂ:!.-lMTqU'5ب"j0$Ɠ\Swp#v,-4-ϙ: :&x*M)7.t<=L{@m^e]a+Zեk7B KKqŚvX Zl;-L;vGt-8]VTضZ+BjD@D%J0Wvs˟ }{ι=y oHXNW;0yh%S+{SK pf@dyo<o~OmHl#/V|N(oj`̀ڱ)ɚfHƾof?eHWIZ3{#PmL zIX9~=cǔ v5HW,]TkT+m.Xb5k5~jƢf}Cھ0SXm@@(s6WX9腞`` j^UEZݑ/>-+g5]Azɨs߅,'wEmp~B\Td'@6(<9'd՛4Dk~?M֍#+n^AA^nnȉC曽YRntj|b XHDa]A>X:ON:])psW[Am+r$M."< cH޷TTk@PĴ\Z4zh]RNd{FC6~wgѤة4Vg֊R . Z1+_g[Uٽ$Uj9mWw<#08hm]~BhZZZ[N_!VO`oLSvL >4(š7>[+Zo9̃ٚH?R}q9G:T i8F6LD^\ǴԮHYD ;'|\XG!{d!SSM Q pttB%śEbiT̂@XeP8:@ #qc\4Gz|'c{0F]=2S Fy[VG<[$׼j"q`HDDXXXG*Yޛq$ PH? 1z‡/X0PHZ{c`ё m`uu54"4ÈP|U{, R!h-n7 ]ʀ|IE]LZ L 8h쪀̨h3@ȍ@ (Ϯ2 jL\j j@T=0kMp*cȓ1̡#y=!;A%6[׈9sQԠ)[L00!MՃodx(P˲<5V–n?$;$+p/9gu{E^RR<Ə$`IǮV`9 2z*BMdUv*Q+OrQCBqbG|w#T,n}"# \GMq`C/щg#tDl;KuCFM 1xkIFd; Ԁ/vd(ez.*Y2p%meޞ\:Ō-vfj=.), N~)weyrMJV9aTE+_J~,/Mx\x63_c=|}hgE! Pޏ>z4=T88!LCe3xx{*+)e`2B"]A^VS%:=j[BY"ToCANA5W/9:١7T^~HRDlj5h t0L\ TjohA^mzaBkJwH?׬Aӭ/l0Q쵇0Sdfn<ÃI{1%oIDAT2`]w`d)Re<),-SWC"OI!y.fD@طԼ<`h)0Ce(5zY4YF ̜s)^ lX:k<*aɮ3vLyE^Q 42WM@O]j)[z5gYdUνtZ4jXvRm&2EmXᗾxN/aAI)h9m EI0!w)0[<{S$aDbXidʜ:o':8k­ q2Ih20pӓ" ^ ph;JCGH$ vAPP"eWm\V\WNB`sNb5 ܍08opb1&d̡|}etj)> wuLB%G2XTc1Z)D" 䬠ȵd+/=n0f<D7.Ym<<<wDB}wZ"w58ry+~0ryJ!ٯtE?0j_@GyͩjnS4~-3$um[鿎+m RFm?F..+8_w^'<. E_]bwj-N@ ;; dGxMh{B?BKQWJ=C%RZ8#c|9_%<s"pF/~vatC356`?~Wx.Js%˪8lkg8'q!jm+J<+s>nJvl J +\C86wAng3#<9U=/WZHM5+sձO-Æ ~DOz.^jiPt#ԝ{p\p783!}{(;3&B{g\ڷW|W/ؗ܁wW:|3>5~P}1) Sv%q`% -<﫝n=?:r4GDoDfC)\~X;0m%_30ğWss1 C$J+I{,ڹiE,ZOi?z"567䅏2 7M6m^Bl#k6Y @ g!ǁ>p[KapVnh7D~FI8OJ0qNXB.ڹslOLos:xZ]h?~A0 ߟ,@BO<ʖ{ Y%Ov 4la](퉾=P}H~JrYK/pX&noRKo1voxD~-~rC!0fy7x}6}ۜ$@`<ėrҚ/?O.b1L[(9:{@s%vm M77V]diItSo״ ٩6eҚf>\pkkc #,@f>X'^btI`NWTEZX.<.wv?{,-Tظ;DŽ i(O=ukR_h$sVB%g:_J --^&w7#-V"p͉)#)HfնFz:<5`3(㝣x3@S閚ukbFoJCסō_yg6Ake$>*1]if;tO\f ROgFqh伨9V\ .\+}i5z~>@>- VT[MzoܻiK-VќQjлw?G?1W {vs 5j"mZ^y^h%܉4 B;'{qNXKd@ֳHbT*:$ ykv+xmWֈO6v1>igD}ͧg( q c㉘\Owm!8tl<(=W|=R3Є ̲5MKZ^&/c9+gU䅾Pƅ mEpFB52cUg{"5*ro*=}7٤FU3h{~~eo`u]g(v\3qQh_I@Y>+Nl4?w(3VdṰO̟};͡wt|li8vě]F 7> qeyDv&zIPcLL}eOXnF&4ke#6?8t (&t~0!""ouE]؋>~ʅrr%NNuEkpw,)VÑ^pmaE )VÔmZ|L|xt2n5J?x6ȓ*ѮaYY7%FBC4S̰VV2ȶT^]J(JS.D'*>G`#{4y3g6o&P7L4I㢵]{ MRyxxxncpϹz;J0X9\XGGGG`"p;̓Hyv1@iwzP~o6 \"Z3U :^?\ J]^aD88Q&8!A [$SHH(T7 ?PMnP&d9psKĺk#uCSލwJWPMPih}yz:Ż!(t.uTmɦH{hl*Nx{d-*Ԕh _$8V(6/FtCN\o0-8qf$MbvϬAuQЊY:BB]{z T$03 ZzJ㈀ڊ^*zdʶqz(}-iXg}wHcHzO#SUrY:K@\ qDItD7v~|W,iezP&"@Q 3DZ ag<,BNtIcIAOGy*1E&$7T+(f #ʓcsˡӀFEKw y6*~m=} !T;)5WC^OJ=L0Bi>hw=\0wZyQO, QfqDC,1T u*4ʢԿ2qry[Mى[%ڡ~9CUYP-Y-_>M Xro&MW_n0:ڬ%mj&{cQ' % y_IbJ gxbMzC%]g464$6teT{G' %ЃU[zLp­%+LƾuNۈ_ ۡ7z0Ph:Q> ~Y(N6䩷E`Pa?`ћ aP (I{ִ͚iӹ;{>U!U5*dAR pSJ8B* c癨OrQCBqbG|3lwbH( yԒp$"qW\ZJEuA#3邑NI*K #L_{T,FݧM H I,W'ʨ:\TD,5ݫw}yl'ˬ,8bhQ/~֋O-4I%)vu`_QDA/%,OI*o„DuLmŦ^X8t7ei+++gh陛g~CnSgc=,V|1ah*+w=\Z 5E\%^Lx/KX"Lh_Dk 6=gѤ9B柉:.hט#wRP$FJJ'Eb,}R~ vaI"q/W uquaDl H.7~5=z [ߑ"iuJx!63y' P #0i 9E/|p]:ɲ3AMYF5g "#P'ľƮafW9,%{ RfQeihfma .?BMgΜjhlWY]f & i )U- KZu+?>2jШ}7}_TggJ/~&BŋK=?WRW}7fˀH*FA ϣhj [= ]L 9l0k_}yf?B˂B5"bKQRyKq2+H**N+5)g>b*}ȸZ50u' =̓ZZS:zOIc7M>{hfcIr6;k`aaʼnri8(W;󘗁~?~"84F &4> />qTbd(Ѯc<..|=>+J_ISSWQ1^tcԭwbfޗΕyp0ODX#l!O1g {) SRXn)SwIH=3FƟ[R_85K4/ԷƶzyGWM^>ꁔA!ahdlUkbcOƫ'g~Ș̜X9? _gqs__-(~(Ի|qtM|i 11Aa2" ɉ|">QwT}ܳ* [6fC,W''_ 5Vb8zƒc)i.鎃gpr2E˫T(P$(q(T:,wJ5<hs Zz]:XS , 1Ff&,&Wl4/[Y Yg'(lٶ%8su<dW)yE|d~y_{z| Da}*&LBÁynbd/ەkW>:P>hb:6O+t|ԍ-Lfb^4X7g^Xo' QBDMCCyND,'#{ĥ#q $JHɽV(}f@vz=l܉gʋJs+k͟=e}T|5ݪCkw|v8a5qo?BϤ~M7?z/XX Y_w0oIn ;P+0DD oHud(9CYQ]p a*A &jn`~ElZd:vLz=1 3L6~6l~`Zqt2Vc'Ј-W +#@PJE|tĶ$Fj4O&V6SЄ_,R;O8\}ESBvNA+c!gX-r-|3/w8&D|uSr?%B F 4>%tz,Ǟ0 [|HԞKu6-7'3\nOfme߻ϖ{Cr#bB2+*UeˮW|Xz[KN>|`0qTUϛ1w:G&ݦN[}ʙ"8k4=ւ‡X][z/_++U"ɫk^k777\6766ǶTm-llP/Q a4v_ܓ Vbb <H6o-8Bv[G7ƺ a/MIưƇ``cF,~~;=.Er Y" `?2^붐B̭` Ph7"O;6gbp7Y?@ xw &}<^ ڑ#e?ZRc^莎/uϑ`[ہ++}mYxG^ofnt; ûѠx/M8y %Eɣ4ZRXHP(2, Бr!v}'F3WNN^g$E:;;qgφ~Vl@t8CLVsm>Lxxxxրlst#&gS4mhhe69~ǜ?ΌOK0nDR9P<&E"[_T42|HvN<F+'͕= p;9x$n|ez:okV:ֱ /] C9D:Թɺ#^uX[-'2YΉ/|;:e:_/ϋ/ʽ+*$eCT6UӓnC粛 ;߭Ɏ3їztDFQ*-He\U"ҭ91q7}Rehu`,NYU\s{7?~8%/e}gͥ]UO#2^|UƑn嶺ղJsԲВzYsK-797000htpzSeTUZS˩utKAMO4wPxsDŽsiN-ay\yDs]^/N.tT.UY'ZN:*O˪e'eU։*DzIGzYuuy줣ty:Ѻ^vQy^Veh]^/;<]^/N.tT.UY'ZN:*O˪-s] +rRHz~ղ-Os:/^|U&VRyꄯ4:)2N4dE-gnN|og_FtRYdXeE^I:їrss{y?q:/E{ǏlE; OUJYڗzn|]Nʮysw.\2*jYN1\,璤*^auY̶}#%'Y''Y'wx||'_9l8:񌾳|s>}ϭ=s$4_\uxnu֖]kH(`jً:rEuqׄsY٥~xmdяc//Eg'7_0OKg˪|'9OTv*3/,5VeEsjYeQV;CW'<%-q*hqtTT97Zdr7'FQژ-VKE'P<0_CUY!z-[)=i),&"L2?я.5jT_|mrrElxvߧ~k',!Aj &2 r.2:"\U^ª-<5i)gSL|IIIףQ꺩30002x 66ڵC]]?/|1x2rY@1Gs%2sgJԩ|Z a2ӲМ`+~.]\{I3xxxxx#I7`IJ\@ezyN_nPMRVs2 /R.˹J_iG/jnK/ߺ ݻ#!!4Mn;wѣGq58o߾HMM/wDkycǨ>~Vj4 28ftˌ^c0u_F]H,7\ &QYFdEHj.u"/e< B{\&ʊ导믹*^5kЁ3fKVrTVq;1<뾀XM^(++î]>w@J =E]{;OO>O~:y):$Pkf7:u +p487MD"/@UdY^=({.}>5/M20p 7 6[K%WyLGXPiŸź$iRD;ej3y*3I@آ#zy&uxn9_7ވ~O3O~%O?dtyxgm]vEnnҹ#8@Z2̤'-v\i wU:]]_yF kͿǎ͟a)p?֖7vů+?$}r{4\cZk u[kF{'O[Ede _~$s%5 1OrI9WױSpz٦X^LhW 8uyN|UG9玪e'XzYjDFE?ߌDǝR]Ѳl֥j< . )))/З8vIW,N:!f].irnf{4;p14GVT¶,\=L~x$+~ktWM ~U׈YDqHc};!H ~& ~׮=!`FƠ)Tc8ҍkQa0&igO$l#XIJ*3_TG-|\u4`@cjYhU. -ʧsj_N_jGEc)۶!X z"њc`;'5ZlZ^u>r,Éuړ}WΏk6R;%!CXcq)ڧ#_aó:nͤ᷅`x5lğtiMjKJPTqHW^)힂8е^S򝲾 োH&Sܲ%Q|hΟ?'\3{9+qbpZ柤Ъ U[Ir¿-_ Jr邔ra>Dre[e{1fCO S/ UGl uug(: l9xxK7rNE6uPyȊOpv!̀!N:/| )IL;M#O

y1 ۪?O.؃[\KϷ+ 󛸲'QH~J'l +nVcQzc`lE3_cxm[m|+ b\>_x.;_>?u 8|Vzl 8[4c vO^"|gካ^@֓ߛ/Cx?Gm\_ѩ l{ϟ>K}c&cIק10l?nRerk zd 'P}U[qk!=G1NmVise1Qy]?I) wc85N<ֳx2|9Y[,8Y q^߽cG?FkrЧ_YtD%1Gȁ oCwy =0@Y^k)Q'@j߯ZQ [B{}F/x%$n8 $4f&O͹NMIGYUNxV!BTN!i.ȱ8BreZϥ#O"=uH1i=;/c|b~=^KJlDsn2W6.sb~˲=~qI#f聭$㸯NP4Ko@=٫=ڀnejiN EsK:qlVd_~#x;pa-xj s(= [?o,߰IH\%b`x_BB1C6\#:{%ѤaOdυ/݋9YCVъ 뫶:ځ??3a>3Xq.z,=W3;?}fQnݧ\fqW*ȥOqZӻĢOWx\&}d/]?[P]nB'}bN9$ 'i2GdUp)H\lsL{mbscZm #rruh蘎$]zꘞBKI3D4L^Jta A2?t/z9ɬeYǫ{ ާ{nRўC"o\cbɞ_|+{i3];XN)N8 ~(M9JB660q2=QF67܎?lX~axn'X'/UD76ó?zq9b'o#{%ž?L4 eBH5A<65] Ёþ`Th:yzn_{gC{ޗ>Z=͈991hPksq[]TKwK/_ͦ7^ QOزi :!i+ zҍv78I%WyBK$`'q ?̯F֭xNqZ0/=3Hw;Rtp\=_2[ġC,WtyeZ9M>Ұ\Oߏ$&Z0^JI )$PO^kFJ*>J?}l{P=$m%@g1tq1 ?=o% j;N`X|KP[& ztRhyRw1㑸171|#;N; AϷᕒ]"fگ{ٵnaƼsܞ[%kKBwh-vzȞW{x s6_f"ڏٸذwB>d#-BخI+lO\2 k:f9NJSJY9+sABs.4')sΉ |OЯEKyNL̉tO3] | Swa#`/A ~mȑ#H$;./w ,òeW߈݉/Ǯpۈ8=_^cG*|못MI-ؾzSU@Ca`h7]0. \[=>=ܿy+MW?Q54J @w*Ji1|S~= [W{7<?ĉ/U|w$?5vU:}إNlBGZr5̙mCs\3GְM<';\iӾ׺2\<|1nt!F]-Cc0oƚ`Y뵥 ˅A6(f&=8"#[\||N );Ɇ ᫹J:0̲j=ޘ9b@ɒ%Q~,//R}3=Cio5- WC1!KT ^ ہape97kS yI3r-I?+/҃*qQgF4hU}q>~:;Yi"ӭ-ÏPEߋT;)s]q]NoPBZOw M옅α8FX!'cq'Oﮨ=>]bϮr3ǡE௥SlKVX,d$m$p!%8}I%! ߀S.9ٌ=2,H+:BBgehdK@Oԣ]}qv8~`/A=ߩ.N6u$⋺#VϷWRSPg{B{z] =\VńI'NLA79|Rg h d#2$d᫹J3@rbӜ&@*uz.r},^x)垉3ngzcߛo]kcc:З?^+ Sς9I\'pbSڱ=W.&Щ@TC2~5Sl xn$ґ{=u㔏Zd@O6p8Za d/O6o=B~zj& ORZ1NO\G9zڤג~7h-Vr4~,SdPw})mt1%S.ʲBsβsRiaK<+1EJ NIVSez%@fJ3Z2^1I,NFaW zy l4n5=!3_2xrb%g{x IDAT~V'ah먟a,߷T0?e:&mjkl+Ͱ,Ω=: 6CƦ5kӊ!*0'p_8 PS.uB.9yd<`<`<`<`<p5\Isޢp1 ;1-uֳIz@0DgؖZ/!"'|=Wl-7,W=KZr3Nʒɍ/'?˦ړz橴OsPktPlɀ3Rv)&70000)'pErWdӼdTt&@ɠtdLKseqI 9'Pp:hRlI.RhIEY:%e=WSeV mmS60000h&)K.E՜Yֱ>|KҐ\/3UIh=k5j B_Ko8%Ms #9!iIPp H.Rf#*q|$Sn`:nu'Ub:RReT>ې:3sZͩ=1 NQE$ɱ∦_ WN$eJYuyYFHWvZ!V|u:΅̓rHgg)"'i43 S0008<7A"oA1~0&1(p.b Cd,:CRvͺSH D\c]u0K͕wg>4 sutV?fỀ7i4?O8MdX ˒dx똷|uCj:'cZ6u“\F=^^vo\i|>w}xЯ_0=cxꩧMI~ KU5c[!u(pt r-mYYi ]]eZSqo5[ mVj_ Iu|~]5Zcműкw9k>j~ˇQQ8y'7իcĉVA]vA=~8ҶC]jtoC)+|`y% HVZvβ&f_GE~ Pccc+-rXuҎ׊07Pw`=~MԱbL˛UkGA@nު!&}Lu?T`dӖnm+'`ʕDpP4ɖtcb`D$ ҭ5t䖡hit(paRcM@iO!IJ4LZ +g\0;HS]ZLl'O7ٔʰlN_m>sV,G+&$c3@ņ}1i@>A"]9;mwy3x6T_EoE_"/cXPathK'2ҝ5븲џF;A9q M,s}j YqM;/#"yUl'- :V5oI żeV5[4+w>b?yf1 |十655};wf<:iuc&kTrz\0eEiNi⹕U.N%xkvu. t+miˢ"L{ m}i mҖCۿUچ5FҖG7ho{mk?(?NCi#G}Q|߾}2=uSf>YNU$OkX: 5*%+~%Y4WOesեkv-.ecEs7J\jÑnزP5rHg{mC/ h )USwRsfWVSth ++KSGXjѹsאn\?-S%z]mj?0[~[}(.[Bg%,YwUWK> I9w_Ⱦ\TB߿z5GLQJ~WV[s"_U(d_M%P[CeeeֹO3a?Mٱy|~< \A m0.q*6/13579^eccdLqR036 pSN,Mzj_SLe˪4fψ#TG0$,eMt9ZKϻ+bqoGO{OX\^_.,OmSiWa&gBt+^Ǹ!I5˟D܍NͷbQ۔WOCf^]#|j`CQ:;4 d1'1Gd"::wLBR=pjA>ПP(n[a}yrhZ s]T|owIݺF]{SjveeY؈֬4<^O3P҃֯ĥȩwZ֠P(ZYj@=i9&ͯ؏kHl{z[k)C9tpG*3#4<Ԩݰj~ѣ'bܟvk'Ňc'AE_Dҙ1|J)y r3BGxC)<1֡6֞16f\d>&O\>av߁e=X \67#1vaMqMwxqdPml獍ֲ35 "\VyBKnwnP#2vm_ئ{A%V69̴*U~}J0f @EO=_w%NHaRUaqɽa@@ 8AI3$ֱ#_PqG.73)٧*`/61s3JOW'L FX?>s_rjT|2_RK| j*S]|G w1c&a=is7*>s>o|lK'|Wۏ)|$1ko'wRu"(rC"9H~U{:d'Y863i =ӥ:eڝ\ ?#y̢;1c0sfl{ H˜ZO_ W5}-!߁QO^֒]SugGθn5T[x@V b~s߶h3`C)s.X*&D^Ro~F. 'v|AI-ĚEy?r(~VW,kc"dn\ DރmŨ9X:=mvֲg=Ә&`dNrHa%] %p흏9?CKh:gׯ[ϣ_E)gc|F,EM(]S)\f%a6>Mg;T褾<+Of_ b _ɏPkr2'n'`Yak؝XQyv ;؎IdwpLlL.F1~>A֨9xF&rG[ s1L]2Yݦ~311 u6R 9o91) 0}>|MW*z~˷C`ήGb \W#>'VfZ?C62裏a|%gs?̼7x{nk6™tRʜ $g=UVI6"ƄsWq.4,4z. -@kڶ*N 5ٝ-Yo|k_À\O>~'=_a{\WWSNֽ9Oz%98mԮ_]ѝgz]=@U( ^ztK%%P{M$7DȻ  ,ů=ۯ6ڠ_z?U :RxMvht.O]@>6':,7;6\e@e3_:|ʌWr|u,QU(xG{v0fjr^nuj;-yWNW-2x(;2ьSfDgeMUտsթ~6m#섘.t+^Hn@+>R!?s m.Åt;Ի0qJTRi <;'GhW7&e鸔%wsa/9er`UN?ڥ]UD|^ӈ'$a^Og Ƒm7~ٲ*x%VZ :uDxoQR7}S?mvwG iTD0p RLު~l݀vOK0݃Ac؞Ѩ0O6UMV][ ܈ ҀONһe ZnFn8OMetl]vjI; t\mXr^̲j?Eı8ƿR0&f Gp&+a^z61UgCN8ܣ9 EK6%mSǎǺ =64lL}i=TZv 7.-ˁqU6b>/|bhFܻ-_pN;T48&wHە/R9ZPt},[eCEёtկSS_Ar5G,Ї<֐{-h߄(+~npH=z$ぶOrOHFD)ʉAO#;>?vVQڬmzg: ĉiUPgﵱ *U[lN888sַVFD;E5[dӧպovxVbZ L`C+!u"h 1!<w>M[,e Czt(` #MipnԐ{ m.Sk?kV@L&^8<`/v~ r} Lm3 Feqs$9IzZNzu֩Ni`|=_MWo\-?Y%啠3~(^CX![{ׯƃ*A!1=Bw 9Y,H} (Q>BQ  %0qʊ0}M=Ғݑ:ş_"*0H z ?2̠ٻ?i'%1%^RQ=g,~nuiً8APAt:CQt /.>[8/O R|8=~Pz^׀B#{$Ztu8ێoj.x:_{R: Hɫ5xq?'Qy [M. IDATI1+<=c> rs^=3klàz@>Q-Ln<&JT`t䣙)_#(ѧ(2!B:"tX+Ҋz$bT*ujYt\W"j`/a3P{RJfznz:#ۆ{q)HQhhYzXfm-Xq0s>u G&]Bzfg)b*›]ۉpч ~ϵ 퀠g@n'P\CKKPk!mp(+8zoҬfo?pEO7'_ڷm rj'RhАmXV~Jt$7X:',[8@VpiClYyIN`B9yΨO-z֊pz tf_}ǮNg\Qя$Rߜ! %wPiKm|OKHA^C6-IF?=cE6ZpVaG|]C)Krh%\s$\/JP>.63SA/*R \qEjdm Ap7vCdy6l[hROV14e8б:c20QqFʒs3*4שrNe5+5ghzgڰQE^/ M_7>C !9 ׇo?[5ǒa6{z|2.X/mn~6pbvuBsU60scG :sJ.*\ۉڐASM^m ~OD,ف?jEKjD4o ,B[[C)K.9"':w2< \uAМ;m|ϙUʹr8¹R0ppkCtT8IG7,kPՐNzr8A&YFaRvc0sv;-G+ ݕ\۰|a{=K8@6ڴ6"kr3큕+WbIe{}d# {֮zt霊tt d0y+'.li`~rŏuq sfМ;m\[%n-ujYME|{2k&K^sT C7yC'10sфkj#aPچ0qZ+v{=l~*~ɍBo,Xy˳^Oҧ{ <5;IGŤl_t\ B| CE׌G!㳆a]m:DGcY`cMsDtD'c̒Zyt6Ͱq5M37?+cZ8Z˩T2)c^pIt}т/7\7i'Թv [H%z<iӦC3is1l<oKxZ%[O>S%τӒU$'qqL*9h'jTFN[xxxx<˟["ч682He`W֍ ccZJ3Od^r]NzډQjٍϝR;%eR.3 5++ʕ >z$I*Z]w$gnW|9uDxovxMHf(D 1A: ꡅWB>7FI`cчQO )̓M5&xN.;QUt'9E_1_/5+!ɶ>B3k6 moÄ<>>[O3}Ǚrhį6 g ng6fj*#ᒓ-_5F V_s3!=B ztUt%+g:,-A^0RkCBN 肣|};҃(-ڱx^1ux g~ aT* A/VA2y+R4\LDc7b[ Hv6[M/,[IЀyb-{P~!yX|ނW_lB~ұ`6-(@M}_ lۊ)XJvA^ޤ"TS0X79&Y&aF ah!09''=obHۤM H]dJ܁iyӰjyvMx7M;8ym@d6, ;AfԟiAnٽ>HǦ[0;i3xM<@!(J[#|h$Mw}tAYַW^]fReULl5-WoP@xVMHA )xPf}?&C'}U8z4܅(9}~-Sf{uxydt=gbR{7!ȼ(e#'c.x1gjTVF~,!kR !}h5őJc/oAj*9Kkތc)aEu9(^_>Uwڡ/Qjd$2g,=fb9qӚGJCC M]#1g(}y>+$Ó)" XHׇ'6h. #Ʈh++nTt4QYGMZV+x !|nKx0]wyC`/x*̿/K>ha;Yaӟ9>uNݻ"_g%bXe! C&u^Tٽks}h60Q)"YJqaLȗ-S\[Xn;qe/fo/W7ߖGjOFOW 29k >dcV8Mz8duӨQoG'Ȗ5ZFZ[_=祳<p3|O="yScG wfnRT߬Ζ0{4AW?r;% TgNaUЏl@b·@M7` Y%Sn9yHb+, )0X6DN]3 7pt":Ru6ĎG.J3%5.PݫkP`tÄ$(aBLxejEai*Ϸpj ?TQqI5쥯ʹ2at[orX[Pgn<;{M"x2cɴ\UIVn=D p5`@bgYce"x ]wHp[h=38iu RvYLHA7ɎR+B 0{2ahxM.iNlHmTCr7t>LHNmEpu5SS GU( `A"`rび_VH8wDNѩc:22bNwDR:=aZ4紆%lGBh.s=Osބsڈ3m%ߴH5?gY=2z}IJ )̇S{R+|^xiPO"0D-ar!Hwtdx$N1I 1Z i=̕%v3 )U՟84'R  #1SӰӛTiiӞ(gV^ՁbOp~쩽93B0>{ jHM-ݺM@3mk0|ݶo::XVj?̎ )ĄSqIEIL<_~m4%@<.~s|ҧW|\W,%%hsv٭QGԂw hK &`KftNx:xNc | 2 8vKe[LHe Z6.} .e6 =nUہpyW܂kZg(ڞrC[ }0χNqww7`FQOrpJŹ )'ۇc-i-Uj@ QǎzE S ^P4E9j?} -T Lwm4/xl(AS4U`yj<"'MHA5`!CED\GHJNoA2ӎ0w4aB5lmXK wvyr B+-tbsqל~x2BeAFE5[̄|܆ޖ;Ԑ~[x<{QԝI2qCm+4x Mu! OZ #Ρ6-Ё 2dL TvByc&`OUlCyv(^nv*0 6bǐ0plQ#{bU]4Xa 섵3i|;Fim^_}e6>4cX&u),[Xu=}V7_{LFR[Rq`ؿ뗥cWe9V[մf8[X #]Ts\692C'DF)u|?7ɲ۸ݤDaMC_. eX^isq}&5=`)yTU)`6!|؇W0󡍨VL1(.d3cq=jOᡍɰԆ$8K)>Ex2z $юP@9ѣ'bܟQuxdvE_ٸh_z?'.EN8%̑nGj63\p:qB33p9s7" Ø{ 9+1VҜ{C7~cml;FzW3T$ʎs.ܒM_/`uSyZ5X5nX-?~oHQP|qq,C阰&}7;I=!fE/n%څ&FuOujv\Vr)OC>%.UՉw0F}]oAna}Ueq0zs>!jE[1PS7 L8knH2Ya uTdJ[5SǠQS2nŸl۸ TnYEOśN>2L<߶hARmzܙMTaX=^=]iYc)|]&-^nώ2.a}a@49Qft=6tqCXNa얒0f.,ۆs⭮?.>jd%zjǘ4;X1#i%!FW-\աS[4mz-3=1OBK96P9'^WyL OǫULK׼XsI&`$FBY!h7Fe!;SՒL-_F9!T5$cl=tf.RvR7]3ATd̰R/la2A>uIU1Q&9GWmNź*4$*S8.ސ_zC w).HF=xuR0B vLA*]Q-+)mR׍8?!,9噧L+L9F i+޺s.,zYs㒄y,|\dT^hRY v.TQ/aNiD$,WuJNMJ.:UC-|^E[;W1@CO}Y%P.wCg xP0Vubc( abi4 :C˼[*8"'sY~ys7j$vTن^v.Ӝ-YR.3 -@|LR6=ר| 5 hf>oぶm8XrVsRP)sf$;F3&o=pDŽN+<O[lA\\huǎg/q/x1)8Zr$h|?:&'=vٙmqU^::Doۏ=]lhll=/" $HILĚ`l*Ԃ<DD% >hER+}h+,/ԖDZ%>BK &B"d,d{wvg޻M89sΙs/ܙ{-YY@Y@Y@Y Tϗ.9Z { 5pN*nߓ1?=rYȉ\3*!%%+0U* Zj9CKܯ6_U1<*mB!>adfEhZ_?A)2K.hį4yw<T=]Px}vrVt>[d폯OgC ':g< IDATҎO,ќRܳ`RQ,`E[ z[J{e >_!ًJlt7U{ϹӶsGthЈ5-9߹|q[\ZS sFwOAL;"gVe2Lxk=IvB\yE9C FDEdWVg_g߯V-p]Bt7,c(CyKzG} ^tg_)+l| )xfc]j{5zJB?;7 K^qP5? 8!G?_Jl*) \Pxwﱼ)f!3}2 -=J/Ygo>&˫d)~[PgtsvaZ ԞF*C݅D8֢:Y| c!%Sb8=Sƣr'5W6S_Ԅ=FՕW񂮔7lcl8^d1plq^O٘Z0z3c~QuȤL|k6oC\ c-şN=^*ދ\8rx"FRd-?h>Pyiq\`FT\~%s4>#.SUw7pVɣ'ij=>7]rNJM{ft@fxt"Kc!jɉz(ƛʔk}l,R&?e0dGYreÎG~dӠ!iG&nACF2e Q󥷞i!M|Ow3_z{l|d ?ecB<~!$4%MČ4Vr>~ I}V>Ac0e4:t8{\z[y]{7́o,S0PeNgIVr^ޅ;IH,(ӜYL3&FGnl[mҨ7kFۿÓtU^mԞv!YZ ;C2!i-~HOzW14hjLسX lk<b Yd++@ us?ܧ1qqm.F&oK4D (??#vdNU!m8BQ٣t#'_cB[q6֡v2+/~. 7&IH1CclC9|ZI1&D.)߈;z (]/G⚛Q3y @uaMԵhھGaXPY[Jk}ReϷv]zљV3|u4[}HY"y> K 5R 8X亐scyti& CJ;?=s[Zb 2^~n "/V@`09.ܼ(pxzkv8Ar#l\xl8=^)>rX1Q ce~<дq YO 7vR)+GF83ǫ:i wX21ay`s~f@e+B~j=niŎ59X9q,~V"֗]ΞyS gⴾ3fUHwݍ0k&\ B'{ʰ4sOձu+,~թSƆ'1&e L7Z)N܋D@. (<_o// ;A .\>nRB]X5ÿVcBBtHXT30TdbJc|d}at7Z%{D.6/֯GN EBQw0<i:X 9>)G sd|_>RzjtڼGl 0A.ɘ(yh$hK!C 0w^W5˰+z]qk6@,ɏGEk!O}~0Utd|F?g4S JUg.%MeY03O )2V5kC Z/y4XP ^4DtI ’$q5ACA]x~x|+ XDz) rtIni> [sOòbqJCĽ@|w|.2XË%_=NE]=_,o4٦J(aI)orOWœ_o+%{<_~2L0,}N| ~YsL4k^ץ %=#雺ۿdJڅpK( (  (<_=UoktBHιiB^ɼ\$ZC))_#h$#9;nH@"N(GOZ]1f(Wj~)Յͯ~Θr߯i’KGkW|% ' OUAL^( W 0:(`o5rA"`{C~ K_c'h;)w`{#/#in7~e׾u%i=@#Ql;˿ 3xymex8y)gnt=;.Fm@4|cnd*) (  (<;_i o2_'RpХC5Hd;R&tK{ߔ+Oɑp1Nzm|?s wAP1]b{, fh:u8 w(rC1~ ]1x/E~MzGpS#=&.e~)iQ,vYy;mO bR RO>?r}$j9~=r)<߹vZ)pD~)?:/cJw v<^l\N|rO~Ň[|JF{XTEG@}|Xw4y{Γo|zr᲌5:CR! Y )pw'ya^Lۺ䔺+Frxzo$nFxO|S$8^C dt w>݂Dl.MwS) a+cWf/}mCK˩Oo/cOdz8YEPU8Lpnts8;&ѵ1mBd 8ǻ^lcg ^TEY@Y {ϗ}IjW< ZW5h3A%4QtG7,k['2 'HCi p ^|cϼ +ΖOh?9| g +wNE[NI+oo, \p5ݮAEPlVNpph~-Vz:_o;(Cb1V#Ng.F]3L4?R;`RV$eðcas%|sdR|}r. /x8poE֧-} ֬MdE  O$4qzrh;=T3aKPt6D_Mx;CV/sûۼt71&'O݌GyR ^Y?r":,~xq lLp|^smB89jNox+4'.|}j15 ϸޚh|u?Ȣ(֎G~?O-p<(ҁ;XGx#x$*/+fi4ʻ&AG7lẤx u!\üi$R5 GcaZ1( nǷms.n (<_}7У(;^1e=eo Lyk_CW#W[`˖6\-d*ƺpiTYY@Y@Y@Yb820p LHG(.9N>ǪҡSbf|6.OL״{/yj,>>?FL) ( ( ( dܶsO4:Q3+h+=U;C !??7p_o&V^B :[md͜Ȇ~FY(JVO+[KC+ݽu&ԓ{(eg,e(TB9}4pIAi,cGn 1yiRzQĺU9h2jVeMT]i– `ug~] ^ ay(dMo|V3-gz979Oӷ|4M. ÿL|:5UJ=ڼlO>)LvIi@6GO2:3!xڰm~ ȍ{g`).ŭF]{?m^Fjt{w| V t㔇Ė?S- rG ePeO!BXǧ8f?V91}Avʏ\A1D2w/xC1ET>P+sSdEgyy}UmgvF71;j_-G9jv֋7i_f;~S_I90g!VoBtA/Ζױ%M(j  {[ j >˜ވ9Y.]Sow#{[cuZٴshU Ay񰣑=gh`ݎ-yXu oE@u0C|lمeybgu(K~8Q7'/YY !T9ZjmY 5n-u:S.6b -PF*a" {la{ر]+Qe.yz)nByn<7VMVA UE;7-D᪭ش8Gӟpn%],} *W,@rHIv3Ξ%gǗcUeP&wDκey/A<`AzuAU.o[[I j0BonEC ,=/tنk]8T4r'U<Źڒ>jlKsDEMÎ6*-ECk%XgYE#-o&zWSE398 IDATktu)hvΈḓhn6vEBvQY1˚n!ǎVb~nn\ U\>_nxPp}'[X A!&ǒ q ͘ iA b7f`$uށNyzh0 %1xC;-x\n1W&z6J/8P@t,ޱ 6T6əGK Wgڵ^_&U 湕ݴpb{I*n\jh^,1J*#uv͐mZQRxKO@⟞ fεQ2e놿IR.l*߂1^N(J|#ǧ٢DkO Ɂ7ҐyhMr0;9w#z!:Iے6(_dv/%(Eq| Ó)d횄j#+m[;6*'J*n ȝ+֯DQ~/+d)Dj t R)S ~"Ԍn8v4}~%h~asI<Vb$M\h~8hH{yF6ؐ::~K+\w Ns9nLL/\O\˫Yja 9[t)<;ن|dXVw]MWkqGxr FF7CU;:su{ q+%~b-7#ܔXS4(Z$wͽj'ʻQp4VN!jv}&mGLh.~}\Y8sl.u %ܭ,pYC΢nRxtq;8E.Z۴خ-"<`&'qqu"&'ڌ& IY^mm6j56Uτͧ/iLI k۾<&IK*1c #u:q4:=F)cMn]KinoEus?mQ%^UxWL^mciAQ,dƜ#Ӯ]/kφvњl7a˭XqW]9F+=ባO6[u{kkcihmME? ј16 gۑ9>̀Xӌm}[4[c`9/Obbb)~n 8[=;o7Hjۯ*?Rt%^ LLzEFpL$D>Q#b 5?Ej X|26aڸ$~xz"'b)Ս#a*=^;MGc aI%b-+&`J"o]6/@#KWFφ)BzDL"~& ,}6 uz9VzxZa>v`yܵܿ4#Y[e1ֵpʹ;EOeĖ7ڰy4'iǧ$?XA2)IÁ ĎlEwolӐdB]9;mqn,s@0Af?n",O?r jL><}4yb?w˟=3馛a)  =|w;"qw!+뻪1G;]xi{\$z7QўEg)&~?:MN;0oZSHgNj‰χȍy{Uظzcc,=䴱I/,O=~XrBZ䄻r|oF&Zd^lj?̋ }wK67HUr창BҚ>gPKg= RPү-/$_{ro~{?'.O)u)ݤ@h҂f]T kիb%/͔3ME٘W.V5Vf+]z Z>A4de~{ĉgFVnBB.RrzyvD%#96p^:ÍdE+vFDt1L:`d`~#"e UL3X EN\3̎^yץ_+R{2v2AXsëYQf*v2/w&2{\2w.r7$e╙gurI)*P^ϞJ?6!iy;*nz$B> PY3_y1}T4F]=u>1* 3X-[ |F?#"gM&XgZP)<0X;&ʂXt+yx0byEˎh&]>&u ݘe>A8eaMLn^)6*( ( ( \P-;Zv ZxC7odc, zn 7@c\'ebf<_Gω-/W+^;_ÎV8[v~ zubT'F EY4%)H7kx ,.ΖB3jKwf\N؜^AfZ15-JFcIvMF8Q1Ԫy0B^h+ϓP~fRyQ6E J|$F7keN%jsԅ{Wy#[LP|4\2- y/@UJ#ݟU@(HJ:4`-_Vi >tbr.pNrCz` 6gBqeqڰؽp( 'ea VU^) {#%,X-[ViJ:ss& 7j`^dZr%8B BVa3$] zez6 Y>iPIۑ˱}tdoocl_2ŒڢuXp&حa9MݮmCǯI'PXBrN$#v6b2)fS_Yǰmϒlc4.:_Ę*%&+:g+:rgyz /yC 24`e7 ڃۊIE0: "5;ň3@ZA9Vy.*rMη?(V`d!ĎJ0 uV- ԫZ[뱠t'#" P\ˎ`f ReO:7H3xq>W|榽//u4>dC CCƦЇB^**հYaD|DbzT=5ǵlҌb,ߐsGI)β\^+x~׎G;&P~N%e& >'4'j++[Zu";VѩB^1X|tb˫Z) ]5;&ЅQCt k|9HkHU*~o%Gak1[A;IDW?bX/'_X>#?XB]G6.uz. xn< I0GBqvl=.+Mh^Bud W71"Ypy]9,g+?plP}K!#3Vs- }6+^GZ%3^!ʝX ħ3"@e>3}~i\HAKta(e/ƒM[ _yQhª,kun79&gD6WA<H0GOCz/-<"QC1j 9ahה1;7uXSu-9޴}!&G Dn)5So@G>[++i brhΐnj]G"[照kph$~0))o˹P 0ʆ2=6V|^zS'PY6|%_5]24ӥ/51z,mOSfFF8B3 &#3%٘mK$xƫl!3xύxG ѳy-\XAA ꐂdW >N{=nUƾ|/:s}C#ܺte}{# K(8=IHgҮ&mLL CN$AE腴.MIo0sԡ,Y/Wc4W}XW yu$iv80 {ԕKʥb$XA<d0.󋱼P0J@HW|+c-y Θ"L3M粖|%qdeݲzy >y΃ֺ9.?͡|tk:yݹ F.OK!J>mLɝctq +0. f,#Fe>bV2T/|V֦zunQϋ6E?2pk[ %D٘W,+Vy+M+_4c/HA OhȡD'`$,!^f/Z^ЇsSV.缂4΍ev‚9׭~n㲖Bu0s972o˼C ŠJH]Bg/B[Ws'ъ>Wf9i.֙#ryU+{ïiɨXI_EޓjWPPPP~FE:6.ՙT f+;1偊7J^UVAK1+ ( ( W \%YY p]`oJQ\fƺ<*HMv~YiGK+m:RmM样#_:SS;()w[iG/yzkPz+͟},xB:`{mr]hO}ܮ /Lh=gK5d!," v{u4mGND Qz-Ȣ8P tϢ64z/",DDݴV)Lb"c+-8$!&&([6ǿ[0!TT) \0GI\tbb`Dq]Hs)(C :!/ 9{{i{uv_E+ITiR`zɘ mGfZٮvT?yi6H}5KqlrZZC*H7/wH1)[PmK1e(wH^2 ?,rflCN](2yO%e~h1$c;&L#||ujՉ<!/DYY]A z n=):Pf iJ+oSe(@_y+ê۱:[H-2eNEEpkU,A6 ej1Vm42LM>qq+:ɗ`B ܄ m"( ZJ ={#J@u4 3yprR2+'r\}34#1ndܒIRNLӪ尕=Lck'j(ܦmzLM-&!d۹ڵlD s&)M.F>,s,e0U]Y"1?ӓB^c!%T)`jho* R:liyBJ$; >/Ei a/jw3(@_yrQ8 }(lDbcon a%`d:ǐmoC-ͅt6 ;x„ff:AN,ǁ_H0r7Z*Gq8L0#M ɖ%dqs{5trJv]8>]MQ<kA7S-2湨*%8ض߳;t! _4iz,ڱ#̇| )&,<9n*/.u)T))~y (8t;j )ȫ$,)H^q!-E` qrGҕD_$?/[ım8 IDATWO/ UMQXQޥWX/#iDHA|aG tiwA&(XT4Z7Fy^btf<=NTꀒ5Hb2igNK.h}7S\68 σ]%8C^2qoÇ48K)Nd|.}|I$,+<|[/"o뾅3Eb(ۙi%t,E:;&۰ez:i|ҺΫ* ; #rUYFgx}| "h"')hB.eHA N8ѣ%EqGh!+ASx%Z_ԥtt`j,}3uBκ0cJ\4B1yywD잎o=1Bs y'֕=A*wC놕H]((kZ=8λ|VFEh"B6ʾ׳=a<ؕ)ax~ۡ註m-Ҡ EKDw0c¼*Λ9MŘIr:npӫ#=0E'9k%},pY̧0M Y6C>Nz㩲 1c0fg/f#kEWBޕ>3buD՟5GN 5xՃ[㋫QI FZqSjy<ݸϗ]}FZf&2_z*${=͢E E8MXYTN7Gј!מ]v\yٚmۊ5[]o'vd6p=(RK[9[uQc UW`a)bL۬xe!kxO[+wb5Έ x)HAar+@oK8upL^~kLO6i͠y{[]fс;L3ḐCV:mՕ%*Q{6Qu3h\1Z oT}ӵukϯiۮ)&b$++j~T|aQM>Vgis1{Az? eZD:]oX+K(:616_Z%-㔩Objdp[X P3u<Gϸ`s,ЮɁJzP2VlxW㍸6Z,pZ Ob[G)a1g4΍et.3,~4A{ M  A&"[yްPw&t }R`ߴ@t"7ȆކVZ%%+w!+ o(i0ߣ^|"zM*aktBNx]߉Bue/Ȣ=׏u-%yTQY @xI'h` &@DtHn}Ծܱ$h'$41#9! ,!L}z+ElJp( 0=Ƽki֥=r>|A{W޻]37 2ŐYYBGi6D.|.8X6fQnYg;vXV ݯY-Bqa`g9W)ǪRI &剚 /DH(LjEy~,Ut~PЀhQѓaȁ(M8K9l`(T40o (]Q(pH=ϵ7,&0rOz1=B- 쓼9-J+&!*F EY4W%䃻FV$g)w GrGRZ:2Ӱ.ۍii6Fmn;Z"h"')hB.啯 tE܁N-Z<KkϋGfQ/#cNpp"f:\qv4(*4G38Fo%l-dmAHNCgǮ QOi {EY0)L?Yl&o[kՉXE&r ytc]q[IA !?#HA~Ksk⍊nGk?.9leê^2 Oe<㳂 tAF e;k+s "ƍ5n?WnٖUЀU@,SBmV2KfB'7cf1g4926X6B :o{3//u9W2]wR E Rt"d#~ag '"6\]"?H'!m? tpd hFՕ.@HA~$t΍ev.ʜsYK^!A 2J#5 RČ&RPl!Q҆#6\s4s LJ')mL I 58XьzTW}2_ P=Z@#]fKDޣ@΅5ki1~ RЯyYcTQ΍6E?2pP$~d@&bXeeeeoC?_O^泒y|ʡZ:H#3`_dDrOF``5}8_V.vfuk )*Ko= 9J&G6bs;AVFR`91)k?ψyڲ3:TyuvƝrDYn%/.+H R[8`H]cjߋ`9J a.*HAIRI}UYs9WLlP6.OLW4)x!B Z䴫$:"+ڊu MjA)hէD"VԴ|c` {_ ) jd|(<&h\e\A ^xbP_ ]X8=L%b&] Ďw&7RGKH{cΒݨog [ [b6qSzv<\MQCk%]]A2<\;ISQV_ٽr}y3 fCLl)HZَA V-)x;MM`;mKrNqxKŬdܵh~ao;:\o,2~kl/5tm9\ 3Ж"7lt}UPYǰm/l*c4.:_Ę*%&+:g+躼U{n𫡡U7!&c:MʜǞ W4'K]tG]Ob,T5| {pm/Uj_֜~tXJ~Q[ B8ZRɲ-o)8Wp\9:JdЖtQesawD}X/3m5*h44#)W| q5^D2G@Ãb5 K6c /V7*0F[_pk?Hxp~32Il^P()4[7ܠʕlaL?+^_Lޒ_vi.f9;nvQfH@ciyLӏ9-ӾOa_ipaǏ:N<3馛a)  =x,>nsPPXtDi~a|aLa AأmD%xlv6 /vZG"mf{[TFp [') \8ϐd1Jc@~S.` @ ?HAy:Ӭ3LF3k)HA\b"=%$y;R02: M@7ͪEY@Y# Uns7Tm& Rd{MS6]`짤ΧS<Wt\pk63QO R&)+)!ee2_&򐌒:^`dq,Fyc+ ( ( ( ( Y0kc_$##f_PP|0V6.d(/XV=H1( ( ( W CeY<>P9@i3}[>c9s"3 R!Pm_ #rى,kv6*7{_Eޓ|P RlU$&'"&" [9w?m0' 1[H_ssMA لJEou6.ՙT Nucy,uAE)lģPU۽ކuM ؾX{^SKEA zJXgD]/lʂOXX`oJQ\fƺovʭYՉrSݦO6t4Q8Ikcf.^@ : oc;ǎ5xUĉ %T,pN, s!@(mr]li R:viyJ$.8( ݴ_xx"-9Vy.*r4zs@<`?ZS`#a#*cɖHT;5M #1h7Σ$A>묠@ F"m4P;|P6[Wg')(,resbdԛ+-bb`Dq]sXr)H (fOAAz,*L6\xON# 1=D fvږx/!O K4HYiLv4Bȑ(Y&uhF*R<f>BN2yMBދ?mgyPS`jUY^*HA  ؔtɌFS%I?_4Y W>f Ƈoa3@A jfPBe+~J>K.qc|cn,/ RPb$\pa1=T-)h_KS/d1+MʕΉ9wbU7Yi0]9;mq.KAg@m2\ |IA i FCI2BICB^|@J¬,Vt6[Nַ#>] h(#`W6PY u@͎X/7޵gCI Ɛs2,x_7nBvG0I͎Yh()uclZٽsޖX$e%ftWk+w}(Xm4Kao4_i() d?f~q֧_NszWJ %Vʜ~>*^Je[SkJ z).$ݴLbqi1KZNPK Sn7 %aԂ7f|ɸrZL _J %3 ,͜8 IDATk*;CfW,;o;Od^L3uYO=m;)Hp b()X4N 8C;gAY? ]N-u'v`;Qwe>k>`^s܁J &H@dc1'/ <N:pmV;[g +d$c_HNpv2Q< NCIUԅFPo#ZR%w_l뽏J 0㱤`IOmEܸqT&ӮqGU;j'lts+d+ӵQcBIA ".1OǹlO;g4s.쌷:ޮ|CIc`ljپ}w-k׮PiZRPVH}we UzNٝy55qwPR0| e1>}XV'N4{7SgM4!d֎qe_/wk/͚^{3wWf-F'N}i`q2ާ Z-6Аd cSY̲<&@w2k)KЁ<ROl!J VQ):MqUR0l v#e+F8.)򌻱-i_AQIj}HI;iWV+@Hfh!^BI %Q%gYAK҂.yPߦ| n?LCIAOʎ1e؎璂Q }]@A3|O&/b  8ICL?5 %NUaCI322op k,!WFh>߄?_fҞR;|~q>PR065Mj%4󐁐2 ~H/uq!ؔ_}}Iק]@@@@@Se)iswid};e3/[()WBP@@ˇ_ԑ$7MLНfuN=V%cSv]"O'#/ٱڝkeok|hfO|>lsB(gYbDT'~#ِcȋ[4[ɑɴHCBԂ&mܐoʞ qT1O4&,?u()`,nWSF!Y"hc"~wU]ҢOw&^ڭrVIɄ9_øu=JOmy`m[e siwFJqj\,ԧ +3o7ƜR7/>+Ii36.,^?tULH̻ߐZEiHcg~:Έe+~m o¢hNͥ䅲q+Ԫ;mN!!B\L9]r_;1 v`;Qwe>'><7WdFHԥc*&릏mo;ɭï$ۋeʨ5/-ۗMA;Ȧòwd71bp{z~̝+޹Lz (c"55OUo^)se\ZEeT ;sJ6e,V#v5=J5;(3dÎ'>eRS̝4ܳlj٢O {>b +eoMaUb"SOӗ b\JˎMK]cOM;dͼ2ec'U@CBZ\LJ\}<L}ִ)nvbwmBFsc BOHƁm".2DjصF Ȩ+GR:X>Mǔ_'{~"RU.xzٲCC۶r& o+F]+2=+X;;QH}:w;i=:JYIY2^= 'f}SW" NMKr@vY$Ktv=?%b6}`ww=-$f*/&C&?2rU)#!=ˤzyQOMr䐁3@{_`.+__ekQ_y[RVZh!X%gn=4{|`T3ݺ%]+TAܴVFx0O֭ gJzmdY0iK&x(w>6MxI:%lZq*&ߓO ,ͩr)nK^EߕnΊvVv m"3_uH D|bq;K"S͔52I'6ZEsd΢k[eZˤۃden= q* 82⏋ISK8 l7Ӡq0OPRsK ϹɊ!cE)O,F7WwC}Oԓ3dt7؊2p|2FW΃:Sn9aQ][z~Jf_'u*sǎYJh#S/V˔h. +~Jd=!eN_J^gLA˦2}ٲwu~v:il Ό22p2PyZV˾0>-tԓw)@:6ʠبRKCIA[>PKU Ɛ2pD@b2Brx*lXZjNqs]_bGh()I+V شeAݼyi*VI{uoS S,5 V8u­1oץרթrXFM'0! wHq|T Y&z6sgGuv'XL}49eG&H6Ȍ3Jϑ-{wTl]wo1A22P  :To oa tlq'|1QIgmաWω9r֕sGI aWC X`<@iSXc&>.2C&,o6 7 $RP-O %NbU]TB; w~%ś={>\x~'?#|.K<+nuON0; dtx aؠք}`#-T3B7u'Y;7޵x?UL~ _/2|(َBIF$/ ,^R,x| [-~l"G1B;INfeX[[F%3tE-SJ56!>d d 2ʕ-A:ߪh7~XáLvO=P$]?W7|ŪF|q(NqQs{DJޭ\vbn%hZFol=n]&7Kk%sLVqYpZtYɲzZ}Hwˢu(LEKXL[F]Uo_%c0_čKHkOZO0M[ҏbZK6ABID,EEEbU0z/@w߾}EΝ;e˖M)Q746Kd\9cS&4NEŋi#Ǝ}tyo{qejxxY:u\ml޹^^1F\ ak"@j{2_F &ʔ>.vmHoomkSE`T~yc\umlX:Kf mL6HZ߾I%'7-ܨ.Zvxk K%meӎm2|+:r(2p"fK`ieP.(@ {=-w#޶mƦʤ߂a~>Z.7\qe;(y2qVo +d Ċ8SUϮ3Cׇ/Pw=w^fJŌ␮oI׾ղp"yɸD ybhA+VȢ!=볒Vg?6vȟTNڭ/HTʴK)x ިWic0$M]/Qhl{,պS_){ꩧ֭[XiFZ6gy6ܜջwoʤ% i@~gMs߬;UG;QˣW)_[R00 |EkX륓ȑ7K3~7NN~ R1R|vԷdKEsջD6ukڈko:|ȑ.Xj9U)IqSeKw{'Km[ ӕ{t{CT"rͭE뷇DI_ WȸKCsS_% Ԟ5aI 22p,fھ}4/,{7aoNsύ(MԈ?s\>BNdkQ]Ym yѕ:{z+zH.Sɔeˆer*\qge%}o8ݚXF{R{|c)ׯA.}<]xirWHgLvlܸKܷ^xLEsԎDI?JBI\.dV#:D+]^j ۷\qri5u?3B| mA&OS[R0SVm]-gKAdRi2rLvxP5Zjq◤נ˥b:kȰaL V B2UnNY`xkkVśdhW}t\ .ӷ,I=IqrrgTD:v2 ۉ~=%D%߻N22˚(g\jJE%m)rVcY=e*QTE%n" 3aZI?WF/LKҒ~%~D%-Q/u@$ټ96   36l=䤓N↪-j&?.&vLŧxc)*2yPGi@-##dA_"1SRP禫DI"kQ9<=J;R[^:EZRu~ Л|u\̞Dqktsh@O__O>MM0  \(R-X@-ufNR5|MTI[=y;It/ŋ-)X }8:ٱv<2?;"dChٶ|h ݖ-[駟_i\Cd}@JBŪLlKBw鼝<^J {1?)b s6AeDъ^= pd"MV?Ot=PTP/J<ve_km `bwwƍwrAK nzW#7n/FHcU?(K#ِuOd?ʤuމb蟑VdȜէoIT<9* g*~ 2?9!{!~l"Ge?B;INfeX[[F߮p:Nqĕ>x•FVy,Jz2TMXU'c%qCF9uթPvS2]yQ˲uY] f&Ȫd¸|՛Jq:㤴Y?m몟-*{jф~N\[Fㆤ^%.7/ҧsa?ADT #eve|P Wo]*q8d%ƑrƎcE賟L^HdLKZp_RWp&{ $d dz}^#<"-x@~… _Bt\ie?q8)N-. Nszl l_X%iK'%N]A5RSbPaSm5rj\JZ`u,ްC]0_XBYm~ JIw~cFsgȆOu}Ӥjy恹2s~=dbۥF y3sdʂ+a9SwiH-c>2I˴EK!Zk)W"=.,&^$ֽ&U<{,֢ӗm,c掔oׅdoM6-!w(<7vLEy٩222[?D-Po/͞ W$aPן2i ! k`INrvХS7iϊQwJ ;K,0N\7o׹c'GMFJ]=~b$DߵR2gyxz鳫:vҙUtn=ɪ2vQ4*n$iKUT"A݅=cq2% #ttoeu.ݦbT)hC-!R﮲ˇmYr館UKKF 楾O?!믅+W܇n c=-: aGCfouerj|0+ہߕx/Vx`wF(=7md<-Qbp f:ٺ,I[:,SN[RM{ IDAT+~v lj[K/Zc@]jK̾|@̠crh 9ji~5JtG Ⱥ cGX-U^a ӖlM'!ׁS;qM.KORAXdƷdu$e=J@+I52 eR8L}4ͺSu'jWqo|Kʙ:}WbvVv m"3_>EޕUUڮdz$T)u['~A.].{e-'ҺlݞV^0](Yi~E[E*}P[7e}s#B5=nMͺhEү%+ev*`yk˒{gˢk}ASu d'+  ,;˵Y/6o]J u -)8}<%Ƿۓm3I\L ֱn@3,Sy>N) }Ƀs+dtifn{o!݊'&+{WL7WT[+SD.7KAlX--xҥ(׬IklZ.ӿ6YTtϓ+Q[e]52pW&ZK4),F-A,C 83P;aP:~[|HJ榥ujezzrR>}qRJ꺴 uْUol=yFϥ޽ni?`zT 83gqFTBw=cC@J R!. J48y*x/tI-oSuJ>jJ봙9 Yy%fHk~+I\t𩻎}Aԍ\5xxS~һ_p/gl/˨[ψ6 x3,CB0>u xƑZ].e|ZLk'e;vj&MLq6EjIȄ[ u`nЫ)d*]R?5*.wHg6kyCBN a 6eGw7GEN7l'OFQ\RQ;4uܮcWT!!!N;0NhgiƆ\-dM:RqL}!!!!!f)qZL/>?ߕ/ 2鬍:c9PR0t琁#>E~ѾnO/s) x \||7I{KxxqyOVO N?vg׍{ݏ02@EeŊ;Oڦ~3#Z>.oC>nL= Lvb%?!R9KozN>b#FIf190Z $W`读:[PZLXU vħsi|<~52ss9e.g|JB 82i`.:+RCfAÐ`Lk2j 4Y>G+EcU#ƀo`^/*&LaerCďЛ5"sVղz!}|y^?JO.~?d<UTHKޡe&^YZ}Ky窻dEүrBll|ᲅLr'bž22aH;vl_ZL,>֖4_w͝ʌԍyqQRLy,82-&lhx/g8o_6U."UU{e+zejl`7Eioݲ\7H&% %%].]I>r D9-'ry鏨xxY:u\ml޹^^1F\ nYpSm6Ȍw^yQ" vh vnyf,~XáLvJq֧ WnGNseFɶB)}UeE 5kuGeݣGOvZ6nIzFكe> }ڮ xe7/w h9D~Wk ?Izuˋ()5<`y<1g+VȢ`O]ׂ:BBBZ,S^ qR ohhܕO_RTNO`ϿA)r`r@-t L%u߯ >nJ\wqA|C>xE1w3:S6uwvqc3a-2 8ХyRg([C~>Z.k'A\l'JL}\ە1_RޞUʳw.@A}I+GE86Y~w쟖 5V Kٍ2/17r9ɦՈ&.3ǍZhk۱v̾wId==LxPlxPO w_MQV¿m(". )@G eR;1O?NÕϚYwvbGlwc>DmIrɴc[t-)*^73˼Wm-)أ ݷz+*1baڭbŜ8>vv] І.j*W"EEȵՕ eQ5ZvX[Sl5N9@OٿDR}uaJ-W>P՝fCBB>m߾,ZX_˖-rqI ߇^<,HEVrngvjq.]|K6 Q >(<@zAnV>jLh'R.Av\p]`~> V^jqX["' |2r`8Ms+9]B+cP77HyI3T^$iwH*'iQCR.8222pe@re'5^f=94D:2ɌOաNN[79)>KIzth\T*(CBB Ӷͥs"tR q? b1 |\>ng ng9qʤqz3X_"-鷡ZCd Ɛc<-)6V^ш;*4 bƂ;1D#;Iqe3R9kph!!!!! 0:n6Qq'C X9(u3weZ@@@@@~X-06|G_;HD fo|]@@@@Ȁ/Gq74]k;ih"9ק}>d d d d d3LxS]ti_w"d};ӹ9d d d d d3@<ve_OS/wfGSnkr@@@@Ȁ/gYZ.Nƕv[}CBBBBr̀3IKӏ2Y\7NNÕr ׇ@CBBBB Ŝ8PcF| 6+]@@@@@Sdc1)qr/$r'8q;ڨL  bkǜ|:ΕGA-f4n;[y |3Pq,xe.O|v#Lq!d d d d d a p6Ypqv\;eo|N\T䐁fCLc٘L~^[c+mԑ SR4d d d d d ~f>x_|7VJ):]~22222m.0zk>%/c|7z[?_A22222@6+&al'M/Nw1lh ,a<x]AZ!ם;Yߎtn?Ah ]WAڃ22222@&ـE\k󍗓PNp'k`2c,u-!!!!!qȄp(S3.iSd;Iϕ=?I^kMNrY˧/ퟦBÇˡCv,XC-[ͥY#skÆ [h3þ&xB㛂ԾXohj?/E$sLMQuK7֥Rn<:y\2)[`BVv%KȖ-[䭷ޒ>hMe˖rꩧJ媫G`ڵ_zymi)YںV>nru}i}Qjtq2)+CS1:ɻ_SuI(y_zPF $]tyrI' 믿.>cYy?^*.D~Ur݄~ݴ[R2 Ո?n L栂p[)u7 'B&^hKHz./|.B*>Q~ԋ2[=oTWOەʩG|׏!!:BLp`_hK2c i׮]괜^vdfs|r0C]w+s\s5>ȃK&+ћ>5BJZӫ_ֽ.ȯ^ƍg W-ltxJ3t2 o2J :"OPtg@hm{{.JKLOka;n_\}G2xfࡃmyϗO?=kxzkܳr5I娅>C[<6Bx|G0&%H, 1>Go۴^vt\gHnS_6 #bkǨ>gSKha\I֟:N1u!ݻu*fݦ-k-|#>%DvG_%'r 6: kf{M:~_zjh}7u;XI9P󂎅!]8p ڰEiQ[n8bՋٗJ^e>ئH:T _myz%/J佗"qT|n_|''ɜI#U!p=+ꚃveOU͋].KE9qR~,Y WOۼقeN2iv;L~Q ;S^tA9N6'KN}GtMQtG4vmOJdßH*&wӵk܁O†w1.-xIf|Yd%cW%_HtRBns~g9Qq\??5 lXM?>z zmWl()z/7>cS%\uV}P;i?!拆S!(r: 7j)gtj_ZkewayOQg'1Mj,}]߫6i?JQy_ʩ_ګ(>$za'xU/UԳ?޿`HO蕿hO[F9nVCL#&N7HNR~\޹Z\[d#O̸|~35RķS7!5n`B|xpZwۇEկ*E/vӱ%QOgY{Hm+dQ%?2U]]Gyyֹ%ex;{~v;N)zKn?OW?Y~E;_'\KW\~?/]ܩ3wѯ|E>&emZCrk!(d k  F7]e]^E8a|OWΩY#K~D7:(n=X>P_}"7/מ#J훿+WfD^[&߾hZox{ hS9.qHz5V/9te'%,!׍hq8.W(>$\||7I{KdԷoX\yKWmچ\TO~;m5⦿7Ϡ;q27ӛeeesK.TF}r|C~]00^Y8A.r߯Yu{WfA8zΩNy䰂O IDAT3p]J~&\^.ѓH5W_-ҹg_ ֬y"6h7@򽞈/>x ڗf ७ʣ/~F8y_ރDZ('{:X_ЦX/Mk'_)w|DreL6=*>"$ qkڃҡ@F~?*Y_ Ŧoe줭$}}:YͯyszS;BA{{;i2F!5J FO_'ȹ~$#>wV˟;y'd\+u-/<0S? Xa_NIrpʯ&^(#9Y{rw _Hcjk c:@xWj%(_j{,wP-Zu,K/nJr/!YwH6\*,{2ywd݋JWl{qs9A=ݯ^7V˧/9 ]mzFB`-9΁޾`Bi`f> %N!bU]f.#OS~dsϊ>pn|+^|0yps}OOtMA(xm,{}[RR\8sn%W߹M:K W\Ȥ\-e-2[Kԛ.Cih]Ib w{{/r )W={)23_M^6zǢ5:\,xP2u;2sdpE~</FjIޙnYr~@Ja:> CsPtԓw)έ@@=(dV}qlYoT[pzxԟLr?}FjxsڀZmc0rr -di3o>y"6L8 }~A,lj+wjFKZenk+EOKY$u5^[Z8b]ej`ꊾJ? #zqy֭_:z6v~/nsf*,;_ztnVBGe P= ߪ5oKȨ!ר1'\MIl qc vbη:B|1i~Y>֖5iN2k zqÖVxՊg Nҩcy޴)3G?Q_"=\ot- .*k'075RQoR*S88QE)TM gXt3r4rp.U;Y)iW5WzɷƕullG$^qWީ?/|U=K"ǍlOeS>F]l'r BqyW^^umwMIKlm= k6^YBL%2UpA8p`TU8(P{5NO0'^/='7]zQn|kX=WU=/qr))Mޕs{f7ԇ{|+onW9嶩hĈ?D-Is8:S :B!O⹂:Ѽ勿CqټN;2өS|cVpO3S&;Sͤ< u)t]|A \#B&ȂwArE,l_O>ylZ}d_#]ONIoZe?w/Sh!G-8ڵK6oެE7E,Z|%_PN;cϞ=`{XY&~;z}p`y^AFFiTB ܹsnR/fR|COL1 cK5T'z-?m {t~˛;Mq8 +䔶Ɉ@BnpnXs;c{t\6)apoSx}¸q37T^=)YlWx1 B5|kXц]/=ECTWwxn}%`f*pµ`zqp++Bΰ $<23Ftr/$r'8q;ڨLGF (߁ 26ŋ⏋I;qgxci_92 9v[y |3Pq,xe.O|v#Lq!d d d d d a p6Ypqv\;eo|N\T䐁fCLc٘L~^[c+mԑ SR4d d d d d lٲtܲ>xXo X9(u3ꠇlB?B WSh}i'>ϗ1hw;A}:z L{17n\c?6;}m\N|+_;b,oFJ;Og#JULtJRitxڙXx~K o |@@@@@ ౫xkc#E7\~YƂĝdW~@Irp8_<}h@@@@@T^^{9061dLLTق/s() c22222Zo +s8#1!tl*VO{V4u;t'gvN<玑Rh@@@ Z~Ӏ^F up]Ƃwqʕٿ:/|/'I!nrh!!!!'p>+^ړi8L1 2|@GMJ.Z8r, iΘ8~БOQMד~mP_ SG"Pڬ~n\OQtwקs(|}:ӹq}>]8>_.tneOG|}:7קK}>Gߥ>_΍ROQtwקs(|}:ӹq}VR`FP&БBOzP*c-Uua2|CK_t;qvaK!n[5 [b\X@FAccO&2dD2(-/d { h?@N|i1hs?N_t&,e|164q4zA>C(eCILh|8>?&vlq K,AGب4'2sJ!!{#|>+wGsv??v~>ܠ2(ehORrbƾRkc|/-'CN2xl@JO9>2}ɓ"mC|]B/|%L}z= z4ʠYJ+8;,}3AFCyӖ3|9 ?qzw#`‡{OPA: }QO'B|_x}Zӄωx?t CO(lԑDٗK'h2tn t3r_tDcGxF` =xa:_SЏFyR 2'-'2)Gl!!@H&[x}M;ep[&6-=)('q֏|F f\(vbN6tUxRD_h?Ƨ(78_~j=sB)7܆%2=w e^ۅ LVG[]C1I-~4`#)p$s;CtA}]A2x44x7is҇oS~F'q,x<~عs m XjBx4t`\6P4R|91RdAkuN"; ?~Vvʜ<%4sKCBdxd90C`e-%>,62:lh1mg%K197FsS6C6&2EcVNXRXxrC=3g͗+gzs_ Wn(1:4}\'OPn F!1>!e?[Ex5eHaDq <|hτ6lU?:z-yU|ow\Exʤ!>Z n.#ڬLލ Od&9?|/͕DZvKy:vw6P!}r1v355ز_vN!eprv;(͆`n1AaGO?hW瘐O9#|1Z'_Ĩ'E w<2i/ d~ :4fu\˕+X瓓 ׋ A Q<|E?il]ȿl吿l?Tx;AF=0~G|)Iѱ)[d0|V1Q aߐn23Kzn!S/9Y(BByR%^#nx-c8tiuA>AQgz6ȓRo"Eg!OJ?PرK0Fv$~hI =c>:4Ph 4M,Np PحL(tqz'9%\~hz a17-2!qXAedz_k.А̀;fy%-O:ƸzKYM)SmTkh1)Ukc8cms`"hFaGly¿#I10y"uۍAvKΜFla,lQc#OJf F,KaGq2LA9&}8PF? z;~QO?uܸ_喹w_?{_kR1d`27beZOx/,usjo\6+3CZN<XF{8IsDl? }>Յl+> "[]?ie ]EVs vFŁ/'B qic_Q2C:ƀgcg_<2}@\+ r\.:ߗW!uչr]txr\9>)͐3VO_1lй~F5C]Cq)), " `H q}QO_P@1ɐ?x4KGOX8[ '%3.?O. ;{NzKi/vJ;uxgчzK/tn/u?XVN va(%zP~ˁ qaC#yBg`mVxї[;:񉌄u}K&0~~<7FcAa#!qc6u|ѩ}P&$ `Ҡ5!6qз~Xis_CK?ʤQ׏2i\eRQ׏2i\eRQ׏2i\eRQ׏2i\eRQ׏2i\eRQ׏2i\eRQ׏2i\eRQ׏2i\eRQ׏2i\eRQ׏2i\eRQ'IC~x͍??lc;l9(dQ?aSqMzžM5R(4||d_ ~D.6!> ؜Y>#{fAL6n@]CAROJ_ȶ3g~i|>0;(<ևKpd 2zUSY[@!Ϧ1L}u]9.zߕG]WweQߕw]~qw8]W_u]9.zߕG]WweQߕw]~qw8]W_u]9.zߕG]WweQן2([;<Gޥ!(ѠCsm'9o|1 Mv"Ї$E`%ß x066vq-.!>8>/{}a}, ק1t6>_X|}:cyOgc,l}>ק1t6>_X|}:cyOgc,l}>ק1t6>_Xӹ1kd>FK4uR:4WNhQŲ7_nԑ0(ӎD0:K]k|+}~5fe胼a][ͼs[IDATG/EƇr=rC<>juD!:ITj8QO9~!>=qyӧG u=7gVSƂӇ )N}t9͓9_Y~Թ1йzW3lyrFg(\8]r&JK9E:Xf2222p2@hmIORO91hԓ&u߮0 (-ߥkEr_y֓yUjܐJ/|Aݿn9g+4b^gNӹ4hNӌ4hNӌ4hNӌ4hNӌ4hNӌ4hNӌ4hNӌ4hNӌ4hNӌ4hNӌ4hM/V^Nìz_:oңyԸ_G/UjrX<И5xUwU"g}ŸدVt]J/u4P04.W5ڳZW_Zwս:_89wOfOuF"C]>]'zZD=kOos5B BtZk'Q}R#IEm^oglyt_+ \>gz]VNO~Gh=54v[M'YxPӵkZ흧Ӡo/wmCǃZjYxww^7O3s:--O>gw۩sx|NC1^ָ1q:?fԣ!!?O`ruNST#loza͜4N [uu>'Z~~{F+GggrL/坦ݟ]ӱjۆ6ɞ+me!!VA7da*ɞO!!NUK!ur>՜:B B= LLOr'^w{͏!!w.r*8D.[A0kь7Ԛ>Ώ2s]wd>K O&V'γ@@@@@@@@@@@@@@< eȨIENDB`testng-testng-6.9.5/pictures/success.png0000755000175000017500000014300612551235562017674 0ustar eugeneeugenePNG  IHDR nb0הNiCCPICC ProfilexYgXͲM%Er$HHZҒsJR ""`D `}>ϝ癞wkzm-8 0fFa9f3Dae`AwEZ#QЛX?6_=E>08gd s0Dxp,p%TZA w=08xd YA+ BP<eAP tBm!4=fE3F0# R2 6acT8.+M< Px3%RFQ(/T(**DUQQci2jEѼhIdGۢIt":]ED36H`T1FoL&SŌc1߱X,3VݏubسFl7v;p8u9 Kǝ]ƍqx  Y  G@dBK](6)((U))=(c(s)))SSnRSPSPR*Bu%<ϏW[#b|~A@-NKDAC} L"8 9:B/aNCKcDADSJsf#-%63m,m!5Ǵttttntttmtt2/0<Rz(QH"wXFF#F_,!&&y&;hRNif0?s.s3.mO +,,kZ?xZ^-٣/s0rq8299sœVqU߸ pr-s3skqrpwq/y4x<%` E Y==*{TԖ˼toޖKmK+HKWKa1Ii,+.K-}"G3Kk[/@T8pLG᧢bE%A%W2IeFe l*$ UEpfOjj~jWoN_M9iM>M7JY--wbھڗ?HYUMCe 3Ox*v7ٟ҈ˈdTgbd`gBmbmRb2k*nj~>`|ԁfBff-+ [XK R˷V2VV.֗ڼs[׳Ϸ>(u0١hXӇҝ&>Й߹Ӆ+떛[7w#2.QK+k[O2Y\B^[gwo޿1"5-!//;(:h$X"8=x:D5tJIhMv85y9HԈ,\M=#. B:4~&A;|"ؓ$4HQ~G%K''MOiOJ=:fVN>yLXqq 3ۙYYY[٤2'Ox *斟Ğ <9WO?w_O~X(_XQDUQ4]lZzF3[%>%:eeekg=Ύk_Ȫq|y7++ UUo_PPW^UbZھ:KrNZH^9ܘ"_u:lsMڕBnodބn\iinuhi3niWkqkוֹ|L]T]];co^}gǥE'}}CwM>gptVz:2>okTsΘؽ'FOG&l'N:MN?x/ļ|EpsiYs7aoSyW бh8>~I՝_ؾ\*ŷ72k77n3j USg˝`P_(|yOp@ja,rBll텖(g=[ ԧRKQ%H(ӚйG0&10Sh5/qqr7>&JLAIJ*m'vyvhqe9}4~hYi_3/1X/oge 25oVM;gm^CmNk\N&;L=<^k3>fdrEBKZXH}hRy8OȜ(h1%qxlXbEɌ)tit)3;YN<=9דvJA39E)qgbJKn.X>r~rS j..Ծ4W@E1ě<- mF;;o^A@NhA4-5<VF<g8;Yⳝ/b_ʽ\~0z4vztlkNfnͽT/v^_[^pc'j/׿}Z{`svί @M12a_QdSSb4BtR D;@T*>%vz N2W 2">bK{B%oݐ֔9*{_`4BTPׯԊԮyW5p7_o4`h `11PTfܮ۾`C!%'ó}.5nZ$NҚLjgW{ۯ?0@?=CPŰՈ]QIZ1', EuHъ䔔T4tc|ǩeff>wxNhᓦy /,b)?CU.*Ztv|bUK54lu]6h0y5Z-P+]_-C]K4T ksO>Ob mca裱'E Iϸc/x֫㧃gf$̧{Wpa}R/>Vu}VßsB'`Qx@`u\'1J*9< ~!M9 XHb c Ss:K.YF> <:|)UwEhDel$*I.JK+8ɕVRVPQQR#KTӨҼա}W_wPo@mk+2MLLyMgVdNPYNX]Ѳ>uv,9.t3W[ N=yzx>J!Os'dAACDBS {^9\Yft]],w(ߔp(ؔ|dTc~ǵ3X2>d*:C3z2?/4B[7EŧD8#xs'ΧWVUp&bBm@KjL57_͛-­,۽o%vq~w=w{umw~Ã+ f?JJy67R;plukh2i峡/_YO從!ϱܻzj]p7=@ {Z TPmXQ_T&4D86ޔqA>XDEvH2caXG*,~@T  tz #Y fª`Y' 7JAOaIqb҅#2U 0fC Diizӎi]aah$]2`g` feae ag8 u;ǒ_@`PDɌRғ2e?ʽЫxS%:KjMZ446thu a35?jbkQnb†V. >;vLpqrs[&qyhz{xi&Sx|2#5G2EGDz9&$IvKy>~!c+k!''l{qqpIqYkйh.ՙG77q7Wސh)opu7GFzbchFyԅ%+_ؾV~X{Q5k %dUA *#Ё\Dꂦ p0\woQt(U'*u͉>TWo0l3LHp^ZEE'%҂,{*U,xy| &YW]I"Z m$nޝ=C xѐq)Y9K:<[Rv:Qb.wn)3-`,(#!L!)Uؖa^W 6r Y*g! aM-/: F&̦v ,h, mv:bY8UbZdS|~\!#CË"\bY% $eYOMyf{\)!?$%"O5CAkaQqrIHK9Jj ;?׽j۵;7j[Eۣw^̃OGtL\~zycSI1Qo-D? yo,,6xi]'X{gA~K>  }0 v .hty$ ϣ(mBM)v1}=c&[ |qp crry DM%:ii.ЖqU#E Fmτc"Ͳz-݈cwהO_\OGOXLDQHE2Z^m׍os[#[[䭮??)-_?KNvwB?N|ϼʝUH|bpev:>IA pHYs   IDATx \G?<@ . "X֊E\PVl-mCk.jO]ѵ(hEV ހRE-AE*HpΐO2̙3g3̙3G#..f[8A @  D-A @ MA @ B(!A @f @DؐA # ۸VիJ @ ^J\]]Jץ aDM AD C_ M/euBA(!it k?7iw6RJQ_sb՟M)2'yOo79I Jl =t" _K:Vo4ēF,~t0tMu"Q\D+hg@b!M֌ vj}c ͜ΩItz~tNSƒ`5j$i`hFK;Ӱrv;w0O\be?}wQU3etfGäu;gFfS^dhjBαLqthYogoBe?޼`*Jd%Lm`i|c)'RSTKsT /,妁_SL6Ʉ:6Цԕ^x%P%\Bܹ'l/b{! 'D-OnOb/P䴳kԕ_Do!&Ta4ap2F^D*#-3AWDZbQ=}?詸S0.} !a#+::*]#Kk*,H.Uh8ƒt\7P먩9Nr]bTSd m}=hVVӢq/v2/Wg=k!-Vk+TC Ԕ[lu.g6yZڛ+2O{_1L#!iV4[sZ:D0M;CCkv271H& kp=RԤ5t4!=MZ)N'qO.^rU{bxܼ$MNs2 7 s;@PjrD*"FjL:Bs:j*.{+qIô,^ 츀a6>?J﯇uw&Hϧ(>mBe|7f<~i1So}F?K8wjtOoa$*%sq{\ :@o//^GK!ȽzϷ[NeAHƼo$rbY1t̷,NҥiJf|xaܷpV)N=u\^vqC+[ȍxvIR~zJ&+B\-RbXZ3¼;ԵLMFcŽ+9I]FىwMSIhv|ޜn²jmb' d`" B 7h% BHG 0Gpٹo5"0Vbe=rq ~k7g45MLVN@5` NIּͦBwv4FLXiqGН8t34ژ덀;X֖.鯓݇1a̭=FNcCqL!xa:|2!TA][vhRgUɽ0i2yaA _!!@Z0)3UT!5vmK+͛6; ǹO/~Lp]4!}G8PB#h5Ěc6uoYiy־ͩ ^׶0pGI0ɸVPqrsTZaїG;-fzEIp(]`GL={1B65kS9d|ѠeIފϴp[E3!vZ j-SΖ 6,a=-%'9zTҵA;`7sM{8?TSzuK;p4Mr)viuxu^ ni*&|Q2G-4r ٩&!+HzzOH[h:a*~Ǩ֩9!/aߕ\ p6* p4锌9s\1+ă't^:-LXvx M=ȷCXBV/%&#ɢ8^j&mw倮] .F e3XV5}ٿ`ZFF,&-s~9C">9ߩLfN *,+|[^.EEh;#xu%<=K-=_<׫a KWi^g /qȋ07ϧsUgGی:jB:0oرcm̷^.y"?3ՃoI(y^*MSs %[%-Vc]qw^~ːw}k{T01:X&3Hٴ|K6F\o5®HՃn_MMMY,y%dSҝa^LD|YPq4`bWDIChx܌`$!x+ .dKZ#Ƭ{{s8@ }$W,h#gݺF?`#wY6&͈V!(H^5hݙcb=*v݆q^e(Mnr<2mlW}7]ZBѬ8 c]4E@9_4qӰUVeDY՗,3i}}#*Vׇ{9c=FY]cua~auc;N}TJHٮV{R UdA 7BnY+d/Ru>;'d~ZG16ٷKnmm Ѧfd;u7Й*cX!qB@ q>c&Ilah`bo֬PUJ1mxO  %é0lTdEP+ZHC}tW bLJEۨHQŕT4c,<q}7dBˆ3Q[Rb+W}eb p0aE##}CT&1gUQ_7֪XZ̧.h Zmkbv'L9U Wen0-k8C[#QtBU![xЍ6{8li|k4GjZHՃ@,UIEEů M@[ȦOba樛C~ck-(xÍ`I+Ҷ(h·#G#Z2_]~E KJ6.EOO̦|c$w?Ɔr }[>ԍ4S2 49388v0))!!#EareBQcك5yҧF#!$|˯Jq ?_+%oU /bvdl0TD6<#7aXq.nE#tG#c"BfL&`YZ u tH4%)P5aY89%̀#T~Tp'c1uPfX9>3VyX('i;GY55u2%>•Eny(+Q dq̐a:\P=(B^aQ0NrF$s."w"GX d$W|~hE*UI)P !;zlWy̠G Ca uC%撜v <@^}mkb84 /-҈I2Z;m_ok Rk9B "n^^uhSѦLG9DxP DxH,Ј @#L"dL09208_{ZνWRpQ=~aT0Us?BMFTz٣]E:zRH$aw<ف(w_PK@GR%>:H"F@Q+]>xWL[zie0OSad32w ]F+E r< o)Q*@a(K׭"J[I$A @k)E"Wi 錾OSO鯄`lOwPh'R! @AZ$!4~D*]~U$}B 6:1؞;oWaCr' Aams;ejB["V鞥IW$~X'.GDhlhEЖE=37€ !0Еa6`lOV^!E ` zЖEKƒ 0ЕSKZ`['&'_٧}Xe9hhQ}ʛ0# t%5kUAG dT5HD  DI QNDA` @Ā "A @x%1HD  DI QNDA` @Ā "A @x%1HD  DI QNDA` @Ā "A @x%1HD  DI QNDA` @Ā "A @xȌRnILijj/}&./cbmR%`AI 2%NޤD4/^tss366Db?QW;}G <7^& k׮<7LIFAA@6eϯ ٬3zŒwttrDN ]W+6ɝ @  n&ϟ~qC | ewi߇ +A 0Hx?Jk -ZJZ2H ^NIXpt;;;,m@_M=qBXOtUM>w먏b"".|Xfkط72b=][)7A`!tMI37f2瀿r B54\$)?7.En?f&J;/M $TncXxV@P[55NF $(L *Lǒ&ŧ%2xEeboȖ4,0*0lZG,/O#+tDӧH^Q28A"^I;p>|X^>:B`@R"(8fW۾:.QOuՙVYY $ʌ?"&鳾8R&l nԁ=-pN;p4cX3Pė/5֜=XX~_fUV}*߻-L.)+ٸ!>:ӽ~ʢ_Pŵщ3*KnӎXG:T8 Nz rHٮV{qZb]/ʣS#2&HN3 >9[-% sh$'|o J^~3yボ 8UVe[&>S9.(y?qE@(!H= tLtKn@} O)XpL}frrϾt#PHP1~X ٟGF8̭&~ =#^0gm"MQG@JpyyE'΄8}B'wY~vFOK[ ((*;; јewr&5HٱĶ|6z,T*4NыN|z],X8~pL Os9zpյ(.,|}W?yH*EUgdz ߹.ȸSP{ <Ǯ?[ʖ7d9li7Ys}`oPŧmrAgZ3)ŀς84Lj NJ "!¬D3:b%D!I~(HBޠA PuhvtҊf|q[p=S;Nx"'''%e5oKKfaٿMNq񢽨@竽*#]C4aJ_6ܑPwR'᭔6^MD!!*1v\8B[0AD՞ƬPz=80޸Zi@;R,WmJ*LLS]+! yYEΈγ|(N)jPHH~ FJ^a:T޶O=T+ % JU/DhnX !7$ؓ:Ч)AAgrt2luz.VWql/Och8Zҿt2']18ax4+ǮLw5H1e} $tdS}"Qss8 ^%;x]g Z}p,|/2#O++tgPbg&yP?W>=#23膿]k.pHԠuF6j~lpŌg-s38Pg҅^t a))/,UyV;Z0|nMspH އ(|*ɋoAN-.ok;'⻙0G# m>)E,%{.߂l]"Ed& rbϞ=[BXU#4 > E,8URǢ("*pPϲGR ,;s<&4%mɈE$#E #i\T3\ACUiT$A Ikwꕧ-n|CS lpr.干L,˓(t*{7x)8y Y'TC-!1DT\]1J#SS9 YPU^c(R5z tu@IC5!#=PJ39Lo!3ϗt>͎_$"}ʘ0#,ꕄ]sTyji*U%!/wEt%$̑" A@X_4'O"cOF$A 0P${T凝OW8 Wqk풮Kʸ?7Rkto1lNi<;c] X.M*:[v,3 0+ KxS2%孱$s%L+0D.XW:oCޛt9WU#]СNxaզ,5 nm.. rÇr=H}v^i݆NDqE.7$n72i̕Dmpcc#wZyY6A`#@zWmtG )S\pAhԩvS: 3]wmnY'%zĻ,qEg5ۺJ)x 8/h)7jp=]#.OpG=2cH҈$u\c%n`ۿU|un윹޹ےcBu ]i eJ:NXͶwFJ6IE޳zQUü.ƶ&w~%pcUiѳx i.͞*a˒3G-rE DZ0F\ۂp. yt3Bs5Fm,4ܹgu|*PY%U]:-5P,^}X)&Bd`.υDEwkL+Kv҄} NC[[[uuuSSpy#GVh]6Ǚ㬑Ӗ.ʮȞ2 (i MDmc z-MDCevRretbu?L0"4i| w $h'p[L{c(-&R)O]=m]a' y,_c̯؁ӣ尅VgwwZBBеSҹ1ɔb.'ympV!87![i/ fdP֩JI㵒\(AFK['x^ T*lh@\:=ZL%aOQQB>P{dLuZ̋N#z*>dJ~V"wc]HQIW/ƺ"#G,*oH[Sx{ 4ݿNŠn{d/Ln_pXTq6ާ)e[}uFZ$m6/^nxZvxCua;w<==a͢` G'Dg}6Uz̘B@:{q d]z'A544qR>&L#GڳSs=ݱj̠vwnC꾨5vlEgݲ5w_ ]]zON~VElg6 qK W{$"ەK+vsVI aMw_ Vg!k>!`WxZn-*_ӦU 舼pi2=mI߮@'y^&Qa_)d?1\JpRNgQ{Ƶ4Ԗ]t%5q`c~R+w*0h@^oR :yB?w٠m\35f…cCt`p\"vssp=FC_4}UQ0H+!o{ qtHC6g\[)ny:,{AG `F\*!vA"ОG8a 6&x4$i>m]ӓ5/1)ͼY~|$ دVD;1s$$թ̠>E'S `dkj=K{Wbr~5wPz#5*g(9Ƕ B ذ,Lˁwu@/XYO[OcR~uy9K6/Ƽ}8*PgxiLt#166 1J_z+!K& uyxĐV"x#./UݸQdin UUHl0?rO3@F9ts(efk1n#^{Sdd ;]e{3_lj?3Ǎ *-`n69cSҴ0/zbkh IDATUZa5YLcRX`|>5GxE+( 8}z/$ɫ#jq㖗l: R]dI^QI[s ¤BE$Tnc(' ;a`Q T=%, $/$0724҇ |zCKь1b̙jCkS 4>IFe.|y֦bSfP{ w>~ fEn8 p1w0=e?nc/PIϙ}1%&1؇\QS,cGȝ oP Wڃk@M1K((s%[ڷ{rQTRzIn!rT>wO5*Wj^Tpxw87ꉣt7+:%[˓oZ;%<ŻT8"%QiYƿk {axMPNN@{/e!XGd]!ae./uG'?R@7TՍ{JuҊybс!nfp5KGWWp.K 6ݗ2|= (cǰ8A3Âwt8s5g`k2ۄt/,+:Bغ9viюe3a\*@ TiQfܶ-|J4my%GqʺNϏfq`?90֨ZwӢݔxKZ;{ڱls6^l(_,<~xv$nn_q6Ϥ7;~֗z&^ ΧPE Q >GrFBJ=·diUPT'-3g>IlUp֙&Ǎ5X#ӥ И;;ۯfXzlWN'fk9_ pxδ}ww'{)Odb]?+fS!3yJܘCɤe#l8fxK'񠇐9{†s84|1֊2[/8 ;/)uΈ5;n^[d@s =Ѳޓ1XX>vhZg |dliFG,P!pV\vvb+]H+k]Rtcцpκ6m--]m.KW15QS&P']]E*mfϲpr|io$^w@5\SP_ش>[p;N.o85!sl|ֺNy<yNJ, 6-ZQgV׼ 5dY#gaFc%Pzuk=3У;?F9#ҪnE&π&y6OI*υIGu32>d+,E%Y NwwC_ef~fxR of&'n7Bp(X/;c2LY ݾ+~܂deg i:ej6r ҹV 34=.Y"׆ӆ<SSLڰot`[԰Y$gX$P/gWm*ceK &8!,̚5ôE`P]>r1IbdmFO RQCi'Sy N]5hPv6;N'R\OSNO}&\/+j%馡!fyHr&>,,ȃe|sd/Dz\M\(w͓ahqĠd\.!daN>zObhv45"MN-  5-:7*fI4sD\NtȎ x&!}2phv\<<~a\.ݸہ,UD(hgAn3v: hf:UWYaŝ)`XV٣<>d5XxքYy/xV D7s s޿VʾTKO̓^ A^:54-"@ fnfϸ'!9{,0EAyk=v H&r3V]iBE9^FH İ|yUN龹()X~2= mcf 6rIpʊ/7)缷Qx1=1UTzrG+;G^NdAs\ͣ7ǵ΃~?7I3~||a'w#>כW"Ԋw-np$ 0HHMMI>k>T l F[ko?`+4 >76XpI}VYT"p5YŹ8 GߦP_/7›G*8Un 9"{C-EU9WVZ: $DKxFL- Ѐ5:a\!&x =@]MJ5 !?膰(\x' 8bM  z}KOMCܞ: 1RԐO@GWK8^u Zz*/;174H~,ߟ^\RE6""z"!؋ I ӈuGgA#/L ^d x?U6dxW \q) =~K{G"x۠+ 1 fP{%/N:jsXA vJCtS F 2T)ª ͣÕYezQ`H);%n$q^So{myxa"/S_Fѡ'\lĆsҋL[5+0Lf'psp-80 ɝ L{Dr"%~6j.ܓt|96R5<`__5i0NPN0v֦)0ڰT_]/`hUbB@&<3$_QySFW>IG%^,܀' $eFzpR=I+*`:ⵄݓ_Dqz'YqR2p EXrsge.tQ+NH:]>Una+.'X$'B_ ?F0pС {b䉻4FKy2Ri+`4ۧCK᳦! !Ow>=w.yɥX?̍C^:UB%m0'$Ww×c͔DnY_#MnVuDj 3 d"6qrBNM F@#)su$7k[CWkqXC3H ` hKK+`ppUPA` 0{lRHt~I׶}J8YgF=OmyT GDzs靼g &B?<2B+꫏;'.hYo#Hb/ٓlw2Ÿ>n@ ]);}F阠O[ET,{lpmOScN.mî/W{SdA k>i~ 6Uk6wzYw-w4^J>8 Ma@ϾeAa )Daw\FV=]0'h [j$9 lVϨKpk j\arp`mHÂMZZ:CL ^Xx/UIa}@$@-vg3 (D)9Bt[&Sx(7tw~ Z_Ć@ .Zn2@5?Cph8ijU|<|.]X.=kw(`us,Tӂ@u`+>1dǕ74HE\P6-ϮH0(](ҢQ(\'*_RQG?x(=<<:`c4/u>|˅ 1c, X-eX@d/GyI)}O+wHk睜%EU#E"sE~Ĥ ow5@>qBu-LC s0hAb7P%_'dM ɖBJ)d0hk`-^𔱼g IWU1 !zP -)uĆv,-e=9Np~ ugUi޽c \]#p{X r޵ ݟEw/[_?// * Rzyh45t3Gۓ?($zTPB_ {dgfil:3הPQbғ(}WC#TE 5L+>x_$ިq|,g͑Q& 4)@Ubנ2Duiq%ʬ)HB6\a dƏx -q#0P)HpΤIpQ|:;$~46ٔՠo[:N_$l E,`<:o|ࢸν0.(BrV2JS4)% D &ozM[ \ 4Z1Mb\r-6WXku7WFe.qWw93;fL`9=s9793>_ȁ$ )>bYv> Xϱ_T322z=س{kͦBmf3]T`4j7 NB=*шCR0EFˉ'$q+[ӚYۍ5T Yr 4e?߱*+W6o1jaj tKRFQT` L5 裏>vgSS/>V ĭ6+$5ofԹKƺ"z u,0IOWTl~, "~anQ9aU+`&eO2/j= 䋄#Mst0Gf\1ͯoH׌E (GN̑ՁH";t[t>HIzSX``0-?ݜ"REK߼Jx4BM%04WA A"r &^rRrs % _"kW.]$:}unMBpw/Jd űhޥ̑`c;/@"c! UW7:s1ۭVP^l:Qz4Id #a)bXe6q3Y@S;A45 * 9<]h9_2B0@&$L&R2{Q;UJXi|#GYatw6#F_”ڱ`]z1W!9" Rev!\¤w ȣҁҹw "Jݓ#5}&@ :Q\Sm!טWSGdY1   )rAb+qjJ0D >#7is9 IDATNڿ[5 $q@$x~Od"U(3SgW> ũlm0`bjc'`k"dؠV[%iiה?9)D{dxŀ @ [vdCjlⰽzCGwjsWLJ;i&ZKSϷ ,mUi Džku+֩'=He\QQSOٝo)*+ I:%<d"Rml{,QNfjKܩG%ZL##&SÓDF5*iThpZ.t5\ Mt2P6."]exgh#e0ۚ*TXoHV̜1SvY3fnًZR$б~6))&_Ջ׉ԛ37ϪZrMOT[@nQ8BlH/q:Hkb6ua /?"DA]h,)#)ث1~JC6?@LZ`>Ke޿-mHDt!u:20ᮐpGPANBwW[=K67mmu`k$D:1iGƬ4Lup3IkJۙа/5 ӱ]<)= }In)~ ,чo R5JR ߑkMxa s K.jЮMuڂ`eC[әgK2U Bu=iQÅ֣.RΧdzO+ bmN<:B0Dہ*0fth'0Q.VtQ !r9}Sz̄=#vY*wc h"1&gOyJ<; Y\6J'*`!\ifU1^D:^eȶ8j`x8+w ~^H"\2. r- Cޒb *K:=_ސ4 |w,TQ;'̽D.2k?&w^f"JB4' tv\1g(iYୃ$|*0\b?l!E$w)=^",Y&0vK _.!{wsV =Q 2K ]`[z(CnyD*Uo o0[w=Ox=[!gaGP+Bn&t(恍k;P EK˭g_eY;m,У|xY+g*3RHF!ph7׍ CT()pmʣPcկA2hDɨ2{ҏ/ @&@MM/??XwΜ.B*}qfHfTƒ.xhg":TCHN JSv+ ciFrZzچuPOJ V@ UPw^v*:v0DE'6ujm`U*oTP(uCV:4dhw@9U-F,KihщumDLy6b2@ J|Zb,%2b鼟^z5MP3 ApYWi>UbQC*'ܞTAQ6 4PTpϚZ:?ǏkSN}gϟtxlvڵkW^|d\`3:5pBN:"LoGS; Bu%ϙLvQlɊ%\__̉  !*' Oj:* `QT: ųB -AP@P pI:4Kl-* Lb CSnfS 8 CvcWm}(ބ&Sou]Gk g7q/b~ )^=u'@A1H. )7\oê#l~;a; G3L0h-KFFI+[s*ij cX׸R# 56cJ4TV Ś+tH2[vF7kzF)7 u"A'yjw[f1UnoȑjL򮊦KgWuIHk}DWƬgĊpL%Iڌ{F .Jsbu F fmc2Ӝ~ 'z>|U@hf.-(* LMbʭ.ksMU3F]!KIp=.E]v SZ@$@x G )Ͽ[QrxVޫGȆ5^IOWն1V kcJc 1w&;9Rkʹ,ZSDȧv1 T}3/g; .:Y1v1vcҀCNq%08%>/u}/3E>;fDžiDyikrSꠚ\Z['F7(I(%dT`+\ `"EՖSΨm[K`pRY$@se䟦]Gl޶1]3q6~G trN%\vGr{ l≻Y8\\pO̿8' 7$KsKIz8T|@j5f!p<-u@..JU >{09aj%xM>clFX,`q*Ȓ724dIDX]HQ=Oҹ2mhiFzZ@τYs\@+'NtuŔD撁mR^}4jm7t>Ep @P A,gK"y2zӻYߔ"X@!n~DO(Z-޴ 8C\w[Rz*= Z(UYݘ;rCB#cٖKC2tgPAS6bK;n* Q *+t?n=ث/tСe +9 ݿ/K.ж-nj'ڢmd9q-}4G}: 5{}|= s跀j;H։{(Ti( K,u-ty6`!̼/~CEY]? te*~_Ƙ cT (@H8s}>Q$֣@脰cME mjjGp*8o8u}'UXխel֌^3 s QΏ~_uH%E[3 +V,lf(fH[MmYuy'w65\M!=M2(}t=@xrzMäc\ o%NTτ.Ϋ^>=榀YN ![>d%+J;w9h vh|Yu5 'pfݏ(t#zq0@ @ŧg?Pp"GFLMeQGb!fە+7 oc4%|ˀV樁xG+֩']u4r /YTez`3Sei-[ߑ UJ|m eARjD T֭곍X :ߥSBA`>yXì~8v"iq38B,jn{ac&]fB7=7;J[4f_2wS ^688';97H7rqHHb͜1SvY3fnًT2tgVā.f!%ܬSRL.w-Xbz@ ~zqxQNH]N9kM^VQ"URE6@_z.c3IsWLH⠮inׂ Xz0PK9~ Wv1 ~;s~ rUde@ +j8nDVVlOKq#?f>nc |P>7!%(yn^6`ÈG/y,o|`kY76{{SCqN\z@ NB! |\AVEP* C 3E*\rr9ggS)D 0S=_DΛM\H^8J48t\ߝ/88a fK~ӏ]JÑv(Xh'D*WG1?qtԄ $2.Rm]ױbV~jnJl(,JT'oRPHHpNYĐY%bפULDhH^9nX$q˫ڕҌj`#D  I.АeߢKFN_nf ,1A6AF 6ndTЂ˫- 5K&{@SYͿćѬm9]TR6C{;@TRKY@[o[$.BYAĽwyɜɅGXQ~N{s&wq%}Ly4,NQGi,ĩ $j--:t""5AP )!*;tX6 byyYb |F y>ckD|^y*q6섢*i# q$YfIhY#,gD F|;4J(_4yx M*NMn_k 84YĉSú6=ۿэ: c@ءCz-N!;1'be=7湶 WFO89i[#60I6E c IDAT~|=Hy%KѓWoEޘ ò?L<7 :tC_F_a[dj 7eq+7ڣh  qSCO⣉<-MThôXHTS :!&T@Q@~B)0 AAиn 4FPTS (:;* )D C~|!f^/P̽^vCo/C,ػ -EFCW{*0bHYW ?7!\nábHgܰ#B|"%&' ?l_{$XgecdvdPeEֹc4ҜCPA"0C+QxZ~&o}-j~TeAiL)<,};~'%̮{u_MHA1d3do-?pAk%H# O|;+fTTA1H$t  axoOj8zS>Q&U(@tf^!eTYx"x"@; O&Qy`#)?O}]-uP%ֳ6"qٶJC~mQs]f ?NX"Iz<#҇ MRZ Q/0N!]!]a@T{<XwΜ.B*}qfбBR o2 4o !$pN%)J;m4#9-,t Z[ICCZ(:j&*:v0!:!԰^(w)IE'T-ިQnR #HiqbʁsZF-X,,E'j 12Ed4Qt*{FF[Oi>^c1RmtpC3ALQyL*U-=}ѯR{0Zo@ M6z5#}CEd Ig?~\՞:u>;Kf׮]z˗M&{phHޮzP٘||ǷCzГjN, P@LtlTx_ĐRO􃈿z!XcU5cQD1I)Tw$Zܷ Fn|sKqG$-:JWNC(颂'3z +_ݼ,eihd]q"rxxxp@P  Ag2wϊ*5Q.J;0H3kr[fK-oG{(H(jCo)L'Ͷi(FFQ)ůQU &ؚ'ĿIP}]R֑=+O}=axCV zϱRFQT`| DC m0Ǥ!GzZ?20IKr1Prڋ-"'C0;"J{rK[ [`=;}]cD _2@|FXXEmzoǡ"ZW,WԊ]Ð-@m'A KuEPA"Cj32KjuKuI_܂G$}$[FI R"5,WWdIBݟ[,k߹ӓ/L-WU\H6Fz4,+C _VxG<S6KVS5ISP_YՀ;*0~:D5СQ97^|4҃G $b6J;ƀ"Ӱ.kGXn\Mds;5Y#tH# @PBF޸w^HV,&3¼ƀ"Sj_\G(\mPFPTEg3Ԁ"th_JcjSNTAC_ u 8MDnp}tÂQT MB* R ( PC-@PNnB* @p r;2tȽ _A1H t.!3'Brk?],ȣ>v9 ;ƑG $( >C:UIc';Lsߐiu 1ķ9AP1(BtYg=P uroGiU)uSSk=lƕypd A'7E@$n)Ȇ }']}z-ġl :z6`8TB6=s˧5kXPyv^ʕXP-1䟧С*_x6Y]n R+OYҫS-L:7),Ց+]VVV\V@&@?n!th@{t:uAO͡8DiH&PNE3>ND\%ߠ0 *0qB8tq+,$f&I]UB"Hb !(ng9q;l lIrS'T @7M]`iZ VQg>dT&+k| @  O@np}PTdӛ(UG*ṡ*5)0 H;3& ZT@V4dN=,=߲EVGPT, qwN##=aslnznhm쿩㾂*n(ۆ&pvappx|C Lׯ_|[[ou͚5\k3G6u5ofT[u*wӎW=Jaԟ2'%<v-gGF|ZF&K]rӢ^GSi~9RUC%˼ v&?GV|LUnOB.)/u$$M(rV!{V4b03* A)1H̘1cn+,>BDBWνLڋqRt%/iL=m[bz`lLH:[AnȨUXIxdEZk3B_K׶p` #lau{.յֲKH֘eOm> n8̅ *M ~G;,X#$Mp{~ZN1#{[ΫՄ3Q`8ZvŚUr8jXu吮ؿv Bj8Lѐ0ղsc^ƎMeFq A{}<+c9z ^#+$gi1@z TjgBBt^D3iYDϡZܳCTF3*{xӷl=˖k7s.b=/z4 %ڢf!LdER$ƼŕUQ[ my:^s}n*"ԣZ5:4-4ǰ)*ˠ׀5 * LH2HIw}J!̙3-[&B=a| [/EW)`(iq38+jn{a)6%2b꼬ZV ?ǃPr#eS؇XO_8.P[gn6g=wi"f6JwXG執GFLGrœl='ͥe{`hQuŚ-dmpC.wob2|X(4VC:v 0G=mMT-}&/* ˦Sڋϵ6:ƲZeh0$?wy)II%s7,BAPM\̙dɒ>8{l]s_8wi*`(=ۢi)V u,B/\GHzbcitFt n00' Bv`|=ĒӤ%09FgE;ll~}C*

j8l#kظ".N@U[KĝKmlڳ?<+h-E-.ۏhOR몪 ծGXGWL`%s UmXn0bdqxl(ΉK\ 1 )|r/Zx18y2s,9 BםΝ=+n^p60,<㙙yڧ٢j@ҙC샫{[.qoD6cM.W4m-d3ѽ+] "q`fbW.hXM76lQ@tJ$ уyJ̖/ЇzVv%(K&f̷Q M9p%|3* $$ L:l2W){C_'3vU+[zY@/vU}E$,a>ܯ?/O{rK.%)B#afڵۍ]*wu$%Tí;pkiDP!"Ɂ$C {WᑑݕF/ٸh7V|n-b*F}KnJf . /޸\Өc ̹vUp%U;l7ݑ[ 9m eŷ~(xZ; og KW]'Vn" eIJlHF9fu_KU!HjNZ5a䫫Z2-RFQ_9+%5f҈K҉+k["e{$mpй7R˜SE4rD̤GtU@dU$%$$l93?q~>>{ogBU68[!l'ՇQVS5rmƆҰ,&  ¤-/C:Uݑ wZϨUҰߜK7Z5 sD< ¾O(IofʳpMÀ LP/Ĭa'5ꕿXEdG_642~AAx8 ʴؤr "4*;K1ۤ!$83XFLɰ̽=3jqt?tQ-࠮9-?IMrniǸK!w&ה*RubCe"O*N?̚5+44`W* -Bǰ c`f0 }0<0Bpn0q:vd.=;t[وys)kܳkv" 7vf|fϱTᙇw;I>q>-C>{$pvvy^ I +!Ȅ*ीm]MG?yÃ4 ']7b]w w TA1HSk׈*|ݞLF![k$s7&OHi;A d{~P(89!]:c;{X1ʐJ2ϼ.$51rC 舰А;m# ($(s6>h  Śķ̸Q`c!^'׊i?'gI.C9 6nܤ#%*IQ43Jb7]o ƃ6e ڂ k4&s0}v`ER :=kţ*t śĭ l+e~O[*SC514#c3!]չֱWsś:XqV}}Fjvy&UWWА/ I- V]Cz]2S0QS1KTߡk*cCdꥏ;((\ |zl"Uzփ{E-4%+~ ਼kQ~&hvK+צBTkp}C(#6ju X4;>M6!a8ckY”kD%Bh^6@n@ [vdCjl9W^/ ۫QF]-:>vmdDg l6o-LYRqs)!ƶ?ДIԥ1763mY@Ose9=ƾ .GgMMٮJ˲ִY,Ɓ4_Ei@^|gdL;(=4b;Jov٤׹\74\aN~9 =FmúB[p.]RgVB 1dZY jd//i-bQ;!T[@$@ G )Ͽ[QrxVޫAvCo`+x]fQ #ՑGCN,).{@MgY'p@F(=53.͙9 k E[{c3/ 9r%1 >EV88?m@;Ffƒk>2gu}w Y<;^Il2B7-7cGh9-~0!( ͖]fOnT~T.0q Ԅ7pvvP4E EkSYD}tߍy٤sh}͍T_ +UP+ 9>GXҎ?E @KxIB.&?DQg)eJ۫u0c4$Gi$F5eM<'p(?YuDmkȣ+ojhM.$ YѾNVe4rAĐ_MJjsfސ7=^#s4%f.RoZ Ā T  oHK67mmu`kp@NgFx$x6>ion03-OҎ{)=WηYwءݾx $IKcD(= XZmRHg3O{Pq@&U̗Oj_MaސUT-KT,zQ0;%ϙL?* LkyZ!E뗶 W.a%*p3! @(0uZ' thĢPT A(BƓEPR (:4Y @p  .u>*g@P  G3L"TA&СU=v?'A@PI t(xCÝ%Kx    С hd*pxDX* Z`J[1@fΘ)e3E :T6ҿQЎġR):n9 СHBE!BC$C+[6XB,t(: ! !+ A:Tn0.3'tpXx!WС?_C:D:TСT!Pa%@ (X/trB>, e"j6?O:H9rm:(* @0):d^.:FPT` tС`q*PV  t('i ҳW:DeD(PK:dU1C B&BA}]fEx>Hi' tv\e6@},&XkF4,op@FS  v9!TH tS=Q(LYB? 7FPT?y APAB8qDg%0* *B :伹6gc*!t(Ccǎ!tHP# tC!<(* K_Fиэ:4>xHy@d߲lE)2CfCgρ[1ua&qY`9ʾխϕjP/LGP+oA ;s%_0|p4o1W,Ϋ޼>Q&UhZvW>m,ˠzn(N !!dTjDA{`}cś !-g'CG=[.Vcצr9ڼj-ʬekp[UWegbGIjI]QTS@$:DlW){n7U땄LbSf m:z^/KxFnccr2+V[hnT6a$vY{Ziw$C]#}6 0lQn1as0dh]=}b1T,uf]6i%˦Sڋ]Auaݪ>ۈe}H_S~ݾd3V4EFZ T/+r*r;xbI]oj7W|;!TuE`Gبp:tell~}C*c,bE)RN_D|jSA"JH3+Nz0k )\iRھciH z$d'NL lk.SNB4"nBWB+6%m{;h&A.!Ԓ*EVL)c_  !h!5W.YQ%?&ʚE v'cMVb|4)|;&DJ;,CfwLw-5DŽ6ƮEk-IoLg}[Wӑ pT(*4G|&DP(MCC;̘w)lPi%rΎY@%HtlO w5 b#ڂwtvs$! WQy`ڹ;  ן'=e.9w•d~V)]o1hr]o9PT`A"ȡCFahKjuKtneJZH*p(n%)µ 4Mxa aE ڵ 2Yң El&Z6\D},v<âןU 0dw>X%GH_ٖ֙˔ީ-ȎE ;&uԆ*0:D t(wli\&LXV"hfI.tK[[<i +PT`| x=ƍ/TFTB>T  С}aPT`( `QT L7QA Lai* LW c:`QT e ZEIENDB`testng-testng-6.9.5/pictures/search.png0000644000175000017500000007562012551235562017474 0ustar eugeneeugenePNG  IHDR6NiCCPICC ProfilexYgXͲM%Er$HHZҒsJR ""`D `}>ϝ癞wkzm-8 0fFa9f3Dae`AwEZ#QЛX?6_=E>08gd s0Dxp,p%TZA w=08xd YA+ BP<eAP tBm!4=fE3F0# R2 6acT8.+M< Px3%RFQ(/T(**DUQQci2jEѼhIdGۢIt":]ED36H`T1FoL&SŌc1߱X,3VݏubسFl7v;p8u9 Kǝ]ƍqx  Y  G@dBK](6)((U))=(c(s)))SSnRSPSPR*Bu%<ϏW[#b|~A@-NKDAC} L"8 9:B/aNCKcDADSJsf#-%63m,m!5Ǵttttntttmtt2/0<Rz(QH"wXFF#F_,!&&y&;hRNif0?s.s3.mO +,,kZ?xZ^-٣/s0rq8299sœVqU߸ pr-s3skqrpwq/y4x<%` E Y==*{TԖ˼toޖKmK+HKWKa1Ii,+.K-}"G3Kk[/@T8pLG᧢bE%A%W2IeFe l*$ UEpfOjj~jWoN_M9iM>M7JY--wbھڗ?HYUMCe 3Ox*v7ٟ҈ˈdTgbd`gBmbmRb2k*nj~>`|ԁfBff-+ [XK R˷V2VV.֗ڼs[׳Ϸ>(u0١hXӇҝ&>Й߹Ӆ+떛[7w#2.QK+k[O2Y\B^[gwo޿1"5-!//;(:h$X"8=x:D5tJIhMv85y9HԈ,\M=#. B:4~&A;|"ؓ$4HQ~G%K''MOiOJ=:fVN>yLXqq 3ۙYYY[٤2'Ox *斟Ğ <9WO?w_O~X(_XQDUQ4]lZzF3[%>%:eeekg=Ύk_Ȫq|y7++ UUo_PPW^UbZھ:KrNZH^9ܘ"_u:lsMڕBnodބn\iinuhi3niWkqkוֹ|L]T]];co^}gǥE'}}CwM>gptVz:2>okTsΘؽ'FOG&l'N:MN?x/ļ|EpsiYs7aoSyW бh8>~I՝_ؾ\*ŷ72k77n3j USg˝`P_(|yOp@ja,rBll텖(g=[ ԧRKQ%H(ӚйG0&10Sh5/qqr7>&JLAIJ*m'vyvhqe9}4~hYi_3/1X/oge 25oVM;gm^CmNk\N&;L=<^k3>fdrEBKZXH}hRy8OȜ(h1%qxlXbEɌ)tit)3;YN<=9דvJA39E)qgbJKn.X>r~rS j..Ծ4W@E1ě<- mF;;o^A@NhA4-5<VF<g8;Yⳝ/b_ʽ\~0z4vztlkNfnͽT/v^_[^pc'j/׿}Z{`svί @M12a_QdSSb4BtR D;@T*>%vz N2W 2">bK{B%oݐ֔9*{_`4BTPׯԊԮyW5p7_o4`h `11PTfܮ۾`C!%'ó}.5nZ$NҚLjgW{ۯ?0@?=CPŰՈ]QIZ1', EuHъ䔔T4tc|ǩeff>wxNhᓦy /,b)?CU.*Ztv|bUK54lu]6h0y5Z-P+]_-C]K4T ksO>Ob mca裱'E Iϸc/x֫㧃gf$̧{Wpa}R/>Vu}VßsB'`Qx@`u\'1J*9< ~!M9 XHb c Ss:K.YF> <:|)UwEhDel$*I.JK+8ɕVRVPQQR#KTӨҼա}W_wPo@mk+2MLLyMgVdNPYNX]Ѳ>uv,9.t3W[ N=yzx>J!Os'dAACDBS {^9\Yft]],w(ߔp(ؔ|dTc~ǵ3X2>d*:C3z2?/4B[7EŧD8#xs'ΧWVUp&bBm@KjL57_͛-­,۽o%vq~w=w{umw~Ã+ f?JJy67R;plukh2i峡/_YO從!ϱܻzj]p7=@ {Z TPmXQ_T&4D86ޔqA>XDEvH2caXG*,~@T  tz #Y fª`Y' 7JAOaIqb҅#2U 0fC Diizӎi]aah$]2`g` feae ag8 u;ǒ_@`PDɌRғ2e?ʽЫxS%:KjMZ446thu a35?jbkQnb†V. >;vLpqrs[&qyhz{xi&Sx|2#5G2EGDz9&$IvKy>~!c+k!''l{qqpIqYkйh.ՙG77q7Wސh)opu7GFzbchFyԅ%+_ؾV~X{Q5k %dUA *#Ё\Dꂦ p0\woQt(U'*u͉>TWo0l3LHp^ZEE'%҂,{*U,xy| &YW]I"Z m$nޝ=C xѐq)Y9K:<[Rv:Qb.wn)3-`,(#!L!)Uؖa^W 6r Y*g! aM-/: F&̦v ,h, mv:bY8UbZdS|~\!#CË"\bY% $eYOMyf{\)!?$%"O5CAkaQqrIHK9Jj ;?׽j۵;7j[Eۣw^̃OGtL\~zycSI1Qo-D? yo,,6xi]'X{gA~K>  }0 v .hty$ ϣ(mBM)v1}=c&[ |qp crry DM%:ii.ЖqU#E Fmτc"Ͳz-݈cwהO_\OGOXLDQHE2Z^m׍os[#[[䭮??)-_?KNvwB?N|ϼʝUH|bpev:>IA pHYs   IDATx} \TUbA Qe觵o`X9dE>O]+mb/k*d[A%TC+$"( :saϹΝ;37p9瞗{\t /G2K|;%Uԡ/^E6K%C?9^mCKWQ~<02Er*S& "{Ӿ˥&HP*̫g`K تj+BW\%-P4U e`8".FAWPd_|j"ж(i &so roO|p:ΰwא" $&ImRK#&LeN7b7+~sk |0^"[t͆B|u#5o[ޣREW@C߫t篶[Y^|[&'wXs] \CW/wy utĬιOA3HB`4/[b״3냨ˌ  YWL+ȼ˼eq%wLu3clW2/U#R"AcQ$`Hڡo&ۼTsp l߶#kA!cOm0*A= ^HxaK蚛l 6,nfC[[FYZ8·Hy8mmM1Jl!wTu`..wvj[?Oԗ'Ieۦ̗r@E8VTW?1ʒ=ꖵ3*F(g[">PIv.:T%' 8\/"t: wѩ](</a*SH6I3\ޡ>l oE oEzT~TT:iXIvt%KΕéX(f"OWg;aNEENH,sKTd Z*rFR]/]x8xuswKWѻ pl *χw}UԱ]/^E& %c?^McKWQ~>ӓ41 8lqwVԇ>cƌQ*^&yK@gEgcussXWE#j3yI^O~WzI20_!^zѯug n6U ڽ~K4}>`]t/e<4-p͚U/M@l7ݷ;FF.LQN%Xjߟ߾zÞz'Q! cȜk83jmx(Ǧֻ5IZ?QG]fY~l4%\Rri *> J^{>7C= زda[ ^Jf^K_P rRXjߘLNVqXmpR;B#FzS04 kHlv3BWyx"!C BqrIHn_Eřgz{('ƏppH7XFAuK5MR~nUEdh,[O)LF1!K^|$Y Cپdaj2w@g=4'Qhk|`*\ oJ@yH!2T\NUup}CϭW|hAռ{{3iJZuA2 8~>.=Y~_#\}w؞sd(ZX.cю ךT8@I?ceTk)[^KܢTs͚%sM6Z]~@%BLeNh>PJMr *DP1hҷ,ikۤzNځ:tE{WwҥK_mE hvWkvq[b.]9)CUofOb ;Rqm{_9*5~?9Ro/FbEn |(~Co/?fE!?Gu'7^Wsd ק|7'6xd.PߦnOdg|#~ќ?W_G=:+o?K0ŷW.L4.ї?l$@7c4c!~|KŞ()2fŔ[;WO!ŗ7JΪj58?VG{fm{6}' 4C*FI1Ggmx6 "u}*;:PG lP@мEJ#mS.Dr-K:0`ltĹP?A^^?b˫υQ^^ jxW=8kj~/޷y?y?[gy-!%Z` _ PspBCS?9yHԶpKsܐaTYkATB+4oCa3ծ~eߋ(x;[ нhDt F<:m?upv jH(]ٮTTJ$KB/;U.XjyddZ]"thʊzMs;ޒu2"nL}}I;MdjX;jKxA|Ւg]1BTqp9 g?Z'|'_+'.ޏ{ڰ'>GOLn3pI飱|۾[K<}ɜ{ U5E}dVShck$4UFnE.Z\w98ѫf]FsΝ_qA;=sj]"*eB8W}ޟA!QsњVi|z邂DMrK~ X'"TA}dm GPeIvNU^=%'CRϱ dJ=׎RN國Bx;"3k!3>dFN#tB(7M}o: z"/E"XTXN\{.\Xu-ޜ{YD€J!T} c2\T5]l/W'>X|>Jp ֙qߵRs- rcIYқ% \5,=>pvq:Bim';ӮdU; Pej"\ӕ9  v1Hu K tq(ҦT[?ODdAЗ1$rUTHL GJe)SYF=׎<aBl@}||?zvs<,ꘇxDݸ??޼9q}/ιtx@1o^s ?g@=sz?@7!eJWq9!o~aVeHs6{{Ng"]v4?~jɾiNJٙS4ח7SRmjxl"&/)O_}'^eݝa jHzbϗ}Г~uߛ뒿Z:$Rt ER|d<&fً-2nY Y=̀İPFaYPڮBX.g8.@b77rӐ qd3guȖ Eكj 1v i.:]ʞ6 u@ks{SDnSgp/?okp贚IRpV/{vbpf?ځQu۲*>hcSX5mw8F?.H+qu1P=8kW뜻Kp,o/yj 6Ǭ2q hĦk > 1kw'? qľHZz &ﴊ:2>!ûvw#ItŇSUt[ cݐ9kWmxK^.faV#:w޵pX ~O/F r"S%KFFS ؁3bH$ Jy;;;oIETٔ ߾Cx `$7vX___8tƍ-wK]CFfX=x KT4hhC2r$t bݪ(9%֦8ȓR]]uuug|Y{øUyA9LeԶjkH^PB {Td)""j2H$Tq ഥJyZ x*OkFmSc6$ y'c>N/5UOr0DG'#uVb4PV^J_~֐zZх"?y)̙3ͪ3LUB0sMd0q^(+e?4DKk6J%EIM{HvQ5ohd>M JoNw)RZcΟTKf1QG*؎P+%0=&ހG1D)Q)V$FGQo@k@K"Oɑ''u@5a鼨 |&㞋ReLoa鉹ߧ;}CVm/kem*&%˗Ur4#/pwȑhkf~-XIEL//S-˞Hٳ'gމWsT#c4PIs@tNS5Q(u2KPI Jĭ,}8Չt_cKmuY'a2i |JBdDB1PY:ߏJ"qB+?<DjA%Td6Z-Da,o,ow*.Jr-Hqo|%YRa7's%LchxH#ƸI>5vZ%O?ԋ²/ waeiܹ5;0V\ؔG>,qqwX'eijN@@贃}s?ul \*Mh$r+p͔@_,'?v@~Ӧ\zw}Jլ\`SKD%'p\SSXS(My,i⾩ukk%h?&+I[![]y/+I'<޳w`#=p ,eDO4x&l@ dx,~q:`(ssy#򖊽dQ217#a騧"fN\[[ۂS[<B7Ӆ*]vP 9ҩ"Rfh1c}#&[̋MF uۤɣ1f2feaI?*nx\(6UfW`}Hn^_Utfj:3|LW%ҙ) l֊`,knl^Hy1 ,:'2^E", IDAT1ҏKla2dvh,z%덩VñP 'kj"֫RgFwȆUKO[MGOmoE rD."3"kogh*:g%K$wf%۽dRw7HwH`n*ԋvF/|'vvM 1pr3!{{Yѽɲdx *NPFGFBUԅp$Mz^y!!6oj r 6Ndt Ct"|mRx]([K!V k)>hS@[? n .g39 DN.s ab vp98*ap'NmDEp ,Br"g 3f͚u{as/},uz S|dgö2}@蓋o|i4mq,~&z&Ei4D?S󻼧s K2]bnlx?<0WS"<{t]M I|a' tzi9=q['\U6{38"~%/Jym)t0]((&42 tƍgS@1gLO0'S~w~?R + %G%oXd$dȖ2$""44(@Ī]2L c)l* >E kOW} g6'`Ѡ%d(4 8I/B_Y7\{:Nh 6:GZ>h0$` Г#PTBrLxv VA_Kgl(JG_)q@ؘtHA-|8aqzƧ}ЌJIpؖrbZ٨Ǒc-N<[槺/vǡ &Ϻtf<=A{-lpFz~y%J G]fdƅ_ ZWyIdp$h{R%1N1J&I=27Dztha`AMCȫxK?!&vĖ2|TP6'N3G^u̪n Gy n .p;ao؅!ZE/k6?Tt!.x?'€wڭ-:8[;֪aJriV~iCR_:4 LPVN $C kl7}l^ .t=iGgW;I5֊: A.rZ<. U 0@Ч:`ЌL#;X,x;K}:yxn%3^ŋ//HC((N@m.CV5p|qyߋ$hƋ&zą-]( "x4̥>*/il ޗ 5۟QE*bk|^_1Y]l>:s;@PEU] Ι;8a 0;Y"*Iv#*>wE#gn=7 8xmSE̜ӳhLS`ލlƨPO`ꩈFer ;#P 1^_U!Mpy bHAD嚠hTr Chu$;bS>ijPl|f2؄d3+ҠepqufX)7b;(h* Ae ue$$ĨjEuYݽ^Ss抡̓$=d]YM9{J!5 6U7#2-!psAlq,^,g0>ض+^v66w={dG}tu67`ga\Wfus ѿS 8wv"jExNR;oۊ.%2QO/wZyqm Dg3HBrpU"Hģ{@6r$2q&{T4Ub&n~YN3ߜ(s<#pxlJRk*@GB`.J'f@H<ʜ9a;;ق8flv+=Hzd@*:p{ B׮CE@(Q$Pmh\%,7oZ!ݙvPx]Չƭ]? L[ӺS;rPB܊AxVξ.l=e9%*qC̀xK],z=yS++3<=\k0Ay1r(sT|WgĐCy=g-F`56v y=SnǏǽ5ybKg mkԕ"_T2i/>oڢxɲK%A2ǩҋ"=@+5 E |7| e#O ɫUacre{ %83܀4,-nvWNkɅY<$fM ~IE>D$dbgEU a8_2Z)!}]C#*\ 3eNW͊&!M{uW"NRQ=2J^2S ۣp3ꚟfa8PH8 u [sI4&RHwespFT)} ',P7f 028@+DrkP^ZNK&S$@`m)Γ2GVopNt ;ڏy[ق(Do[5CPH,wuXeJ ۞jK{=e{T&HD;:4 b1TQmOCnAn'82<>E7 j=fyC)viC0o+[[؂b+O$fВq?#6Sev/z,x/H_k u% =ψ\/ {(nP!= Qwh; / nyEhK|-y pK‹\ґپ(^1bϮ,8#*s{x * Ă3my =Z$^ tξSv? KN}StS85 xyO` aɺ^u/l >PJm'3LCkeʺ@767/jiXePi6c"ilV'b#%bLBlh${xQ|`:`),jb~~#4L z >;#+!0 BITT.shdVܕ'v.=zgܵJ 5= ).Q.=hWx[:fC|ʜT.si|e`}Cp%Ri>x뻽A Wcy{ SU *\ X2i}Nś{O_S`mu&/fSxݓūB*d(n9L/F<Dz*~ݹBxl*@ +x/sHI ;K/]*ꏦ2:Q_ӄuI3|jW !τ(imC>F- LGќZ5`F;vFm;N=Mjّz/{'0z| o\\.#\vbe}gd PU#GLTk=ґnNRW-6zQFG Xi߻MGܴ ZfX7)!4]BH.*9țLI3].Ubm9I)h@$(jg| uKگ]@]f,,=HQt\@SOoɇ h(yvF&!"|v$ p Z݆-0(k[jKtI &)ݰNա7+8jXFNҌ춊AVi]sflG$D+WXmB$S7sNCuo.%$"Ԕ.Wm/beT͑ 89  I,TKPMr(0;8Vr _fl6youmoI-} qpm742-;["̸숐S/B^!2 2oo\ 1BjwCXca^%JNKY]H^x< =6T~K!Ŵ Jg F"¾R[<0mPS0`*&n 7!rsQ/xSQoΜ9Н2̜i5 m?/'p<Ybt$xV+JhEGbr`;6uƀ"6M\$F^JYF{+( zeҦM}v/V^a{L EnDžHfQiV;=y M\r>~˰};3E{@Cx۴7 %˨3hR1483r>1zM aDc/Wԏ T1J9j$vgkk9L08ND2cAdQo 7Q@D5%xZh2;SH[LF\Y)tn[r<'gP5+)H /jHou{j 3|S\F-V7J=V- 9)"E͜(dE|R{uU(LބSCrՆ׀-HrOT s!c{[dEi}U3 yπHt [yC'*5xzK=܅n{oNyhk=8>1L[Z $Mp,@ >5 mԒ"D$[rD AS RX\Tm v8JKГ}Q1m#O-R8U>n2|r%s#<[KbSHa~Ɇj/z{Ǫ^Z?s(9쟔夗{68 ,]^/_eA+a+<[v< ǀ>EoR#GK}ܹLxG >slyVXf`u[ǒ;ؽ}-t@}v`#'|Ā#2_8reIHM&VCQI\/6ei (pfDNiG5+A"=u~pk:1 NmBN:Im]n_Z䒐g@2q "r;Q&(!\gpRC`䠊|Vp6l/Ru6|7m } CuC"_C "zxf,8$<@Y=Ćh*Bnh(5^Xbߐ;cz";M5b \HN=loJT@nd쬦4m?|::8r6TU++&"P'ߕ; mj7bJRVkrUIbŶKÊ&cy\?/nZ p ~D,)>Jh:l*p3x~Im0 VVO?_f&oJAXA7[_>zc{4~LEbxʢsC[G\/de7a#򘟡LApKYO@WviRòlflXsؽcFF5v 6* ܈ t FiGn)g++T6`Ν6)9DC]Y*9%aa <$.ҽG&H;@ŵow(H=a:u!ݜ[pݐ-Jz[en[Mp[@^~B &*̌1=%^M;=oЦP[‘e{k v=#K<,V>s~8Vܡ7&EnVPg;Fp!DMfnoh?i G}wm{M~{];:Md4;: W/_HSTTPw<^Cqf`>AyLc(7v^n ]R[9rHGwJ!&g}8{ .hD;|4vQ[ϓƎ*i]pFg%pti&kZ9Nm/y Cx @E#_t47&j;8mÃ!s ":[' {7 m|\|_L}k\ zahnmAC |c*h"7?D_Nf` n & 5-SQ݊@KE"Ԁ{s`Ay=uPNWWWPl`[$QA ק3CC"Rڥ(*o/7tT9* wD{)D72{ml'd ?Yƺ)WeD$DX?:H) NaGn9k4|`Q4pĈl;nܸ@î)Syzz7a{,h[^+n;vꃷ Tp5v&*/ɐE~ҲO%O\~oXFKD ┠x%MfJh mRF,G(+si:> i>gҐ:qeb;d^ۤx(?2Bo%/Euc9pVaBVxry!ɴ>/<&n:*bJImAZE\d4t84vRZ=h&-\Gd+Ѥ?C2P?͋Qafij}U\lɤ/ͅHSƊcMڦ҂cMؘR5V\Um >U&yEV@VŠj2'r38y?h~K.]#ANΎ7n .~3j?ꨆ+ឺB vtR@@ |yڣxw퇆`J:7N4KKS~>TB|x>P3W&e'$H8e /׌^x=Mj%H/9: ҚL8EN =ʞ0 b1` QF`))zcn7i.N.bgN.;ں6C/d3+% JBqL(<<:+móa˂3Xy`tkuOXX- )`4y)F#MY˹24 uч0iHkF8䗵n̚) 2"={Ey  [~t6\-EVKm4FF:&P dщmaF { S#!G?j >&.499ҶHF.==+h03ΐY\AdfNG"B%;O{|Ȱxȵk| ȇ0B : ~G[u- M .DCRl/'֚²:{ MNe =&Q{䟁A/@^f&%4h;} <qZgrGZCTxw nfi8?kw#2^YpC\S6>eX-&3NWkz2I}:EoƑ9xI)zLhX4 yxŦDL+Ur6QM&f' I-Wi,$ y:mlAyQup*BKMf$"t3N!Yv0+иfvKv"" k ZAAEtn l+Ral0Ki95A[M'9fLؒ-rܥ#/фY:qWTXspx?J[N(d Y&WHq|y,2t(%j&2Z/&7^R/HzK*i0GC4yR#ڬ\nsN^Y`|boD dOVBoW˰dXE{Щ$5P(o R5ڊn\y֞E<7K~8?V/2ؼѥO.hnCh ZH7P)Ac,R7 w'[vx~@->38-#-+-{+MZJitR$BnX[Zl^5 9DMtGFkimYCf'e)I~7sau#ZҽWLCrS!T:LE];d&z1>7FW3;\pA}W K|xn&H".t 3="mPt"0ͫaW%4qu'!kϊ8ΐx\=qqRHO i݃b'ИAh9G-E = #U:h` MG|dHwy}e7y~G6]^b n4TCU]\ 6DiؾΡ;۫8;q x&+`mETHw$ m HΊ]FT dx uzl+IҝY50Z͟—.?z%tNtQ=C.KA&C4fG͢zp^'\s ,Gc-@5ڊnȭ|/!ݹ*{58;V›ʡؼ:`tb鎅$i:QIDAT66BcA%wqyv=[csL .[fCtyA#fq +a 1xx~]7؁AlQs EWD/sb.AHt,aʛ*NnSP(Ģ4$dn5Aq>(GWqI7=-RC7iD '%TP\0p (EHA\$JQ-辛Q=gԊ.hȃ[t<M[i>@7N՟y3:Hwcih6JX]}{bҪ ]M-%L'w8j1*QpGo6fSFUm,dSCdH7zٱƕD BpIBZd]Tniwi} D ;Ά-!@{w Sf  xo>Z.j S"CaB%d$S_ڲ.4bd =i~\d&;6=Tuy ȡqtfFGXqզ6aS0w_jJ e< qM{֚OO#J_4&* K&CɐnL* ;4vHÓ.ʃt# ZFФ铣a3Mx%F7/F3ҭXf"x>x]^SPn9Ž==( dH&$vPhE)n{9.)|k"KrEh̹ȺX[ͺx\nwJ$IENDB`testng-testng-6.9.5/pictures/refactoring2.png0000644000175000017500000027021512551235562020611 0ustar eugeneeugenePNG  IHDRVINiCCPICC ProfilexYgXͲM%Er$HHZҒsJR ""`D `}>ϝ癞wkzm-8 0fFa9f3Dae`AwEZ#QЛX?6_=E>08gd s0Dxp,p%TZA w=08xd YA+ BP<eAP tBm!4=fE3F0# R2 6acT8.+M< Px3%RFQ(/T(**DUQQci2jEѼhIdGۢIt":]ED36H`T1FoL&SŌc1߱X,3VݏubسFl7v;p8u9 Kǝ]ƍqx  Y  G@dBK](6)((U))=(c(s)))SSnRSPSPR*Bu%<ϏW[#b|~A@-NKDAC} L"8 9:B/aNCKcDADSJsf#-%63m,m!5Ǵttttntttmtt2/0<Rz(QH"wXFF#F_,!&&y&;hRNif0?s.s3.mO +,,kZ?xZ^-٣/s0rq8299sœVqU߸ pr-s3skqrpwq/y4x<%` E Y==*{TԖ˼toޖKmK+HKWKa1Ii,+.K-}"G3Kk[/@T8pLG᧢bE%A%W2IeFe l*$ UEpfOjj~jWoN_M9iM>M7JY--wbھڗ?HYUMCe 3Ox*v7ٟ҈ˈdTgbd`gBmbmRb2k*nj~>`|ԁfBff-+ [XK R˷V2VV.֗ڼs[׳Ϸ>(u0١hXӇҝ&>Й߹Ӆ+떛[7w#2.QK+k[O2Y\B^[gwo޿1"5-!//;(:h$X"8=x:D5tJIhMv85y9HԈ,\M=#. B:4~&A;|"ؓ$4HQ~G%K''MOiOJ=:fVN>yLXqq 3ۙYYY[٤2'Ox *斟Ğ <9WO?w_O~X(_XQDUQ4]lZzF3[%>%:eeekg=Ύk_Ȫq|y7++ UUo_PPW^UbZھ:KrNZH^9ܘ"_u:lsMڕBnodބn\iinuhi3niWkqkוֹ|L]T]];co^}gǥE'}}CwM>gptVz:2>okTsΘؽ'FOG&l'N:MN?x/ļ|EpsiYs7aoSyW бh8>~I՝_ؾ\*ŷ72k77n3j USg˝`P_(|yOp@ja,rBll텖(g=[ ԧRKQ%H(ӚйG0&10Sh5/qqr7>&JLAIJ*m'vyvhqe9}4~hYi_3/1X/oge 25oVM;gm^CmNk\N&;L=<^k3>fdrEBKZXH}hRy8OȜ(h1%qxlXbEɌ)tit)3;YN<=9דvJA39E)qgbJKn.X>r~rS j..Ծ4W@E1ě<- mF;;o^A@NhA4-5<VF<g8;Yⳝ/b_ʽ\~0z4vztlkNfnͽT/v^_[^pc'j/׿}Z{`svί @M12a_QdSSb4BtR D;@T*>%vz N2W 2">bK{B%oݐ֔9*{_`4BTPׯԊԮyW5p7_o4`h `11PTfܮ۾`C!%'ó}.5nZ$NҚLjgW{ۯ?0@?=CPŰՈ]QIZ1', EuHъ䔔T4tc|ǩeff>wxNhᓦy /,b)?CU.*Ztv|bUK54lu]6h0y5Z-P+]_-C]K4T ksO>Ob mca裱'E Iϸc/x֫㧃gf$̧{Wpa}R/>Vu}VßsB'`Qx@`u\'1J*9< ~!M9 XHb c Ss:K.YF> <:|)UwEhDel$*I.JK+8ɕVRVPQQR#KTӨҼա}W_wPo@mk+2MLLyMgVdNPYNX]Ѳ>uv,9.t3W[ N=yzx>J!Os'dAACDBS {^9\Yft]],w(ߔp(ؔ|dTc~ǵ3X2>d*:C3z2?/4B[7EŧD8#xs'ΧWVUp&bBm@KjL57_͛-­,۽o%vq~w=w{umw~Ã+ f?JJy67R;plukh2i峡/_YO從!ϱܻzj]p7=@ {Z TPmXQ_T&4D86ޔqA>XDEvH2caXG*,~@T  tz #Y fª`Y' 7JAOaIqb҅#2U 0fC Diizӎi]aah$]2`g` feae ag8 u;ǒ_@`PDɌRғ2e?ʽЫxS%:KjMZ446thu a35?jbkQnb†V. >;vLpqrs[&qyhz{xi&Sx|2#5G2EGDz9&$IvKy>~!c+k!''l{qqpIqYkйh.ՙG77q7Wސh)opu7GFzbchFyԅ%+_ؾV~X{Q5k %dUA *#Ё\Dꂦ p0\woQt(U'*u͉>TWo0l3LHp^ZEE'%҂,{*U,xy| &YW]I"Z m$nޝ=C xѐq)Y9K:<[Rv:Qb.wn)3-`,(#!L!)Uؖa^W 6r Y*g! aM-/: F&̦v ,h, mv:bY8UbZdS|~\!#CË"\bY% $eYOMyf{\)!?$%"O5CAkaQqrIHK9Jj ;?׽j۵;7j[Eۣw^̃OGtL\~zycSI1Qo-D? yo,,6xi]'X{gA~K>  }0 v .hty$ ϣ(mBM)v1}=c&[ |qp crry DM%:ii.ЖqU#E Fmτc"Ͳz-݈cwהO_\OGOXLDQHE2Z^m׍os[#[[䭮??)-_?KNvwB?N|ϼʝUH|bpev:>IA pHYs   IDATx] @T?ì,3싀႖j5AEMJ|×&I撹hhb"$(lwf߹wfU0sęs};wsνj A @7;X,*Ⱥyk?xòƷS:uyT*5KDcײ$TJPmmk/B,?a.NQT:٩PijdA^*E5- ~KoA @ XA<%  G?-KV>c_u_?r*(Tr ,A1Z2I;Fj҉X5OA'5&#Gzo/tDB!C A#NPTx`3L] E9nΪY&r`)AFÐ ?(ϊ;G){|GH8TO#Gd '4QCwpEw0ҁ2rAdaUUUOd#gA>F  h4,Iqmaq9@`V-N`os9XRll|NWe\v~]  l"R @ <Ta T0&qV'alg''ݦo5}]xFeg=3-+'x_aCFv[DZ^RH3 Bv !ѨT<`A)n{ |OWxA К1ΟJЏvB<|ŅU3^ roW!䕕'IiY\Gv}:7n:dtj l۹;{Qtҽ@a\i'Vi%jV-J<#H; ~0ah*y`l [TpzR 44,վCo^!L˺l;_ L\s?H`(> 9D>QW$[`myyEII\Y}_P#yH^yJ0Ϫ<{ΟL~^y&Upd/^ W͑m.Q[GUJ* oڑk"Z-Ne߷eϨyM 5!Pz<0 s .f˦’чK^GF\+@! %%eUݺ>BȫBN̢>~|-qm<$h'I@6vIK GFA!bE1eCs@$3ف gMC͡vyy2gM'N_h.J Rg+қ${x lR-h|k OOT\ֶ"}1x9e%UF&taܕgݫ05~?> 8~ZSP^P@(8\x T҅mZQ`MM!hp =ruvq_h43Gɖ)Aۯe] tAV%MT#r#"bLij+@6+"ˋ~8gZmAA:!F ibM qh` ƚy /{Ѽ/XAWϤ+sSB#"d 3&NZD5Z_G=`t&Od,J]5:fTnN+n-cq %'3$ҭmhAgeDJBgp<}:b5?XˍoEd_dq7}R-ڝyszƟ6l~?{Fc H9сE۲^KlQ.33oʴ1D^ D` T_BP˿XoqwxXRX^UY_}gev@@eu|mlG90@N"[g<kPO_h&ٰ<3J6CB.uyp$\.CF~BbmEV$TTȴ91NkU9@LRJ+K/HD*ZX%I GhnRNN(K+rVV+bRJ$iZ-$%GZfl6vB&+χUFօK% ac:HHvt062C["V%РąIڊm(|SE`IVM(BX#ӊӢvOYN#0 :$V/cE T%؀&XHUQA[hٟSRQ'I9DJBI @1r?"?:ͅsd3V 4rpƤe~\+^2(.MW MP X}ӎ6T5~6'9N2Klik)6>$ 5b6[%UKVlNu_[>Ա¢"㿟/‡R?ڔ2~x\ɏ{zժ3??_^] KF!UOU+W*+T'?pߘ ~לP|9v񆗼=(bKBղPݸ=ܝܔU(򛡐):kc`ƎB傼՗r046!֋ '#(r흗. ߴdBQA~ٵ.~3`]Ն8 `_#^C@S() :ΤQt~H4db9\%.TNLߺm/|(}iu6dTu%bv&;H7R=e;vE7h}`w`;Z +8:*JhC*2.вDYFx̊QS_"''Z|0QLP^]~g·qxԪ"g';^]&Y(HۻeYXଘd;-=uWTՉaygF>fA50O:ue[P܏N >+Ffcfo FFSoՒF-qD1Mi iD9#=)_/]'-dFC Ս9!="s:|%9DUe-mv<6 y\'&?t=%GA6%dt??:Β[D,D/-w9("̬e(!mÊm.GO}6câC`( x`v\dOYir(;7sČ}F=F3sco,zX: kwrU)#ș};7Vb )b[zPoDI@ILjFpRV剳 *w,r]F\H WcS,6pZ:#=0r]}Й|`G9ilͳ^(hoqLU7|W0>ld}JG𷑅<N42:cF#3I %׎M|}w~6恹siRiSoުں7?'zd<((MjJkOrZݬ|;{gv<۵sَ*?Y3S]gi Q_L!x筈,'—hvzoꆔEm10dI4|xIIX51 <–[ t.̇ l Yˠ('`ý m!HL_ybsR<|f¶ D}DlG%| 1E6z@oڼr6 EvK*$Dɂ!F-t(R"iF8Cq}>c/DXA #SQȇg$076WX!S(񫰙P\ o<=ޖ)U-@22 @@ # x$`bL4Zc(a8XkP B&b̌ Qj%M A @ 4 `4XSZZ g?AX)X(|cDp!&) +}y>!B"s:NEix-kgˇ py{cjG61dP``,A @0G0qOg(Jt1qA~E8=扷8߷F?ϳ~*| o !kŠ XRSZ-pPP`% SXJE! &z ԡ0zQPf B|ԭm)@{儀jrgJ1v42e4 l)ҤA @x҂l%g"}xQ};Ór0ĉ0?YNzS1=&D A @  cZ- U;"=i-& @ <'"4?Xt+T6)I(L7y@,f?. F(}R A&mO, s-Ao|hAl6GP`CL5*ЖߓB [xA Yzb]@P`=DA @"v-?h,q_ 4F AU+HM=a۷?a&sA 8 ~(A ")))y"&A sm0O O(Ў!f@[#@(& A EP1,A @hkL=~x[# A "0j(v TjV @yUY.K?yY-P8PeΩ"֪+vA=8-Jרmݠ[H*spssKGT-biC^O]\ϹS7vjJNQ֊,5[yِy*[t9O< GF9m0T~AF! [B-BT"Uˠ '4sۿ{?gjLZ,-!Ϥ|\ aY-7p.Z?$G[ri[T -Sȵ{gqkA6(ů8qI AFEj).";^싋~Ъ*S5"ЩϟVX V(hnN.dX+|x0?#g@8f1>j IDAT?0c}2ֿ==/QBYbl>iZ ., ͘{EEWviKc{r=2c6G@ \r[Uth%mg+`zOq( Ry; BbhCH\2LuX#oa.xz7z 1+iuc8\%ϊ{2ux\(doZ5ttκ%{is ?/"¬NA @h{H-AT6} Wo\,OB@2ŷ7}l7 uv}a!BCV#R)(~9ɢ7n:;Dܑ;u7Fnqhǒ4+RfZ,oe ّ蟑G-,:4v{i٧jGTkqv#@=J zj+is.?g\!>ʈߚ?΍=7_\CAKl/.>;/wԻGhީTQrOHua$a·'rXܜ5N]aFИ=`ў+>ߩ(uӲs$p,Üa%˽ڔqkRQCvߺq@Kk, K8>|9z9 ɉ=b?Ï_2?/.,GNH0: F*wں+غ@1O Ɖ P K! @ `KÌa"F@- Xрѷ˟`Q0 h7XLՄ#;JYx*V4tXwtZܹsvvvg$X~Kz A({c}7T3z2I _. CK?@@,q9P 1.ӭaƹTcx3ܳaZ1Y2q='ُ)i1]!e VaaTc|ʌ4GdWdi9LaT m^ pdHζzNHևG!gUyz(A @h44fg:ј1z3zU qݻMT`AM SJݜD*Eg$cZEࣟ/:n~bccVBbN=^2&L\^ )yUzj*3e&K͘1UZ=.gWL}1 :B΁zQUYYUC_]SN Vr\ڡb Nc#?qX=\ hJi0z,)l:q!OkknZFNQbc<WLT)Z[ȉ]LҤŁch-Xp Flr.|$ZFVEX$ibZRsYs05Gּ;?/1 @/^r;?YTb-Wau(zקO 譗cSK;$c>~^\qȇ >0QahʳwE.R qrphnWf'# JAxrp} ~×D zz.弼7AQDox|G]sq7 w\y qBOaIy>dBPI*w3w, b͔1#:{?=';cЍ5Џ3]vヱu>܅Ցo >>lTD @!0tikcZ' "jK-!˚`LZjviZ(B6!n`š|Mg?6,w/>waJќ0f≙eQRO&uzx [.$TR(pkC*H\ djyf-bٔI}a,M  +E.,x5˛PlU7tdUˤ5\3&!qr)vrS@$@{㺁#bPPir˄4vVAqR ܼZㅣ-AdVCeeP r#'8^r$ A fᏮPcH$Bn#F#@(1$A={v+HiYthR @ tbf95k{[A @ <RSSU*\Q,s\LV Ihm033s޽ }V ,X°+>pK O@o"lB 1phd2FK%ҵ_ySfc0x#/w+c[бcGCzD^|L}rNm/SP 0`w$T D~$B. JR`שQ_sA:3?tٻJgWɲzZC5|f4Y~Xrȹ^C[u>OzS}A"P&) KFAy<!a4~S:~PI eH$mټIAs.ٽ?h3Ƈx޽8øɓE=`D5eʥٻs4Nak_D3_jYM;>Q~I;õxV_|d{*r/w)nAh]ܮ}'pxfZ/.unM A @x4tj.ę"mHWʤ][7n_ӮW42͡ߗW Wg% YJ4NtPC"K&z)9`Aƈ?G DGEQYXd2GB7x]Ŗ{ xPk{*GWK*nǢDt]&On!-?*(>A 4"nhR,X,P& BcaRK(]~{Ӻ*g tv\AeC2x___>};䔶3bk˾JM< Vݹ*p ~@owPR-k'g_) KNOSX7%g%3lMIE8r`E.)ksa7ToK]+W0XۍUjTgőbFJ2c,kt5yyVмL3G 'G: ^ ʊ&7PH ~E1x10L5xU^`M?_Ԩx2rh @ 4Z Tw˗/>}7o޲e˾}Ξ= ÔƲS U8v~>l-6ofgVߋd<;VŇ ˜d&#Έ{c/)ԆJJ|`,e˳lB OC(0vgv/83l=Vhřpu-8lgrJ+V?>%.%g_.TIoOr|$}aҲpNt5-G:y>Bg*hK]2pZ928?aK%x`J3zi}?ȦPe;G`vrc|٭V,*L$ŭ^M&/6Ǐ0W侘Sr0H30sQX&.ɇ3Z 7Fڽvƅ{ڲMe>sw w9_pT5,p$*;yVR=>v拵ڒMmV^I n߾}8-g\ZKCO-ɳ86< Tԭ }\z)߿Xc\WP٨C='˳\LV!W/ (I(؎ ̴B݅!%}T~ jwȥ\fm[Ց=3=:@wg<߽ Y@ uX} ?غdHb7>_[a嘫6߅`lPUpx? N*;eBߏr`JI~<魝(ɮN<}Q1v\e;p9Hvx(΀A \V{3wqY"^ݥnN~~~f@;{ ~cV EaSlUj Ͳgkx3aPPݻwa|ݽG4$ e7%+Ne/UAi QY\4tO r#_j#,' Q?neabU+GbJ$G(ti+Ջ,ΥC/p `,-a1I9b8!Ud'^VvLx~aAd,}e#%910uJ5G2dbiVVg"I\ۻZwG"^'Þ,9X<^<nׯ qw ]d,t=9Y!s7pp(q*4+\ϱ?>a|VXPAQh٬U7X\ƅ=B7NJ.ZnUZPj4Q?eɱgw!46|t,H| Btf ؅(̬9r:Vp@:_#(IiUq+8}q/hC 3Xݸ]/,;E fcI Ff/i!sB0%9p=BY"jSǼ3R`wA=l߾/ ^b_Aڻ+ KT 4\VMQ\^xBxnDM%xfeU|{GOJH1D2^$5Gm 0oXߖ %eu@PuX koMt/wcF3QG9)øPŝ s ,ٵ)p}C#X %rHH\5у 8x[P+cgaVr:÷p8. *S`zě7h[zEe~\00>,STFu rH @ 4,M {^D_AA|okkhoD"-3Hd7&?~|̙9 ֖ŠSݘ4 i)+ O*?1̋9b|h̼o`'*`t;=M9Gw8PrLlpcJ"qm8 #@GJ S yWB]NN3e( ]L WH 0.%7Ee7*%\gB #l0'1vf9o3n\"Q Xb$[7ɕ Q6Yj 9p*ϯpX}n2pS@^g#XNApv *dD̪d "Y<6:^z 5jA t-'Mڏ]Ĝd`=ԩS^bYY)j-Ki??}n^ɏ&.yoYL18B1q@)uX eJxNMo ZGVgc,~tI 0 (G!B@Tj1)) eD!fA R—"@Lf[َ'#a\()G>T㻀VFtq̳ o+X@ ml}<6^a/T z`C?>i!f-KSu:-sU>[Wkk+~L}CFb).-jQ9wtm{!@΍W,+Ba/eiy68 _GZ zEeXU(VB$2w%\ YaݥAJ3FhO_>8Q}DQO>g}ӃE 'jlW'}RP-Bl>2qtl}Ը._5^UJCGkJOS È{g ⬔4H_++͗UZ) 1lXur#Fa<ҨF%{΍zMm(RPiW Yk?!a-X夆-snOǍBR]ie.&Ӫ= ¶IneK'ZKg\`L9s`JOup̈́K'*f52;{rP_?69GVEnV]19jٱG9NpcE߯;{1sAfٺtRC%M@? Ka-ml8663Ž uw?8h=▹4LuUZ ~ri`PTG#vqǞnt'B2jMVzL̢N=Nv6%>s蜲T;9PE^Β3zl'2_+^/*4gvRyT6b;Uz ];y B}8Ɇ)B{ C/Ysv126iT`grvVey2J5WX@'ʸXuO@G9eݭY)5ʨ:.zszŇ hSNTtiTNH:kg5vř|@QGn<3 _y?P\n'q&ܩ$8쭡VpiGeRQs$c vw) ̠ {[ZUֲׇw'½#Â{Ή{wW5B\<S\{# HTlDaƁb\ F9^/+Lʪwf/z1. q4r s繢;_ \{^]h%Sk4%9./> '굱1e/ͷ2(3䕐clgPv(Js wP0vNV%WT}&$~Pߓ/{;[UPF5ȋӈk.51h*@W Bm``A8h^ eǻl ;ȋ`\7Pfk֖MmC΃8.ġI'f"a ab_lN u>Fݑws"1wyXYH v1l5WOˀ |G^T}L l `9*4;k4 `i8cLM0T#B3Kcz7]ZM@k2tt%Ջrǭ+Pxm`aDE)+Ub)]AIBֆ[ک$s78ͦ[5 /?˹pC-z Չ, ]?/7d:L0gHуsvr^L9c6D*AOD-Cz5oc9DXCy8Nѽ~V n(w4b q lVoE蠑[h*~BǡڭWt{5pe,p_poXݥ>$ME~9@xA !Lң6Z<;/ˆ+PO2d [f<׿JҺ[›fawӟVEQ+1[;=(yaZ]RAVCn\eqcðIKL97+:Xk!^ 5ƹ\\r·[uHv@' w+ J|TdfސוE۝^~KzwKwpK3wUY97})KKIPnOձIΤnf wqttfMݖQ`$(oi9eTw:S|ggf33L!K] m7,0-;bK80>lpӪ sҋ&W~#O;A);~}u#\vϱ=d]I}%c$clí]$,\4QzvZS>`rs}k$ Tw~~j'F8.[$WS{\Dw38|VS0p{T;Ma}w+j<Ǚ_^wY5j9 &ۺ ] VynT?ߔ\X_Ig)~?: I Z K>ejSx {}MåF@߅k`܁#2|ݭz)P .rEa\== lh*1ulx;{3ǜgTvu1~q {vi&ئ/`9S'nYڹυuP`]+ew~]ub8Yݱ;nKiWL|}G~x 5[Diy_n}*EgU}y[2%NWebzRzO SI@?/ؕVjݝkwZru ٵKg"NH'aܐv_JN1/}R`QK'r<`ۍfw=J椙݌7F;\Z"Sb WλZ`ǵ" Wœt>O_x~9Ls 3r _ @onɪnҪ]jfrUdI:-{gK9ePGMp,aߒKew:5@!d]|+Svb'm՝0'?]m|fJpLL݋o g!]jh`XPk9#5mL0|saenb@PQ+.5i `6[R?pI l 5`f ٷ> _J\RU?:,Q?k=~#K+'PX?ŧKBE37\ J z9EaUy]=O_2 qeql2a9$!ݯв ,hu6K;U=\YF*Y{'V_e[(zW‚^j,<)mY5+-1+E$tvdX$Ίōo t xGw Gc Zs~5sQu {v)ﱫU_ǍF?hRhI4Zֱ),x!;Zi1 4cKf) @ O,'Nm0-5,xA ,/bi Z<AZ h5k$''>%Kfyt9C'*M/в-̽{r8 XJ S̶F$,vQM _`Itg/kx)yoAǎ2喹2yə'4bA @ %-/^/0T/X2WJ߶lMdf uW㖹Tei%8Bwg-gM( MJ\;rWk3iP FpǖX/0֟j(;e o{= p2[81-s%#XU.Ak:BYLzkZ</jH \.r$kdB &iL.b@vLZ_RZ f*~M,{/x Mn)}@eY` ~Z&` "*.{pg=_-s<9;,qjW#A]sԭ qI ׺YZiuiqkCJ! o{^sA5hv/ڹ46W5+:2R M.m{A[)픫W˪]5*崲M᫫öEo=hڢLGt )#|}&2>^sGIe.ds Kϟ?e.DPL@ن?§mFS[7U[!z,/k~`6BTn!Q HM?RE zxu"8Ks fŔxjP 2Dc>>X 1P NUX=p,Y]qˌ=Yg]ZxHBR?NiOJQ8$=RS9٨`KHatCeHr25UDa}CBC[B僴.TUlɺk㢲Xq^ ^0"d+Xup YPLhY*|b#[䬵9^6`6,p+U#v=b~Gq`b*%TAg׆:2cFA"\Xc?J/=ۜ!+*|UVtp*h O!ABXb؞*D<+[<&Æ𵹹rY;0Up  YXn`fH`[0B.S]ڐփ_ g6Ua J7,ZYȻ 54 Dgx!55m,z9/dήxhJ̝=AQwٺd&濑.Ӥ}YHM11'lHXI*5\dMF:2F9DaЬAhb1rTX3w.vTd "JuFPjBRr*cm ty %Foė8SV%B,Bm%(]'k-d K-[ ´F-=ReN lkanY:`KlJjjzm2F1,PaD\[j䨮EFcMe%Y3* u ʚD<Ȋa&:d0A&P1# tdPjAbM 5 UFW [b uF}M%[M7v}Ij #^Pa=̕j %Lc u*n*Y7"J:' ez3Uꓱѫ24e`4uNo-IOeP#oցurj{lu()R V΂aW'2}d0Jtۈl-9GFav#czxβH5=ioLv'DR{.jQ7x9y@䊘2Xb5E.`ML[EgBa.'K*]8{`#=X.ХJ;d(Ϧq/indWd8⩚Y8YCŲy D[~Y 9i3Ts ˞:>ъ@ _iQݺ-Tg@ePUX4P掝6}W[H`?v⾔sɷL["GhXT* LDJ)f 2C C^x#TIQ"/!Pt^=|OLz2׷g>=Hhr3lbnĔ;_΂x{s$·Q?{TN '(WvLEEUURw` \Q$B1̈*Jxt=,}ĹuzmE({^5"iLUySfy/ <}T{5W²#3Q]{^< ⸆y A{=TRs.z ]W"1Ahќf- ֢;[V?ࡐ&%0 a8[eZ }_ 7ux g/VV#Ž+Z[>>f0k1ucgrU]8^ ,M9\b:K[#lݍgu<ܮ| [ #{۠U>jbWƀ6_ b@i,N{'Ga5 ^yvFjIspO2UV=r{rGUlҶE ƥ /468Akko^ *<󭭍?%rl2m8ؽu&Y0>^TxƠ]^ &T"UoԒ[~n!p6./ZKRyX%JxKϺ+`ua>5ֺhI`UPD] L'\`;UdL$!8U2&-4z Jࠃl&IYr ;CXB>0:~d w he ? ylu\4U!kr# ,$2@,T&; 5qkޒ'vm`c ,Y7P!X{'Aj Bnr`GȘؖAb+$%8J6EJFϫ7Rey1I֍yvLM @AÙ d聒L+y)oЖL0o*6ԅy /;^1_eXy+e2Ț ~x9(*8oD3ԭu鎴 Ǎ՜'O !qA!VG㶐=i$j,F@^>#,)`W.G|Tq)cŠ[);|` V(ew>(e.hQ9ZW9 \Q .ۙi)e.a+ŭg4u.x8H:@Y ̽) +h1,2ڈ (6(e.7nHGKLC㕺MFpRg§Bc)e.|x,/e.b]uRR\J 'ns7N"(eit ]c'g?N{za^>WpiGi2@E)s/nҬŁWfhkN4}s6b;pG)s)e`pDmd2Wyˠq?_aϦ&|<]iԗx}JkCX^7 Qӑ2فQ2W92R wt G)syzQd!CMp~f3t.l|8)nňpKue*N8.{AP9#<2RR\)uSbp]sw14Y.7Y, Pjg2]65ZLFTWS߹sgjG{2h1o0e^ |iR\"2S\Ɯ|Rl2} 8c #?/T>QLN;BVr-)0$1暈w}' 'KǮ࿝ǒRYNJ)s%i)e.عc^ k׮/?|tRkGwW͵KNn?g?C'O?~<'E~/Rr#vKJK)sк dŔ2Dl~>3-̥G Dԩӈ.V]:vur~tmd ۝\ _,rP\>L7?N)sAE;wڝmEEEKiQQ'tup޹cڲ.ԳC``<7J{kuR:Viwe_Ҹĩ# ]O_㴹Åjt<۷gg$^/rI_!nE"@Pn:p2^i0O-:tڻwo566mrs2F(E&"@\{.\x"$œ[nxJj\ ̽MP(> 7xf{]vt"#Rlܡ Rh E"@j]@+={`3?]`{5ԝ5Gwo%[+~.DskuhCF(emo=*l7Bwi0JH ]xZz.Qʌz4أjUgw Z[WQ)8д;o6ܝNY}\aW?s1:SI_s]6,'"w=UL]ڐls  5寚VRy|ClT0%$ #fړVLj9TtÂ[Ys*2A|pCŁH͂b ) 3nI[@ p+i(bȈ_>lrmYMH3~)*H`~Gq(S:?pB*74Í(*|b#خ]fP+ >Aš$|GYɊHhx('<+[Ugz, ƇˍuMl;~y{e(,׷B\K3 RV_Ԙ`܎fl[^k o|xCJVsd:473r_ٳ gyT.K/m)u~=3"EyVR4u=-A<{u @oҝf4|˪W3}`\ {F*Rz܍T>^J H.~1: !}> s %jԣ/ xW&[Ba85ŵJWVytG؇ M"#aFG[, 1{igBh9sqs. ׫g~{"4nܜąϑAcZĔD(sqd ?6_/XM|}{L D~ы}*Dvtbܼqgg(]7%*nPc,j1+^;9'Yl$1rbы} o;N~WԣS4W1^>^-53~tA ?U⋡x0-VS۰ #wYUbQ(sUeIƏ$f O0)1f"~qA_\\ .9S@x+&3ܾ"G b{,49UCm{lR=saPFD]|πIs.z^ug,,Z9&m\eP#lxVo?gxU4R;Am[چ؀ZZas얱aPw,PL ϊXOn9m6#rvG`9 a,6 bTֽ .ֻR׶0mH`_mV1P -:1/1M-;JV,#Ò6.Ͱ! 8Ch۠"M@hڍ9 x&)11X~2+ˌYpHl++XD0 3jSm-Byx5E_2Sar} IDATҺ&ܨKd$>e\uةxeo!2 v} Hl%JRme` I)2N;MNn1I^[ٕTi"gW &d=mN@}I&7J28K~J I΀ ?KT.Hl$E\Ȃ7^{mdb1q8ȇyۀb5 ."g2,iI,@Oq68qẐ)|Xp_Ï?a.xi"YŭXskE]^!a|v߶ 7 ѯg]2~uhNh׿r^Mʛ.D+=P[S ?[ 41*ViqA mqy䴮Vrlmf洺uW͍00؞չßw1߄} Cdb c.T3c119ȎΫx97Y컹||@ eB9=$ODcB5 5B k^( -&3ޭD&/_'ík816qaKmBH[f(i%Nlfjnۭv}vlx;e7nܴiA~?!lPt60>^sGۿ9h3F5*!M+E?&row/Dgiρ [4s_Sd@V5$REtV6CRX5$=K| ExpJDZ ϻ-VNZ<Io/*N.CΌgɄ9_Ŝí Nz^% -DOu06t2x^wZ5>i{ 2/30T<^ⷶ|"pPx;OO>#ɞ ?hg߰T8!:Epskhr֮9 E#z{2$Esn63->s+ صEMIHO婔T (OKII](PWkTF ۩qYބLMMM >;2,VqƲT8Tz*ge%eYZTk4TVrǡX[R$D|z^#l$؏+ %aB|V7 ;m`<9[T +/^V̈́1vjZ} Cl۰D؆-vubެ#ɣ@SJ,%[~8ENw3fe)SvdRPlP2Zq>fF${8gbT=-{ z:8b'֣!( 2|E&N]=/2P a{PCs Rv Pq(uez05xloܞJR!L",Y1A3^ǃ/b0^*hi H0fѸ*b%z7turu[ʈ qy+"UmC*,$X[2B"V`eAŧeȧl$$؏+|.PL4rn:zO(M92D%|G:d$fW~ q/a>qڟQLθ@> Wjϖlr o5>Sβ(&p\k0 40,HBLP\[R/Ln9U^ a71ŀDxe3jrrtuZ*r,u%%V#EHtq0@ Y)ǬLNVdu欰Zh+<,/̒8Z혁138I& >aɕD! Kt'q4r6m 2(&#O[5kE`isGpvg ZP64+QRڃP?N\+{:Fȇ3 ,Z=5'VBY#Yl1%}>n /!>k6f9jXƯT-\ۃPY3m] 3Dyn3 m!!ԏ$3Av,HQu>.l&b1K *PS@C֚wmBن=I}^ EfALj-IB 'k<+b3a\/@`Ts(s0;[[ryц/!`Cc x,5+g-IWbҖV?1nJֈl$)j&PWme ?>)p Yj^Sh CLj,c9f! F٨q !.Qȑj 9#658(olU%W>\nAy*]OSx ]@wq/q1 QBk^6gB?f{`q,Kp0;ܶm̕ >&Ig h+`|(Ow{o#%.v`r,Ƶ<0'ăc) `T4D9%E"@PnqN>} B<-BP(3BoP)E"r l9V4'E"@+{@3ѮGCP(!WE"@BݝT{E"@j jhAE"@.?=E"@\5aZ -HP(5Wk6̖'xeysqUwliӤll~ͻϟ-9dtHP(v|wvj Ԧ?̮>sf\;zU[DHb 愔]`YTxk^P P(#R\\._@G?Dgr8ݮm>w z8GX!>EV+ 祏wI(??o SR/H#EvD\>B`",>"m>OYSx2Џo*yt}[>WB`^>e#%ñ.e0+r⿃/_ڵ=t+150T[E""}.Ocӕצ /Lr܌7pLl!b,f0upRw捅d3mC,sGW`h!CvYoj[ׄ'IXR0Ttxr(dyy<<[91Xcw+_^a"d1b: α;K0W],Ҽ%$),`D/d2<8-gϿ!nzm[l>^yUhRr]iP]B7Dh褥ݞ=ax]=񤱥W`&/BFp,y^B *hp?MNp~*͏o<9hɖWUM&p羉1Տ.-Ѫ}?TŃC苂""G\՚VAE"@prx3zu`?-OKyΛ?i\Ac}F-G8c?߬[z>oO]}2f~7egN&.gX27gf.ډY[8:ub.hݥ_6IJٗ~^V/[r`BlM>&FtdLK r(r (w}_Wn/?i@xA.+rw 勤qE"p#gU 9ras]LL?\v?ۀײL#_<d_eaK''V_]ge"gX\MDck޽yk| <}#{_NԤljI\ \Ewg6 ? %GSd$׺\ J*HJEVA<7+kSIHOH ~Og} ߰nϿf4^'\ct'gN [LCuu[ԙnmPZzׂk½Wo\C#E">`VP(E :ޢP(uwi(E :ޢP($ӶQ(_-vCIT^R(=|n@Mv Q+BzIze9(ypP3MHu}P(!@]FKQ(mu}P(!м l?W]}]](TݩFi 9 yEh E"`Eim`El슽nH!GV:M d@XelJ.|70$d`>+6ke~iHT^R5p篎zgn:'멖837]y6eh7LMJ/Nx/ ?M»"pCp8 l(>hЦzs_U#t|s|'[c}}՟7V}~ +}jo%UϚ5iRf<]m;wgwS'%|}cӋ|;5՟GzyC7q&X2Y'@ [cg}u+il~-;k#6UDzn<[@E6Cw^=C B 2 AQdR`NwAWL%?7"Q}|c7€k'B>ndMz}Õ*c<ޫ`_L+*o,&ˣ(JbձZȠ#%]vO{F#8+җp}32sFlTV~3!8.`5KN|rW-; ZϜ9}yzGǦϊ Wú[b|M ͸#у3?`Oښ܄YpV%mTTzq%:"dPTM?dEOBe%{7ptf'`b+ϔq_P{tUOcZz{M=(}ook'LK7`W2|ږʊiO!d,\;_C ߨ!0 !/x\"z ˏchh3/^Qo7PO Z^]؅Px6lL8JT=<^ȤpLyO|]T}bsf뺕/dGޙp('%(~>KFmc˂8M3'v䤠"c 95>[QE*=[~Rn#` )G:\ 9 V՛>@=ݺ!#tdΜ`< >=`qλz+}cmEvAuYs(%S(c#Zqhe3GLN'}:^pr71"8v,h p8 #2WVbU":tre7HLF #JrQ#aVtepl;(jKu%;ۛ"i "]9ξ0.,bSOs9ޡܢFԝQԍxO46{E :7n\@b3cM0"1n" ;w~;c# Hj;2mU ˸r'N #8tqhEd}v謙g5%ڼxQKpL5FOj泤EL5jHnJ< 2v}"&'ޣLC'RP[K>W}N㱷_!țlyreh"p Ш7):(z"m<`6ht}qIo-qp5[&HP:k8xVދ `){E^0{Sߖh4]q$zP}a_1$jQ"4r8tc 7~)+  F@PT靊{fT⯑E:vgw!CgIZ?5%N,"h.-'yktH?CltCwzt~o=|rxvDT4^70jPi6,E?md4baj4n,@ƭWXn ^Oh6-Oza ~3X|gJ/k')dcF[(]ae֎AXúӻ!y>oԑuoM _΍g#a@UcLoaE]Μ9é}sl^D e7w낢N2i?4:IߞcL{\ih`{ L ۸(`kK$bȎ ٯN vrᥰ Hɨh#S!(423@2є/TR/Tshh ݜ o7ݛ[ _=kA_X;,qE7d7٘$ T,-.D);:.і<-"63H9`rykZ46Ν J. )E%ԹKWe QVY#"0 ّfdi32ӹUM׷'Ol rNhu`W¢552 x"_sC Cqnɉ_dH^_cf2-S6쓧m7lيe%wK\pzLx ].]z 3BBD lDZ/Ká}{Z'tWwwu-EȔwԂK=WtP9UR{Ns7nլ45P ɷ=!y~o\OrOV]{wuq厫lYey]Ya?A"xDXЩS'RZV ӥ:ANZ ׅ(qVX1͘Zpp!O&22&u{xMQ&=0wtvj [aqٔ!\п_ 2aYle`i%dL̼##qq\ ޶HYD`:S2O\NRUJ™y&G 뗼9rlѣV)%w|VwZxkzEyJvܵl=bh:ϿϞ؊RRo 3?nkc<'G7=)<;?evS|o9vϴy>{jL,=OSd)ڟV!ZՎP&Pi4hءп~sfca ̟?dole'e\䎅+p_hH6[OJIXuЁ#/~;t5N[F?GMp_[jo?8~v:Xy#, $$$ M-\㎕ol>֕a?37|:+ `-\e !SG'|< ߱c/ aaWFϙ>]\HrʔMi'|0NVFƩSZlN'lETB'm5bYOdM?=[wB3gzis.̹sΟ?ol ۘg쪄`>^l촷[E5A :2j242L9Ƹq9ƏG #4QfpT#)"QC(]^?}ڵwuy]2ҹK~my.:BiYHmOuAԱ}¹5s Q }K䙣/Py'NP\}&pn~?}*k1k7_lٲodl"!VqZ*2{Oܗ|hﺀ0Mfv#|iޅSP^jRIXv]t|x'E\mʳbjÿqF9 >5aGw ǂNI%M1.?Gxhq^ϼU76Eb^9Pgߚ[Cgk ̳:ǿ պ࿞`.56u OjB8B>̑aBskkn]=Q9*p7cXhP5B$qSތoFG(>#WvLy`&gMx&L@i(_ (Q OXZ:`_X~xkNG"KJޭ+(K,2mkW5ěiql!3sM9%ޤQF7QI[%$$@)oП)I#_8F:2A"3]gifv8z'toܸqUՑyyy5tqqܛ&>eɟ׮J ѠKh\炭sh'!OradQ_{ ĥDÿ8plp\@ȧ~e47U*Dp̨-B=r-zឨ&vZ( 9_B_Mn} w9`+o0fty6~Zp!ny}%zˣ/Vέiz' "?Pl=z5ܴiQUb>6uWǥHX p_j9;~E3ne7!{K>M:zDS1p "DPs}IYG-w^c"'o8#^xo'LB{$ @/ʕ+L}5n@(, ЯS9T]RK%mZƚy_>F+p"Y|Pw5c!\6̮wԻ;p]Dgb~/{>z_"&Cr7% b͠ex}Yr'*Ve5hj!-#<ؒZҋR㡿vrUk%[_.Wc@j4wbO^cBvAW;\nTE_^?M::`~GkFKHũWz/7-"G5gFq~xUdnz9赞Fi%UE1sYC u ߚ\3'#Pe'Y5hֈKzTBӪ;)Z9Er ~=Ua2٢>#?ZV[~` 6‚y;wCBDbee{mmm!I(uk>h^s0mŽ%SYێV};{?3i сK+_Ew#??Wa9G i8e҇ I? Qym*v̕;,iS"ٴ#rTR!c7%M7bӌu^0H jp(J>⪈ZC=NO*M\;^I:<7YI%Wdt?b使 mMtkmco:%ȯwKQ-Xl~m,dIR'adl/E*X`0:/E}]S^զ2,#a%xbsKXlu#Xp"caWndW6+չUۇt<;[!T!JKp wC'/|uTyUA;yJ=> ھ8-Ox2z۰a}$ l*C8CIO ́f"Tұ߸8}!IS J. R"ZQ*bRyPYA$Q:$L5nfa%LN||`B'g!á á!cZ77.:fLi/HI1Y, IDAT2&g_eXrc~AiwТZj..522c>Fך\4WRS\ 3m,~$Xu25+M!!(?26'?ۇ3\c飓ͣCUC珁dP :2 ^q\ skBU !? 0$j.]Lﬤ?PSiN'g1\ɿQFЕBۭROdgAE5FXQjs}]Sqoqރ]G߅tztuD𠄩DJ!lC(+soMU]] Θ F@577b8@֊  $9Bv E>Iö;3Sc9/B~3g|t]諛_Jfyx\ELERbJh= YGK_t[1$7@fOC(dKϯQ9f gg.>aQ?lK#%9 !֍ ěp7( :K53hB{SgA@U%bk3&1..Ψ՞0Ewj;SY#E֦HڱĴE.L-:*A_ʃBa~ 6cL W`^&^"~{qu@Mb;KsGiA< v+@D%,$ o:A>ȝA $Fp=(!a83RR(. 2+Q3$Y"5\d*65Xdpn+LZ8 Q8/jU $ՃI=(#JDyި68歁{J#W;K:YYk+VVVq~ٍTgI@5Wc})9͐$["6tBt8ț)B֊+&,I!HtjC] $JijjR+%Zͻz)/EE@x:LFFH<ӫZVpzbkEg T(5o믿"OY.N$gIdod aYnP̭~95$Md$T] 3LzE3(@@"v4 /`"0A48 Fh*05ŋP`u"^cHCj )Ծ4FAy%1DE)!##2q817׺b<%5 K,D&R(O 8StQ# 쁇#ѐ=jD,$ֆv1U*G^MkK5S\0x5n#CAq tM4ȆD9zW,JtX˗%d,ü,}y* ^(xBoQ (E1:1Q!` Β A!ȵk!l?BO\EF1%~eG"Z,#?_?02[=R^ƈ+`b0)s""4?Eg)<6`G.l8ؿ6"cގoEk#T3nRkYmu  =jl`#9m`(CkSЌbƚ@,0UY$ sd.}ŶG纔eR:ѫw/sf#L[{/Ro4P %3ָf=z=BN4)m kxdCʲd)K'Tw}O]9OʦsӽrMHD\~AzkVM"q.loaG*1킺4 \g=fzb1oW3~Aw] tHb M&+G Eam(EɌ@,?C \A}g K~ ^ PBF&uǤ*(Sx&M 3qh*Df~07-9 eee7 -fs?pQtZb[tZ)T'GȕԤkյ`M?W02MBsiHz(s4ccus =۪aYPE3Ds "b=SiLJ;ihW^+,ކ4&/mdCFDe vEy bPGSaS/t4A:[Q,Ý%qUO>gIR *gI*kijLY65%"ʫ/wGJڈ|4w>nHDf\IY[﵉ NB:,i‹jב)Zh$X$r*}r)(L? eմdRx>R Ӄ*$j=M]WSӅxMJBR@\kUV~ӧ_+eg=7GdcMh<1<8 zO5™i` M zYڎ9, ݠ)).DlͭV^~%F9 N..NEe)LL>&k?Ԛ}o016>{RhF$4hgY%L1hY].%HTVF@(yd^#Sq=;Wo;O%)()!zb 6= ]/ņZvra@ebS qz7h()BW ϔwedLL̑#GNnEh#\xkV< dJ)x3Hb#P\Aa_+*-X>l`*P#LL&&3(v Ep ΒX&X\J =f0N?y%Nmqu>RX #ܻḿbpJ4t뾅 R4" p7%(Eney9}bSu_AH? aS׀}}.߁\UK ]r笒dh྅e>8uf֏3qKS0K|`UcNmÇWh-/'OCC9ۏUyAs' \ B/Po: , :KOY4ZnSQQ'K$jS |%VjiduHb%Q(\$p^E.K'@j[Mԝ%w+SҰ~4p8JF57;ŒF"31'"jblFVz"k{;GBx3)gr|x齄SoF Ư 3Y.lD0Vg}Wp$Xbs,Й&M9r$ԅ? FU8@uV= ^ ',VMzsQS 0+ 3_N]NYH^ɄVVAj ac1l.j%QOrnz$6ܚlyRP38/4 x9/'dOLXAF<;(>F~z$SgIyZ9^vD{trqYYW:3-" ڒyU_ަx8 FSQi.&:K{:P3Զ,)73Cpil4yG<0υ1bӐ5xBC9~GM P(E$(A9gg9޽{8!UWlZ"2 @*NHhW?ңG¥QFCZmlx?l@4P(EF>hP(EeB@T(l_w25#ZWE"" |ѣ*S(sQ-֖%P(_ bk'/TJP(vH_EOPulDH7E<7GP(F*ЂE"@h ϐ֨OP(E@:[BQ(Bbg ^ ;_!w1:nCP(Op_ 8n0i/L*"@PA9hL(-E"`GQEEE4BxaIkjkЮ, <湯;+H(7] -}TUUClu5ka!*,,||crdfFR^5)w5)cO_Rtk~e*sD,#BȊ qQaO,OQNF`\T F͜X|W,w~sV(;Sx8d8gG~qf^z4Liqs %EIT bry]y׼^3 B_X8mIkhꃘPY^udQµXvF2ӎ <ْu$OhO*sca"L I:-i+r7O+//y`nkkf0'X%ql၂% pTOKHԓ='͍̝wfu ~n#'3h)ž KVz~9_A:65, [jBDl:wA:7VNu7rZM_Ivi%E.|]~3)UL.J \NcsmsƞX3tHDB<ܪfAAZ+|o{S#]A TX3H[U]Bt`6/9U4,apI䶄g&W YZŠ&$4lJ|k镧߰Ѫ6 WQ +gZ0pȡy_XU*2w$ҖUM SݓCN'.HԈѠ$Sa,|Yo|[BoiJ"*KkĊP&wHTlV !qR~ǢGL&%Vׂ~[6iw\ M7S_4BsufJ-A@ϖfl t?7Ѓι'6Au89ي1InmMTKj.ڟq&NqO.+MKN/CeY)iiiiم,ǧ"mq72o4!^?=ˣ:*_9彠̻> ׄ Kb&U6%(w~_uQ޹.@[I=wܹs9E<߬@״U~NnnnNN1aqN?r,[BT^ÙNNn~lH)ɋcW9Sg''-rTS\GN%̻y)33j1xMA̪NNN됇^_D=9IQOyg8}-?`Ptf'Fr(|)0SLz1O[pfG x^5#EG3Z IL^b* gcH$Ab qa|0.,z!Kؼͱ;=ad{铛zvי粨~\}^mZEI۱% LVAE9soVMyVԔ.ZMS2ٟںxoxgo8l/ Uܜ3&&6IlMl^'߼{ u/r؄,p4t7?6˖'0k(die(}=/T# FXu^ eULz pks֭1%;@47>77uj{gnO=s‚ 'YCSek&&Ǯv w0%UAޫ%;feTvy(/5)cҮ?٢-&K?=Ucs;S&QOt bzٍܒ6wRs5v'6JIxq@߳xr@C}$Op`'^t @NOIގlu面;fhzz΅_SƳRUqo+Hp[G+QϿv:}I۵"z/KcG,P=ͭ zm 4Yu[\`|Hb!{ '4 8'H_1:Z3'5*."r")åLYr )Y9fW0/uj;M}ÉCWEض@Z!A0,'q#e_C7M f9qZaan6ٵ4%ƂP IB4eCFDe v E5 U P[[{Gu1LwtQI?<Ȱ:? ~]|deQt]a'r4Lx~56'Wg Q59h^G&L@i(_ 3W, Z}蜷SF"`4 vIV9Kffգތ7cɢAJOG"ځ(9D8p`Zdg}$=k z: BHz"y[^En7=?wS 3 glj7s$wv W>cbĬۙSk۩Z[R;qm{-NZف.4̦w>dL<]p H B66vFWy&"7pُ}gׄ\o ޸>JW\+eՀI!ZMMR)YwU'L,YtwQYpr)Ut Vr_r:~ '^us#Sp7Z<}̬^7f ;o^y7qnh;֛ ޵b$;9Dԍg+K0ir5A;<\Ju@X\Q~i-[z߻<ܺpz>w 9ʫ {^oGNt <[#૫''Bh9B<\=rU:.eFOX1?z\OeP2# ,ebĵvWbIBﻐ#93p ѡ>z] 2511`h:4BI]U l7DkDAZV=(<`̆yUrL/a@XJ#cp‰r.oyٹj<~J-ALAI #@O)LL>&k?d4~@른Wq-; ׏a@bS qz7hׂ׮BBo03H22&&ح=yl釢4889Ha~jA'+ nßNG$z~(WE0ۿc7zJ١QyY1튻KO k7f|ԇfSAVS@˹StaQ?6wbO^cBv H=3IIܞ. <WG^Y*Ncqtfť=FYyUՂDZF./,).&$K(-\QUIaO K\ ËoV@(Y$DA⠡'kx=\-<= 8 $OiTyqjU6ƯMQ3vD5B2Z9޺c-9)K~o❏ɯ84[֚S"[ƚCKqw\a^O[ץ}+(i基~ ,SYE*f Iz$I' "n("Kx=C=NB$εTӎ U8s<V89/f$k:{j!6^zL KcAc2q{8u%:z^kRqB 접X캀ۢZYVo ܻwO%'LbkGwWa) ClE ֊i~V6-  taD=#9`1Q]7>JvvhC2^Z}b duG0uBDV%}5zA)oF 4.Z/~JttԊ:0 NIط`NInZ1BtM ;t$d@X6BqbYR8h jF'Ad#z=~Жt[(rs5Œ_6`uŐ*T{mI )j|e {U>䝍'6rZÔcHTR2Wv 4ž1S}*"2 CÇ*Kܶb =a:vx6QsD*H3!hy sY"`@!&E(EI (`d>h;Kzj(CכGXLӁXHe422r]ufmld/ШM(O(#©$gF%a-Bk/ ,llM9ۗ=R^MdG-"-D`*VT;`(,{HM M"fq 0Ok@CKv׽<Gp. l#,mu&тA!жd ,m:H޾KusD52gzF-ng6NplQr~]:vn*qPu;=էW4An+0#8l#1AESzhI@ hHQ2ʨ_n7%v@f=o 0li RK\ZW9u.e7֐wa2h(=,iMrIШT;aџc~Gs+0\!Rtah{>{ΘC^WOx;~b#)޾B38WMDb,7"g ي܌_sХԔ И GZA4mq7pKA,L v0 G?|$g FYT~JPh$`"Ц]fVgәh۞S7r]RQh0;Yvd߆ʄTwpDb*U khjƖ)Ԅc=u->!voC;O_{Ab>)HvEk$AФp` ["GQ'|<ٍ Y s/lI?GV燻.x,p|s˴^pM~4EYb|i|n*xtv?E.ǔ=PKЎRgaڈ5/P➟_`GXi/]oeNЋ]Xo>J=R/C+$.8jwg& R8m)>G-A%И׻qe87m:`Ԏvԩ,{;7Д㜅%@5U"( 4vv0gk:3U1^*5cFKP' ѴGPU_2`92*4h c 4+JIhBeܠLkib'JOgӦq.!\BbCb $Z ]ٸ0OgN"y ¡A[<mA^4ά0弢iu) ^2!zmZ㮞7v', Lqax.psݥZLj-]aKiAd&)w~c  )- D@y]3*5MZmk V6#;r`233,4dFE*|E4YfaCPcZ*5eZɋ>9a݃IbͶGg&uŊ=z\guZ z^MuvV?uO~kk33&wWN؆zg>Rk2=IkQCm*Y(-s|sv։%zY_N E@0lK5`@(ڈ,+aL6V>sMMC{ل KN *KX;_\-+áW YZ=9F!-g7(4>կ[+NEq)0'jҘs12Xy̳f\ذ  Hzn-ˀ?]Lh Ep`ӽMuյ1LZV]@IR٪(2j{[gY_M I_W%P+u|Sy2MVV&d6}Kyw)JrO}w0)$潬ڜukhɯ͍=~x0v3;',\p5ak&&Ǯv wXRqX콪nZb:غskZv@e>RO;v,:%gO8(x.d|TwSu面;wMOϹpaݿ}*?>*֖4⭴Sy)Q.~(0")tZ sn׊!]<%sJ磿]D;y-ª|38c =y/\or$jCJ+**=kAx ۂGz:6`U41G9;N)܈`(KSdr|]/%%~p|5O24B0 ;,vaP]m LCU62YY~+&{li$XsDѪ4Bt12釣T o,8N+LYӂ|}ۜ~}~؜]ş_3D5sBS4Fk /#s?e&4/۫S>tێ SsG vIV9K3] QG]{oƒE*;䟎Dߵi-?ȤĬۙSk1-6=G ]k>;ptbQVƈӥ_ @&ex -ll,캍+C}=oBKb>x""40d`SʃbWEy'gN;*L<|TC?ʇ+6*3jX Nl $<;s3,TR.2ۃO th\]&^!:3}QNaI;OonK-aѣo}l-w8BCxkC-2Tlߐ<_ٸ}Fl?FQa"~Aة/%/ IDAT֛ ޵b$;9DԍwS9ޘQ^OnqEOdsEw(רhq\⏹P{ۧ>;ɜg7)'0g++Uy,#Do#ɿcj䬼jAU1I-JK$Iһ/J;WTUy=RRVWwDp'BqեEU089X ˥Eg u!NTX.),M<9J󠚩V wf4qEx(T1 c}WwⷖRYYy,YPͰLeAN^%<6%% [Ytv͈ţ0ZV t_̓6~-q;gc>uec*98Pz ~%'Y/E"Іlt]8oZ}o֮t=rwvv~W`Z!Tij'"΁#o5KkJ)aǾŐ迎X3k]wpJuqy!^ѐMџ g1dVzb6; [w>U3~hS N<3cJk9%G ;41s$S>oK#d;!y8>ҿƃfVlR=V7#7g'caI3BaLoH"JEP#Б׍^<[GG/ ͕J'ћ١m֢M)A.qAY3Ŕa_plם>s_vzecm>W^wRdG;k$V|Z \0Hy !)Q#wL # wq]c>J_KK+ü#-K(:v : AmS%&L/'0KUD;%Uڶ,SYEpKIf+88Z.2=P|<,gQMi:F^U%hv0hK+Oə 8t(TU=D:IUұJL$BaMtR]C횫]⩖bpZ,NP] ?݄s&/}nEGƠ\(4%ե&DUeIO- FNw@ncS$-K)2*3???2:p.XA*/n>nͥ,Ttߚ#Dv?R9Z,pexa 5" uB3&˦E(N,GI2JOcdn1SFh^~DR T@29^SCIO]2d4"@h%`x vuZqӉ5k0%, |<QcՇJP^$^غ["4ߧuEi'Т1OH-*"@x!hìuBkZ E"@@@ aygI&jvj VV!CbD[]V&c!VOdH"12'Ό*vPN!@oc YP(1=1 A5)PSYv-YF?6=R^MdG-"-D`*M7U(s }dTA]*5L M"PP7:0! @SdYQnFQm|NBզ!OdiWG: qPu;=էܖ707Og-R_ mxnn',߻wbSZ6AM 8iYOn%g4:iN2g8Za2N]-zK 5]+XCގ^˒$zM52*voC;O_eRWS*ZF/^B˭S3Ӿ* 7LϪmHn?{%:ě"ٿ2F#"gNk^8Fc(DI vB-G ~?wΘk]DZv4xpWx% eLe%\[wE5s7ΚNS muX{e-OSCeiE@ˌ~_ᒐl E" ALבIƾ3 b ᯏR*WU4+$.8jwg& 梔(Vy9ZJ .1w4)d[ufԆ,:uj*'Z2aM'@t1:04n 6uMM`L9JKxah{ [Qx&} o. D؏RLJHɡs*+eL} Nszm B?TL Ä&, Fac{p#=f+ž&mϚ$Md8%}& oB~hl/єsTGr ~3hKD0FgK ˎ@@0׍5qzW czJ.۷\ %$1$F nB+)N"y ¡A[FV | aGgVTZY KRJڴ]=oNX7a̽\7&KE6ԂKB8sPz 2[,ϳ >@&MuB0rt1ok  ӧ=N%(6tqx;w_)OV )r3>0D0Ruj8_0"@бGm߬+-?Ł"@B]L z%^R(EB}B:Rm(E"@@@(4"@P^ |2#E"@& MP(j_LHP( $;hW1Mzy߫z("@<@O$# D8!@&  "DO @&2H N t D L2"@d@ "@d=.D"@'P("@<@O$# D8!@&  "DO h2&O H2O"`ңjj{=вuҡk7wN^^lkxo~gjQQ%ʔcōFDp ]dXrS'-AP @G'`Jr*f2`ۖdz\{|B2``^%-ҢbL'@ ( dL>0P)@G&`y;p?:}^[?)!s'Xfrv`-gu)B&ǘB:8a7T_Li'M`}lAvJCy"HtqnA\ׯ_9o.f I" #r$4LxjL'fO VE-a읤/|X/֬Ynv3ދh6oވy6'c`tliPnlw`4t)˴ F+&U *}}%ML/'Mvn1X?v1co^{JA=]ꠠO'g UEDlWl ;:EZ[LuuE[PJ"@@p-(F Du l] DdͭHq%P7e=Lz*<6ߍ U52R(d=D>},f}G5''o$dٛm-hb7ŷ*G edHXf1Wgxܲ'51jjfҧo^r+RkW[uR i!cE ߦ*8y7f @%K=(eUbxᔤGu ed3e)NgmeO#k&>+N,+m"ciش }?V5 هV떜-ź_ u?FJӱN X!0`,uPILV 7hQ| Ҭ/#fS+l%=Q Uo̲[\)K >l_#ኘ%W]]- kXMod.!팀!/m=mz pjϢ lc u ;bN M|$ ȏYQO'{*_SܤWA5GV0՛>c}x G/f L"'7gO#KFPo%vH;, >: TSM%D&(>hF};&demro\Mtb:X:j$BI ˟.(mƭ~| Y"$:iІj#3@^ D.M/QG w5ȵ_4G/ߨCN017`Zw3f=p. `CGI见PAQ4"О ˿n0Y8 }ΑaiLLIޠsၕ@OPM|yS&baGzNzi[;3~VLvv08ֺ;E$r}ҞPȱ l?9-3].UG512T$n7pE:,`_ 6h4VUUWp͐L`3%Dy[QGZWV脷#ǜޱcyHNb֜`'kG`CJ0&u k؄)&q(c#8 9ی%'8".ez߀s&Q7YRH. @q/L~k2upn͋mut+;'Z>/?Léf]~]l޽&MB¤'D)[ Zؼ* WjNaÄGAA6ā!L 8R&&imSv)%lfSW!K[Z'aO(y^$,4ӷΎdKʒ=ɐs*镸eSro%&p!|f u.U uZ}.^RNT*CpBC^;dg(1@?#qgkxXFT! ՠf?=6 D@\ r;7!mE e&,EGnۄqaξ'.}ЖE?eI`[&\sS,z3Dug]>i :emePD% b(M[sqQC.77]=|k '1:8C\ޫW/XfK&"`-T\"0u<1````?64mb=_'?]E mBgxx8Lzbf ~#oK 0;xbfI 2l]ox;S-[]K "֗|!!!ě?@lyQb [^IN~1 :x_XmJ;w'D/@\!שnٲiNH mE1'jf&дO~wp~t۽\vuOL͔,jB1k'CoYb"@@) IDAT' bEM &tqnA\ׯ_9o.f IJf*+3>Bm۲DR"@@; ;'|.ӅZ;q Yޫө,[vbc̿{B;ule%ɋ޾-K""@@[$fgg Ef &]9NWR>x!fҎ[IJACsN|!$Q{1]OHޘcwԤ2IXɳf U̘&|Um۲IT(2 D9vعspuѣGv~=qC+7lY;v’|=vPم B`~oߖ%"B"@@;!ì>L< AumE XS2l|bTn]Tꗧ}hqE!툀^j0{JTT&ݑw>hРaÆcƌ#F9r$~h۵kW Rw십WZZ*Zwh{N1mqCuKΖ{/u#ӭA@;tngn? 5JLiB&dpӺ~$& H hQt%# !jSeģGD;f{BsGG)1|#{Qk&5)^BvA@]]HD$-$h`K[nɔec(%&~ Ȱِ)1F`|"NaKW78u͑yq2Ҳs6Fϋ{9Č7voYFfev1ʥ s\xӤȅginN|G>5( lp}>8k1L [ <#S CvQŔURR;3nߞPy+uo~y3>nG{V*d Wq&'7U."V-F 1KW6J cG1 !?TdNo64T%I]x pibO~:jxф?EbŦ?z~aFv6'UӲy˧;H۳-^;',hh@H> u)${B3C{Byn|u")c{B1C + e&ؓ>Vu›BVN?5s-ORx DYVlmE2{2{ dcvĉg̘fclv 1=U7$Dh5EY,/5("D3-EVD&lK<{ށbwv_:Gt&XWxkJt2e q܌pҸi>xq'}Ƭ?|<̯ͅ;z.yadp@L?~C 58-H-|&.Tsde^SWwL>NVs4U<~DoKJk5 =/oD,l”Q\]I/-`+ccgƯ[=j2{ ϒ^ߛO _u-env`c[ /יDoO(E Ush]Yk(a=bd}Hn :nܼf>'JSA=,hjc=&il @2R jgG o'ŅG9c:Ys;_|͆L·njWjQX$t@_aze],b#mꓙxP&|klٲ>}_pJ רPvf=@#qgkxXFr4Z"5w)/S_FQxD;{B!EuH|O*4eq.:r&Ds>q郶-Jm6z%c"ӨRX?ԷvO!>={|g###aGDPpDo$渑; gRX:emeVTŒ؄dsצέ Q6K:̢6[<*p wߍ_f[A@E5u(& D'vN8m2O# r l,S:O Dqpb$W^^.x/L*/#;@e| >|V jK%oU>rtwY> O*x3"bPo_ H]:_:Ο? s둑mHU&ʄ1pV:>Rb.@jo >b#Z)x}]6;LhBSVz 0Qe 4)*RnߣK&- RcQSZ@FT`(< Y慧c >޸qׁ>?Dqsh4oe>v[Q]TUU^J/ Rx޸p XE"~PR1GСCΝ;*g;i@d&N>=22鈙rUcGi~hT'Hv#%REesQVǼd>UGp'zSeEQ"Bˇ/%;@DDŽ PT"RV僑"|.٤‹?U}+M~^>Z*DBECE'm }>Аv!H_] DӀt';ĥ)ϏJ:mRTFdħ⸛^kh`;'(@LfBN8%y=&mϞ=sAc2qDLAoR&$`"Kju?Uoi~(T).L Q`bVUWap(\z*4!B? TX{,yc֨ɢ[fդ0YLJzYMdJ Bkڧ6݄jC& "YEY~V 3fD᳛"Bxpv]F!~J6Ф(o&{Ns #?h&Ў`ũqbwU={d!P>I穸iae&/A 3#]EV~]c`b]()(;ם ԫG@wjCp aTw "&Xp;'\" q"!idJ6ФTCпHTLxZ˩V5)6ګEcVZZ{ x }k ˺|P)7G'gر \}f!1J/&c==l$rE^o2X@B~Ań`!i΢ XX5gTM9%G:#$+(_t#BwE G_ȹo4#G Paͯ0Tފ qFif/mIDAT $Kv6ΪpBisB ~Օ~w7ɰ9`׹Kg~kk!/x{d n#Cv|^թ+eQ|iPRXeRº=__R[fݲX\.\pyaz.dhd`V4[dxlf& 3U[L;PwPnX.Z-(%Ֆ*3VnҫT?!>>Mx/4E8qgD~x M=XUexp_Ȯݺ̘:!WPxq þ?~QH;%?S߾};u 6U{  ǭ[ͷ˛\JJyG]R$tP*S ۏ?D1Pkqv9rG @bCu-c`_RiM-mmN7?O-_gy?~;@*\m0 e _}`GoM{8t֘hd {>{ !W~!d xOx(=uV~~<f fC]=>Tn\3v 3Nj5*Sw,n!px1q!ek8 iQ_B,,b GӅ B8F&qwނV ">W!YR"Y>]p_ɽ?NjG`njB\K?$0oT rMՕe^Vu=k i8e'uSHfffpx])BL++4A) bh(I1jY&j+"#pC:M.s. Qfb ASBӠm-x C # RJP"뒫| 7JzYM BjUU22*;R&mUb)2_e*0"r8}yʄr=ji&o棿hu@Ugw1\ؕNٳ 냑PAÉ]B.׎mgؠg}S!F<<: .*\VP]ZUw@.1Xgc:!UF(Nouevݼ㆏DH ]'xx"8v9rC 3F᫔kT^S&Q_WGbxVa,.2j9" Μ+Lad?f o9bŻN?pdVj?'0wH-"!U"|U^>*UdR(\vM"Y>ܹ{A{Z_o1 V\.6EcxA]mop TruڽlkcB;஑sFfyt oPm\xmګ:wʓ=ʼ̾_tSlb)Zsp1 po"%_]IT*~ק߫V٭.ǘ{*JJYiy)By}]fR_ РAumqϞO0LGϚ1qćhAJjЮj/9("Tyb׶>2N餅(8J|Yۻh+}z~Q͓s,9 B7hADP kӄqIY)rL 5UxOTVb)^PKexaPy+au|6i#c;[n`A8>hΑW/\=#5r&Wb]9=kE07"ԓoMZqCoy1Fd QJ[ 5x9Φʼ|=6noJ1Bx,(* JF)X>Vaڂ0 _esԋs.sV8O4!)]}ڕ2N FuG+ܽw5F1v.z\QP0؂.qP<͇X2W)4SHa(U@g0f0(QSyL7 A(^}=/?A/=Ե࿏5ݝ6V buJ(s{fLHνkpij=Dyh4RJ((jfiFɡ9C&ϾWW=U 9ok;dr@콯\6ffť]HT!Mwaq9hxKYiE'(q=զ3]]޵1H(z(f%;0|?غc.K3ŧ?7wocЋٲ̋G}T c̙zxÏ}?<|EBF TѨWw{_/4@F4UB#Y  & bdC1ElqÃm;SB^]"{׍c3-Iiٞ23ALan1#_=cTFz!x"'%~!> ¢x]/<ϞJX0 1]ɐC7|ž߂y/r+An|?<{O\0<ZuHم#TRƻh-bgaWi.xt}7*n[!G 3GP: ~pcji ;?x׾*q# K[DdYUԞU_5jfp/sVFCdoĄ(Ҕf+k9t8mP@L0- /T 64xд`XLKAJ}wŏ|Sw!ioH ghm0X BXG#nC^slC^̸YMdxS~`޽LO#Y~;Y},"wQуth,&k_ c_8?(ʅ@}eK4a#=l/C grMb= ?3ݏw=ף x"o'$w[8iP{#Έ. W~8yscs6k ~ΈO!> nq5YI:k̀Zȃtg>= O/{a`#zN5漺=j/NimƬw{^Pe<1ook_H1\ըv9M3uT߲4x_^ fXK!X@xB=S?ĔjW)|FD>J@V0TV{x՞=꘵_?HUU`},JmaV JcomWz?p@ :]@CEU`u slp~a^]uG{Fknϻ5ՋsƗ s2ooK-}K|wÇ'&&vܙ3kgj =BXd1\iYse̤ j? Fs-ɷ.>όoB6n8f̘Iϊ~b zzg)ٮTMjNIo:Ge,N$xpr ighk^ʘ+oI[ncO)*ri5tV%፬G8ٚ$\.%K.J>&N1#%Eq0wVAkm zge Zlqʂ(BɑXS'Su]wWRx҄ؤxIʩJK^7{ZxX??Iජ](;vx01RnW$ eK[%_"6 k$%%A|@2“` N+bRHKp_%KuCTwM>"D%BgP4Jm i2(4B%WCX ˄pB1\Q*;C v֭M`')\aKCeI@Ԥw( 5v@!H$I\.G S/^+-1r5UjQ0);•߼ӯG\\j#WsL hiyXy`6c ޑ1[V.ǺIН''*_`P k_a Px;ؤGvD={B'zuʕcxocXXl. 4ZHX>XzuA1 1 BI푘 i+%=UG+Qú ةKLt TxZW6T̐?4O{RN8nXTubcvcI7IֱmsΡS5CoPКۇAaƂIq6A_4鐔Ppۇs-]R-rݏ"XKӡnaPZh]Oģ^.` ^G,COϝ癞wkzm-8 0fFa9f3Dae`AwEZ#QЛX?6_=E>08gd s0Dxp,p%TZA w=08xd YA+ BP<eAP tBm!4=fE3F0# R2 6acT8.+M< Px3%RFQ(/T(**DUQQci2jEѼhIdGۢIt":]ED36H`T1FoL&SŌc1߱X,3VݏubسFl7v;p8u9 Kǝ]ƍqx  Y  G@dBK](6)((U))=(c(s)))SSnRSPSPR*Bu%<ϏW[#b|~A@-NKDAC} L"8 9:B/aNCKcDADSJsf#-%63m,m!5Ǵttttntttmtt2/0<Rz(QH"wXFF#F_,!&&y&;hRNif0?s.s3.mO +,,kZ?xZ^-٣/s0rq8299sœVqU߸ pr-s3skqrpwq/y4x<%` E Y==*{TԖ˼toޖKmK+HKWKa1Ii,+.K-}"G3Kk[/@T8pLG᧢bE%A%W2IeFe l*$ UEpfOjj~jWoN_M9iM>M7JY--wbھڗ?HYUMCe 3Ox*v7ٟ҈ˈdTgbd`gBmbmRb2k*nj~>`|ԁfBff-+ [XK R˷V2VV.֗ڼs[׳Ϸ>(u0١hXӇҝ&>Й߹Ӆ+떛[7w#2.QK+k[O2Y\B^[gwo޿1"5-!//;(:h$X"8=x:D5tJIhMv85y9HԈ,\M=#. B:4~&A;|"ؓ$4HQ~G%K''MOiOJ=:fVN>yLXqq 3ۙYYY[٤2'Ox *斟Ğ <9WO?w_O~X(_XQDUQ4]lZzF3[%>%:eeekg=Ύk_Ȫq|y7++ UUo_PPW^UbZھ:KrNZH^9ܘ"_u:lsMڕBnodބn\iinuhi3niWkqkוֹ|L]T]];co^}gǥE'}}CwM>gptVz:2>okTsΘؽ'FOG&l'N:MN?x/ļ|EpsiYs7aoSyW бh8>~I՝_ؾ\*ŷ72k77n3j USg˝`P_(|yOp@ja,rBll텖(g=[ ԧRKQ%H(ӚйG0&10Sh5/qqr7>&JLAIJ*m'vyvhqe9}4~hYi_3/1X/oge 25oVM;gm^CmNk\N&;L=<^k3>fdrEBKZXH}hRy8OȜ(h1%qxlXbEɌ)tit)3;YN<=9דvJA39E)qgbJKn.X>r~rS j..Ծ4W@E1ě<- mF;;o^A@NhA4-5<VF<g8;Yⳝ/b_ʽ\~0z4vztlkNfnͽT/v^_[^pc'j/׿}Z{`svί @M12a_QdSSb4BtR D;@T*>%vz N2W 2">bK{B%oݐ֔9*{_`4BTPׯԊԮyW5p7_o4`h `11PTfܮ۾`C!%'ó}.5nZ$NҚLjgW{ۯ?0@?=CPŰՈ]QIZ1', EuHъ䔔T4tc|ǩeff>wxNhᓦy /,b)?CU.*Ztv|bUK54lu]6h0y5Z-P+]_-C]K4T ksO>Ob mca裱'E Iϸc/x֫㧃gf$̧{Wpa}R/>Vu}VßsB'`Qx@`u\'1J*9< ~!M9 XHb c Ss:K.YF> <:|)UwEhDel$*I.JK+8ɕVRVPQQR#KTӨҼա}W_wPo@mk+2MLLyMgVdNPYNX]Ѳ>uv,9.t3W[ N=yzx>J!Os'dAACDBS {^9\Yft]],w(ߔp(ؔ|dTc~ǵ3X2>d*:C3z2?/4B[7EŧD8#xs'ΧWVUp&bBm@KjL57_͛-­,۽o%vq~w=w{umw~Ã+ f?JJy67R;plukh2i峡/_YO從!ϱܻzj]p7=@ {Z TPmXQ_T&4D86ޔqA>XDEvH2caXG*,~@T  tz #Y fª`Y' 7JAOaIqb҅#2U 0fC Diizӎi]aah$]2`g` feae ag8 u;ǒ_@`PDɌRғ2e?ʽЫxS%:KjMZ446thu a35?jbkQnb†V. >;vLpqrs[&qyhz{xi&Sx|2#5G2EGDz9&$IvKy>~!c+k!''l{qqpIqYkйh.ՙG77q7Wސh)opu7GFzbchFyԅ%+_ؾV~X{Q5k %dUA *#Ё\Dꂦ p0\woQt(U'*u͉>TWo0l3LHp^ZEE'%҂,{*U,xy| &YW]I"Z m$nޝ=C xѐq)Y9K:<[Rv:Qb.wn)3-`,(#!L!)Uؖa^W 6r Y*g! aM-/: F&̦v ,h, mv:bY8UbZdS|~\!#CË"\bY% $eYOMyf{\)!?$%"O5CAkaQqrIHK9Jj ;?׽j۵;7j[Eۣw^̃OGtL\~zycSI1Qo-D? yo,,6xi]'X{gA~K>  }0 v .hty$ ϣ(mBM)v1}=c&[ |qp crry DM%:ii.ЖqU#E Fmτc"Ͳz-݈cwהO_\OGOXLDQHE2Z^m׍os[#[[䭮??)-_?KNvwB?N|ϼʝUH|bpev:>IA pHYs   IDATx @vAn<@ ZBx Z'j[V}T[mVhW*hGEzVA V@AH 73M "*q7y3;;O9Ui49&8}tzmll .br-I wv 믱c _r8--222l2~ 0(˹st#deeKi@Ye?&I(/"nu䲨6/_{O.=e/ '5t|ϭ;|?ލ_\çW1(noNܤS;giJJ۽9d WFiR!/Itq5TyE? ʤ52MSJ9s0urD_2=Jj+El~_O:1&/Rr/uʶVGJ5"o]<қ RB*X#EDNsN"<(-˂{񐫶2=mmAγSjŧrn/Lj<*MT%}6bZ#`8m)|>A9 8t _Ոq4F(K Rl-}2ߊ1M֕'}hs tnPS\./48ں%8}ZgaS%9JuAqءO쌿+^P@ RԪ6W2nMB"tDn^vS書>4UX6sG&_NWm`V?'GQאJռx/ڨ>!U4{K'ԔD#K`gY]Vz̹[$SP%y`|i  A_O#~(ȹ>x2G͉gwЪ.b{  pfl*,PXX#-rjnE^d%~ `)(ORpsQvL[{*X899; |Xvvv޽9JJJrssA4aPez)qvv4\YAnczv.,xg-դd彂9 lԡE]4 &̒GqƀJC7qIճy 55VB.y 5 Ţ+ |Fh라qG_M1mb^=d&kxzr)_0ޏaR77G k#SX%t\ylʥ&]k@QR>CSVUvo>KM=Y` f,-=,xZС5a@$=\dra 76c D`tR1Reӆ8B@U䱇mC^&YvovO" dЁoWȲԘ%y m9,S$AdQ-L)a 'q;kg-RuԔ„1#4%jy6xM:li'l 0`Y5!Þ[=veLPy^}V/YcJ2n!Ys Ñ`SP%m$mFJ,j,Z@WU\+3*ܟQV]f :u]*iͮ.Rf]L-{'L>z>`Fչ3v0bp`+8:|4ͺz`(3U_W4ؓc_eQOjs"uεLXXg+yÏ L*k}nCߦMѪb#ꑶ\xz{Ścb$O\U),vy^ؓLDiSSARA\@88+k]gY'lԅ%Rwډa@fKgn=/ Vpl5[)OqR0+SrJ@Ԯ}Cfezzoȇd ^>&TuO]z ?@* p:X@Ga]\N,  FusGm@ z/@;,a$Dz7WoOliVw: 6 6ߘ-gQGe&@ʲJZ-w|guLds/kV/˧ vbF([זH־S,?c褠WChL"΁ybNBF$LH7&TETTT{5X(7'**NtN,y߮s2ŵeڻg*JiYt&*7SmуB&KÂ*gl!TP(ѕW8qƥ:?_%J%Z"9iJ I V, gwR''=*0扉TJJ5ˬI^jjt]T6{'Gup-k "֟hRn u:V{x:wkeXse6Pڎa&mq-^Wڤ0X4!1հY=ԗnKIKICZUoؚ,T2r!*k\o`{Q#-)5V\-o̐U&Ias7}:kxLm()oXqJaٜ֍lYKZ9O\ <*ܾߜPBɶE^y?{4lLOw3lOjԅu-[;{̱?~G[96ҏuYp<]7YUz㟦7LX:iS{ʚou0uuUÙm3ֽ 00Ժ 㚘ѭ|'t$K^*C/T**гs:垘׼Tg0Ջ_ ?0qpqU\n+=\q)fCWSr #RܦuXx+̘~S1Cъ;FhOH1nDg;EWB09H[{MU<ʢӱ0+Հ+KiNf -Ň#3+-V5^ X״kuXRe) 4pTWfE/umg`%#l@H),(GLVLwhx,i4%qq"TOZ$#$^Ϝae캨'c5h;mp+ w۾S5\lja$Ӱu]0؂w`|4de,P>:噜VL6|`|k`l#5v]F`OF¸c:'}_/rXki;PndZ{ O^ncJ)"F2e[bs*oq+b +`a-3v? FP#!Ep+_i oNlkhd*.ЁE0g#fϞMRz N 0Wy}"f T5^%^2YQc?÷RFt̼(C?/<Ǻo~@f}gq(1}n[[iSr B̝7/jm̀QJ9Wݨ{ژ9\w.H4RV?!x_0(`xor(Lg)6ll'47-PM pC̫1(e_ ۅO%q4E2|MYمލhX+Y]x}c %( /MqΩ5;E4a}T_ĩ:sx#MN>99֐szq v׎[=_y@kVUsG y$? (xV?UO6j(PTF9C8?Sv3Y:b$2>f@{UzG˘ nD6nݗF y}J4U )7^|: PŅLp0nlfywn⋾:D^y a8.lNf ͞H34Ykȁ; 8p@Ϟ=%pl7/º}[J1- ^u#$ 15v_!C\xMo]"cK,J6pv f ud1?lGae@mZȃSB*u n1f <* n?պ{  n<$9&՜~.ffn z|sft@N;#~{>ӿ\¶Dp*\ KP_{ʫky3:2f <񣲨E _hsSS<w,Op*//ʃͥ UN]lx[o%W#XQa:_"p97, mCMgRrÑfUY"lL#ѕs*&$$4iUZBWMŝSt~cJsn5Dpҿ{~§=V֥wo_29CEa~eL:1X(/J\&/gI17N{/8Gq?B i X$MbkGG;[;[K!i./ - l>KP`Z< 6Uh6{xxt ;΁O.Lƣf},PfN =m#{Iq`)Ƒ?[# a/In+{.o7l(p7GK=eKq\,ǁdAd`,H9:Ex4&+dafLG 1RHH6CJ(-∞POj !2$& *e;[c/ ;#x }?P@2-xھmpLjDB c</"ۏ/;wRg ځ1>[ߝx$ExLFa,쮈 W)eLr?dGc,clgh2gЄBP%u{"[ p 3Ձ4%bW>0F|9!aP+0g/M{ᯯVi1g|Ih6MUyaG"^U[:g1 ҇^@ʀcWc.LKT"#|2[R @@|Zr[[3 --@-һ/m9]TeR+$*ck;RS0WB $Zֺߘw2VO6nanL\f>cZpWp"&g8 MAickB4dg,@Z X 6$~C~Kde.nLz|{ sd{&wGw?,{8 t|T)H#@x탛z'Dɹ*kp[.|Z̜E"gk1~{s?ٔ\8"xK(az,Qb" 4[@hDJG_&0`y -YjE0O,4%Qe.S@l3v ٛip`br6-a/bXqJS bիmP¸*(ʠ/pA.yťCiֶv6VPq6$D䒀|aHdB.&kdHlA [ԝԖS"H*EajlޫLg ]ߎ[Bb S!$̽5>ï1=</و-~DDQil M!DP i(6C}6lҨQc77g3b-36XpY4pacRr2L"Z/|6[f7]FZ:߁6#ثG6svmT.ES~VտD;/ a̝ܘPXjd%2?;Y{PHuo9JEVV-wrs ֱ8 `dwd .K2} ICG?42gl:~VŷSOK*PZ GC"M|IJg}p@ͪ⮓? l*-*il|*A$ -P-P,,$KE \ vpϿyz9!-]_'7G(R"6`fbH O oG.@Dq3NA?"1a@\cED1Q/ <|ƓY󿫷f{610[?a5sXmXonrC&N-`ϏP/V+3fiLPչx)o" tf̲t]22p[ټ:V1nf'w~Tg [7/;w~m]a@_t_%A^N5)! H] S_k2 6#U5+@ݚ9, ߫wʆes-̅TXDe,aBtDPk-mzvvvFZrKP _6bׄ'e߻i;>cK/~>l _bОO_ _IܿFbn|<['&+ލo[D\n>Er7\:+u%3e֋Uqn{w>ëaæ-ڍ_uQ$kko:IXfQ?YwwVl43Gm0XI"!{Ӊ1-qgV~rxw>ܭq`>{⁞hf <7tՓSN9E LL{ [+gs蔿&su):5Z@{p׸<kfЧEZ#I("- s͜0hiK+XnJt\t?ɵ˔EHȅ9xD| bco^ұQSOOƍl8LفÑ'!b 'đL _xcOK5פ 턶r4CsJ%] y%*!=rGPۤu{=/Bt蔟ϞV3h62o AFЉx:ƙ0{cbwǰ"(=vExG`9d| Ro>-`bܬD\0YUsj쎡ߖ|drf_z~ǿ͗QEZ=tZQ:\+[*:;3ӠJU d O9hTc]DV2i(t^L*DFRw4htJI :e9q5NҭuN)vu?:%!:q'?u9.4ᜋa"v@}Sq7LIҋ) (]aR#l*,[M]w=s\ȿ`?~R 'nͧb=T U^QՌ+/58Wcg P<>,ؑEz"X6 `iq7T lJQdDn-љN;D>5Ya?~H٦gSN+6:ZN p/A;E !"x6 G`z l5 -ZZ0ZK60-JꝛbP6`9 vwbE^ɯk$#(^-S )gS^ƎSn_ @/E 8B>ܥFB`ȜH[$Cy {, )jKL7_gۺH/n=P1~!ؕ"Ux#?&)V{jAɔwB=KkqRŶnv4 Gqhȶ,zPg]f zX.uw*_QLЕGnabܲk")WRrQYd4zBoN?1eHp9MS.{Ch\1W*\ܦ}F)y/2^'AA\ȥFyߓHAh-ėZgS~շH.:ef 1;34*HA8^ (@ Gstg$+ќ"nZ2Fpž}tH[*2QءOFo=J,f>f3c^~9Zk?ܒڋ%QJy/5 lɅ-o6w_K l1??y6_:wEfMĄA_AAYɇ-GQ~d<+NzϫGrL a-FSϣ"ќl?ysEŖIߓfOid>X(8,0u_SˆBcA΅6uU:mKp[i3yin!(|e}\LNI>qVyNĠ8Q+y:8/`| z){q&UhX&zDԲsu38OA#:%BE;>}̵"&cz;^t]n=ˎ|7-)`H 貑y)Qtz%}E0/!aw Z5L>Bc^M>xWGU/ȤY#?klbFӌYJZ^Hjo 8)ȸņZld[c{;^īG?#'vزTb+k1 f0O.`9L6%UkRҤ? e2xS~߽nXc#N0ԦÔM\ y[;&5b]#ǒ%В6;h# RKaW϶7/ `ՑSeS:h"fD)!Wc ;U}R-2Zz mZ\)E({{B͠xEL'U5}&wbfDȖf ,`IY}#! MXQo@\.쿓r4MiiiIIIQQQaaa^^^VVVff۷O9.8i`;zeӰ\._;xˡ]3`{e`9Ϟ\4``)淉hWWa: m#b>^&ˈ%+c ^BZiO`q3Hl5<*렝ݔ<=&c. )$AaşQ~^-=SM8wu܀SRXhOxFɍ8:VKƽ9:B341P'Ay M6ޟv{ (~uZW!EWرWYX8iXJʼx\Eh.őyV"w!%LJm%_W5_C,'Z;+b0e+kn`~͛L-_C &y ԭ׳N4ݺuOLMi`wC*۾ eoec)+*R/XyĞT:[a5PZ"-{e}ֳٻ9N(n_40& Aݷ$ `"`6B3[zڡ,mLul&1^Q}Ƚ-L!rv2Ѩ>i9x@ӭ(Dgrk~/9OKa^,0ڎ /x'h 7Y~j5' px3`\nu{{c|7qqkQ7=6IRx '#P|+fD|4~p,tO d3k̇ġ1Z8( Z> AȞ)9m|aIE~3Nua{6:fa?^/6 z|^t;=_Aa%,֗g$YD}gmR`<#i1n޾}±_~!iE} /F/'ƌJc`2xl$n֑H0<1KאB7Էߔ?OжCes]N>}W$YsQ˰ف5؇9'kP :Zsq5]>VHU)-ڜV‘G2Vgf#%زE͛O[v6M\Dnh+VytFzv)E;?w76:[UNaBkQG&f\9ֹmFM;2)koVQI *z1K'ϫyWG.&XN'e:'}[oC` {g Ȟ~q#o^䐖A㏦Q}x`KӁؙ'0mH/z6%>뫧L p!g6 m|W*o!k͜~{nF$9/xӏvWh!JJ[;jiᲞ"=~&+P#OV`5_cGn@_5>QMp{7onFQW#vRWFK& 4rJMHs&=:ZPT"͆;*XVúmjZ.U%:M %9V§GM/K_E>߾9%*+Ok^n#pO`/$HY ɅwLv0Ys8l?99Ej(GYgCW0DDaiZXJM}U̕^5 ɈFQ2 iUJH`8ClݺM(8%|mQZ@]n!|C w|OY5SIo:PF2mvHPeZX4r JkibrUZB\TTԁq78FH"C~ j灸dNU֍< dr:ZvbXlZnJ'* g)n$`a򺼸d|5 F}nFvJ_ZO߮x? }gC/|_ps&l**,:%S\sE{= 2n𸪟d9~%oH)"[FFea djؾڒX9:z(Bfkc'(ֺ!4'=֩)B0YԔÙf:f4듘1 "LH43æ5m泉ۦ P"c$={6!g)Y9{]1w |* <6>>rN{e(qD{Yd=|mK!cr{߿)W(TV:MF\ Ԉ5sN?#` {WTHYW0 ): - P4QgmE:8_(!wjsЗ]1 aͽ- 8SJ엠/?s "y.Ta=d$ nr첈"pM)4Ɛ^8H™ϺCҾϴIa)Q̈H`Ff IDAT| L 4'jtE( Gjʁ(dOQDĨsA0,6tȥt D#;aCތP@+bՊM6B"+<+`-~NH(>^nI(pI%6aJ:9. H_% M#ziФI!SAS w?X\ l\\y3Rvm[JY1g g_RyL,mkө2N4\\\?CH{T,x"mHOp/C1mX'& E]i;4Qxf N 0`ed KPzݚ9|f)kqnL0Nx@E,&b@<4O k금e GstJCjlܲHsH>KZ5С0Ԉr:!:D)yРij p5#(o퐣wϮXFuja>q&MP/L 5hatIPRi!VfVJAw)2sPڹ(M DpߢFss_!r ՍL\CTyͺB| 65Q%QWpGʉv:1chq;[IiflOl:<6^?:ʩCf&\%uҢM0I&֜_VY5f7~PA:؃RɺK󝬽8,Ew[NN΃-4LB~9D}۱/w>s/΍h[8D"e(#$Y`9Hf Œ"1)B"#1ss2[Zד%Sԑ׍%8cOVص "C J;bZ$N/ ewGYqǬۅOk؟|mG[/8Bp.]0J<Mk.ZK<"[Lm\P*m,p3dM0OK@OFO6{/}r23%yx?dEROw[W?@d}] ==HKfz}l7$hW!s:" M fQ%4`4ڳ~-5VќOY6Smbp=<<8 -PG ro`fK!>ajZi͐Ou{At _?1xu9lc̐@;.?h)ݴCK!(A1z)Q>SujA2UnyGNN ?Q!6 4IǤva!K?ix0I79wp(Ɓy0@\Ll@%r - lh%\Ca䚓pզ0FFM{VC)Sӊj6!SIg*.T۵p fFҤ4v Nk/¾\F3N݃maXܴb) ]r g1'펷O | DvqOCUZ:ĈE{2Yp"SK҂*+x?JukUkARN "](l[I rvrv"[}.3eFl'#aZnoY 92B^?F#&W$$SV؟gVU =p361w@yN*$e?I~o 3/=m٘"b,C\ԩE~*X)@-fR\b `(Ga=^^ 5IDiHIb {4,1 PfC>#[Md?R\Nav"f J֝h)U|2d&fdjl J;.D4AvlÑ4Qa3ﮢ|/t=❢Rwa_~w;vB+Oߺ}EK  [;M:YɏQI2A$>Pdk*@`F$% Kcq>Ɣ"M)pJTw~A&ձy`TSb@h-8ɴq@h$wr^*hn &B*y d4x㢠@ɰ/RHd2 YiQq` xsN:uגJ6EKXq7QPzN-S !m%>o[h(ƴ(x y]"K"Bg$%sE\,J%%HS2Ma$fD"&YKIM[̅ 2->!. #CX Z"+7+\Nc⹺sutg:\~5إ$6`Mh RtI]:ك@|f aYyT(.)q@2b3>!)IPDZ NHY9ѫZYa(`,ϟL,^Ȗ^&H>vH:I_݌?W~^.wBԨ$dzMYL3,~ܜ h&}H0`ВBHD#vO/Eu`T.He̐ J8b1 UQ=7hb55*eT(  aG<c}+韑ppfLnKO >8h3<|]"Pc>2ev@_zM:%V4xۏ{NȘ>M']눭y=_"§e<8q9|THtܫw#0wsu/Ik+ZpJt+.y"٫ǭQg3sa6fi)_W^\H+8CXC+ZxyKN(bWXV>H5"TB-ww* (~8.Ev>4>ل1KfGq>lm#fFH_|#SAzWciqaqH,D56DH ԉz# Ə0WP 8쀾߀# Gg3b(-%/[N[|]D}[I=ux ^. 2j 1_Q )0c ,I1 TDWAYE(\]z,e9{–51cT{gP#zVqO6E B *57RAɥ|ɚaj #6LZc/Sgif${u CnalvTB'<Y*Gbd+_1mLweO"P^|:I(몴XbggE_1$t9 =F.7FUv+Pnj Ds |u)tQ/T@0/zb7{cOHJa8ҒO,j栲L\QϠN`twQCh*Q0؂bM"Qc]lQ4~S1?hXY1 vQi(h@rW@@Pʌ7͛ߖv.$O*᪁b# LɼIEv.e E$6tr. [edS4kf*iV5rct_uXZg("1r4{<fNh4_9E[![Q"n8B9%Jm&*7]rPKNq[̀kt{qPx" eyf0(چTn|V‡AjٷaC?YXç$'=շu6/(<,KB,T2:`$/6;=~/-ϵ,o6o-=kں( x~iSM4]{,bGW8M.b9frDy/ޫIC5ShƔ?u8)R щ9T'yexV[Q_̾2ߔwo~m,&-#ۻKVu~ hcs9пkmNb 7ӯOFNp-UHUɚTrb/3S?jo&0_09yѓk(_jZ/Ќ߲k5fzK/#gm \5x&^TB{ 88`',0J^;%m'OXg2@@ykɰ&dzY[z(!ROY` $%euvNdB5^VPP^7Obߛ1#% ^V]:gק, W>x戠Vk,|,Z:ߊ_0[S?~¤j]ch/-<u3+w%̪zO1Dx:ܣ.aiwy%/iz)D H.{k Og//T/T!H~ ^5ݹ|B2pӕ쟟<ɴj֬A4`_taDˀi[d$}/d3(VN^bE#+:1- 2oLRY?bz~k/#uJ>3Te(_ScЇ\|sޯgoRaNi;\cs.ƿ[ `!PZ/*wJG`k/-16F|c?:A˨@-6`0 A0@:\zbܸ)p;U!ȲPh)$L$He?j@|mbt6ow/5/*3,!|m9lVU'խeee8AU :06jt0NY3cz:;)Pr%ޘd M\sjɗP _.]DC(aBxP^Y.br !60Jq(c)sH\OyU[e*wO6 %{@4n/*wJIQtI{ݧq[ ]RCGӵ+M#u ڄϳ/nݪDןk3χO*VݽLBi[$Uif`+O},ΚVT܆ =?]0l,V!h6wΔ1̤tO˸Lf Pث)]*&.CW[49I*lm'~ܥH$췛c|k-N_mԮG/1I|8b @օQCz[/bc(䗅RbC-&:Oӓ'P~r`wyg{:ef!^0 *)_r$^stاeo1jh_gQOS_X^Zy}c?xkcc C\|iY0Qp~a( Z"KCkJn>'G%PzHV.;G}pHUL>L4!8>):Mڀ]넽Uثd)%Nxa3j;ܣ-~eCH"aPx#v$B%Bff82s&ygGKvi%prS]&a0^;%%J ~Z_ T߈L`7k\MggHHK&UU=Ab\KzB~ ,Ve0xԪ2f /*MvJN^Lgqt.\;՟a+_8f|ޓ|\*|RG?!b%^fઘ)!O=Oī2=^dMSeknVî|D9;ܡ<^QJڭ. VR>%*`)(]aUM._s+.5W?^T7 UCҋۦ@z ?/1'(<ܜ{l"wx2WvUV}߫ˇ~~fԌx_}mwU@rmZn}{N]H:q5: ޽ yrlwAԢ/GM9" ^شu675rgJa}^Jy!K6&l0d%+%d/8lAn$[ai.H.P u=Cc'(d{5^._v/ς$u=׊&-؂!5+?sSsٲ=_ʭG$˷oޱcGp- |*Dydqߎox5 $NpRWCjhZv%\Al5XI/Lث< >Vzt:)BFt@W/uFDmWUͬT*>_Pg>]yO25^yx!}rO{6uBYwok]NR~Ukв{:!s/T){g´uQ] [->.X5,רɆxW :2TƯ@BGbo,k`GEqIHHxQ6mSpYض眯 W?Wy@ȥߎ+so ˡ7 juqKOM`׶@kO]-%Lo#?m`)޽GOsl1nq_~<>]]u4*[JR\\Mҙ#@gJ~R^(EsNNԩCHvuޑGy3&q}D}k'K;Lj6`ش>oLwww}aJI3Nd=X-gL=Lʦ˖t֍m+}:ign^;=0xgszVѿ.\)z| ޿R֭J-NKx::a4Y_"Wg^>*NPBTRpa, @]Lx&(`|{Ѿס {ԘƊJ֣|CK}5 % mTRA{ϵ0o^ ߸7H8Un*`0^;%a/-4hPOmJ-.b8ާ70a2((Oţ Tep*2"P .Pޝ>sF HRخy`i !Ϝ×^ц6^D@TjCy,_ۻVA%N(ÑQL`SY *7T dzyT>lл~4xp~g}N[XFעKԊ,pƆ[hM*T$4{zT-Qo؂]KZXXwPV[[ΎO71kN5=w&$!{3ѭGϢ5-H RA(g1JK,%0 x#RBd=S77Gx;FzVJ-#ݪ蝎Mj7W]bJ5RxA۰[AyR4cWOݴ=^Ly"f١֨)}N>4yM‰b/{~iNUBѵz xlj KKz܅5j 0-횁DV>_~ϗZvpGW'ϻ/jdׂ ;X&is[7cSQTilx{VxzZrS):w[G eA^ؤ_A!mY7,X@]xp!n{n}>س04jV?UB8Qn*RtYniV ..$CDwŊJom!O7XYD\Rz3Yȓߵo'AlQ ?n9Ң+KvF?AgBl&7UFǭ|oFY^O/ܫHN3[P3MPlh*Gm?.Gdm}l;W5 Mw7"%w=<j>;$e3ɇC}f~ϵ E*W4 <ٳr#t)Rd7sݰ_(u}9^/\<1Zv~ϭQO3`8 YS$.MEJ;0^:dvo9)^OS>03F-{[1oݼk]pRuu㩦ٹ8< HݫۉM$cCy|D< !715<|&Nq¥KN}s`}K,'Cn+r / i2lAT[W'4ىCa)Wg*U?G*"M-A-,;Cq-Ȉqrg/mJ\䖘i[ XvHrz/rQH`ϼrW7K`j5X0Z뗃:9MY8pEM04gDxv-I_K¨ԴU/2RlkXXYy.(+Mz3jBȶ= RyQɃ j`ixl@/$;-_8%2*=bBOMM @ſy~NA&9|pKXI_MyL&.~ 9L#a.ڬ$xeۈ,_ALt+^l v$ĽSahъO010vJϱQCN;̸%K6˲<5.af?S:K[4k63i#[7lBӆam#MY'+ho?[wYxrwy %:q_/{PL"@H2?96 vq pŷS_.OJτ F}ڦ Q+b]؈c6Ml-)"\E#g_[-._1R4(}^ގ;5}w0eo'O$1.9#y0p#>s5.D>-3)im^O*c~#85hd*ؓ-a ҮPsC^n ]?~ b[h]  a׮'f Z9+sS[ۦ[NA*BQ^pMBP~\GWI-mlB<7a:}5)://OZ|8c34U+>L\ﱸ' 0 9 ݒzv?y$/N=\`4ij-٥_>Vʁ7UmBnc'FxZn枋a2!lqW>?xj`llm90~t>qAf[{.M ԗ(n|svnn`^9j@DS΂ )@}&5YQ8L|7Ѽn+.v:nI:̄}^ oV fghB/ChRSgfT7}IIEC6j@SJksc@6HcR ]yNm_CT9Ò4{;9}4^\?~h~ oKUICchi~>Vh4 2+++333##ÇϜ9j_z}W;(NVId{S{`L&w5>|\;du to'B+eV'/?xeDDURY!4.67O;#iɓ 4> # F֨YjcT7 W\Gp5N}AOKVgobӨs2RN*&DlTS1I k)jK4p 2v/(0X.Ev"arͱ,H•),`d/y6ItV L3HL0D(]Ț^?{M~ ψȳ4fg#+ t903 YnE 83T 튧Oi?`"1kס!h rk }QCg~ i=4ov |Y%_#oV=]\(I<ǠM58yo|-C0+IvMTKm0Mec#K齸kF0 PmDpeXҠ"RM_t9d8_?zgZy:4bCe:a< !/1}Β0mV d@"L-nNwa6D5;<ǁFuQ .%\G.\|oV=5wE}3\wYQ!5=`}]4G/!z߂w4|60XM IC?N# R V߼`p'PnMFN= VڣCGoIx*E/:mz=ssݲc(vWO)BD1 qmsC@5wA"3 ;t{BnR,:lp v`n3.|FQz!RU 3'DT^5.CM])/W:+["ZE)o)8%]! !n{AqFU,z:{v47~U)ٱD$vt4/5cѼZBth[`Hq{cw({\bN~iMuC;L􊿕-ݹ\)Hl^^ ثFYFC L@\jaGmO>ŽW޴돡~aEv7Q6-F<]^Wƣn\&ȃ4 w"D!JRXAk#~k?֠UCP;.AGtmC d/;ZF5E2V_3މNCP):{zn O@v' d3Ccf&$jjpA.qDڴ`MmEЁeO&Yj@R#GvXNC"`urb'Ϸ᭕Og/p=1ˤܠ`rLF[mҙh+!XaTkaZ!)wTԯ5:՚QhE;M*)Bk` aԻкZܮBH BX& ;\̻B-(#woqs6j6"v+;ЂZd> >mZށ6.= ,&8/f6FM@bh3Z˻M52 P[.'H_D& =6p_(HX3 TMsx0 -2ݮ 7,0jEh٢cwf*N~,8x4Lk.)71Tj8IT1$d_Ai۷'ϡdSj3C =$g8(& . %g ӂ;-&,4(FEbEsy`Ct ]ɉ!ʵa4 \;qgSȞV2UxP('jCd.ZL)|'4x,QT4sӑ\qE4"P %kɉW7}n s*qGXLnlSR/Lފ|if[bWoyCX \M|\7L_O}{ %/C,' ˄]>^""W.hȍ:m5"1r4wr]䠑A}Sɝ_іG.п{6۬YϣD,? EzL$]`<٣xA_挜]jմC\YнsʾZ 8zQ^;>fD 9ïe!/&m_ <}`.`?+kk ڳ|#jm @CNnN S5pcW2/m3T]{WS z}2/*j Ή5ȅ-e{OA}!98<ɫ%Z7^ @^.ԭN)M75~Q~sߊ F3-~SgRf. _s޹}>o%Bڰ2icno& ׃2 jn&Օa"++;;_VWJ\-2"ZSJKGImV,OOhM]7CdB5x|eh a|Y|]|ڨk]ȻX_C&.i6í*&PmC}5k?=Zeҵz9-ǔO?)QPX{uS7ү܊ui~lx8޶ؽ]#%z{HD<XLYXYW ?uIkc,[@sg? ȿ{-M7N:{:0c<_Hۇq|&!mڥQ%2' U^9b@dLIWU9k(aO:i Mډ IoA1W V!l^;F٧ӍWE$TfRɯq$#醪Y9";j;OҹBu;=BBZ3'aj"J̅שPvK}-g6ˀ -!?\բG#ɾSقP]w%5zQݣ!/g@P锴 "<8K֪`[N%+bP {1^C*f (H|Jf|ļ^I'խ0@(3C!PÖ=*F"ܿ{200@EHp߻Ƃ8N#"0mvZfW3Mi\ {olCR4%aD gͼ} ?`{O6me {5 n^C!F+rZoJƫP–^)U'tC!(OX>: 3?"Įd!p<՜Յ!`0.`5#s&2r#,MRvlQuq*^3 kI+_ણgi3A'kPtߖA$C >ߕ^BdTX(T_á SYLO~g.3%ZV;^Y}!5@?B 3BjٷaW\xJ2%ug~gam 0sRu~ ] 7N*>" 27 [j~MiF E5٠ak52PyhC$Bu}VN9x&zP˱?lfFG/nՠ|+V|\dT.VHu$rN,9 }i;o܇K¾gfk VFNr7!*l뀹{;jĜ 3?ⷛ,T0sAOK6  y$S(LPqNV~ʼ/x(?YYY6%%%99jU ObĊSϛ[Gϧļ28= ;kAm%NQAvKDKR"Et [!{ߧ[Cv0##o#4YA ,Z!]. 67OjZ>-M3PsY%RfK7LQv\Ap\Yp}U\qpA5hb0 A.݁I6j$61sg9J0amBfvϳ ] KPq_k/[v߷ouNjm0$@wȑM#G/Rڣ{l[%Qc1#pn9G IDATzVY[Әq-,\2Ǟ~ݙox_bAEu>,w/87M"z#qu?FAhjfv7:w؃ lL2ħAdVu0a-0*$'DV6l|Ѕ/9v,!=1" AP&뽄ቊaA.S!{HWorX0~+,<WUc\E+ثL<|t߳+~0OlO<;?{Ղ \K`f_F~طu{FF|XG :+}(K{Ԃx@25gk1]3Wwq}ݸ=$Ͷ2htIyhh7OUOB09}sY0]ǧϵ0pgg+}mLgDvE&I,8g(a/ vU - ;R)b"*rY3 @B*da5e1Xuf+%*aebA?`X"YޘaGޚ!PX-_x*,d ׋A߅HP#CM`wY`,'.%-"F+!PP"#( G]4.H4)ܼ̄Ezh +Y8+!(s&('>H2V f)U;%,B$ Q@`.YQYA @"@_I*"uaQڂ-F ]lȬWa,eQMZCxKRq`MgTRM_?W&K`%C@&f=7Lत$@J0oaq(>B̞ Hp^YǟH=`!ܿ! bG~yHBT%($ A OTA.^TAh @5]]aaNQF݈J!a> X!P-D[ƉVuo"cw8?V0bb EKVC(7c P KGQ K̈T1e/Ez)0AEdD̥/wMҤ"W#P.#9pZ,(se1+!& b~tv U [!IӅ125af!:|",#,-LKHZ¸Ў N:\dBYkEk(}L+ =ư -?[!14 ;8+$Kb Vf!ĤeX$Ќ ~(x$< bQ0@ ثtpdVoG6[K)lW_YC0*.bL!P.*K;\0*>f,G ثL`eF A_tяY!2/̷r=6f Aj Y>G$as{:2D3 Y,Qf!PPXPF&gO{q99kXW+uHSE}aOsVg>^ r[U618{qH#Kn&Z:P_UkՄ)/E|h1(]@EWHԲo?î5R k~?Ңǿ kw,n"T;{' kkkq}va-E=\^~~!g/ XzqWįŇ36q˲=-^u*[/VC`J%3J5}V,6oٞ}$n{fvp,`e^/wѫu%C` W[~׃gN9%|VsqwVcSBVxv^0Z)ulȦrR2* Tր*MZ7>7⊍$\dgF(bmq{rޮ->qb-.Q;6v}8lWlEhM܁1q[gr;Xu{Ҝ#V:`HqcxGUtkB#(W.RuY/4ᓄK߁@SI.5곥ov ywF"(GDwQ'oMEK8J] Q7ȩߊ44㜌"7 ثun^=}%7G 2[+.H:NyQ42:G))'vyIF lR! d)m/d@@aj9=ozύYݧ#Tkr5R_q!2L8$N fgc)FXLO^{If1aB2B ̬\UU!`2 + s,5RisMԄ"5 ' v퇏/YTzfb$; ]58Ǐ OQ2c&gmny;zѓ T^_W>8(Hئ<#sif9n {U}rʸ,f$S0yFD"a?{C@yU9qZ]N^;y Þt?w)$s۸gpNX:-LׅXY㊸Uӟ!l{n0 gf!`^|[, ˇ<8gxLEC /W{A9r}8r+BrHS+Ac 2 c?2{V.}Y54{ZZD*Kc0^@VMqq Sdi C P9*K_`0 7@K0`ԀL6:FjaqgPN2WZ[BzA |!`q^j]QUT|G=:2Т[5~/o_?ɴi[0LS!`08Fb-ٻt[_kA-H41* ڂe6|ΫYH .8Br`42=hŮH}y pyKv h$l]MML$rB}A"/zom bW8X۽i(ju|-|]΍K5J<E d+`0FRM a}BÊEfV<:C6.^I/yG C'h4'&gD?+/){IͲynҗF bڀG֧ U2Af X%މMsAq;4lӴ&R$ =O5P}6 vrBbd#57E3}g09[è`4>ehB(t;g e|8i+Rg-VHCco Q3g'+7"?6um`{;G2~iҝA' V=4ov |T*^o]|˥Dq}xlBXb#HTIІ.q,CF `0ocC RAJ~llWoEcB]d׺.a½71_p_j3HvҀb@`.Yׁ"ԁfrH:={R5ki8A^yQH`[o~0dq̦at]E @FjS–őik}xk{!?FD#{`9Fm5oKԵ[>NCxq<@y)L[+.kJؓ4Cx4My h&bsD #YT}<"| ,'`k] EgqDԠdt#IR@^'NY%Ek9/2222R)G4g*YD)1^/N5rGanl~WPs"%x*%} Q=&ϥCPj6. :4'k':tp"sQ _, +p7D?[4%(!L2 ,j-k ϨP.VV/+"D~c]pSgc:.lCvh]bV?;bĈqqrmRV Kq\׋yKf0?iz]]Y:}3>Mޓλ0)b9J0wq?Oy+]KjqI(/p^ kEkZx%- \^BF_痴^@+tۺש. =sY(hk]Gg|>?O2k#$C!@0*szޚk)Snܨ. Bv)n(\YHQ%n%kI=soV|9ofoC㡣Ւ B UPM5 'VnEXO)n 2~=ndYH[xN%>Y '\8fI%cawC!N`ګ.T( ZZ (`&萢I1GwˏdZsα|=}Aх&l>G|0sk%[Fi$!< ;}ߗNo; g+^CGmg۫˄Yۏ}ż ?$cK e0MwzLPW)}w~Sl lDG Nt󐾛y?]-L4aMGm(3mʎB/聩=Wv-'Ɉgy38:dZȯ bYш{P ‘c0R;|ެrLG{x>Ŀܻ7+#ۚk `a #W`5B,U֭ۛpfө=7K$7-<h؅ Ȁ:ޏ ɗԔr՝68ENu06Vޒ^VS8"@\c9ش @C>P / 㢩qrd sj$ӧaVĹ޽lPA9{+ 8RjJүp0ٙ^+F{^!YTQE8=E.4F)ņ@4R@N`0*^{:ڝYpgIǷ?[&[.+`08fm)sq 'KY0ch;fJJ^LbӹMܳ;}bڋ} {zǧS65W@l)#7񁖮 ?>F̢#HBx#j+ջae0 m9|S>TK1.k[cM8ıp:egibG$Mc0 R`ѻ<ހ=Uܘۣ `\U==| =n!C!`0)a6Y;7L V2`0 ;23uδV-u^N 4$e* g0 jjuF(O0VV+0C@@YtJa^!`0C@M{)˗+++ (W)ra ! ?$DG7 #GnGҀA(|UƍqcMԴFSͲlss72JAT+xxm'^Aٸo8mKv5G(M^"{, 4ä潂$hkmۇcΜa[/iZǠ/>qPc齽T g֘.WkQ(eÚ~i֦yjx,fӎ[hNk./fU tvFZzmXķz=W 4kRQ4Ɠ|bо޿/#1NA+dFG\}hz|6Ħ6;sAVۿ J%EƐ|rͬ<[+ _ Ku=v:h5- ,?d/qt8ﻩF/{~hu={]𙳱MK$Uw ZJ IDAT5D"\ g'J2#C7Ɵ㽞:wY:|h+"gGV~KZ'I!"eNꅹ#EmZ tdI̔pFRWipcg$]8<:xPyw*W(uX:}||_T: %zΚ}|vx!4&"/KWr%@ѩ ϣH -P Z-^{tnZ02C\`Sn =Ndϟ!mx"^^6[Ç) n7>C_K:]KXw ;o @{A9r8(`;;G^^byoZ,9y,x6LĂ#jXul3hFȤUP(*1J @-^QŴW Mu=rmo^Pu~X ׆|"]%]FAa@4-ǕgƬ;xNDӿo^޿㲽x6$GbOD}`ՁJ4'@s)1(9wF'TyA N9j:],{4ZGj) y+$`Pjᬶ$gLqW#s8Bvhyׯ$MҖNZsa)Mҏwt%['͝>p3+^lo^H&uUJo #U`Ta8&@bV&/,xвeaGQ%޾Vy Vn%ڲ[%>;IA(jF<%Yy(VAD#9/gWDwi_E_ew1SjIqBBֽ3ʿ8n%3$qx^1+u.[he&$D$$ ޺aV}o]թYv,c(x4}_ۦupJa2Bg:3:# 5UtuҎ y5b-!0tiY[9O-le Ϋr4sWGk v|z;:O۷9]FLێ6ַ׏|~?_#Yt1Bǧ7t齍HE} J工 vYyTa PRJ04ƈ^Zqp'<ӬǠ@uYYL^+_vmP]Y>;ez^`Yq9d O锽( }T02|0Q]p#&m3[onfLje .شgL_\ 2!ahBo{^L{i^V/>vՕwq = {z/~芗uzk]с+4bgC<բOWw.[ʲp򃗻/'Ut(61S: @;Kgc AŻ/_+x`e.uo֭[?rO|O.7% 3rysrH$60X.GD,'V#ȷYdPj*GjG3?6\45Nve& LLLl֬ڜC0ظ}7t{NJfEH'bz-ip a;d<> v!H-Kq*5)dovű1@ytIŦX4OeRfUdم c̜|7o[ᵰ`ق+Q(l@/ef"zaM-qD->F:mΤ/ak# Gi ϡCׯO2z `+`umZ`nBt t4{&w]# ?_MqX&#o +1!ޫW tڵI&0?^YUfTBgJv }r|Z4cQ3QT|E'p-JЯ GN=7O%b)2^շps+~__%2{`0^xh!PF_ѩ7R(my?ؼ򌍆́c4t8'j5[(hZ)dy@$# 6o^K_ cUI4eœ'&®=Y^ldn48N/NQȵ -2`F;k-oϺP %Pa^ `^x2 >q.v6EP5k5X"窃hVVW+pC<#D@DcB 4|<ƙp|,_(<ј>U7nƽ  U~s5+v<?>r}m^;jܼE~zU34KB?Q_ WÕW|7݋eGCEzmmm+WT͊&`/^۷oFoxQ@&? B`!Ne 4UzV&9m9;h u=L"NMx.\ppp033O \ipM2G^lB@Tًa|o'\**%V?zY z $m([ՉP矃 TcA4GL{h0C"Pl|QՅFDߵB|?TqcV{Tu@پ0۫6`K!Uw@eUuJW Q+NapլSeۮ[u ڵkS o,ABQO^1bT@eDL: &-?QKiJ(hjaU1ycr(TU}uj5OT:{Ԋ( 'q ?MM^Q.Ƿwmg?֩^*`y|e;3 (FgT)Z@*n*% O&ǠZu(}^ſ[;xe{j`o7mÑssiy+$(RO~da&!"J}MkE9awCs17E'!ڋs} `Kh})B#pUO0KDžo9,Wy~{1hJwP]r^:5]5{T-ij8$ Nlzc'{c''_>gPG6tjb7d n2s?o Sfr%^NP'e>ck{[Z%Rګgvheȟ~Vt}RUs.cYW NqRiOtX EZJ6~KLf#: ЄK7 qD.6~k eh |{ZyAQ_g&g7<ˆXڥGD$Mѣo=7}r P7y*5@q}}bT#`&=ѩIOD?: hcQ~b{)wgpBO^d֘fm=+^|F·fc~Jᮯ HJeo}J9Krw,5 K?e$_!㦜Bz$C 4$ 龲L޷Jiy.@0v<(0olSk'_Hp7(mLMMZLݞ䍮2u?)[Y(U^0,M# ?߆ Kwo֤HqX }w=xzs=P}^SP(k2 ˡOHPW:Ւ}=o:n"^4yۍ\ynFܭ1=|3kȸ\|nRi l'\01xVt'N4WTdP}1[Mޢ:5qG{-Q eO?!qTvK7P^qReܐ ↮fj~!Iʮ8Z\h4nBDſwoBpMS{8E:{hG9w܎E}d^G8؂!֐ęEzPP5k..<6%kPmlcKêGvdIOt̲$wtљY+F -޺OIYң3Y/iO :wCoYa ឱoBNb?kKKqʯ@/mKNJʹzGߝYh?;9=3rJ,&~hܪG~X!sCʃ-AZ읃eXoZ+gO E~l=FISzzV T WLzz5ӝf'0sO\U+)2]V65t r 9Z$g';aZogG[2aFц@+!=3wYiNMyۥRe@B%E5U85>2<4b&e):܏<=uggkˢ0OcaѓHX@@  Qs YcJ$Ωk|Yi]댞<T/L#8IJªB}mM?mXa !؃EQt[!Fu0f?K I(a_ԓH% QEDK?Zfd?0ӑĄzq @*=&<]P€,Qv+lw8o?2ZS͐YCǴݍs˿8nO;x1\C6KҨƊua:MEId4hbfI# KˏMիqϿ;X|Պv<Ou\zv^fAV)?y賺tZ.f%^^C, Afm{]ؠvSnbk"ϾB!ndq(MIj3B A'~l)na(iplx<^=Ҭ.0T5UI4pQ(d9¦Z~hѹ7B&0(l 斸E YQ?z_R<G"o!0T@ׇs$&Xx3oX%*; & o)Wh!LJg+ >.:N/m J@"S)ރ}6k8]ݽ$ m؆ _lD%YYo|ay;b+ZTTb4,I~{Ҫ~g.#eJl;RՕqa-jIħyڭ"T\ zR1+Z+P,LȔQ:` C\R,b#LdުmhrD Mj^U ʙYXk8rLZ \Qca:9޴ۺֻÅ5;Lim[ iLEu.c֋X bYsIOm#G]N#6k9LJr4oҶ a/s{&?T*xGk$V_xD5TG!eŦYdKP:k8xX#kE.ZX^06Gb~<PA 3M3;G~|BH8k =12k рq/OQ󰱐75Cej.T n>H%)*CΙ3gׯO\zz  \yت O5+ΛN? J0JPHC1?^o>`#@.]4idhѩ=98d&QE@|t!`_PP bYi{6Kyps&;SԽ+a &*c5JT FcM*8CWJ\<1C!P(}zcR..8C|RdS-$ѷޕG%{~x 9mq,P:7xD.oYϖgv]мyvڵi܋*Le*KR,9ny|OM*)X>8ryHWxаXq)"Ҹk ;~ˑهp⍙!z~ ͌ɚԲq붎p藪5jos+aYqY~-%n!Fwj3 r<{Fm>qԾװ*217m]Q"c츓FSƂecPR&Ļ(x!T} "q3%'mLVX,|/A/zJ~y9}mIxtqm;dWv*믁KOOk,#ӯ_ un*.6:8TRP39 S~솺aZm7Kl  )j#^kWUg$(˔ӛR<|$)^P͍! l#auGWyX¦?"M◛?3 }z\x!BglP/:2#P8 NdKJQh0y+"ٳ9Dkq 3b+a2p䅇 hj~50΅377oܸNR#69EvJKdu w mشˆPkf$j\p8~7!;N~xz?}^%^E{gį'Y&&}XEl'ɆoIoȸ) 0}wӒqܦ0g``j_~Ȓp08*~*@/gN446ĹrFO9KrwOU7,I B>vP#@{0} X\݃U^?X|;WH_nFr ts^_XimAmN,"9mcN=m192X:wތIIlVFBEENwE er,TPD -p:W>bD{i(s,YJ{ C1p hpi >!Ogf?aoC(f{trV֞vby|a6= Z!͸Sh˧Txh^{d%G; 9 b=_r9bO]F/r]t2󻏾MI<.AE:oHIGE3hǽcE_!W[Jb &eփ%=xpWPB_oT"җk8-7UIBpM c5e[ >i/NN~o^>Izћ'on]u ^-:J'MtR4u5"SZm-) V7*)Qr'۶-t۶g8p dy&%݅"h^31^FM#[:w?nی\/=PH&"iAntP'pAѮؘ7'H/Dqbeo&_i݂kl~~8KO7m*HZ7F>{4j%;M La² CR,ڠhQ9̀|A!zov_B2΃D-kf=&%jM@tBֽsSHyF~8U|T P(;8k:3:#B8˓s?~{إ=G#\D/6`P$k-?\x"!aC~@jG-5ҍKKVX,>/<[';@D'6h':21qcdٔ 0@]OduJ5'Y3gK {a|BMP dOz" 4Xà?T۫`P,/x2b38 f#ҥa$egWw{#$wqY`Ae]*p\} \'I땙)ο\<'" ,˗Nm'Ovg=:Ѱ~<cwA,%5ہkk+Pr¯//EHTIT%3u"|d;R*Lׯ.{(/fNc,k vYzb\V){4~ |\uwh .,qHE>M3 @ICf?x4w?@3P61¶y7!a+Rdj!gm>jݴT-,lѕG)3-ǽ&; CGW Jo · 6е]SG9i`KYZN#Q-BbAnG A[RD%KM0{ծ;5gk \7h9eCFC! ]Ok߻I;  2(n3ʿca8C͇`}A+"tfp%Pxe@q4;ϣ=&AL wrfuö]:?Z™M[KMvhgVΑ]V3WŇD 2[}M:'h\x>ywĭ&-'Ì!-pʱpaH?Q \Ŏ)-K^s7_YfG@B `nf_|ޛNk`9؈ a$FNKYb$۴G%{Ӥk?TrN|M=e;` s0 5w\k{c/nIo2la!7-O+Gёg(hJdODfFk" aINʣQI">X",Ƶ3LCDMn3E,~{swO0YꭝխM]>rށ1]t)H>r y Pah"ǧЍ}Ϩ4o'HLV5ddJr k xB SRz@*xT`Ï>>3y*x{ 1 sDh>1S )jծI-|y!74ԃI|Y>Sc{diF<׿|*,%/WW{t=p ad KV^,N3p`4eI%" jgP*!' ÔJHR 7;K͉HR(qW- dd #2ۋC/`t9=7#]AoڽvbҥCܓ'W꾌 :\%8`Δ;I)2Q *CUGN*I`#ģZٳh TNZ0E\-PbH\*Pb8ȤU<&."20j`iw|6 W+zR$u">sO@R QE tPuAbyA >hTTu%L)\`RAa|<5C\㙻|gnyܒkv;w /aYcJ`0Tv3~V˩_3x4g(UN#ǩе Qa~*% 4.L#G`G(j 7 59MqE_Jmb*0ķf{\q?aӨ_ԧQȠO˨o?~A!jGk+̺PXD|^bkռ`UאNH!/W7hgڵ )X}M@UU VTʄJ% ķk6G)8wnݺ&$t"XV6(CQ`\YT\M,}܋RI<က=[e!PRqVV@ǸZ_u>(U6z3)82d͚5Sw8{,j[^󊺳Z},8n ϊOYΪSEޓ<~%ItT(J<G>ݫ?HƽZe3;E.|i< "W_&[JxuQ0pyRznT9YsnyR^(,oz,,˟; H$E%#g+#!j&kHWw^ G.[2n[ôf/a9 <&a}><> -9~_J v%*6<;+$K!P/ɨ6GQTV1YYY&"O|D2E]\Mvwj) X\jŜIKpi#49fX*>S#rSb'DPޑVw - E͝7BpԼA~ f"G?"rGEs_2w3z%H4jh7mr842M])d d:G{q(TaEEXQզ(ĥDR5F~W\;_0yeĦ^5j N::nIgJQoz$XH'k77'V8j֮'Cutt֝ĭmNm `ckv(ivLd^^"eTS(;kW]ukHk4C&ϓ.]f&bZ&ޮ̫I'I瓒R3A}kD 5]ibe銹m~F\[fʈ}1j{@rr8GpJ5Zj%v.kM/3= ?s(.ܲ~_++`>@y `Qbuʆ. HOR#݅H)O6Tx98-~b]L u,D$KjfŒ܂+/ yߟLL8xʟ=_;ҦǙY<|zDiyܿŤgS@fAAt{}m4W:pg:a&8y DQttD3L*ƍ='8a|H~ˢDRATXZ WZoHU8}0*WQsL@=mɢuZ s$ifȱ) u at%z %a-$Ԓ{pô],̜Ǔ~"DbڪS/'G6XC)rkrZc_~l$WE`jʾrH@r HoXx5,<6ހ 4-=a~D&hN #<Z4Jc\qgn)CV> %DA_YQ 8]b+*(,t_ɳ2JejNSW p) RlXb_ߘӶZ,[50Ts=)s 7%~x|cis0z իw1GК2%\z'm[gv!MI_~N\P nTZ::#~a롛ۜnFu_A{Α"m"AGWoB8W.1UwꇈJS m{v(PАm+fVv]q1.Do#@Eȣ'9w1ת娘(X27t>#r) Mpo0;O:~Vyxd.2בVZR/Ĉ5IƄ.I۷p.Cy~_3vJ6'W 2 d4 8-qkQ9N)hL.}g>fɥfB%KDS"W^9tv Owk{mP_z@4`&ƺEفA+{_ooU!1]5! Ϻ?K;G$Ć.ן-Eu'C^_Pwx^xw7F\1T9D-b#qVitbQc4Bgb\`iRۋvEv8D:Em/Qqe]&^9&N{T&Ϲ 7gI(ͩjF%xdd *2ѳ4\&Vj2KdX-XRǽ&E$bQ.!/?bX!KGh fyzF4 [A?Z"W*Pn9I|^n؏Kƶ-ճ͇ =$ۂI}E![lٗl]y hO{u4E #1@l(la+Ki0Lc"uPHpQiEq6۲ek.]0Ј\8r"8-8r՜vr*%\Z Hܢ JΦ UII/HJauf-I b& u*]دYnyz-c`eE&hSolU8ޣ9SK垒zujUSL,ۂiMNN> t^mE$Fp*NtTvQ8VbzS/0'LΞ@@iGSm i YF .kQ6ʕY W1WDIjx,Ɍ+ԔE~2گ]ܻͧ(R G$4y%TԀ;oIZ5}kfξ5s~M/pdSU {.*"+J/XN;`@={VrWr [٫<9c{am?R ,6h[$wĹ qigA[J Xmi)FBo!t%X]dޮ5(Yv0w82)ɓ=y)UiҦgcs+"7@`պus." VE`[yQl'6%+zrcЉo qׅK$7q}rŘ&zy)'O:z849y0sro?wZ<k"8jeT/ mjy؜0JdĞ(t{?F~L!ްao~9-aCΝݽ R?l\_)ݪw`<*-pL. ?կ86cr؝!x|;w'jUJIlS$ك?U"/@]2:+g<.{ g^ЃşfJp{]jCӮ1V.x:FO[۠tVˮNˀî2 ٮިƴIBh/S?V3c/ZԐ#j׮-PTXQA(ƊSi.ovX9rz>PFv(K9x+ wtگr/YI&7ݺu{J,'_34de#vR8E> r.DB2korDͮ鶦߅z"K}832$20R*7 |#Gȋ~lB?0Kl,a灪Qf(,K$\ r- H ` rً 9s NF`W$T iPJ,Hr 3 D]EofW|,:G̼Sݪs@ҡ|2MM%٢A܁EX”^@e5jTp$G!ڧxFx_]Hwm=+2ɮrd?NgX`Ur_7U˗ݏ{.ufBe|S ODא|6]EYxL.w/Ą )x!_90=80eޔ3֭ojlm +;֨]Jb1ʅhJPO^ߎ坿vm̳Yl¹kPìͻM0,*,WfLM_2hFbQ <"~bpZJmEc+ "1xM4Q]J91e< sa}x<^_qm/t;OD6b"+ԵkyQٵDZ㲶@z(I׀ddTBr$X JQi$OdxK飙$#lDgT)˹ Um>'Ӻ5m+&QAhӴχڶ-VV-#jc xA;͍lc!ps @UE!{l/#֕pphljaE脃ՆL<d'h2JG@Wq7ڬܝ{&-2U*cCMJŃ $bt`L:"[  heC9z6;9"YfB%qK䑄?('CGy]ϘcQĝi#Z7Z9/kǁ)®F3 *]DyAƄU5REaFGy@Wx _Uc̡M,9K&jO~ӡqEL?~M{nۖ؝! YINՠBWz+dG跏M R)}.OV]ڟsB?Ѐ{QyX&8 I$x! “r@gϞ-}YNmz*+{g]XEUA&5|f\T,-󍙊&)_>YTDCpم]̽}塠wĽ3gΜ99sfΝFx?GAā]Ӛ0q@{1rdooӗn"B`w(`5i  802i9>>>CaQ0#-#0(KHY\r8bt3 icR0V˞l{h9E;^#?9Д|dfSO\޸Yƨ[y^々c~X@JKK8fA@=|,z@8m@𮵮c?gARb- p.`nMf@w'?SOC{ - DR)xݻ,Ex>Ȱի@jz ꁉu QrEޚXҗ/K *Փ jŖ_~ZӽT| %II_>~gQRbO"WM>Q\TCo&>l!kO8p9 Gfq8{#>ajЄiK^\Ҡr;#k(AEqѡ7~ _)m׾=TJX߾}GPuܲf+B9`yAz5 Ik+a<C|@1u{x9)Ln HZ[>_^0,LီZ53qPb:- Qô&~Gi /M }tK`:mZ#haM=ϯ-MI~B9="=JN5IחF>|ޢN.7KY` I <~6evM2-Qq->ƤeV Gc}}g/MH )U`\ӓ5X ^ĥ%%%o.,,Ͽvq1~hέc9)Ҝ?+& cc t,scch|iH( IehҔk F8$`f**r}'/-eQSL]/Q1ܤJHMNw 8(ȕ2)-R"{BUrJިVE31%ϨW EyFPБ켔uEy c (寂LTLb7JӢ E3BCg̘A:?V`$ԾIlUk5KG}gKX\T@Mnjc"h[ѥt|˲G}oD$#\uaN {P1:&!o" eOV ဳ+g\[j*|{Z8_0 0{5ɲXHd{fDNφY?v,Y R X-{1+w$!Šnd]p|㒔{y QH=dH'6B V Mv1 RO-d^S|=뻭&4΋=ZQIǥG :zn)0:*/rd@85۠ "_=3[&ݍu(t8 A34:(+=Ȁ%dˉ%P@@,`"[ڽ5Zm/^^.so26rI`p-Q@Īʊ5: ԩI, i:ڀA=tkʺ.Lxo8PpLra*UDZ#DIz՚q SBU;8J[tR̽En}&B$r;%d/hc,. <=ץlLwñMjgz1Ǹ=Ub-x% MV&V4[=;S E oy^ݨmbZw3&mZP"Xx]އe{Ҵ8"Ap>\0!.#&HPiF 0ѫC -ejZ$sj6Nh;)V]H+qyKкLkK!u{<~mTv]ڦ&C!}gZ0 B7ѽ&5 #ㅪ8@@d:0m6qM"dѐ(b{Izq5=Hٛ+Ҍ+.w18'0zPJX%p9 I2jBh6m%7߼yDKU0[r nCYN‘BwL6X]<~nM(L?D?0w77OVčZrΎbW]7S??Dzlr!~7pM(s=0vQM^F$UΊ=xznUiMDsn| 2b~J`r~Ó~dOT䣕I9W]e-vƹB1q`97nSJՂX!D̿Ļ>UlLuтٟ6ѶO=?xG̀2w4Y¬34[ >%NLP8InʤĿKf vfЦ"'7I!2suzYw1KQ`d$)g:ȏM<ݱ粒oǒB>g9IIK}xwxxxe^i^'};F4p6ں+g/*9wȥKʾ$-io)}ڷ*'"C}E`QF\ᷩp -Mg U* ΆTW:v,TX_P&qQ5/v0}{D@N^1.ū^aBVo~4F?a„=u8_L8|xg̼tʖ?!U) YuƄĞH&V|bO{5M^) ߯p<@oPSiHrZ[/% ܡIr7 ;mV$ãGCFޕi"Ic;Wt5rh񤻔T ˍ0>PsכE.:v6dj' 3L;g"30iP 26=۔+Wm0~]Xp8P_X:3mS]6?90/ [v O _ Ӟa89k(Ÿ33<~zPTo߲eKR9 ^/=2x._t<_rO҈8 pQ!pA_< .8ӎsFRuh$U xpLJNX~5LǮ+H1mWؾyxK=xǼ\Dc\"ryW#JJXo%f}}}mߨ%|v+gNƊQ^H0iXtnbxH ny2>6cТ`>|&R uLVԔo"/ΘG* o8g֢S<4;=0dN~;h8Xv<`$3/'gţ$tA7'o֦y[ .Ɍ Ś(:lΆ4ܥTRW1 x ]N*,$6S5m,5-?''B ب}$?_P C|A{û ȗx]th sss̾gReքC:c) [IRjbs-^#/hoq"y<")^L})H2Mx]kGhsG=+_X)onȥK٫Yls)lyY-={1ga;N8w,v 'wGh'xO"wGl:{1Y ؟ף27Gn ! ?o[/%⽨^?&^ͽ|ԎT R zLr3cdxujy~󗯞%dd<ۯ>PAX)iJEܸ=?>5Š68W ݙ\d.ܼhtǜj4k„ӦMmFxe6O&zb⣄H=i׊#=E-.'11]T#/˿3]k2l i4ΛM!?˽3)5=4:'',RB#%" 5zh>eE+AYI'A:i4y%~LcԞa1 &Sa:7_Hr%PLzjxG,T}\oe=}!OhOa,` P0De A Q0d/. a(yxibF UeWDЦ }6@0lbg6%ieSnߡ*dޘEv썊mx ]:#<+v_:td8 q4#xh+M`ucTyVz Y.v]hdž/n\;õY]`w_s)( | <{:G730͹5"ѐ4\UbM,3@aE@tqJ8QU n>(N[n`'53fqWk &ne֘Įܕ'\^LN ~TIS^Z^#{ p)Qð:)s,kIg_үJNGyٌ8b\VHxqY:vs7+' ),J .O8`^JNN~PN)Oz-N[`?Ӡ9Szɽ,ougyw_*|e[W ޹ o|41N_j |Rf%,"lgn>@ XӕtXܪT=yxrt+ 9[St0f,HK~Ob"P4dθ~bspWD8Y'sSA-W*vdIU_Pԅ+?@6,W eWQZUj:毢Lo(+חïL_W3g(sz?)'R"e˝`ϒwCy&ٖ,F"C(>7Ҩ? \AdX$_$'u m^E4f{QۏaHgؓ JR/n }~=ex ȎPO?ytGFզ^AgWO&[~Mie|XOuG?A__\'M=XOZ)Mqpҗ=}+-0 '|+7Shdw_. xI ; _< I熆U9rJ-!*َi_J۟%RoaE AVHҜDc0hR?M,~?u/p,Kn{G'c8( |߇Ť@^4z;m>^\v$HRETW/\el*PTxOsXM\~I%G5@xrz=8!'XKw4:R%d?x^#hc>C 9` Y$%rL] w:b/6uﲽ{uO_ffrK˺Od3cނK RJHسcϫ|{>r餤J푬@h{ЌK(N03o>/^Y a=zT#k=j%1X!9h=*zJ3T2hPX3V Dn;ؘ64yjAQkI ?iwU=4%MFbf_OGP\o~},4hN\B~` ME=':ork`6W堦t}?F][8Y7ݩWPe̬΢<4-M~|Vx85mw:UKqI}U3̔ eOg:Ã$fH{:8$}'jn)Vy;wU_Ki$}vb |krB 1:~$g 7b[6 eR#X` ?P&L?mTAt? 5ՎwG M91 שTQznʾVA%0lvlPMn#sC˲M >tu]!prZrvme[t+* $@nA0] !ԣmĠ<4" M"ZGR9.N#GN"hh xjLNExpƣ{Y@w@hi -L^Dˢ~aզӊC?4<.׺Qv#5F'  \iC5ﺕD>AX3!p>8'fwMInS7m` \DTV$s{3sͰqT MYuV;YR6!C} +D'!C榀H8BDdH4|<趇Ǟ8)\HbUL3&XPj}VPto"wo_'em?kd^\7,qZ$48 +K9r 7NB!EJ̸d E^h8~`/ CЕ3÷GI.{ HXУ9.uZ>磂oZݐ:#0i/`ouq? \ӗ<۹ 9shۗzoˈ zp/$vkMͨ~Ƕ$*ע}HrzqPP*h|2'nqq^GB[(@ eboP(B1+<[l8Ca,j K EUceΏzJ4ZSO"Sr+qgMaV(fAVҘb\5>|*(DtݿΛ8~>,Ntq\,Q=!@ ώg堾13e}P_2aMwEI(IYNJU~Ҷz>C.'11]J҂ٵc#2M^bx Pk_ (f9[L#i2vmy~Rz4YKiM7U{/ߑw4;G;yr=>V,zYVMy l)A IDATN9 H{k= 끶<8aWEP ث,m8CA3?Hjwh ڢ#6C|P\H#%a 6WuWn۸%ع%(N)V!X$Lgx9C{yC]&\MT+"?dFm9.pfnU*;Hg=R^{o*VM-K~\!CBѿsRӘQ!= ?slZBbjHuPyCZ-%q5zU>w˙ %-f裩, NBα-@V -V/@3&K'qʴZ ɵ X_ t`iمLOamfx1qPb@xª@!ͤ=̟}LwJ엲 /JpP 8^a,)͸X֬jXD3;9C1+ܸa&e&R;Ŵ|ȵmԞ3uH{E\J5A]1kȧI%fcI_B,82G~@rzLL^,BNKeXP̐rpwG4usʰtۀ/8FY?CYLx,ZNŃ2'n$DLz N~|cUo!U.}Wn")YmJEB$^}@@3͌.ޭ$B; yY ;6gncj_="8X8xvx'fvnV޹bYڀO2BB"FIwjOe`vRs%cO! W!Օ33sUa #VtrU>a5uE/ \fT{|gq<q%iZV\ dg^[ 234)cnnȰYU RCLAP:! :rd~ذ)wy͙1.46.5̋M) ˎe*܃&XߘP鰑SN$+~ ʷpҳnSvܺ.E^Г29 HW'΅+RsR'IW%*8?T I.|  u-ꑲ)W҅RnN:.4e3ƌK Z.<5T4Ͱ<#s^!wxxٱ7Y z,B"ȩ@ē ?!{z|6gސ;?.-K#4tOq#X呻wBOoC1#WqK\@)"8q˝ gҖ(vaUȠ99f:;2bZ8ÍHHv|6KCx#Қ̮36 >C]ۓ 4k'ۺ>) =ɇ+w{bt{K'B;7o>~1Nʺ[AۃW~߿|?>zq 6_PC "tm5IWoٹwvr:R-6?_c'$6;?SXT/CK$>{ Lm͈e7$] T3{boƨ㗯_=`w~MH-q1Dhu4g5s Nʛ6N.?Yt"HvcG^l ,f5 q_kY e7m[&6 BHQaJPP k/m:,FP@R#C[mDP "Ն%gwYi.HiŬm\.$׃IM%Z @O[0D"aV%3\,|c`u"Tߊ rssu'_%Ű(s6l`Mt6`Օ@Oof4H$*2#j ^x h] *AWffՂjFq/UCX-z|#W vӫzc> )8*Mz`,6+U뉀W D&pkUe`>yۙUAMfd0(#%6"~"y2927 =-I>'IQvb rG)j^&XR(h0УG\M"t D'hLMڂ!tlRe0yCFa>di ʀ$Gsc KLdm&Bus&Aԍ˪e䉐8p9@U.5Q1 %LV-jiӥ;JZ(ډXA:d>RktFt (^ӕaS8KLnS,1:0fFgit]QVzfi%&,^ā_4"r`E^7Ffq֘%HJ/ܞHףE'D{uH??iP}[@LZ𲋣KjmKWݧ Ӧd>0%T5ԱE'+I&vfqyaQ&'v,U, Z̛!q:y,޻j(*,Iܪ7"|l؛jj :Mրnx5EIxj ,T(wğI6:ͦ-\S}BI {_ʇ͍ZFuY7ȭZ-^:|Z5. bQDrgl6oY(p@@=s/#2R%!Zg6 j22\ґ٫غ:q)H/S% XiKu( [D|?~x2+ѳ )"xD[)0T؀?D@B#y>ݡI\Y.Kh0b/Z-2oiMk1qpc:S UJ\ O7C~8l3rp&S Ȁ VC#?,&{5k=` xHm ܼKq1c4&st<00\н#$ R!T˗h#U(pğM[7ksUZ@W4n86s!L+mlڽZx8@- =xGo4WSM%`|1?<\d"-ޥ=I'ٮHy" rZA#5!LrjlCرK_ų7O( sǒK^<9Ig4bVfSQdngI.%7tLXETT dΏRkYTܽO[3[jDoěeq1U KV н|R{ )ԁG:VTl^˝N4јGޮjU:~k}tfT^|L[K)GQ|r!ˇ~zg?LYwWWQBvboɵ&[aLlC_wXN9PB҉n!}fe #.T\6+4tYp&jfs pNx̱}Fg|;u*K+Xaf,gkۂ{֧>O+W;rA _TBg-y 72;N=$=r;%n/ ] Ϭ'CSe[wHou:TTfmJm,{kK[^a ed80BAKWk;y{{-Z8DG *%=ǮпH@ΚWIn[z{0̕JDM{%1P'Tr,|YG 떫FUӛi\L^nLV(GDeC_gx`[ex[2)BNx/_̮3$ *e"QPUh gϻ=XX] E! ?5xKKLKeGu^A-1,n/jPwuCeb^$Mk2bQIܾ\62G, a;Ψev:w=jXՋ9l]]oI均t}I/FfaNIIy\.7Nמ/?H kSx;T^WNŭk@lJ2J8a7nCe %R\sN]'v Wp z鯞*u4f-`x1X/FOTYUژ)soGJ˗ +-3;'O97m,y&<[Q/0e,:rgF8\> =ʼk~ld7w x-~F 1P%t7ېok;mЉ;i7ͯr*BlR{j%(YL*$OR<VlA%ޫX'˩ )Mթ51֤ w O6gTtQiAzY0' Of@tS G0`+BƨÕ;6{f/E k{,tdf;H_.}va3ڗ$9Xb' XU@}q6.?Ҙ˝0oZU'WxiaXPcIʭ%lZ] 7*mC \Qu4K"Cd/ջKD-fNQ U;έMH2h̻CåX9ۿ^lȭȪ͞B+wg㒑#7tr*nM@M)0\)Jl(6\(C>JKQ?ʛwd4;тz 77|Z_Iɍ^y>pbJ. fr|D YD@jۼ|*j`,-.*"H/Є{1KPJl_5o;dV/86xU@-8Tm)Q%E闌z#pR(?i!ͼN: j,ѻ4BeX5T&H/sz O^]@݋t2s%M{Q7ZHTVZ)dؾt{n>9 SW!d97 tJrv"Eta!ܮui+pճ#y :GGu/nVUncþZ!h((p.8/:ʨJ02wLMev/+ʚeX%9tnlD;Y%dW CeNnο-cg-ӯ0k2eɵʿ!liܕf{YAcҤ.#d)]bHجv(GF+ ]hݤsHvp- "R0y[DhhH^ B|bNJHy=-Q@ A]}v<UuSSKMW4C8cmYNxfcH6>miL*jˁ{W$vP/y :CVNz-w/VfftްT Z-e; Ɂ5 N^ZvmY.*9+2+ѓAo١Je+ (na2 rIH%#wJ 1/-ZE(Gt\KFwrlV;puywB=گٛEBrwWi`y'ײG,tjMx5@B1jež|⮊s5x>5b#ik/ČS]-O_AW>neAykB΁EijIw1;X dgjFq/!+Gjq!]H4o?J֫lISL0 ͑b ]b@XoĺaG*q8gjΰp&L0b4Eݨȩ@]-*P6A ȘW?aTv0Ci5$~:Y72Y׳?Sp!nղ i Z\)DIEٜT*e`HZY~4YjZAz񰸾ٹTu,p:=t~F.>UQ"۩{o )l#<iV|C#]z+1.⚷ccɠnϸ/Un rR7 wLB9"G[3ӤR,Vn|r=5ү03VP/10N.IT) ⶧J70v}rEъ8 R4I0xG b:2+(孉eS{9aClz]I)=g=ZIuD߭с}hz>z`Fi53v}-;]nؗZѽ}LW: !uL ˺POO+K}zq%',I}3L OT=o < Jc6y3}&&c_wF#67$RqxReq;(!b8i+ */cT4ya!2ڗ)^Fj%1C˚8L@V|dH^ՆLIW1Y⢯׫e.O|tEaXQ P Oj'Ƀɧ<'>OJ' 7ɱe0>TM+'PzlsT1N fRQQcsϡ^0Z쯭c%O+hUfwQe+B9E~d l`W` *́H/W 61;49?[S4 Y3me+ &- m2=d2^P9"/z<{|ڒ,嗀fbɂE (ou Ȗ  @,՘k-SMj$@WUDX^#qD+E+^5c1>>&=~Tم)E5I_DEirC|Y}3v/xܦt iN&g5]p%>!p@%! A~,K5<aPQo 0j4V^?c /ȩN[iufhgs~ҢEgyhTA^ pk\O ʟfPJHx4,CAWj'X)@JX9g=-P@<X M/gp`>s~Պ]=}yFcQO3twlR!xH9|+BhOl0u YXK~WZGs]^1E(nLH6yii3 yƮ#omtCIe1[nKнxn|q㖆.nd z bFE`k4ciYD+'H9mYUI %J)뀆"ҫL#߄No|$RL;t.+9 u9>Flqb$<@5{7i<kiX ~q r*z!ܹsCղ’=FQkrSowXm ?ؠ!NY})°8ZE #{  >|oժ}-G&ggɓR_E?w<7mQ> S^xZΊ9?@66sf)'GnUzVfdgDf\o??ܻ,CGGWVfE.j/y?#hȏ+l&V֝sdKգA'Af# | \ X̞=G__/::|Q0m";8 Pѣ@ BB"@5@.@ %iW=FvH $``)))< !ddha^z7O͛U( GmwU55:yݧZ]o. <T{1|ҏ`ϨjS-9? <0X]HZH)6R{JF.(l-@IHEc` /ݺu;:: )_$VQ.ptP;he !Q9JR+7hcO$cWw)gOH2D1IIz l`d@0 lb\4ZJ$1]@Ü$ڵ/KrPm-K],؀~bL w+LO]:G[&-g`ؽwK mJqs$z{T9B`N؜9sͣ"ᎄ5poù 0z CGczכKg~$|z:<%yP 0IL @À$0!$j 2 9RpA T1w^_\n#ˍ ?dYxL;63jU] b_t{KC L2(2\ul1\uU #e hr ߸| Nx "$5 wpqA Ed>l̆TQBbh<$=pW;pRu+02 |(ˡ]}7}_TggJ/~&BŋK=?WRW}7fˀH*FA ϣhj [= ]L 9l0k_}yf?B˂B5"bKQRyKq2+H**N+5)g>b*}ȸZ50u' =̓ZZS:zOIc7M>{hfcIr6;k`aaʼnri8(W;󘗁~?~"84F &4> />qTbd(Ѯc<..|=>+J_ISSWQ1^tcԭwbfޗΕyp0ODX#l!O1g {) SRXn)SwIH=3FƟ[R_85K4/ԷƶzyGWM^>ꁔA!ahdlUkbcOƫ'g~Ș̜X9? _gqs__-(~(Ի|qtM|i 11Aa2" ɉ|">QwT}ܳ* [6fC,W''_ 5Vb8zƒc)i.鎃gpr2E˫T(P$(q(T:,wJ5<hs Zz]:XS , 1Ff&,&Wl4/[Y Yg'(lٶ%8su<dW)yE|d~y_{z| Da}*&LBÁynbd/ەkW>:P>hb:6O+t|ԍ-Lfb^4X7g^Xo' QBDMCCyND,'#{ĥ#q $JHɽV(}f@vz=l܉gʋJs+k͟=e}T|5ݪCkw|v8a5qo?BϤ~M7?z/XX Y_w0oIn ;P+0DD oHud(9CYQ]p a*A &jn`~ElZd:vLz=1 3L6~6l~`Zqt2Vc'Ј-W +#@PJE|tĶ$Fj4O&V6SЄ_,R;O8\}ESBvNA+c!gX-r-|3/w8&D|uSr?%B F 4>%tz,Ǟ0 [|HԞKu6-7'3\nOfme߻ϖ{Cr#bB2+*UeˮW|Xz[KN>|`0qTUϛ1w:G&ݦN[}ʙ"8k4=ւ‡X][z/_++U"ɫk^k777\6766ǶTm-llP/Q a4v_ܓ Vbb <H6o-8Bv[G7ƺ a/MIưƇ``cF,~~;=.Er Y" `?2^붐B̭` Ph7"O;6gbp7Y?@ xw &}<^ ڑ#e?ZRc^莎/uϑ`[ہ++}mYxG^ofnt; ûѠx/M8y %Eɣ4ZRXHP(&I-Zv~ĭ`|ݑWFF,mF4l&nlI+(Pς֔֟ԭ[7##Cm """&Y[["}n2|_."S(OrIY xk#aK,K-B!n`3_R&JĄ$17DFp=4}PD< 2H${s^W݄4I@....&&/TnY@opW|~p\ ' ﻟ4QSHS*pf@!YkvXh533 beHt&_-=Tdr 3_dQ% ѫ?4JUWf(a2gρFP,@7p\e&df!}#s}=B H$ mT=^y max;N< /}\I<sĬNy%M%u͂B𺺺:::ˠ+XAkF{h&\s+*۟[<ZYEṯNƪϖiXL"?gTG RzJcu-Y -hh7g-?MO"p8''D3׋8b ڙq?R͉Lez@IȤ(pzxvá.uRM̗ũ֝ۗ?L ($l XxPm>߇^?LE.e/6Pnkj>x_Tl Uo.S%ؽDf~4NCsε,n*O1yȠ^5@_WO,xtU#!&_nW[ymfX I0#g~v^d',?y6=V=~2%[۶Ӭ !>Ӧwݶ nyWφ=h#8Ǫ?Ŗ"(*O?$/y/?⨨:u\FWOT<(AlZ;eD])))&&&4D xȣ3 lBCLjg%zڜ̫x6!/PW s IZx|e߀i3a,xoߴs}w61D9[\|Nuo&\G䟻KWsg{R_3yu'`##֗_Eln ,# (}Nb`10 $h4t}a@5D$fDH[|j_MyچzZXWC(M+FЄի8իQ@T]fýPb3"3}> [pV0M(d ]~_:=(X/C-}FnjdQBdCvZr.NǤ p*X%-<ߗܴB\$']Qj9v[7E- ![o'3/O3Xs2!t sxFrqCE} ?"LZsHDP/\Sh1r'C70v/~M*k[` LdB:WA;5⩖SDJN!W[ ʑl m}xHUK)2{48, {`׿^ժ@,aTbRU=]j ydQJ* J Ze펔ybyAV FWaRF-kh!Ą2z_I(c:pP_"XrPDE,ɄehupT$ c[ -$ Q0 ڗ-z:gHKPM7M yxߞV>RzZܤ>טL`՟ /k7+o`-4z[n.➽onr+|C[C{ɵ F4N8es!I) Q$2gBT1 S&s>H }u 0wͼ}+VM79;1l!0ju X43'|@kP-Y%AD JNz`LV >ӵ\+)GoߟΥ@5Rh4,> CԎEccthPoeY砠+@^ + [_XA%s+lp* % xh3.^j镫be"VCB Y'09e v-` X K^4ڿhpl\ؾwq r *}C7"e*RuQ]X_nV(2$P9Ee@r(;+ryE6:/@eBtͣw(˗,88O 灀 pzD$+\mm?-{ҒRL ͌tٵVBe0`43~V+K_yRM9gIf]z,QQX*d7,UTߓKZrfhrDW5=|4H6evT4yvGK}`zݝoeP{NuL ~hSv烯M#^:yҀsӄCl(G||8$:>Y,M$G|K0W%|IMIsNm$#y~b)fBڿRRmk{] ƛ+7^ 'Mַl`WŹ͎4f̚t۫ވ#kHQ3ɑ$T1WB/|18 QOFRA'\5}w Jӄ={c\ z@ӼWPA݃އwǽw2^_\Ц^jn㘑kjWȩ]جή44* k׮j`d"A0<>YkepLdd4b.::u>7ؼ @z r!Q'DZgHd'89_v"Z$ZBjՃS!0_3bmqU7s"937sa!QVpҢqz > U994D>\9hAs)*ө +Z AD 6IxYõ vэɉiм&S}[렄#}"UH\}d]D1s:M\Sܥ+_VjZZZʧD @CO+X~忑>F}NNJLM5 ;]Nd矞}45xx*+n˥` }9%Y+32gCS9ɡJgE^E=èт(Rwv }2h$rBBq\LA>x"r&テ%>ϣ(w8l;z.sxKIx.,!=S-G ~y >P'Z˰)ә_54Sҳf攙`1VƔj#rytdw?}}zx/s1(L+%JcN_4ٯO^'} >B#nG cwN$J;k4LZ&m)B9;;;8Of'i֬=]33#*_R~S! >SV>Zuג+і-FNCDhmC- b0eUT$58c\+Jk&~[4xUASܶ恨WÒ VH~7hҕy\GWWuV\\E^(jzfDus\D(m)#nG 7ƻ YͷU HNIPí{l  [%Ph]큀[x~|Qa(O _KyCj̐YuK ##\hYtߟEk!nv9S_Ehu\nBxx+RO3<εi g[.mRͤ-m,V\K;hDC$Z :=A! 3/KR}JUkљk|s*hTkEVAݦ(7V:G}'2~ܸ"S.C[u}wxRȲLt MM!3ؚؿ6BI邯B[/xlGFRdA,sX}ghltͪ,ejt7*,tzid![}RLRR0swks'Ʀ~w8;$*b\8$}r%C:ɹ}d^wR j&:#bTJRh!(M}da sC,P@]-A~qQ Q+8 !*E5hp0NW2t9`3f&% gV 5B\-H:0lحK[gy ̪:ҲZ@ZS*]g y=rso7;[㱋b:%6!Q/?Yz ]j eXٱ[[ݖJ& 0'$@6Oca6kVuHG@}-i߲s #",VRmLjJJ ,o?Q\ްkn$ED\<_<øFm6{ p*y_x3^6WݷtWo!߷)fmh Zf.Lƕr}%He™ujoR*Ͼ$l($.L DCׯ̾{Rw,LJ= z@P5S`yP{3atrZ=3t#)! IDAT5<\NW'S/c^_¾tԚ;یXӮUA^nN :}Mچ<6(ܻO|ON)+5:j#eh5bn qZr nW`w#}ab5C+NJH3l[vk0)0lWdCszCo"5l2Ḧ RXݻwa)Xf ~/͎q9M hыRz4g}K܃M##шwfk::8znlͭj` `$8u+)"3ljպ xY+9۶mkp,6֣8^#SȋD2ק<9#0%BC}ȩ%';[BIn[J)taԌFէ58kG'1 W𡜬,Qbjϯ"j'- s{5Ѷrە0ERhVioB3ہ'ζDŽq ؂͎uD]f{H_Nw%rO<{\wp˘S^^w2Sc_©Nկ۴C#]q|Nsb K{][}˯Ȉ+JeH *J8篿[@i j@-EEE`i|@:[fYB<ŇNJ1ضL)AaY;1a`|(drkхdR/ zlފ@93Y:]7ݪYܽ~ǽ oiYۖ=Lܲkyss`Qg{8')tӣW_"K2jD-Xxe^.;ƁpLe_u 'k @|ͿpwJ8 2B>ICuRQ4& \jfJMЙ,%ǓC*ʱl8"fƽF~@Plp( yj N,1m|/N:/j;TvxDϏz};+Q[OSJ, KeE/q4i@PS*RʝF2,pIU8ܳbw [5L< Ōq@{aX?X3 {Yػw4ļLQb|85tLFN;8Q~Qܰ4,X\F6vǭA\~JI ~ۻG;Y~ [N bG;¯'^ :04"_SW+`}RN]Y_dPJy>gEf`6~=Bf+[J)w_ >cMtLseI)fԐZ {J26SnUu\PX@uP[&ʯ. 1/SyI:, #gq:m~5CqC,*Rpj6vh acʶk";z-gy^8MWnOO^6CTL|nOOi4ڿD`f ):=زڛx_J!RT-;/_8=t_8oms*(Q_,e SDn:W]ʼ |ޢ~FpX 4,,AM[ #Hh&nzW\ǎ2)klc1 cc[с+o?צ[-Qmۏ Fz6 y4}xv_,G+Cmݚ`OWfC-9A:M&896rԜBMJM `14JLG§BʆHMc)+Ol^,Թ_KpРñ9@b4@?qO %mAAuC$U );_TJJI*`ӠmPƠa3 l0<=-EWe y:٧rugQk"pI$D/!"yHh*P@cg)=Ydyu@}d8 =~ Rujk o-{DYPyl><9Qv:)'K+__% u]“xUT3Oxb Dj4K)ݏ(;>ڪ`,t?}5rb.7t) d3BQL=VAk;/=Z%?Z4|oaCLm+3U\ TT}B-hU@Vjdc'l5 `j8%Nrb&MӊZw)>lY%h)}Z,(X+Qc̈́fGłkUA 2K 3Ra)XYXvY gRSM,!nS0\Tc(FU͢ qI9   mR)DJT0 ٸ27kjX8iT(_Vo~,,,VWĻ։EEE ?XBl:@EDub``V"""P`ElQЈ"gPuoCUCE%˩# x_QZS&wj NS G2zH$V+†v1ʲ,~˖W[uxi'_[XЩ0OǞ!?\Y28dWf3iUi2aT{nCξƦl߿doEpz}_*8=).Q[V߿rM>P^S9@2>5Ov8p-oKA/L%F?]DqsOq!ui ֱ7/nYE@ᬻd<z_> ,˖0 r֐Ak.$M~c1?7w@ |dnW0_?}9ί~ጚϯҩ#__r!/4⹒B"GE)˰x(uZ4lD> ȳ'e 08J39O+kc+cLz"wFckiG@2ڵon 7o u.׸v{]XvYXwQE>299zO +U#QZ |B>#Ti 0=i2608~=ުUz_ZPV@|E+na^kkkP+6Qh$ fyC [Nf* /eX$UЌΑ R/dZ;w^r Oh?f>*F ̉\|w=U]^YHAuG Pؗ/ϻs(M,~;lfys)ɫJT͚5A5o@$i252@tJ"D3=*9"MϖPqPj>~dF/7_IG+)tfPա< ȱj^ǜ |>ԅ")[ټ4jO4Kq1S./olL= HRB^O2ɣ/cֿ̨gcr}ٕ-m`DNyizk2n֡hNXQv4F )+0Rf@P E> 'Eh0*T;y3(TdJSK`d@pM0":718)3|"I{/ŐCcb8 K9wݙT@kmkӬ?ߌ7jds 嘛TpM- x',ieֱ!rP/f@KKN_BThVLJ~ @?&j#R?;`G5A>Oڡ!/Q1995-a3$Zp^U+-i$'km/S|iԶ!?e+ Ju4ǃs~Z)SäQtDFalx%2lߢA@dIZOU.÷f+I}7nZwFYՊL !e!_"I"[8U k jMBW5)Pʣ+DdJ3) 7 ]+ʳYV<λ$Bl~s0jև`/ \bJ)7/ W4"qX)R4ets%nS=ɳ%rEk& fǟV"dfMi'ڍa+cV3M=҈0Č!6-hA^^1cd&Kʥ\eTɞ F#v G(QD$|T~AXׁeR=ZPVbAKBT8'ֹT{9_orOڵ.^WxʙvT5h$G/Fx-OSW;Cwj1#OA Y|3ơeiYF]O{0@޼M~/Gc$Jzn>f%o9xdY}}S˃9T{IIw%#3rt="E$.7Kve'6{L<% 3 E _*OqJl@yd W@/$zp+kd$i]d L ػvhQnqdÝ$nƊ g&}E >4I-t8o!;&KJqr@֮|Km /eEwMiߚ4peE|!@.e+;7`l*@A@>O=X0'r, \ ) 16y;Rӥ43~3"t] h}ΜUÚIӞn-qŻFjMhW V"QZ`຦MWܶmY㐽=F ꄄsI:AJ/9 ^qvÙ{Cd a=~VHϊWc]8>΄v_R$s7yֹxHp~U_+G56B9~][t76u'WeHȂ6|ɚ47?hxzuڑYœAEq!3ԓsJ=TS/E (]*~ XAŃfGY IDATPGzeff_|>?%%%111..cݻ̶~&)e|g4>Y_M7y2o? Wy^{ÔV$,8f?ǟܴPj6tX0`IJIu\d05N¨JR3V7"WԬ5z"ԔP Qf:(;c/~BN8y GpzndN/+ZԆʑQWw5d,%cIhLd6 %+Wl5CGi #.,R+\(hkM_Jj|Pin 2crHQ 4s$=ݴ.ZuڹV@:RgbnZ3UKg!0*`=,J~-e 8auC)FzL]6o L rUj_-Σ jylcd4 F=$:D ]?WDsc=,%Icu 2Yy7B:Y7 5u}M0ó{fOxiNck' WG>LPM5}ʟ$q(wmE7 k5٧wr26ӶͳCdV판K]ӤET$mX7/w) Ut2mr|*RLSuRg֍: ʴР\5"Pu\F^ˉgbZ6;v0oUǺ~jO?μ߈J2l~ý%cۏq%XO:F)^zWDūixLC|%rPRr0zp-?QM{UV:/vTլn+yI$\'4xV2wJW|D d}{<{KG4xɔ9[&p{އz B_bH;l߿? \4+U Q |2@cKZ\D-o桎sYT/s[# vO'q>{&H.xvlDr$pa}ljI bf=Rk lE Pڿt,;}|~~d߻FPKծ۠I1EbFw "6~?̙vdJy~^\gSK/ w9uOC͞u]{:m{/Ħr,f:SeǴ[gN+_zoV<Ϙš)0N-}yͅ$ZR+ #{i m/v_=ȁ]I]{JB"Ȣ8i:1FE7W[ݛzt R%v&s5MkeZge},fQ&v\k埅ؐvj̇dNlBb2_/0 ή8Ԋ$Ècǯ\Yj~gWpl*Q?Z9uр [5Ց6=pgVcT8t ]s#ʔ9]VXs5jZ[ (WN}"ɘuCJ2$~ܢ/ #dY*( #GfggTgbe"nk<(}6m3}q18.wK{M\9a7ṄOzΗk.| fU|Cz3g^~toOxs)*@kJ-yU"zӦ?~y p5tCsO_ 0 ;(:u"-vnFK^";>rk6e}DLRs$=>ii3~V|ҼC{L[Z<4 /cցֿ+&chߟ\ EQAƒ\:Aݳ{kQhZXL{N 3EwL|S"!z r$AR:zL7okeb[D[&7yyH[C4z~fT\ikPMb:аT[| ڼ |_r׹Ϟ_$!XlM*Ly0s_Y6CA$Q O ۘ5.ֆWu_[ֲevOū\~&ֱTj8lAG"WH>}ZИeGAJl\*2`X `0RfHR"]jw j-;jb2D8 U5r)FF*U<8y~`,o#2 A+eNj/wsOE#AGeGE`d,_R3 ~*a04JFY(_Fsstf4JA44%?1bu(ѲA@de?@8:v%)΄CY,K@ɞb<`q'M5%U*" JzշLTEEE#jJTJX_)o;[iJ@ihQZ8V)=O{&֕c4(:EvqXY*%/mY35ˊ/GgRJBmw/Fi:sa';qR뉙suZ]v7hK뉦p[}|Myv&PD9AJs,kr8_*42ZEE(Q/_|C^\᜚O—UՊ~E em/\8Mku}?}򔟟߅sN\Ԗ|Ͼga˞\4pm?=.v>}}A%@iQ|ڮ=>FˣU".1q={fddFT"Jtgfl @9\u׵%dό-YlR' JÅi=qf]XO_t\[ӿ4I i͸ip5lܢɬ+R H%8븞mݢ>mӃzSf\ ah6nܴevP , %7Τt:`Z౶MWܶmY㐽=oeY;G{z3EfLJqu[ sZؾ^B࿾.0ĺzڍf>,7wt5'D^Aqw >3BQ/{Ğ}ͺp" y.u/ ;ZOE?Єk缏"t?={Np0>Ώu,Ȱؠ ~;wDd+ʵa,pFq{%|':TrǵK0/8Y;?al~W4 Ȱ19ޥBp'5WCO5:'ũ5|Hk.ݴ [O|DAPҽ]#*ԙ?'οBjM{ } TJJu3~bv6ڟ]IPV8IHH[C[_ +@v.ǂ\lgI'.Ĩ3SfӞ7jzL>f~(ϰ'G-a߿ ¡)8;9]oVCƠ~LAv޽ca(KtߟNvБINR2orlMHnu >Qmm<}YoA\ <;ch|$<=f:v'R:b0Lr'wyMÙp4RFYU[9BDK_ߗ/_ɭUzi;|}vi4k _7VEu/z0#[7c>n#`wk)]-[>E+BX"%r9Gaե,kœ^to96_* _$PE,G[06xb"q7#&/>=l\GfTK1^%[6FrZnQF] 4ųKK5WUFW S"]I6}-,y6ZN0& ҐUc;N+/s 豋3J`$G5(GV8eCtN_݇ P=C!O}gLt[4eKV 4*bY#kK?0Fn9V6aYݝ޿m%׉ŨqzMM%w]bH*מjl-C["r՘YbǯZ0!MFW׎ōFd£=/CKA]n!֠ %_;ýKGb֪ն[jAt3m MwAx[!}0'S땇Lkf6A}釭栐EspܿSKhU$ 56LٲYz3Qzjɤ=]a[(˔9~+|wWnH0ϝ.nB;b <`=DJ6}=!)i+ L{FiYC"0vS%O*))n$#;WO $lJ5k p-Mj! 20^L}fк[xzL.i(Əoۚ/0-a;X>޴-6ܢZ=_˦M[v>cy`<߬휀X(n tв$U;\زyä%`7_ŹK/ G >Õݓiu'"fn>F@`d2xUY@RYJ£G 5o;r4 O}"1λ4A*9>yRJDH*f<;z,dv^Da|Td+n$/)]dDZ\Y, n s?k)=GWWqI3nЉcd%V;rO:}ۄ~&[y!Ryuc CB@Ƒ3}OMY #uf9-Z ;lأ#_^fn|^w[snL$/^ͥG[.Şc|mC Tliq]V 4WxȊXB{uI!& ZD㬎}_|iW;+;L { +zN\b?>ޑΫglγ L d5;ʫ,^ӫ{Js_}V`} wL/hmMrnwί{\ 9,GЙcGՉm3ү[sǹN][RPW |N(=l!-K{uԒCm^/Ğ:[@?f[yu~d-[be^žSZ"r `h?mJ;6D||tp5 ty/[O{l(_70Z q_GG5WG&&#$2CSYbې@ZW)@H/?X@H@_y 5EH KBH T~GWw~K`XLj8|QPKԚ%M8r]ǩz4-=&vu&J3I7)H %C_d,Ww&b^ rrRVon~|9<ɛs]WPM}g8m+ bG%iٵ'/>=m*^?=V_|R,Kgq50Gf;R96+@Յ &r|ʕp~!1᱉L@׭@}`;,W0c٘ИcZ}Nbjy w'AQۃKEADCXߍ8zKJn+AdaIjF|@ Y94Ƣl6fs2ZDy _LL:~=F-ql핞2r2.\\{zXl \Sr_?)w21UgP*sx9WÜg2kez->[&~-I@oS]3Rs5[H"pmvkm\~]}Qcl913vп _GЭ ];{s{^5a " $I~~~^^^NNNVV֛7o^zz޽H@ h {#W _+lz# #9w|z%wv-7Ua!w2印:9\o{.-}-K=2ҳWU2¡ gMV9;U"%QZa$nf Wmd܍|[ Etq_!`;P&$*'BRO 'Y+t 6];Ydml-qH{]7ԤJOj%+ dM7|x1#TZu=6_ Q(@7f9KWAX%Z/p8A p 8pAĐ-F&{_PP e0?Xy"#/*r+j_mͭ:uZpAb ZX@:}q^LM&AxD)r\[1J Ol*=dX|j%/IZ)R9}'o 0RY)gxImzuCͱnbuݤ&̾]`|x,~pJu޵Y 5IJ_# @"PE*Z )MTн_WK^i&hck.՝yDܩށF'"dAe!Ik Ԓ%8n?YeyGL񱳖HB䵚6RS*'5EG B-w1aW>#^ KBPR~5Hᅨ뇚J/;y*+8@E?O,>sm]GxR|47Wk߫{~cOZ}h)9n祙xo&kcNHz DI`X/!,gյԤ^dY8* !<Ҟ'P̤nGv|u"4F(AZ~B2il%8AIb@FGֿ]F!`[Hɣ7 Cɾ՝bU/>c_9~d\[J7wmӯNf7S =r*b^Mn2IjF^'kŭӮwӌx-F'/bC'eNfmzu7uOwE8㒃Aˣd+<[DOڽZr՞BF#k]Z77+0@ &`h_^B1m٦Xp'w`` B~%6ӓWwNQ7^;T9kR׬휀Q>?"gOn~㵟 lZAl;Oζާoy7\opԈ*`xc1aeFZ߶ `N]ePZ{klg=Z\? Sj :nt=pYm"$`X>@H(T׸X$@ѕ2l@H &_7AH T]hnbː@ s@UZ۷2$nOஈƭ[zO?[OA gtRbQH̱[@E^KLމ9wṄw135fVAాyͅak*T7a[2lEONQ\od@Ւ@Xgw^9עENZB G𠐐M8?\D񋫾}.B)]95`O8{ NppAjΥE%/)'ٳ-o'WG]˙@X'mMۙͲ~c^0[f1~ s5%]ww'+1%yKCUFh9ڶ3#̠ ==OKۡfEC~!s\+̤Ђ7EO?Ө;/e>orezCR =!t`u17t 3;^&KrpbbQ_ ys!02 ! cdI-mgNH(oĄ'c8a@Ֆ@<+@Y>5U$=OܭkyY7G_<.?ڿIaQD{QϼCy)~ ;eະnQF] 4ųKK/֔_{E_v}[ ;٧:ZqxmF_ Kswa7. }Ґ3N ;#nh/ 7{@5&P< 0ύ>ѿ"ZՈ_q{} qaH<{g&(s͂;v?H`E|49yM=5;9 _ߊ j'*q;u28ΗHrg$Ib"EԷ2|,3O˸=B6?|E$P Tȏ@&i^J|DZyߜ^sܠ>{!d Z2237lX_OϋTK)'rdX,>k O23Qr* qzP{&L\Y&+Ƨ3/O-ݕ$&OΟH"vV&H@O*_*$9eQRLƚ, rINfqY n77&[WzEFvm&.l&DՐ@X)`)rffd↓ܟ}'A^3쿯;p ȹշٱݘH^l7r߽fKt] fʩb_В@Մ@X0RuOwR IyhhTFIXm2M$3] IDAT夓q 3S:,Yw6yiް>BݼqM Nq40qμo;_\T $1K' 5Xr I0^WJt$DDl7xMtA*S ϒr5.&൶qQf&H+dbKW{h7Ū3<^~dCD&|*#ODW7c4ESUEg4lb].6Lѫ6̈́{ҟg7  <-3ڬ9H rWkx^;ztV8VOjФH $@Y?$~ ~'I%#+d Htp$@u Pֿ#:6"$@|e,P1$@!ֿ5 $PH! !$էH Bh Y` $P}Ty/M8k z>{4 O\CZLCIHtHWxu9Gzl<|Y}_m[8m+JND0N<*A~[`*F+n7,oԫWw砐A))}cJ9 J?ozetv)a{2rﲓ؂E2r"Q~5޽6kϐSuMnMC(*~p%n.\\PMε+ s\-zg]=kߩL< Ȑbfyc WwFZ{ۦv3-\Y'xh'=єП _Y)V4* ,q d&_|p`{oI{_g9&6] 8* DTήf=LzQ%nҶNv}{`;W~\сZrk6+r2gif`'M߂y۴2/dmCmxdi+ * XXԩo:GSNN:boeV栢H TaǬI;q-רLҍOtSypig)o5hV+K1 v *~,khѣ#L68yޭO{A'0moZw2*@ź7f[{5,'v>xݳ̛LȢ@ eheO,p% [߸gw೯uLg7^__0q2,t4)}*=/ګU YV8Ǚ6MzEz|rϬs4n\nPI[j#kv/g | OQBKN eDٯĤ"锡}TӌN"J%%D˺Dj)=ħvmK"d俒,]VvP'5׀ӓOȞ@z/i +&.uyf񽎯j*i;y5PH42 S$URN_a+G\<2  >?zzH ΩÇ,;yc%[T*ϊnߚr*q:-7mAtL4ػd{0Ϭ`%8Aj5%C{ V )V\\\Xl ?>L/_kT2_b ԞPUvF0 *F?gFYd 77UEmZ.amU*yh ,?`U^pGSZ uS˨_eT‘ z"$Z# T $h EH 9FA@H@/+0rhP=$^T2 dfziZQ2[EbTWgj30*ɍ,5ڵkrYɢ j8V^82d*A-G W6=SQLƞ Э5Nb/Iuumބm 1;" &Po}?F_Sg񽄇ͼ7+_1$/frkԐmz.F5-<6)[Nj@95`nyw##;68m}]:;=ӶvݺusqVZDe#J@?/9 rh]{0-j0BRxmڦx:v Ꮅ]w8*?x`n9HsmiγBB"&ii&Zr H999ׯ_>}Z.]EEG~䤿I;02 w(ǃDx$B1,Ɵ~ &2|gCOAc/BadB.YIdA`=d97Oz(DAͿ6){OhnU\`lzuvw.<>?dg܊ C# Dcbm0L(d&lPп/!wFjTsJJtkJ/;>׭wӆ jJJ,'r8￲.^ܝGo8}& ҐۛAxH5Va {ohz!]<~![;{Kwg:<jҞ- z}Y_z|R04w:p( G96 !ph=aZ>Z:mQy=&r;v.A1U$qkOѾ-ɀkM@pN։U!c!`Xvʳw$#dW9Vxq15Sr؂JP߂_Vljz5 Y\(B23 e'`5i*y:E/ƞ;w ʁ֫/:1 |v35J~R,SIJCb+C+E\՜%!\.ɩѬUL\+-zI9kL8>Q[m6 VF`Z2i,wR6'4h V! `kUMz;8ox|VT H {Bݔ9G% wj(x0k6XESc`”meh^˰u0E#fMVB*+aN\#?HK w͏լAӯXd `P/Ju\/^q8-Bƙe!=Hgsŧ'lcaΒ # /[wޠ"(q2!%%!vĄ c߶_0B%aN  tMec]OU3?*ĂK7_=zKPBzɂK,OR*p[ .[%I~~~^^<zͫWRSSݻ އ{ԙ!\R!j#(<)6Wn_@8rRSUt* &eB<"0K'_ׂ=9h;V?y|`` /;?p pa >p"]K_#J"})7(Pd] aN-aVG 6 gx<+gfy ,E?YtYc-gVQ&6C2HeWö9F|*@D&*#OU W9t Vu6fHpj7*|( Hiĺz ;@TP.͛s111a0D` jN yrN3*<*unT`ܭwUWE8f ҵFuR"%XCgՠFR ;$"$OC"FH "߸AH ZpZ@Eqj0 ጵ $){n&n+eod<;›VjڂgGci͵J4_Lļ K[{ǧK;{7>-}߆߳xUCبL췩MjH /0ۑ>᳄֩yc[h}ϟn]B&זIBҧ!k5Sд0c%P]C?/Ŧ|%Kѳci;t kP;~lSmN%邑G˶J,eM7G_h*8Uqw:ەi2gGƚG~BNq'Fp;`6c=!5:ǁloo<n!`+CO$d ]r~q\Y`*յ(S*+гcJƛ{C`OWzzm.X4gcaԷh)_פ(r"Vw뽨g!|֑SKyD#[`ܾaq5Ao3rw@ԩU}NܬCi‚:EPtu$\xD+?;8wi ϫfh0gG-c@Aق ۰7)`~j{]0ZL`αe+ŏޔy T[GUH;\,͍pgGc'P P!pIuM}nk<%T.'qOޝզK[GښJ5dXa\$*W;쨽gGƪ?؄X=tv1󖨔.9_N'1Bgխ#Y4#$<,JJ;H_|asN1# $KYг cx7^]lp̈́SNvy 0:F>I;׎?=.N[?è!AίPX') $b*+%zv*ώ*proЀ +3&FQa{uT,KI#8z|>5O:~!=HZT3гgǏgj ѳacmO<;QwHyUQ[GM8[hw >0=J=`6@"`q5 AH  /f"$(UcYH  /f"$(UcYH  /f"$(UcYH  /f"$(n޳g@k7-+fV!I/ Pa!axZ (Sa ~ 4S{BU_ر5jİ%Jl?sjT% zm E|}sSUV0 bQ?}.P VUa؞jOG~ (-?Uz\`Q1ŹUF, @X(@H 7B@z!_/XP$@o!$B^bH #';CH @׋%*͸5p4Y6vso\ T.=0Љ>Z؏r <]bi߳N_ξ%}8#$@)BZDۑ>᳄֩yc[t*z}aǵ%:0 Gn\\UViQ Ta'5a \]n<8z9=u:_X\Dž^e )ZJ([ՕT649s矆CFF֟n~4/ε7֬ewǥAQl;X`#8"Q)G%bm3r3vbqPSԖTG,؝}ӕgiFrʁ)~ A9+DL4~pǍ?Snnk"=0 SzGtrژJݚ|ˎwuݴadEQޏ}6M} ϑJEBޝx]y` l8u!zum ϒ##~ 'd呂>.ۇX!%O #dCc:'ZU$-~{C=%ӺtRtG}@9%n;;.͠7=waS+2GH\힨'-qx)SƽPZ>(Q`:/6е% [ДH] z)Ի{|(0:ϭA@ K]Չ_?\f]^ 2`nϔ*cEBF~ԪO>'?/r5 Y\[|Gs`G )FeuL?lj'd[Lmrق`!H%bDyL*μ!g=lL] SUAH TpL8݆I=k5aQ]Y咜Z5":T#02cg-ЮHj5^]xwf}w ]cP'|2zӠA*%(Wڬ]V02}m{ٽ61[~3M*NScY8Km hIԱ}S;PYcfxxql =ӽ3 +aDڷo>֕HgT #CУ96sH3os8!߶_0#*qtWARba^a(NLP`~SRn[HWuWwea^)xmR|%K|Wd7`MV x| IDATzjt U_8mG-՞0r{"c̺S31ӏ͋J1qJEx0D_Sk\AR@,L=;q>K,rt:qwQb,WvW(C н{7ګRt*Ws\%x,R)G 6 GI)%S)ŤLQi+l43SD8333U(Ҳ$O{sTKϴ"}W5T%J)9SU~K޸22 n޼9W-p8ff!8 KŨ{$`?аf9'ƌôPE,K5~^J1N) αԦb^va-CH T0CWpsz$  $P mFH } $P mFH Tb럗~eCO DH 0/&te+ҪHB92<~ŷO}Q0FxZ+a}jOCpgEW4d-'B(bL%D<;D.UO-L 6[<;,̮#1vOBZ H1+dƈ; x[7*E=;V|C[Z|hM&vAԳ[`phbL1;*=)LWJ3n,i|do2r fCƏ!ad XHݣH"x "loo<.|߷_ti:1L,Ɲ䭇V8Pq{=?k$ mqb gNJ叵 E^7Bd34o襘}Ck;і4/bڼLSYgbN,E46e;-^05?ڿIaQ11.^ r|8tb 읝gh^ܿ.>RP˝ї/;vOw-mWf޼yIĝ/1~خ׳cb"CխUb#w7@-*iӁ' }Zoܳ;uLg7^ n5JQzގaܸq͂$ %ܹ2IHHy,#WMBQ.%xV#fx8{(qN0*~q9fT[sBz]_k=zb3"uY6XD9f@\@͋( gGT@*ڟOQQ*~pJ('zצY>_ Iit"](ӯ3HSO,1~w&V؂C8;VXR6^`Uq!ͅbѣFφ]ځB.xPϫfA/k]L-j/uF1 @@⭿<-aEy]m?a3g`B]Qǣ)?9ڣO|jIV=]#6s._$`,S쾍jWӜJx_TaAr wV{|YO 7WLܼND X}P]"~SZ3.u3+,`G y=TgQoun;|vVW(i_B+ kTpWaAq̺Ƅ}Pw1S͋cHD-~Fh-vn.K:BLkW]%C@ώ&C_Q:+<+ 9e=5`TyWjTajB\q%;&GǸiEdﭔvW#VCBbNE&$DE䯟RON&0ꗓ gw}qFI,f\gu$I/0im'h(G3%N{2NZڝ'~hn# +2fjWQ+w0'۱{f`cr3!fc~NSk)ۡ>1v lZAl4ՈTOy@%([_ ,Ix>L'/_kT2V@8i_&} AE5b T%e9sV% zm E|}sSUV0 bQ?}.P VUa؞jOG~ (-?Uz\`10S6 GH@.0VhgP/$> '], $`kϠ^H }@OX6@HX 7֞A@$_tl$@_gǂN&,ai][DUl=1%rй58@@XGFfbMTԊ Zv>U-h3yMu9qQH8.zk?N?]K [*l5iRoA)saM%` (LFAL 򉩩/;^M|b/6pL*OTM}H? 줢Y?ozetv?gaǴ˫,-m;$kֈYT.kRՕ?D a?^,$P |h.ʹHj0ر'AL}Sg7ܑ/ OIAk&O\q)e6V҇ǖ-Ά G `֩-R)pJA /y.w! Qpbɍ^TpN+E[xfBww7vJAF~ Ȧؔ5LvUa qH!w RW<i:1A$gf;OgNY?c/ʡK&2_~y͔1̜ko­YKS&IGb2N `,j:L:d_r ^)Ʉۆ >PBw BbTȅ3֟ʪTG.Pqˆte};|&Ļ3ERna֪e{+S4ƒQ9.t ftQ'Rڋ#rZ},Fӷ?-"t'mݑt2Z_lodJ/%q񭕅ZB/ȣ lȁrx@X)ɧ! >kEHflXV>c_o.v-XMU2X-B&ͼpCcCД*[J0:(~r!B淪Mm@UU%(a{ɓmvL5j8nd fX^0]*(!) C>?aSaމr2 B'4-ܨocF2 _&5Yw4|]=GO:YSZR+>eV.ń{[d€@ RoQ~߳#l9)ӘAЂr1ƕ.35_5aQ]Y咜ZiUN.%V=l}0!hu|YK$ԠVݏ[PTR Xp~ʖ<;lָINm}d?ؐ 1PVN޼Xp饽xl|/WBBBZg(t^yږ[jA O=m;EЬ6g*$V.Xg \ȑx R~㬎$iW?M>7-0yf5o!mj>}T͖k3dIߐ.#=\MNٝ|'ODm¤g=Pl.k123(aZZJB}1Y~dy&=} :l#U:gSC 4_3USOFX8!v|ՈJrRqhtrԾiyS $<{+!gwHy$zeY,ۼɀ ]L9q?FJ:x)(F4QAk&{Cc F&5ذ@cߊ Dߊ{v۩G [t[|JԣzT+&cw""%y}cd "jI+A PAGYէ~٠WhnYY\uXͤ!%tA>ן0ߤ3כTZpsƼOAq֭{Ä%_}f[X)B>˗_.}oacmܱ'>n=C>w"<up -,{<\Fvh;r7}wti<1 j}^7{,S?wvt)bZQ{nZk񸟗;̳GGo0*VK:գR@`2[q}ZOj-uBE Jf>ݝ* >rX_U;V;DtCdX\ >!x<:5W\ vKثxCwwmӦWIH8%iSЄۺu؞;&=3K>;x-PlkżK*''Zf1"E"3F("*6Օ)B4Q4pL# b4j/PkȉtB4Jy%_0?>a}5.1@Ŝyb5-30SlY1-m3@|8)Ae0m_T^9^(zgN^M..Z$|5/U>_^C?othr-k\VU?sr%2ͧ~z@>f#sڔŋS |TV X[s7#[ǒ GȘo5( $, KJ yu&j_\닚O{ʤrboQU&DZL1蘩4$"e XG,omC<AvҖ.ZoIiD4)iMbv)+K %[ah_> &ij%)RF2[1ퟘhD0 0g9ȧiw:~w;Pb1b% |HC+$g.]lٞ$wq4zpe^]iN`V(^kŋL,g/Mƴ*vڕDՇ6VTnd?V3Tk\]%.Ϛ̽nRd(J +ׇ ƈNG){@?=U?8 @ @۶vY"M.s4˞nŁ&0N3hD]}e3c|sc.nW6b3s]͢gN>!Ya딕9H}֟hUdd2ȘO0u#7.qH-0b-ewȩ&`FsJ?uL;B] g~Ga~L l)Zwn|i.M)RO<ѴPƧcc3<՞U 6S'?Ҳ+I1iKPh9iGb-[)|zmO1l'6f)7Nn |:(gs?|5/ZcMV9W23A8$c-`%zwGJc*~^)[EyQW2?W$JҺiBxt3N6ܛNh*_̍fb`@bm0g驝'بq~}´h 3d_.۶-{/B`@>&~!~WPH3O;~MSI=ٻ.чLƈZer퉺0jRkNEXAZ $ mi hh IDATva|F|;UJ*X%Vb_כ"g|1ofV#٢U JRˣ[/+bNVpWo'%*VTlX?&EWBG|p&~CTiJrhg[W! *2\Б# _1Bʃ՗'|q_\#?8s 7B 4`sV(j*eU~C4iJ͙wFMK( \ӆȞZ;P{wHRD% 琏ٵSI(BѨ*{ TRf۳C>۷Ÿ FR:]NY 8l3Z_PXOW-R:T _܈W˖ Ԃx78,.4M5c E+k;5=}b:=ӄؔ,?aSA((LyMu\r{+<cWC CS/v~ 8(HL 3E\OPA^{1VRY#b\FlӴܑI~L_Gյ b0Z,E$ij*U[DIcl[R>;baX巩i6ͥLqZ{^RɊJoJzY_s_T9ӌjz,ZN[H ~L0Ո8H$a%wU$,IʫDGLzYXѤSdAE-'ڷ*uyVPzI.?L3՟ 󓼘,X'v1oS-y);hM /.u_Meڕl'&.,{Տ"$E&΄645ՈkI2Ŕ^94iJ1G }C-!/1c_sˀ,-d/B0>8 q~":eZj ^!> #q`B!#2cb-s#+R^džΏ]vl_R\,4NZ) '.wHk~zI3_,f|eyeDzSZ@Zs"jy gYs0lҢ5}(=wqA#` zˁGTƒ%_SfydL[sMdd dRFxLtS >c*$aDicr\ܻd\ꊟjY^Jr02զ\zJ]{ObԋxJ K*z~M:LP\ߡSO['1;@R2mYh@EIU6?Bk֬Ypo4,05;) ¬EֹfY;rvK+V|F%Mv#/K %`io+ܼٳg!˶jwt_UViFy#&V ІLdY9x#Gqõ̩,,XxK5[${b7K/8",ũum:p]J~:L)l&QF>S(.\{?g9 F!f D p410w~I~1m&3ݔ[_nFA UsK&zY."`_onyG] Z#x &<4Lb<Ĝns)%5q^¤ɱ溱l1殚Fyl37/Νy'}5rΞ==^tv՝ Mqmے݂=}v*A]?rz*A7sPO`UcWm?0~! yju~*xfIȑ9Sx QF{Jŋ'M(e}Ul1w4[Ba~0!J<sٴ%M5ňm^Ih֩/*ѣTO`Y!EG9g# W|lsda|$d͛;z1*$zmg8}o-8C࡞vg|_}c?.a}IgnKRB1!,_VJ1}`6/9+VsnekZ[˯PBy*SΖUc,sCB'y\󛖵J=qIe$2%%5j Nbst]de ,ڰ>_Iϧk{;U?x !E_yNƪ_Hwh=1~| \?wĜen I?.7aiv\$p]$*LƌZP9yI8Q| $)<&uYMrt;>b'U ($*#{)[W,s2kBͦrp1Xc;tQȑh/=\hZԽ#?L^`?jFU?3f"D%#K@,w~ގ˷P߂ [9wS`Eۖ[۷'IQ/*sN< ]oM%AF$9z\עI[f9#[\:cΐp!˷C[Fr)%`pwt/Ghx%cE*TVFZXʃ z鷸+[Kԗ* K ONK b ۶#;np;JnAo߿}5?z W}i[z)<&7?*h٤7cԏN?>-F?\irn\ ;Y^pгseLwnr3_]|we߈C*Wz۞5L(CU0BW<6k?-"9T`39ϑ&33%O>J_}sߥ`;nY7x;gW*Q]WAMqb/1+Ct[8B\y{;l ;;tnپ}{ooo>K@w10p͜A~'rSpWOt`pB _9M'"X7ݽG7k\-`-D(b6TӁ/(eLIJW1XA ,'۴̋Ȩx.rH)C0Tj6Wٻv *)&v$n aawF:ۣǴWC,P5le9IIJA\yDP=ӿM&&ܛm9+vuSL8mWC_5A(ǧuϞ] M,= UͨvSgSB.E~BXhKh<<z] oxxw7={Bډڸ;$dpc骂;݆tiM]o>z5KF#RBէwYm/j4Ӥ,]۬z:d{HȮ5 ?q68>qpEk*T,rzxbqwnP\tqOnH/f}wϏ.~_z#|7AhrwDR^_\WBu)neNN:Y>5r k׶fשٕ3Ύi5ޙk+Doz?zE^c|צ뀞☬#\ҋ {;'cjVBj61>朋꒰녧WOvU.w?yx\ݿ}a}+UYQV]ݗ] P9ꗯ+3RRUvso$xK%`ş?w"#]6}62?G8, >y}|$F}u['~6L(Xi:sPvW7T/I5@v[v O: 謡 ӷ5N7BsiiYl38vdk.}NWCD.c^\t>,}?fǚI+lqiﻵvv4g5ʕƖWۚuVyZcNJ{$pr EA,cMR'7w"%imŸ Mm > bR EgِB'O > V5K .tjyŸ9< Q: deGWyKfa5uۖNhj  %_|haˎD3z.9[V^Ђ7ȡuxցM)2>TMx/j-iɩ>r%C"'@Mw0}We 04dNdET#n(~􇿇6UR,\ Gäd2W?eA_{:٦xCFjzoloc=mYbF5hQۨWON]`6lCJįT sGUF6];Zyv5KkίW13-9c!]s͂ij lx_#m N ^M_'S:d߰(X>g$J/.]-[%QG)xPPetʾ$ˎ#FpBqb1sa?຃Y'9qp\2kQ0Ѡ.O-?{Nĝ'P,dkbR[DE^Ɍ8Rѱ7 :(Zˠ+wػfxFj 9W)ð}=sl{Gpv_8v'"2Y= n>C WtNC+u!nNcR끽gFD\ 烘%_utl{xW_蘷"q&΅o)[&|R)씰g<7]G͍vкAx36 Ml˥MՂŽC/ϯ^РAU3C|O5&cYլiI)sr/m<j0v3wWWi-q7FU]Mҧ_?J!!J &ǂ@*lQd2d1>WB۷u&}?=vw-7cubxFS o툠tJ!- ~<^OdIM|M/ ҅2?J.2?v.:g,sfʐwT|x}?eX0zͮ>I\ IDAT|FELf_cg@knE=ѥgm*G}VeP7:ڙ*ӗ^ϣWwSlQuݻeѧ≅H6_lcj|Pm cB1S %sg,SWo0Y];JyD:6;T?\NmjEbpBHUGc϶%[H\.>gGd̴Ӓ~<%NyT-!_; ZJ0*0N6^;/%~nSߝmv?C&c~tym1:$*}>Niƿ._vwvWx@=tr89G(Wxo rKUih*5﷾y?քNPts֕䐸/^𪄞LN}ix5TՑXo#m!u-|1ha*wic_@2\HZm`L G"]A'0OE.CUr˶sCh!09*`HU 6c.wX%TfNR n4/z7gZҰhc_?"u׮k^QԂFuH UN{wˎ̜k뷮Kd+EFTFQo0_ zPl0n_UYZġŕ85^/M.&-tj  6\QLP ;ء4:2VBKTk*uMOYe؛m?DӒCiɢTag[!`ڑ0aҜOPVAXs$LFf8JZ g`ٱ~ ̨,̊ p,0p;iyߩjfkˬI%V_Urkȝ;gP4!L*;'9ixn<÷`|Ңn/ -ێ`7Ĺ$Jzcn+DUc깱zڊ-j}$z%эO޼[Hrr(  2٦ÞCY3/IZk̼;CչۗMU}Fߕ YtIv*qF&P:R<ؑT҇9#jM7Z^WkmȉGꟊԹqsۀ+UӒD"U;) һNhܧk`X0ja *8l|[iuh>8PF$eG_XeI2 Kނ$y(h6#˲ţh~'8LjӃtEaՄ]U`B-8luC,QPdy8WiJr͂5s0M5_D <ر˫t )(緓Z>ϟ??u6|[4)hJ:ibrrhXQ܇wue/Et>w<1CDr-cgccC>lA÷+Y$xρ&,6 _.$@4)XpU! pEH eNhStA  !s̕%e%b, `|r%n4hi#v/&H,9ܚJ>ڗ|) d8Yp8ہc#O\ghג/ͳ]:4ۖnuhU FkM# XD>n 1)Lk ^:+P V݀>##Ocm{/ܼ 7{pJo'ͣ.tPWv;u&h,"ᇒxnmQ݇8E-.pp(HفOUk$@C`:(OV%lIG <{}r,{.xJfUh]w͉kٟ K8)|go/}uyf?;կ`8v_Ws9f47:j=PXx̼*ۍG1v+w>stwybK4Xrb2ؿ?; Ŝ>2qWLa`@dGOx7/q}48'mN>p$Iʂx=a0H ڟ!@Da=#?jQ@ YClԬ nɰ?cwgo s U2 zlT?w3XƃmMUY>KG򸣁K#k/r|12MB-+8ĵpS0←sc}SKn3R,S"V!yرCͥ649H53h#P2;$@mJ*[M-NqEѢyE3,537h ʘ+?\lxrOo]KNʑptӁ_WH~#?J5UZ}RsNMCx*VAlьd5J* |8Rh7G,eĆm6p۶|U:day]?{ݶV/2Ō50p;Cc:VUy }4uxu|~$Qjr_lUu^>{|LP_J0myлmc'5.et Pn58H:*G`*ҭhq176rt13,L<i1VA9 "iTcx x瀉xY-Kn@A)sq:XZs|W#"MoQL*~^Oհxj*\c$q[eԚ{1[5n͊ѽPPEG> 4%fT),V]B/[ l#UN|U-KLdTzmdM! glh.%-;#1qCLE>!P4(1&FES  @$gD^ baQ#t!ucR*d:Ņ-_DEhđc5u'ޝF!J{Ia*G1j[,;ꪆj-pi(z}r0M 4#d '9QM >WIx,/b% {E)kRM'"\y*<2 !Lz#3|Z7hDS\ ަLŧ^X@"J1fC6h,9(bhifDRGJe)5n@Rԗ"6g_6hm=&WK*G:}(h4sJQO TT[][d6r0D_ZYēL|(8R 2k$[9 l N 2V!^L``H7A0>2N8=L H)S@ 2"!%!z~ rpJ2Zc8x׌dKPuyIвI+zו|GXؿ\}+i1U?gp4L>Erоf"@6 ͞Y,,;VDȹ{_|@wᾥHg9&><>>*鹾iB'ڿLbVU"-6J7"'1fwVMRO/_ @@Jm-7'Vݿ񉪅{7(:<&7S7& I K5U}ŮAMv&]"/ti{NYQ3_S$t+ RK i^ ܲyTP0hf*`03|58:Tq`W2(zfP 0AΆ(vFΩ+R@zzmY#|)2N@.ז2`QP]=p؄4oFş գ}Cj2 yx*wz!ƦnQ}gUw ‚-ܽ܈a%z{lڿگd"NBߩǬ 't8cUn fzxclcb,}Jo]X隨m3664f 2RcQ[uR]}Goxmh{?dRfޒpy~gp7,1l5M<Ūolh,;Y,(l)Zv\tȞ㡳)aqW}m>;fn3d:}!3x˻K!uEf尥=?}|w7}]3LGa5>;~_-PfT_,֡kx.(Uv􃉙m|Y.?2:KkίWɉ zm݁ӧMM8$>h >SMMm}: W̨&:j[\BJ7zCX{m2v=7:|xpcg3eZN.2*04O\GF+sƆ}mee`#|@o!]b̥OYrc=^]o2H&xw7={W|q(1Y&tmGKV=tY2.` [w^zٓ'O"###""n߾}+WڵK* B^M5___OUXvLi]m8#uԄ)"?KEݪh6HB)K y!l`$Ga7WcuQה:ŬCo ;GzIF*3}nKck 2rW| + Rdvj7ӯX˰!qdLJz%4rm/,܊4ILhĿȹNJԂ."eRmU7#W}mQ]'ȄΏ!Aa!Ada^D_o…ڃ=byeG[&xy!Zv,Uaߜ:^E3rV\,[O.աtvJѺ u u + n|= W":$<:^_ߡO9pԷ N1Tts]Gj ;A]7W-N}Lb*(5-g|_ttĥ ӤC(8\ ?~(K8j?4G T7:)GCmk, jzA5íD::`s nA٩R(YR:EΐeB}v 铃nvlro6,,;9iјc1'3j+yY":&R7LRm$3>?䃺^~jOgRU+s) G'~1v7_? CƇ:銥xJkXlu,Ȱ,YXٲ[vReGq>ٲck[xV)Du-PsҲC.BHQ$QUG/o')0U)YGmC= 6Tq5z:):rS$ lESȐh[#.RK^ʤ-磤d{wx5Q=y۷y :}$aC^չWoØS߿$ ;ɠGj#CfB?Ũ7'X +K@@&$`iOYv&ϋ`Q`qm蕈;gl^z'Ox;7ed(nP ·G7W QZuT<.0(%OEވ;]yo(IS]NVwQx=dml=q;ksmUri7{l4y5,ZUޞ}V} *'VXDr+S~؝H(f7!Մ+m?y'A,į2-G_vX7s]4}qc˅YRgGǼ1K~ja% K s0]g^Zw-Ҷbo ۵ߺ4+ȌbgnCD&n3FԌ:&F]!l:QmFGCi3H'rybULJ Fec 'l `J 697/_&J%~h`bӠLH~]Һ7IP{)[#B77!KȉLtp1k$TyzN:^҉bLKg3 .s΂@[}'|4bo^ٖ֭òrR_墊U& >~XwVi>Y2/rR ̣r W^L6ITe8 :PIDAT,6*DlCf1< QG Y=:?H@䌂*C,KH9{Jr| nK3m:C'&b)P tDuRg24:1K%HfYA/_ #0i7DEP2T2JuisuwGK, H"r CAN|;;;t{!X'OAUTRfB@0R'UXާ̹ &OG.]ri4ނZ>nOKx͛7 .]:Ÿ6trH; >i|,X[d~d _?rGP1\sjg(Wb,P5DeqEFA\[@NzX"4CM'baT%'' RyF$e@@N'Kaэއf'G] f,9EY't VYZ^(\@CK'K q1ڻ-kVQCP~2  pSIP*QPF?:ݟb/u8' s`T*u.Ҡ$&֔%O0 oǃK@J YSW`$|FS(>*F~JDvԠtDh +mr^C1bn¤e.' K M ?/ijR>DhIDGPٰH,PM(h84(M 58OK9*01cU8Ү ˇdELAJOU VUGYK yHK})UU8[k(e't@Ӡ0g%BFŪc,P(z;t j')YLS@VK Y7ʖvkrTI|oլ PǖQ\8hԵ:w~sQHAe*u mթW3.PY sAK!u|ʔe d }{0` `"SWQ\'vh i*VrN>dǪpL#K]e X͗QZIENDB`testng-testng-6.9.5/pictures/new-2.png0000644000175000017500000024221012551235562017146 0ustar eugeneeugenePNG  IHDR]D,[xYiCCPICC ProfilexXy8To,c'=AdߗlYc`%I)*VR)$f"ٲZDJ3[zy|sous,|@?H&j`mlԯ=8kp,o0, )- 7|sORF[QC3`@0G)e[Rp9 xQ Ƒ0$Yk8ƌ]vqzRtGb%y{+M$j}^w $+0 <ïe8f?rhÉ;zV?ܢYA=r;=mo/± - ~!YF.zk P ChBnOSQibisB7cY2e8Zxo^1_~`dTAN"C3򛊴J@Ն#jE4ifi~S[DAaѐɴٺ9!kf6^v'9 dqtvlE?L &'= ':<-uYsߍP{R}\WēSiW_Ξzpܭ쌆oe'u?=7ATWs#B"bز U55j=zjLAM^\imjni+j~ûٙ%۾ץsuPpHh+̯$5c{.v\m|y{l'ON>}7}_TggJ/~&BŋK=?WRW}7fˀH*FA ϣhj [= ]L 9l0k_}yf?B˂B5"bKQRyKq2+H**N+5)g>b*}ȸZ50u' =̓ZZS:zOIc7M>{hfcIr6;k`aaʼnri8(W;󘗁~?~"84F &4> />qTbd(Ѯc<..|=>+J_ISSWQ1^tcԭwbfޗΕyp0ODX#l!O1g {) SRXn)SwIH=3FƟ[R_85K4/ԷƶzyGWM^>ꁔA!ahdlUkbcOƫ'g~Ș̜X9? _gqs__-(~(Ի|qtM|i 11Aa2" ɉ|">QwT}ܳ* [6fC,W''_ 5Vb8zƒc)i.鎃gpr2E˫T(P$(q(T:,wJ5<hs Zz]:XS , 1Ff&,&Wl4/[Y Yg'(lٶ%8su<dW)yE|d~y_{z| Da}*&LBÁynbd/ەkW>:P>hb:6O+t|ԍ-Lfb^4X7g^Xo' QBDMCCyND,'#{ĥ#q $JHɽV(}f@vz=l܉gʋJs+k͟=e}T|5ݪCkw|v8a5qo?BϤ~M7?z/XX Y_w0oIn ;P+0DD oHud(9CYQ]p a*A &jn`~ElZd:vLz=1 3L6~6l~`Zqt2Vc'Ј-W +#@PJE|tĶ$Fj4O&V6SЄ_,R;O8\}ESBvNA+c!gX-r-|3/w8&D|uSr?%B F 4>%tz,Ǟ0 [|HԞKu6-7'3\nOfme߻ϖ{Cr#bB2+*UeˮW|Xz[KN>|`0qTUϛ1w:G&ݦN[}ʙ"8k4=ւ‡X][z/_++U"ɫk^k777\6766ǶTm-llP/Q a4v_ܓ Vbb <H6o-8Bv[G7ƺ a/MIưƇ``cF,~~;=.Er Y" `?2^붐B̭` Ph7"O;6gbp7Y?@ xw &}<^ ڑ#e?ZRc^莎/uϑ`[ہ++}mYxG^ofnt; ûѠx/M8y %Eɣ4ZRXHP(qT},~QDc}'z_T8XzGʼn8*N?QqE?/qT},~QDc}'z_T8XzGʼn8*N?1t~?1s\ۓӦ nG#eHles:_uIa6хi@ZluU&g#Uo{'oIpa=~:_-g(en=ֲ+}6oX?&XDYiYNuNxɡ}ґ%>0{i~~?&zYz_'z}{X|91}"[\?kcщ^٢qkEEI ?{d[So?c?uJ kZbO֋MeKMGEߠd2feXb:S'M2&#։_Tp° ӅGX{OG&0taa:?Naa:00'00}oΏqoN>7L87L'~d q2 Ӊ߇8|t~|taQ:?cM]~/Z0g Ӌ.Q#^HF2z,2 ѻHԋ-:OYܰXl^g~qMrb$6Uo񆟽RD~'#Ha~_t&z!k2f/iCسE}[#7MW?"Kua2uB${?jYP> k/J]T֋oX8Eh/J]T֋oX8Eh/J]T֋oX8Eh/J]T֋oX8Eh/J]T֋oX8Eh/J]T֋oX8Eh/J]T֋oX8Eh/J]T ~k2ı]d=xߦ,cl/8 S袈֋G鴞XcD!0,Md^k}.f3~/{$l{'oHr[s0ߴNd_zhR/6de8'62d̞MGu?uNJt 10)&}V*rW{wtİgl G]&M3Ѿ_i\ҕ ?/]c{ۆ~M0kz&rXO諝];ܵ'Aezha9tLr6K{NN]2oT|K.d 'if!`G7wlڵok MCc_J#IL-ʚ{i0YteWԥ:vm}^Vػw/' C0 ChGEp{g}?9L6K{!Z'2! S}(2Z6;]L $JzI*$J|]dѽ1ZnCsrrplV0 C0 `#&!// /p#],[%IHrEYGM"JC|}Z}O.E^)]I/S.8cs˚!`!`a'tg{]$M$YG8>wbɗt`= %KnrXQ=s T8l-/_~{SQhծz*eе+v[y+++b ر l"۷G>}PTTnounT;,صM;?4\:x8tJdk0!`!p >y曼 $.؝: #zlE0G%)e{_3M/]_zsHXܽ\,]|mݽN;=2e:lܸ  >qECHsrr͚5Xr%ZimڢuBWuܭΝ;wb׮8ѳgOnm&%^Rg;gmXtÆcٽ^6Cλ8eQ0 C8⋿7wdZ/r:KSKZ8tiRx,:MDNfE_ʩvsR/ѳMp<\z)^{ Oze#!"WT#ςsҥ vc;v B6oيr|CCfe@r7/MG mp'\K^]{*wgba$^ꌚ!`QBc#ANp^;O%]$^^UNl=w-|U_ u#]ۏc'qMXܺ u;X~jt=2-o)nذݺuIW֭"D-yС Z="-..F;w+3gױ'iC\NmPj6 ֻ"Q;Tt#* C0 C>ExQ&{QkD :PrLIWd"g$*JF/87ZE#S_mǹu@G9#gg%ZY[:Rr'1a?HH;b&g{W.c1pч1m\O"}yO ɛ@=ؙ Ҧ=Z_ *07D4!`!`GGg";[Baz ,~c- bdQǵ av.+żO?u;1m[WWo;Fu.&Y^~ ;\$\nWK[,Pƍl'8˝bEɭƦ #wyжe; pٝY'IsC0 CmHQOoFr^lNL|SkBNBJtDG].\,ǔzxj]P\ E tsbV-vrݵ?]so"Vם5dKH&Yx6rlWn zRmy-ҕ/5ssAch~t;/O3~!` @2V`.c&ZZ'zFڤ׶zrI9ً́Nlz.v%#207/s=O-tY^q6̩B=(ȩDYJ+%#bO%r: 1lZjba^> 9<CmǝG!ɢ%Z!`@- "ЍdKQDıO:acN(woS2f/+)^dittwmٌcA GrڻNvЊFڅ=+yph١cJ23\$S钋c6-K/A}Zv膪{Q]yhv滃y+Vv]qsWA,'f!`;]$X$?{ [ EW6?'!Uw? v=B쮬JizC0 C@-pj~ ϠrO(K`^7ϨeBXĂu"d=.ɘ=unwĚ7}wV Ė.Gj [[Kz嗂1A|֭[Ht4>eL=qٹ㍿>ǔ3N@~p\Yϱm7d9Y5C0 CE܁D;ZQfps 9PևW"]RLxq.Fd(")K|EDZ|ݲs>.SNDwP>Nw;3ی+3o@v'5 C0 $]|%Isla=u'"],8^^:ы.7}xsJ?|زYW)i[v |=pIym۶^\IvMId1Rg0{+>^vj qlpo0):ۚ!`!`л]4!$KE&bMhK6v-ʼnšmWkA,c V "]>|8iEA=c mw^9 6ql$S$U<,j ɭEz"\AQ[gEusd:}yuJ~ C0 r$-]N lp`q,:|߸VLt) SMt#s,6ݷH$яH֭[W{lwۍo/JMN6n:i6C0 C(A@,W/MN8ş4X.Ot ,eQ$vαH>'IL بHU C0 `\Ex e9P&qPX6-tI$uAq/=}|`25C0 C0A|&W9t/ZGY~#;aE2%]oZ0?GdJ( SmQZZ C0 CC ;=5 c'wв?8O"g:^"cݓ0pYLIWDR9:Iٳ.>~!`э~>]hDC<-l6!QZ&X1-!]RL*c驧DzXߏKRo0 C0BE#"JPhA=wŏ1lSӇMOr&K&b/MX|}?zm|zC0 C8 C^]x M"C3!]8&cJ6!Skr> C0 C @p,-- \ =9FLXGĉ8Sqˆt3^pE?^7 C0 /nݮ^WF B$v&6.cmsnM#hȖtIuǴ.r'!`c1v/~q,yi"yq*jjɘ#~k_X.&Jմ' яz6ѲN0 C0lx6t=$aYS)29˘lB⣺C$w0#]☬WSXKO_iԱ(y^>VM۪ PT\üvQپ\GtV!`)np|-I,k{o?Kq̦{#z6q ~jnZ06I%$K*eFKs 7uY+1:WJ ODN~;t9:thi9Ŀ۵xu36z!0 C8H#I2ĄKf@>_!q!=$('}snH1e1.NlmsØ-ѲNk1?=u_:~Lڣj̙x.|e5OtTٌk1Axpx [%P$& kgq<""qd,>gHOd~!|iSf.Ҋq=z8Oˉm;rBL9 #6`$f/Tknhv&^ؖϾ2'BIP\Zc.Mm 75 ) =ށӋj] q#kwLv53`g.:B50EP;rQ!`MF" U]F~sZ2 DC]:-] ڿIOum 9tm kju5UNrmF|J zb=+qY)/b`RE1ٞ^ڮx;Jz]75۹=,NUu:^Zqh+YHCJ b-=su#o>qt Z-(ŀO+?cCp)y`LLxt.F܊Wتw!`@ 売OB"+g\C˾#2{=v bI3r2]Q6)RЮ q?#yofi]p‡CP\bٝQܮ1{0NIYC0 C ++w~DlL>.P˒C(6|zz R,BEz^&>~d+qo`߭]\ptl]&LCpTc98I1o [>ڝĈ;KV\t,w luk){tD*?U<|xe -]YosR:댜 !`@$|iLE|]à `/2ˢ,/YHM~"4dX2Ӌ=qovI3_EYx`rGt) y]:=--B,_'FzZbK^M<3aDo9|$a3zHwɿb靃1ոt"̞( }"bFe<0%oj=)p:r־#d)֙j!`!oI2.]3Q%+GtQIX%s_cb9f[2Nz=%x}X A:W[S?OzYc]!;ΤV'Lv}&]{1AkU b?ʝRn?+SKkFm^XN|w!WcIex|iSGwW3:Ns$\{Yѣ*Ø%٭!`!@µ// /]fM-|Be^sx h8"X N*6=Ⱥ<= Eȴ2urFZñ"aS Z 3Ca~2| ՕUrw  +MiL#LE(.jݛMj,t5R;ɭcQЋUnCU~8p- SǧXg~!`I OD,2.ir+$ d,~|a~WZgpB(z䢎6^ԅԱ οVG9hOjד`j6 '-SxBt=sĉG"RЩ{7FXM#ϑ/=C7ۥXg)ld!`"@%D(!>E6gd'~0!>72شlHWRO_-KiYzC0 C8  !J㓚.oS>wR֢9EڮeɤuaQ:&]Qbdtf4 C0 C&M?Lo)&qKjTݍ8Ѫ;?BQF]?|?MMtzr_~:dC0 C8JÚ;Q#bq.&I0]/K!`!p>< ^! [Rv+hit6Z/sOM2a&MIJQئ%9{1*!Ò9hc5dm~&ls3,[y33{+ 9G;tn܉$Д;[|vOh&dX|-Xҥ'2c)P)>(i䡨E(rK:.JƜ)ݰ*P]~ț[Àu!;k0e\ݴa =,ڄ㑅kݤ=0 СC]?17r\97}QRrL:sn%nNg70j-% kX<[vFtgOĸNv~t H 8 .~GMvQV͹ cKm\@,/¸fbS"Cy.nͫΝ3`m8Lļkw16G{mj {ī Ɋ--:\rҺiFM]Wr0i_y> u E1ed%We{vtY>ӗģR%!`+O}nKkO YJĢֳ>L'ueC&Og2)Џ^l~׷7r (fʍMs1bAX&̛ ߚ;g]5PЧC S16?̸坊EVFl~:u.>*-68"ױ7?ÀRu<]8u>οi*ܛz;0cQFVSuX8Ưj o_ ]; OUUX7`wS̸J;XcjR>v=3U9*{ݘ\x]`cЯ` 1t;4[1qX宨ޚ>=Ǭu.v#unY8<[WnDs7oͅ1צD9 W@V$y]]?{C@lE'_q?0ŏ5N7wû D~{mhG$rk0yW&4)4m K#lHLtaZf 㵎GZ:so]Xݩ;t)mb)xmT5qcrT sg 1Xme/}~A+( QzYnc|+ټ8(9Oҕl")V%V,}Is[!\ue +錻iPW3F< ?wL~<8 7Mr/E\;[)\p2>l߸x%Ւ6m~UaSW [ -9]1|Gør M.F%AZ,qFiUGƤDz rt+{}?y% 1oMY^̑8MBd{s` )D֟kSQ)^LW1N 佹8>̡=n}ڹ]W׎PKKY:]?ۦ!T@]FOB+ɃsK{]70,HgqYna!iVMsFv- к(G}Sbu1Q2 O+Vp,džq=G_^0?; kG} wq!=/} Y˞1TWKwc͖Zn{wΪ30ޭE8Y݄ʷܖʌ{0g)?cش~S@|R\Yd{G 8Kz}Wx3?n>{O>:p7;v z ?څ~X.Lf[|9 O<6 #fy;[`glq)eQ*^ZuTM"D۶7G ~+l}˲۫"aw l,n~2Yxd.dyEp(Wnr;|b۰|V~ xl֣./F7.iγoD G dOG@nj:&Y=i&] ].Ɨo~|mHaq{ѫ1xp Q}ȍۻe 7݌]fSnۏb-棰<oxc6=aY1%8oD{p[/"̸R9LWKb%qc^QWO"iX`nWdwoXgxNS;%ՎЍ4 =1}Km#W>x ?Mc᪳&>?yɹaۣw`RۛZ)aD*k%#m(E^JŴF89#[R{3`vAκYu7(+(z{ ]gzoa\{_’3ާQ (-`aGI7xbw.+1^~X2D/rXO&s`α~a;-VJw`Н]bڂUpt*c@a:m5UWƝbd-"RPYnJRU;T jȯ_w:WW07+trVx֟XFSus]Օ!{-iQ u!`|H&~hF+~N8;W-詨)bA襯 k~M=0PjN^C].:~:RLNǼ,6hF9hBd^E'=Ie!WZDv!ZSE|)t[) C0 C x[Piفߨ㹭8r;ޒ:BH&W"d+M,DD,ZOԵzA#jF2&E▆?oCi C0 C  GFnq"PjdaA/j!Fhonҥ'EEi_}[o!`IhK|-̔WHa/оUL&ZN{GdC0 CH2$-bXAȔ(8S<"͏!`!`d@pK05D<o-W4H+2%]%'sc99T!`!.@"Kb3^2OTƽ5вGG%.>SҕNR9tZ-̟zk!`!(t.0>9c??NXҥ'YᏥ8seK7 C0 +S;|V&)J:fOhtd!>ږ?k,hEd? C0 C 3H>L5 Fg? .6y! )Џ^l~ml!`$O)I7󗧹oKd>?RΆtIAe0^(1}3Zo!`u?OٔlaC"|#UggCM$Jղj%^7 C0 ۊM|kNdmײ,_teMMD,(*>"h!`pL8 >5gԲ%]Ni(!`G ³pI/xa\C93c#M\H(+/z C0 P n)uOkx$~^E  Zg!`!pt">9H-h}4-bME"S-v]e!`%Բ7?S->:޷!Om\+*.6yB6?66 C0 "ЄMp{m2](>W"SҕQ%^XwS!`{s3kΡe񏊏K\Z}+"1sL[? C0 C=a+՜CDǩO韗*C @dY?TXb`#zC0 C0EpAs^l~W|N⵮:ы!/*ғQc'tbZ:5C0 C0"C]Kߟ?/z!c瘲ޙjmFricl9?^]X6lӛ0 C0 LDϞKٸ˔i,NeHl!%y7 C0 sh4؅olHWX)ZXӲċ!`!`a1ڮeZ({ojU.&JfAQIaFC0 C0R 1ҧ_tt_~:dC0 C0 t%:udKtARӅ6=~zC0 C00!:ɪlIWXAa:)NۨdK|2!`!QC8O8-Jw], LOF0 C0 "5)Ol~9nnҥ'EEi_}[o!`@*^!/оU\+jR8Q>z!u&!`!@*n?4H6gں"]~@I`s4 C0 C TZ?޷gJ'[^q60 C0 C 2pmZ>Z*gJ2J2Kn*C0 C0F@xFTZ(ĥgJI/3.^˴So0 C0 tsh9}jޔ%]zeX}x0 C0 LDX^O IDATyG$^ɍ%]z-s,j=e+!`!`4!QC9?)OZefC&Og2)Џ^l~׷0 C0 t9Md>?RΆtIAe0^(1}3Zo!`G7Q|AKFxϪφt%He:-KYo!`@hNZuaQ:̍Qbdy%a!`8pǾ}0-eW-s?:&\\Jߦ&] =Fڗ7@FQQQ n/^!`%H*++q}RGuV̛7WFyy9[k -[DnгgO >:tH!ZgC"S'[łtOɱ6=~v!pg2iF2A| C9Ȅp/TSSoǣO>h۶mƹ;wbŊx ѣ?D'}2%>Y՟- #Ja:)NۨdK|2Bz~VaS!pƍ3Dmƌ`)Sp'.2ZG$gqJJJ0d<0>}:n馌a!'a/qjߖr-J8 Pʧ}|LV t6 w2٩?'OFqq1bXPѰϮGzb~ܖoQFecrאP)Ol~O_xܤK z td IMn:a4Z0(>Zvmp{Mvw㹰 Iϑ \s[Os 'gR QM#yM,8Y$Q>k]͛yTu܁/~;|smtX9^{%% ϼ M1 C8DTWWc8p v Uv۵//)кukϣ}hH﫫Y x4K[5R7ܦ"]~@i"RW/n芓O; %: LuK7/Y_;mY]lq^nBA[?Q咇3rAQwxvލM6SOENORj_T<'xũxh^s׮]رcG x\!NMRq xVf:>q Ax6ɸ٘Mxgu9׮Ģ?Eς&I$IzǸQ^9Z+VPXԭfZ*gJ2J2K4\-غmE~hfƒgC׮]I`mxvD;-We/L폿'owqCUܐӵ-Z34$,pjg0GSnbKpv,v96ںgԮo/^z (,w~Kw%\[YSKpzq~c]()K\E990s̕xL_ZUo\t, tgOĸaG/r2z  9C:C0 wsİp3-K~~{1l=l2a p9]gcM0We*''d[ڵ !NM؄gDԜCLIW:IEck0n.w zq#K<}KåǜVb0p=7v*kjܺ-T}k2>h_θftze=I1N>wމw7}Kc^[mm]9wG[#mq):+⽹0axmG6wC?g6lwr>vOϬɭ^ŔΟ~@n7ѭUmtիJ1N.]){d'`ջ0x|G9{K\_aw+jpj+F*DAQX0'c7pu"T~na;$1zW/_q-VW;])*j<֚!`͉" ws4W-RD&7/1AX5}h]^n'} t8}q zv -ktH︳׏W|O}_-uA^g97`ݘ9҅r o q+6^@< !NZf ?NUfJ`'U$v=Ȳ,iDϱ.2n|_ ?x~%.~Wwuq|0][O!j0'jKuo[~pўjp}yg-:+vw;XExw*rU{5#{SeLoKKpƜ{E~' cw[]Xo0߹CDNObȣV.:# E(Cn<tۄ˰)C_FÆ߁/9ݍЩ󉎳uFNJ&n8q|^l%wBvWL C8Oȣ%|.^i<4|ûYW`]Q\ro힑(sr,gr 1Xӡ|d:w9_ϗ?]{~ qǢ[uA1 bɭC+_(`cġ'4Ox]hk]=+ic)P)^aM?hoA^x sq,[{ޏE o߮NHޛ<yɰKq.G+Ƌb$N6\v*PWo⊨;åW`+p鷾/ws~)۷Oji2a~[){qڌ5BY ራ0qOl`z:2/V»_$Y1MI79쎟:jҎ7eKh3 C` @rEgϞ6wH2ގ῎mFX gBPugdW/ N?\*;_U}'{y"//@߱\4Lnhڌ~5']9W᥏g=ת-kY."D`n(,'%dC&Og2)Џ^l~׷5޼ +뾮KǸ]s]GvsphIp;b;G.Fqz:b7'_Z˱'Re@QiwN z t{foad;Wnjy'֛ks0fv{]3]zǪ`ޒǣp  +\ p.]G [s7m (W5z JݯWU`"\r=۽I޺#pe;9y=]0p pةXt;5k=J"ye; >÷|GG>#d#]x\oa^ q8X#@A\|mWlԵ^ qM;"[Axֹ@+ZF"8# &ar\02]Usy70V;~u+}^ 1mĵs>F%bSL0 C  [Ylz<Dn1g;%_xxgq?tkPHR{_򸭰D;p:g4|痨tg_ >y9]?o]x;sgY&=o-[}SDz7]/]}u5R=1 ѩS6i?txtd=mrї'yQ&^d";19f[|~5e# kRmQ2mQ5x?ne-X* .IҒxᄋD=K~Ī.p0 kpўc]ú R.`K-N? p#\[kpš!pPVǎqyԞylٲ%ȝ9h~P:q}\'om۶ s zA\AlԴKϺd2Bu12"/򺻃Қz*6=m{pxH CAZ|׾5,^{opHO<_T0`O?K,'xݾt%FTْ.g~QX5j1|bxe&\u/$C0!`d@&e2q#vcʕxǃ'7A3)}Ż6w޽{O?K?D'}2%>/>[FtRQ d>f;p{pV!2t[!G ʴh TpLJ@Ls)V&IϫmriXCN^9)kߖr-J8 Pʧ}|LWzg C84t, l~~=Ԕg;flδuME"S-vvh!`@?2/~o7ΔtE%OHmql`!`@d+4G4:^۴^}>TΔte"h!`@ :&YKsE].Ɨ_0B&U5PQ}Q^R CAa~ +`޿h=nْ.g~QX5j1|p QwÆ@v*k!`c/l.йmayOF'gKˆRN68Ylpm܇e?ՠA~ l:C8@hݮ :pߏ}WfGwnn.xh99~7CK~1Ƿg6IwP/ q2־#[+bOв~ܿWe!ppۢ5>ﶻE6-NW.ڹݮtI֭[1o<^ػwo:GO˖-ѭ[7ÇG֌ 2'6Hdh۶m:GΝ;b O~Aao2K5ɨo.Y$Q>zu&bxh^pu*9{'w8U!`r+VTa/LD͚1c0e|ɇHBBygC cӧ㦛nwaCsT*H_dЮ} >t>=q [?ty~6 ?Kɓ'X,?-IٵyBOLp}᷿-F;^?IxK:>q.&I0]/KGG04 @4>xkڵ5ݡ3'c .?<ڷGzl=8sp '44^z 6 e~>U$KC!R`FŦY]b KPݬX#Ka΢ώRFC8TWWc8p v Uv۵//)кukϣ:n#r3Ă <VZ(ĥgJI/3.^˴S}.-]\CoKe3W~&'8h}},]E[0޽6m©-3];*vIb1^Tr>8{p{}uڵ ;v|| qf<'42_yzwo,,RHċ\;漃-Cg=~YdL[,$Y#Vf9zDb@$׽{woOpTV |kn{ɀ ٞع~<;d [s<)j/hQ6㩶vݞQQh6b-jkI:_ܨٱngD:9VͳɏO!f%⩹CĞZ{$d}RgdbvVisyEF:e{B@!Gn={Ճ_) eQK_ 6`hx]0,(AD~5ft˜oÎ쟐r??S6F- (&גX ae8{)^Y _t?p?d ^;?:Md<-;'ϓ| 500PÇqd?d9[St `A}6zi9C/0w`x/Z񑷰N'/c`/Ѯo nx|Ox u "YZ/3PW:6Rh'8xƧo}쀝8F2}8wãYB:⭌pL6d _|A bн o Ĵ!ڭ·ゐa2 cNFFL|幥v#G;+9Ǯ1ڬau-NIq8W`h oC^_Gc?X<9dt k,ϗ`p4G&*%ZCC;oz|M_->5`~nmN0X#hQ߅LK>؍R(RC~)+%gLw:7Bp07Q)#:Eçd{7W_ uG*Fs80 8USs {d3Yߴ݋lH njd/˸,e%뛖eVEAShCD6-['~RSY <XJ"N@ž1):%5>y i=q6k}婋^Wtja')\;i BSa 2{Q./[H(ڽ >> %N_sjL} ƫEj:5| O(i+)^z[zhz奯.ɞa t5 =sfn*R_('o ҞReE?>Qk$&pj`uW5N; )}b|qK'IH>3YT`Bg>Ŝ$<(gXĚ}_&Ě/?֯+5ͨP\c%C@\bm`0e ,}q@n%q*CwҳָD@]z\Gj\Dc_⃥#'?Sxqd!|M<|gk</}7Dwo@}GAL%=)KLċ wơ!SrY YwK_^3&#gpHeg} K|gGA-BK6GH}: ?xWg9̎ŗ^8e-b;`8ݲ7AjVQ4hsC;Y9vNkVG'me-?> I_aϾab=?/^z}hm=Կ=gG2e`i= G`SSnZ_aHe +&Ze4l1пDkSE(:9Q} )b7cCl9} ᡁP&m 'Y#×#NoG&7J4sB6?|=A;CMܩ X 8Fz߅8jdLϑ\y^.EJ<6dNadVn˂2f2߬]W62sVvƬw: wNo84ߎ IS󎽨"HB9>'I혘NMC>k̎V}Hx}h#@#$1>DΙ ImZ7բavwS8&Qt8^"t2UGyoۺ( |oAl8L?p^9S,|耬c s Z<=X{4Z` gַ5IH}Hk Kyl^y#=:?4x$ُCYӋ8Wv,|hX`P#Mܫl2؞!>o&R>È/jΥ 0\UFZ١TM!(?F21M|7߈oO'c]6)vg7&II32/4[zА~z`;COP} iv7RxmxGV೸9p㰏pf1ƍ]Sךx8)VRss\M~:3g:㣏U! 8s-R٤KvHvTvF_ZdZ r (]\vtp12 /c=ЄZDN&B430.Vv|b7c ǫi1 A㝵S#/ogޤi\O+qҨo(w/ ;/.ZЖEsc"V|kФųyRݑ{ԤilmZ={"?Gy)%oB9f2żOh xxäm3h\˾>p`]^ä1*qo à=am!Zam0unB>PΑ29G}.mc˗OlD{hsr S%BF[ٷoFR$֘҇=P+6wI[ϭPH̙lc[u#/coud".jR"7 1f!.m./msi}ʴ92sfL} S]!Og#c,rQ6ʙhgV/!|ڕ۹.dfy+WuVst"H mZ?g?m(Ԓf/1q;EBNy-lǖ hEi1ןB'KvuW}[9гb=t__%:]ZRy-,AlZEtg/p:n{ W$[RK(Hҷmn9\A7OYԢo~F=t%1g ʸ* a MhR|g?k֭ѨEÉ\k7?~| 7pϭqN [{jr>2x7?LXu~e9]95qYK·B(Ln36uMM7iH0e/{Ons5[jdž-ć`_%g ۔à]:n  NDrMl8&. +.v 3SY˸^Bl|O}>.WKxseN+rbpp0:wm۶݇⡇~7mLt œ7s8•= Nڋ̸0>UsOzd}˺g! b",0+d܂]ۤCCC{@ݻw#==GEJBOs:"x\N O@8* dr^iVk">=QW`jրQ28[R?-{Gy|m3էxVW=)TR(z< y{'?]%Ըqc%Mbxw'WA]Y0M4DXX*"\ŰRs5Xוݪ"]fΉIrЗe|S:ԫs]Jnk'p W(B8^HCg;a9Q wux=.~"?|}}+\zX\q #!s WyT,ҥw]i|e4 =A8]N> @!`d5;?MثC5=M=ODJU /G\*Gxj1SwZ_^)bF26s:؆FOT~i$/ 5_Rhz4 L4 ¤DJES^_<&eYǬMʞ.فrAuþRj'?𾶥}ëIav}bI5B@!..&\Uf'+,W _t IW\6#}t!2T?wsrE!P($92wiâKsyQׅBu,EQWB@!P( O shuqL_ӫ(l\_r. zS( B@!PYF_qYH%tUP( `T@K WW7@YtCzGd'1]&e OH^&N'OU^ h O~ٳxW~sF7B&r%L3{KL8'L:tTD[oj׮xyRV(Oq|U2] 3!8 碟:6uoIK1 ɺf:J~hܸ1ZjxtC P( B=zSydN!D>g]#r&]C\@&*UCVZU U gJW%xpZs5Q^U& &f:,Pq>~t+dZ.^+P}WFCWhEN:[egBмe$EFeh2{|([fB@!P(W-x_׷{J̌;ܦﯯq*zxql<ÇLlX= }i]dzRn Q&v s{Fᳳ,^vКRW( ?( 0$rM:ܰ)ȸpl^9s6`Z4m0|fy ~ Ģ/kH[tȟ"dܐ-tC0b=I{.a>[ȦPo=qpXyō;㕁v_&}ֿ-4g,ssvw\4-DeMٖOGcy6 ;5c79,[ l݆· fD B@!p02^__w5 %],& gh,~ d{f|CZ!!|lP"exױ!kۆWz,@gQKРA(Z/>Z_C>;+v"{hh16]'мAR ڲߥb=ou_P- p{@՗`mB=37 \i qW8Xg$PD,m#,xl mK>;@"? ;F()- cti(5y>(“#\  )8z_he~ c*W( ?z>a?\FhMee%]rׅB^ƱʬԮ7 wmu߲gв\uGԤn@Er0G$^Y3Kqزtr BdW#"$u`Z:4iwꎛI&Y^- s?li2(A!IŃǠ6`ggWբ'գ;y'hw'gvTL1Kvx!uyJbSز$ Ei]?tn蝢\ߠob=!UZ;Q iJK`z4iP(|,gu#q =oH &ghݪk =גlEg\9Z!Ev>ǞNsbRӃl+ZxŻRq=KhxʿhԊ%}GQpkA>6mд {_6 N׼8 |y#yS6J%^DnH$">=Djk.ZADd.?ς1o5ooG=]Yޣ;2(iD``úGKïh߾=ڷimBA; R≩},-oSݝG,-0`,6!$ikq*/ Gn,1ӞW.m5՛B@!PTf|27\^b3˄\95q.Y@97z.E.ʢފ0+-ZoVt?vlيpFw>!Ec%}V4pO6i*ۨl3˚7}uՖ=znݺvUzdD:3qih|W*'Yh~ P-/?S +)ZJ B۹=1_f\R(OҾ%QqfS80maؔ=o%fOIyX1UR(ç IDAT?[JIǎ͕TA<0G/Hz&^222!eEZDFLI,>IOΧM&z%"tE>T#]&{ \= :ƪ߿UTDB?cćJ B=r+tQE#MLKLdzTuDY+}N*IWUmdr/zB_t(2XU|}XItnl,r2P(Wp^Iqʛd^&ON&e=o|Q} B@!P2;%Bǝx2rH&X&9% DIWX7źR(s7=wAhA$~";/\ֽ%]. ;D*&`$3'(D?#||Jou"].!R @5# =~tU"`52zM^zU.!yB. dr^ir!Э[3,)  6xz͹W@d=W\È;r5$LG-e*+ B@!0B02phLeEN:n; B@!P [E?LSef$6}}sP( B<2Gar,ݑudaSqE!r/]ĉMzŢgӫ,~+^{~8Ҏ^.7+1y.b_3s|N|w6az'XCR1K) B+^!&*U^Ulqn7ӑ'"eYt/M]J 1.o@m_) QnBph@ٟͯS$I*Pj[]@q#o:DzjUs|a-R=w*.ˈ=~;5cȯOVM<ƔqhwS}4nҌjX 4F__Æ=P& B@!GA02pտB8U;j.Th^w.e{D뇩oo"QLAhp}(q8rp{l :H%l^LD*]CNfp_hlGNOs~Ѯ@XdD|ڢ-4ng$aQh{?QI!P($\q =׷{J̌;ܦﯯq+G{Ƈzoc􇑻l5 >z(F/u}2LXDe~q26N\${*(\e&Yu\mW&RE|0ծMK$Yf Ҝ P/xGoC B@!@@'/aʬrѦD:ι/ʔ9T$;$٦.\* B@!p__7)zg㖶y2ԠpPߟM]o7nXԘjP( BJmBuE&Mи*qP=MݙoZtNˬ/}MĝСC@EJQB@!P\0*..,馛qT9dFC I̸pV8ϺrYerYz^GAÆ 遦QfMEBQuR( @!ŋ~e>{IdNa.eFdY&leY2tFAAAh) BAI[ y?>\bRI>>Zk#B@!P(ՆU2/qL뫷w/2yr6. [uy; :+ B@!P*JFCD9d$m,6B@!P(2FN"rcԟ=Jޒ.w0ٓutM>uTtF1@ B@!PeN!D>DW״^{'^HZdHHH@Z0~jS P( G˜kaǣH$LGЗe^!8~*0} _윣U#fՍ@nn.V\N5** 5;ZkvWWˆ\U ͭHIWvYB0,0je|{i<vTZ^b֧@*T vaU ALl4W֪U߶#H]Y[6dEa{M#v9r$tt۷cŘ0aB=VK˟bƠpx%4Lŗ`m'2j ;K|M%xELxqR d= [E?L=]fƝMRn8W~On[0X㡓Iډ:r,<][{xoETPZ-OD K2h/k,Vg05eo8w *"\I1 ec>JXn5-'bpTcb"-ՠ3]d>ډ^XOYCr_~ƮJe=Y1*!C GI~IG/TڈEoE"yG4k"[c"k,T92OqBES^!sL/rZYG=%]7Qs] ԫ^'Zu|qsGaرh4>u>acz)8?w`]Hα(/"b06nsc;lD`Ƙha܁Msg#H'̍E97`aR0 Y=]菲 $ )X ^;.W/9ialfb}L~q`0aX(a"T Ѩf Z)kWz^?Mi ((FPD'B:ODx'>uw׆LmO;wan0OeSU^$l@D_56/4 ?Nn`Bg[rY7~n垒.w' ymF,ėAjR⃰[n?S'O}{!= ]^,L>fu{bDؑv#"KJ##A ^0t +bJw|S"9( >6ҀPj'bd$#;zZ2'g4' I$hߜJ?>l-o6\Ѕ'[&#OɥVkD0b/lU5O'^;r3]JJJX )_U1 įYJ"/Kr2X#`_k(@J(OIA̙py"Dz-bF#iLڂܠuEC;q9O_4lzճXӚNKH9zYIU>z< oø:2 P}˜C.3Zz}}.+JDYLB_ Y& *9ze"M܉3ٚ5xcsh2Dk#Q1tz88a O%vܯ#n37d1#Fj $̟~3#pm08>fަ2rl~#N {k:?7 k$nDvvnSSIA$MA~H_ IEx~{r3|$fž1;`g3ZRS,C){'!&1:دG#DЭA~̋'Iw܇=+K XIcǎK.];>IwNL?1Og)(0*1 7^_6^9YS6bf\ܶf+ 6efD`ʊ]lE0Ȟ}(v RT5#9hF03'ڍ5'G ==ox>tLDfn6/ݐO6tc'jvdg/ΞN T&QudRgis2 tLJœMIXXhi9iZz%uID™_ %c{@t$=50,ftد;`kf62'``LMGxǮ8e#B\Թ=ΞDғvnv ^$TE!p #fCȅnБDYVՂ2<\f}]8(˹,يR'V]_"] <&>'~ܱR3k勿]q,&wWg$s' ⬶:]}pL4jf 餼 [}'ڱ|lT9k mEzV+!&cu-&"ĤbGS Qڒ4_W =U4)A;1N⋷eMz|:5:@CŦ>5!I0bX6]Q% Meo+leVtuDj=?OGt]#Qxԟ.gv՚9ԟfipE1im|єRާklK?2XB_.k92Džc,<c쳴vlY_"[# =Kn չ!tǦ 3+U~lc+uՈ_1=b ֦(:h6žo 2sO֟U"]$"XD`d t p߈'2=u |':FڼY B(~:mEڦl>#V 񉝣X~tvTy"(H˝cbB1 @1{hdLe}%]* Nq41޳B?Yt1L3-jB6=5bՈvBǫ#/rDXExD2 J,{V}kcWz:,Ri֎ \FAc9+9ָ9lx sv\(ŀtI^ {#`|\K%4V#<07z%E[)T3nv qهTI!(SC&wd=nw#뛖(;ifXvL.p^u6wvbmuSK{wZQtSiȟJ5qT(Yh/I1}&lCf6T3;rꀛ֧D琩Ԣ~{$q+ CMHbDt)Ka]͋W _FjYTZܳAH:_>Ѝ@۬M+NwYpQcZl':tf]j!*5nq_n+VS¼K=QN6,GS8er sgߪZI7HM+%a!y6)}We @( کF7B;)P5; O6b т4ׂ b;8yiduYVAN*͑LAj 0JǙ{`uMՙ3tLv$bERO vF!t ,:zGkcߥxCѿS ؎fkǵ{4}Qt\j+YSv"NZ41t'l6Prي3]CBF@9d(h|UU r6pV8ϺrYerYzՒ9b`#w<_Z*"<hg p=S3I>iE7;K PX>;'^i"qwҷ50I IDATQnz9GƢKb~f|GSe2z9բzKn$W*ݖzW\Ȝ]. !ˌDvMndeB.8חJeuQ:E]:|LjwҲq7e6<z9zCX0 g胆w̶b诣9֩1F[q8μYm21&Z)seR|*.(FMߙ´h;v=y}-"7+ݻׯǐ!Cl Jbb5ĈUp-ʏaARA"rMȲ 㣸4lM\nצ.1? RJeL>c_Fzl409Žҏ!S *F??~rjW;$$ubxsws+s]~ B E.Yf"qZJ9K. Dz2a9+hzy~ ~-6nܨ=r0M{N𼏨|f݅!*q\O[v>, +? $\շ&#*$]zfDD d%86{ޙ V,e\,E VKn纐UNz,oOOg]#ruW]IS@&*UeB@!P(bҲ+!^UE& v3y"B_B@!P( #\q #!s Wt[VYK狼 pJQ!P(  x_=%]fƝMRn8* B@!P(<@S^!sF/rYG=%]7Qs] ԕH!P( aArY7~n垒.w' ymF,WI!P(  se]RK@$uᬐMeWB@!P( O 3!B__7Wm,+S(<.\2B@!P( JDrN_7)zF3pPߟMoGoznn.V\3(:SSmՈZj[ P(~9=mLY۝eoH줙a1yDK*t1rHtũ۷cŘ0a[N+t.,[ ?/FcoVN_|w"TmۉL^~oIA| k,Ǘ?ŌAEφ'N חِmE ۿVQP(*=琍.'E_^^$s\L.B/jN:Z󦹏}L,$Gk05xl+p 9d)^XlClh8uWddB@cbѫ}uP(*)rYYfL&kJh̜1+xcUn]:Gڴ1jԨA˩"ۓӛiXHKĠ0 "6m셱qm+eLjvو1hWI60F ¼tX#a+.@~^!kmM+PkX#iY!Vvf5ʖQpWJxpGv`P@X^-TR( O}ťneGde2/zrj)%*&R]wJJJX )1׼ѵ>v$'`툤HPFW/ #JT]I(GX\/l$Mbbd$.EOKF~FiOHAIiٕ#aW,¿d!&aFXhCNh#|̧'.wo)ri GҏE[+J]ƪ@Wt`A˘<<3QD*v)VNu#k -QxZ'Ldm7x p1d7CN.o_Uua+IE,GZyG%k㳥2YB@!Vp'yOqt '2Q}\j:v2rqpX\k;|mμ'aXۇhQ#fap|}lΥ=;#7e`GŹ"5 5g";k;Cɿ J/{x<= kp>nQkFFS,h=tAD"Iޑ1sҲ{ڑ$\iY/"Tt+\εgcd,{-~@"7^_6^=ul#fmkbٰu'"&[4j9iM$ٴ,ڐ$VuM@6ی'g*) k #!d"wKWyK2 6ugt*ѫ5kj/>р;B;4s' Vm)k+>5EX3RYز+] QX>g6-~ʫpȍ_`z!WSӋ06iQt1L $q)2~4v;C$$yK"pTy|4­7$⠦mWh_hbd&mH:O[\#DF?]#֝HښcwݧPnHukJ-7p6֙`I\4]^FqF/Ghs#]4iCM/.K БIO>_s=P(ODrAc0g:mp:4eLl9f7TEյv͎oEE ]˥=X) iVsC5Fy>B;2]>F޴8dw)ˋOaǶ 콊CB0)ڐ߈;1f ]۶FNίsfΙN8 iv]!Pp+e=W\C吉WL:M@8f:I/*,DyԮmOsE>v[Ð ] <'%1G˚3sWbߘ6(Bt8,<;SBK&s"u+: c;Bj]bF,|m 'Θb5^/c^ӯۺ ᵨ.ne(EFs ѣ uj^3Dq1ѩ>qwZ_0/b2@m/wcm]M%U(W l_^?ɝ2"R\(9ń̨LbM:AD۵.t H&mѦ y弗]vGF8KjB޽_Fz]`e DET㸞6}X cbDC]=`MZ!UCpB{J&}>;RKW͈[&yt70J$cu^.*W(w<2G6Y.c:fmV F (sbs}Y/92>[|A۹.UoiO?y3hIJz9]|wuJ֩wTs)P(~TqKD\H>Jbыr.k*"'}ӗn*KL.G s7 zh܌w8Tj}B@!EOx?;å~EI<( Q!\W[66@"]B@!f sYM_N2_)NVFר";$YW_r. }%S( B@!PYF_qYH%tUP( `T@K WW7@Y[%;$dGmr]TP( B0B&rgDx嗷!#pNnc\wLG) B@!0fCp,uQQ] &;'&`$3#TX+Wj??>** T[5"֮VC) #!9mu:׫tr!JlT._tI#GK.rS۱xbL0A-r U$8 ˖O bbѸ:WTfa'྘1XteP(<@d=W\È;^^t5$LG-eY/^:uhϛ>>>.1MEìPZ-^XQL{Yc:){,k0V-ENva$/Z {ƮVj1V·~|.]t-oz.e&3=7z( k Wˆ\U YY1&N&QL֭KHrfF,00jq~*"=ɉ[;^ uıL ."bFX^RFm琍v8C9Mb9%xm}o~3l9 wd!:R,?zαBG06Yhbq`0aX# %s\|""#>Z_;3GŸIEe8'yz}YIPc) GO~2uO#]fƝMRn8WDDCII0A>S>fᚷ=#ǎ̟q_R jꅡcY+)"9( |@* "DADEeFE@ܵE(ZEVbmkZ\@T,Xp""D# ,B !s&9ɓ{.(g\99s;g,rѓٹKW2ΩX[T:Ɗĸ30[-d^p2rVLM]95Ȥ3I`5BC bc^~!*厛Z5b2aƭ?|_kn)ݒFb烤M`cxƸxh c{&A5da;:>r+XF=/Fc)/:: ;Sy5ytJF&w(u񴏶c]1 3Kܖ{͘Dtmذ"ڲe|=%vŻ Ḧa|i|I缺t|y2z`4#sy\ gkWbK1fr?ֹ1EmpoŘ4w)b1}l_\5&>k{Oâ)F~8\77+cb2V;R7H8ꑹd='e- 'gcM'ؑOul5yxq 0c1+[ڲY<Kn;\"MfapKocy?}T8s6I]e+Otu$774Ϣ4ޕ_CE1#iUe Z?Oܱۂ7zOG^6?+;xZPOU*\E~{8yv`-8 /=.톑"9R!.V#`-bgv1m^^L C~n[vc~MJV#jXjZy09X7cΞy+z,hZw6}%/e)^BKJocGFrrrоM3hiU & GϠ8UCgQ(l:Vnm썙U#g#AGgoz-mIߞ#`!Eh;mX?XGtM8ꐝp.}ݫnR,ۈauRխ0yr&x* IDAT.Zw=7=})2).-M89r0y}=B-^nmӍYY3o&m{=!7`ʑq['RZIt7XӜ;!@k; o?(-޿tl!ށ1dL9FLHM/ d,}pgzǦKKcQw+ywsb!e]ΦQb}Ӳ;v#}H#/p5n#~|`]lݒ۸t)e}\JW%ǰ\C׭[7Q7|jՊ~OEL4 DΝ#:/[ : ;rq+qP^RT"ZHoEʾ/EI hP^te.AA>Zkkc㰢"MIaJێNTױ:l>t ΜmFСEMa-[@~ys[M|-ɃmRg s.>5]M%^{v /Q>VN 0ϯ瘗0m=ɺC_&trGba,HDyH 3hYYU}z /=ؚcUu,{f\u #`~=ݯ?/>&Aop]nnq?!+Yn'uYݒ[VJݻw{Bqƀ" 4iN#nE[vfZ%JGF#֡xo ر 0?  t\NY%Jv벺%dEXPq[J]g߃v{8 Dqۭk?ђETFFvvyihݖಭ رn60FC кct;!.N@'II~O_B;hphQDtv쒎4F IIhO\l\' O($96:$>#`0F@AC4<_<۵c]a'قӾA>f7F#`BFk >׍ lW;wJJF#`p Di +q%v@ #mV7F#`hOh-oжd.7h;'th0FѴ?b/n_ 7mWJF#`@BkF>mhm*bgF-uw3#`0F 4AZs%.T 3n:6#`0F%'uwzNH1ǥk[W\iӦy (DC AVVV$7AvjMeyp :]xM|ͥk[zK'2L~QTG}Ϟ=KѣGS̝;O=Ǝ-ƈIܲz!<7_p==jemJRр rM~Gjo;v%SGB։"6wffA0F  lL'ulVF:@sЭ[Wdwĥrբ8^MTwfM^!Gk͢?#5hʦcCǧk:NF4KX߄e7BkOH>?s ku}d 3UȪ_>#K>jժg~q׌+@V֑p伢|Eu#ȣPq__D9:2y7WɊ$G c0{ =iI_Fx񏫌GtEHW%Vt]ůKDBv(..`hSu[? ]z6¼C`k7L^\tHf-ye(庥 '+[%B+ccc9 hOaWˆ9k+^&do%f"NF.yem%^%۶{Mt.\8$m3V^˗ELay`E]VVϸcfҸ㼓{[:OMTMn#1r0w`񃲑5Lf#w܋;|Ƹxh cЇز7~4xji]^\1u\sV>V8 O_G+l+pk1? 7`~-6#`/~;u]Nd~ϞlN& G܉D;Etmذ"۲e|=%vŻ Ḧa|i|I #u3H<=0g㑹Ѐ\?O8{\#Kg\1C% Εo/mէc+i͚ٲ)2x~cWtsuZk íW@ZhhJ7_p>&?|FTH7@Q=v %KDRڱ͛)}k?g'q}c&-Z5(Ic!Ao˴fhF-i踵=li9}͇i iOsl~ t2Sg5iF7F$v>*[#'Vh]c&8!7$'>~ P<W#x)^GK[%Xkt̤zga {.N=)FANCG;r1zn 6 V!z x^o.X` AДVrsGs_9r c-Y9ݼʕ`8;'l_:i\<ˉf-xteh&5W0v(R&e0CcQ#A{,u  G*20F@O?$Rų]p;-^v쀟-h<䓰/G+DauV#0>CäsOE1㮿㦧/E&9%7\tka u{=9N7bgeCWj%ӠuxdJM9r$fܖ T71wҭޘY44hц0wtyaܶјq14G5Cvo|sw_lǒ8GӍ1j$41;ws5uV/ZPHBo+Om!c"b?b* ֭2H, tnap =G:;ٳƠ+ zZiw-ɦ0[˖-iE7AwY]n!u.d.sX*9MI~>&ږ:յkWOxOFDԩxܚ6d]!/ACz9N#10FYnaXR;3"oXlXVSjB{۱!#L LkIۧ;>vS#bzg&#`π@eJ= 6K--,)هgbYҥ؃ʎ5bntw~~ƍE;A*I&t>VkmNGF#a y;04^0YU/`AW'su>WFxd&u_YDedd*BEa7m.۪&l#`~VbZxݧi?N`! / Ɣlr -łjc#`~vDg%.u]ⓢW\'b*ݝp<)]>?f0Fcn;ڼQ]zNmIV~;6+0F#+WOW|tk[zKO<ۖbX" -hDLd|5F#`~3nO>R.o0In<ۥu}ۙضm3#`0{?\'<^ )p|`=ѥ X'/Kl 3S^6j۷{*F#`^KԜqnKĆ.]d%yu6]xA{^ 4F#`~2ZS%u]$>߳'zO;xP::cm#`0FB c"J$[tt:tՍ0F#,a%:&<]:!IµD>~2F#`H6?!6)#+xK&>v%>gH9#`W !K}ܾxW\ ;M?[x7F#``~ZChM!~疱]zbw'Ni_b#`0.hB_4}%>DWHwDF#`#M[5ږ,&m_N0F#@ pGŝ֍w+c]AGIƻJY#`01UWhxݧ:XEWL(?f0Fcn;ڼQ]zNmIV~;6+0F#+WOW|tk[zKO<ۖb50F#DACy:S\Pi~Lt.}8o$pM7aÆ];>5`Ϟ=Pͦ2Fy2mغu+xĸi؏#hz܎iWtD'';g ODg>1 {<:8N`sEfȇ1-d;NThq剼Fo+ēK[(\1'V )|Kn˷׀wGc{|K;q|NHSnˀ;9'x"=ؿ7"(hO^3jF#`~'}nخnѥ'pwR/O_#x QL+]n:gxƏ_ z\t2] =S >u!^ ֬[_.x3_.-vj;j\O*Өg[!.vz7,uaĆk8J\OQ2mqS!.c֊1/J4E_ \vnk8a!=#7E ySoُ9E-Ќ֦5]+Y$pfCoJ#`0?_ѴZ#Z|Bd&m_$ao釗Wo:Qx /鎇O}e`0#Wt8>,yai+GRK4len%e+UPWڙ3C+&S8YISx*̪F#`~Ni WĪ_\n_ 7mWJ.iuooo݄3~s=D {cXW>˖#.<tP v(,)ĶmQXvP)|w_KkWehH[*uJ"tA.F(wv #]EAc#`^N V]5 }ڮhm*bgF-ud+=Z34`.SkٝSsq8.7ƁĮK;طuSJ jX*22XUlnHZUXH-~]JU5.B--Z~~Ʒ.#`0ؾ};z-t-T&X? IDAT{nwvӃ9lg!6>6ypoM-_+20IEonZa>ǥkϦAk[U {O3; 8D4${Ӛ0F% %_.}n<&>R⵭RWtBcmIP۹.DX#`0FD"?ݶNq}"[|IЍgᮯom#`0F!j =>=Ex./䁃RNL9㵍>K|f{\mBC_4#`B@߹gxc|&*z#x ]#" .Jm.g^D_~%Ҽ?sf&bFfF DEc5P_Eh_|M={EWP::'q'fݻf&Y0F`$W~ǣ?tLXD瞮H>=Sn]x#`0F YKtLy+tBkӉ}d,+0F#l~ClRF%W^.lcnGJ\#X0F#`4??DHų]p;-^v쀟-h<cv#`0F0?!d?sX|vu.=1z][i0F@4]!/оWY]+h$q;"fu#`0F- mKrܯ}B'lF#` M[#VNƻڱ#sva0FĪ+Fitvvz+}fxIRq70F#`B5P|]B0;y s?m3F#`@X~zBk]1]mި.=e'ܶ$+vdċF#`'m+>O⵭R=Qѥ'umKuWJF#`H" <)O4]~Lt.}8om#`0F!j =>=ExDL8(utc8^۸#[J#`0F`&'Z7ŋ\e<+D$Ͼ.ڦ/~V#`0F ,)bt6 {ddu2AuN((>NX0F#`GHÇ/]:!Nƭk?ou#`0F$@XuI8xENHpm:QOe0F#`MOMHD|+^嗐M}lHK|$3F#`&h)yxknǴ+N}|n0F&5'}nخnѥ'pwR/v+0F#+_EW*Kt$A>zG_۬n0F?ѴZ#Zߜm]nvO#`0i WĪ_ixR;V4x}nۮ50F#Xu(<}ڮ>[Ut4ό/s[>f2F#`@h3uK\2VfPw'6ugmF#`KOOh͡<ﶣ?Qѥ'ۖdlx#`0pDmyGIU'*ΓmIP۹.JY#`0I$?s~: f?s ku}d 3Zi0FSBKFx񏫌GtEHW%Vt]J#`0F%5_ud~ϞlN& G 4F#`@iP%٢K'ɸun0Fd?.1  IM'4F#`@ IIO\y+Irm)qc}F#`CM"%v혶xEWItr~oٍ0F#њB-cuc-ļNҾRwn0F#`\tkhZCJ|\euĹ?GkՍ0F#G ZkD3-YM2p 9#`0F @4mX;Wj*ύwە0F#`b Ou:G}뱊Q%ynKLF#`M@tFP.AAv U* 1t}~l#`0a 9ttvy'*Rpےvm/V#`0F Vb7>׶JDE@y- j;^)1k#`0F tnO>ҌGtMf2IЍg㸾n0F#)pxG]2yԡuxmnla_+0F}@`*~Chވ/qHI~2F#`H6?!6)#+xE_B~6INM#%.|#`0~Iqٮ} ;NNv4 10F#`2ZSe,nl`EwISWꮿح4F#`K Mkh_.8m0F#`D~Ckh~s%KtIF>6G#`0F-\~quJXEWvRnRr0F#`@ bZ4:^iNGho=V>3J$m#`0  КC?(>.qXEWAݝpw0F#`p5nO"hzqK&>v%>#`0F@AC4<_<۵c]a'قӾA>f7F#`BFk >׍ lW;wJJF#`p Di +q%v@ #mV7F#`hOh-oжd.7h;'th0FѴ?b/n_ 7mWJF#`@BkF>mhm*bgF-uw3#`0F 4AZs%.T 3n:6#`0F%'uw꟨H]vmKbAI[i0FX z"H]ݶ߼$^*]z]Iܶ$\{Ĭa0F$ӹm?J37y$A76F#`@_$XGt䁃RNL9㵍>K|4F#`mAz%z#ZU#"M$Jm.g0F#`К/FmI|PgO JV'T焂#u#`0F x􇎉4|(lѥ҉dܺV7F#`@Z蘄Wt$ צut[XV#`0F ؤK']~ $96ݎG>#`0Fh~!H&gvL[+$:9?[x7F#``~ZChM!~疱]zbw'Ni_b#`0.hB_4}%>DWHwDF#`#M[5ږ,&m_N0F#@ pGŝ֍w+c]AGIƻJY#`01UWhxݧ:XEWL(?f0Fcn;ڼQ]zNmIV~;6+0F#+WOW|tk[zKO<ۖb50F#DACy:S\Pi#&3$Ƴ]q\_F#`CZ{}z<..RwK*㺷؉gQclom9g]f6F#`/3H&R\>n_vr'a쀟͍F#`#5Ok >׍ lW;wJJF#`p Di +q%v@ #mV7F#`hOh-oжd.7h;'th0FѴ?b/n_ 7mWJF#`@BkF>mhm*bgF-uw3#`0F 4AZs%.T 3n:6#`0F%'uw꟨H]vmKbAI[i0FX z"H]ݶ߼$^*]z]Iܶ$\{Ĭa0F$ӹm?J37y$A76F#`@_$XGt䁃RNL9㵍>K|4F#`mAz%z#ZU#"M$Jm.g0F#`К/FmI|PgO JV'T焂#u#`0F x􇎉4|(lѥ҉dܺV7F#`@Z蘄HsNMD'~O_hX$~uvmGC)}dFسgvލ]vy1jJJ QvmԪ .a[U̝u Xjcc B~TTQ0#$~~s7RIv)]?vKՃ$96cuwq? -ѷ}Y_/|k0gǸ_ܾGY%yqFŪUn:ܹ3yG[.ZjmOG&M<Ȯ bǎ͛m6QIaÆDvv6իW-"ӰI]i<cʔOܵXb o`Aq~8LMgz}&~!H&RtS>n_ԶL&v%SqS]R~MnّN?) .nIg݆M-7J~Sݸy+ڎߏmRxGϞ=ѡCdddXc޼y3gzꅳ: uԉ'˗믿A6mxBOZ^֩S;N\"~ɧ^.dWб%4L 1;ض˾ŻoNjV⒋;>Bmٲ dˣ.zD(2ظ:إ.v${+is)K&+.L."m"&2D׽ƂkW櫇nlڲ xeKoهO8kT<#3I __JOOFxGыi7.8Dh[jԩXt)4nܸ|YOE'gpwg ײewߡ_~HOO/:6i.íT==wE[ic=ֻDȗ#m<Ə?];= qm $SRR=dn5*GSNJ 7cӦb jhHӓuf{UZ]0W*}ejݺ}NO4mER)`A#]>8n jN1}V~>>EϷCOJLé'LL%ډ/%7ϧK @~6>79-1I+?l%ڶnCB탏̆qگ5| xwJ~؂mw`:E\]+,,̙3KY-[UB_ެM\a$w{tθpu,WǶճq@GzLRɄkayx70l04h lXbwC~F "G: 1GaQ"tլ'pH|0݂R ŸS(LBWۮ:t?I+,v#;9ڃ S:?'ʽwNtXR2PX>< Sv0ҡ}XT"~yfUI W͖b棵h,XǘID;?xt]2(~tN?b9Im;6W_ŃZo\=5;KO:AZTMcg6H/Wd[H|2o "}A FGz'~Qjيanō/.G:,ۋhlPV:7sKps;=[*Y7YwCز7v>m.Ƕ Gro,!̔O̸iӦ‰ߠq&ol~yzĮW7 ^ҶІ$ȸ9Q :mlFj.8shx٩fqVCB|k{*<,xȽp0Zk}UӞV01hHw&gdf)L-[4+IR{ϧɅ8t4?3_͟.Og8E_LǕ+'}aW|wmUN?cFqga\:gLhJ;J{򹽘DKuizy﷧CLJet9nLhˎboվiHe@Me7.lUX8)rhR_.=]QڬIҞs [n~׈/br2[O0kpqٽ~hsUŸۀGtIkS'c.;%>= >kp1&h\__p a$ig3:~-Ffm؟ 4~f/l>2~5h7w ƻ\{fN}=`D xv֭%z^fj#`68{h 4u<>zkZ&Av0꧑hɥeᅢS@q‰=8"`̘Y{,b_'a>z5Y5ђָc |Y87q̜v#f>YO=w}ֿu' G01Scl Rp yf`c<{IG1x|h{:svP5-N"6~FϿTJI@J[ zԪqPC*n}OFblX @t5̿5}?bL~kWca]ګW/;hnw t+NT4WUݨhհ:kX~΍tbsF;s]/VRwH9mKuG+~~-qM}u=J?yahH/*oNqgo2_p|2b'}}O㮫35_{Ho*+ .x/>q㍩kȣ}W^2$FǮ=2R|&6ˮ~GJ]̒7.L-3~^[M K͏7㩙5nNM4a!Y~pˠwKk>Q g` O B'-]Jx̝Kfˌ?x}=~+ug^;U\CGImVw8j|hI⎽Щ((.x {gdddK +z]_^;{%i:0$8kP iA^:)jM'JG%RBTzc bPu}9܎~~[Ns]s7w0|SEj>ؿ87G"vʽ+xjޅ;vjqx^?! Cq[k]\G,-,o0Nl>wnP?Ӻe'V7`W+ߥNم~> /ԋ? {bG咅'/e_Zx%Q1m7Њ()83SPV83+Ц׵W1|2zsZegzzÓN* s@֜زb]U-nqF$'9׼E YU /~.4=ËJд rBOtAZ=̒zhP\O~ $Rj`Vo>[{n8IqC,cju1xp,*o&_^Wn#Cnp]G0[1 HnϢ^_p>z :skxP?U4=BO1jQZ╞zt^!{"s4NZ0[tR;6 z%7уkcoӛHqwu-bk_Ӄ[!TZ't@JHɈ]jit[}!i^~"Zj Buʃ~G9%$։:KiG%?r-xWdkӪ)pBnm~ɈhZ$BoK`|Aߤ/YeS3'z^*p?q)]/~äu|!AVCӱ7r.>~o)$2:CVG_CQt'R#'x^6d}܉eEx^e4&'y>xėΙY81g^aq r-^t qPA8'@ ӷBk#e}_5q‰|.|wmZf}c'g+1t;CcV݊j;xOQ\5< ]UϷʥ_l~U3֖4ꊫ|9|Q ڊc!\<?Op4O',|:$xr3c0 8n|E 9^e_l[¢^_(u/A)$C7=_ĉUcCڅ{,Ri߾lӨ{$6CDa?d:f~.xgz %I7H;}'8C4G+\|}8!nC7!?ߏOZx%,v ńw½W cbZCC[be=Ѕ>yit6 ;'Ylune|4d/64N-z /Gqvehr"ᒟ|boSn1Kf#I}@#Rle EC1~'fy𤤴 ~~7|ѿ!^z yNUFգbWXEnVR18Ioh{McXհˇ7Գڹq+nGky2!.CbIE# 6K-6.:Ê]&msvˤ" 5jV53yE.4ҿ(^I3nI\~^lִR5(((G}\deey(8HtѐZVl-,Zہ:tgRU.W_vGwXПv!U.o+_=26&݉O|,Xnٲ_|ǓW1[q}&)7&|#ծuJߖ=/J;~xO RKrk|/~KeAu)um~2۹mIM?ݺhv[s}?Zz7}WɁ?=L|?\m ~ڠ5hJ'JT^Mx/+2K~2[fmU&Mxck׮>UigKhyF&>I,Q%`8z6lL5U5tzΗSP_սUy:%I8~j =]Ek核 4ʬ|D'8'|i'GS ǗӇ.&Rp=Hh{$?gͰ!w$NH':In~O%}{L}5&M~6:_7RNOf>XN`9{aڗT1g 8sQpWVX-y͗H* Ν;{uĨ_G7{bնm[m"us*,5N 9449/Lmv&@/ًt-X`:7,"≠7?!6)(JM'lݒKkb6{lVfӥ{/){xQk/= ʂB: o|OO{WRW 'oLYYY,Vs ?-;Gu# ƍ1X+5[̌/sJ #|pIJ>|@xeeyhܾ wlJۂ loV>;Xˌ"_BˆRח-ҡX`qm[g߃v{+is)K&+.BK.K)"`2)t6c"Ƈ:#cʿ >!ݹjeI (YLO|ۃJD$J ߈i&OD=m &| ,߸18Z=L't{H=~ūY~>ƷNkU%| _3t>֢E ﵔˊ$n'[~%Nbq%vVb6Uuocn".uGt /WdtɎ~{|l_aA^ת5[}{tA/|b7'q,u,Wo^轕^:y<ɾ' >O\V=q:V,/|>ˇ?'ѣH/TZb+]%bKJWpq79ձɄ"$:?;>͛ှpDvزwl!9_d'z~O(du~$cqX<1NUEAuN>96~TLJ|*fWM[~C/U&KtIF>q%h'H7Iy鲰>YٶwL܌QDSY;2hwv7ԎUj i'u+%g #`0F@ V]5 Outc]1 3Kܖ0F#茠9t]Ut cun0F#`Zs:hFOTt .;%Y $^4F#`@ UVz"H]ݶ$^*]z]Iܶ$\$m&}V#`0F _~]VAC9miǝ߷\$ȿk7W]_[i0Ft⋅#p$KED1xDL8(uhXf_OMo8rXxGsƆx ;S|IEDmM)W%B36o @+ ]~>pɘ1o'&ku 93tޜ7FCrzǭ@+ @+ <?#W);P"}mp6G#]op^ɾܫVhZV_?>*!g+9ɳ<5Z{_`yy3Cϯ}m@+ @+ `駟c+Y™D,b\ZWNt˯4+kg/;nZVhZoLb$`@嬡2Ps:tn7*f̛0fJ.C- ZVhZoY_~.ƫ3+Fmu6gC/2tᕥkM#&F E @+ ߨ > Xu"d[f3 w8w액+ `^+^v @+ ߀ \+^pppnl%Ő-&>9s<\?9Nͷ@+ @+T<u-9>/s1ߋ 9_؄AM1rnJ9?}b(3V=g5%yWU5VU7Vj_3I|qXMr0|n~[7}3zފ_a6axp046{3]X{[x의o3.O?p3 O?p3 O?p3 O?p3 O?p3 O?p3 O?p3 O?p3 O?p3 O?p3 O?p3 O?p3 O?p3 O?p3 _ ^ N|;XeOLSǬm\;ވfb+'?'FILl' @ŎxݵW'㝱'u^͞w:ʞ]{5{2({2^wxgxݵW'㝱'u^͞w:ʞ]{5{2({2^wxgxݵW'㝱'u^͞w:ʞ]{5{2({2^wmUy1dz˜!+s!O0[e{[vuMh:g_eGh#<\eOƕ9LsViIDATfq2ns)ϯJz>Y_,6n7\kzЃc䘸ZU[jOud4|n!(o\׵/X1/cC8c]gxr2/CseO??y:?犁csQ3˷vs9~f:U?oy^FLO WR<׋ȫ^<qel0%EM1=K7B^=}` MEy?\Zba?w?JlV"L0Fyӷ(YՊb0ZOfU+jmW>}U+ Q^1?JlV"3jnNs1sze81y5_}yublB0Fi=ubx.7pLdݽ_.5ĒKK,Ժ3g%\j}~ȳK.>?}~LY|`%Ę}|>crp3\y|Vk7耙WsSB^ԍrS~zx֌s"8xbmsQ.B]uԻG??Ql0j^EkL0Uc0.ȚQ<#[ߠf1s;˫t7ٔX 3[3J7KK2uJ.kcI,&_,3w5\:Ļ@4ix7W u?q\X Fl>֭g|ǭ%Ͻ`o+3=S;ܡr/pҋYng䭧'׋&O+ou~~Y?#G}~/LoL&气xvV~5s g{cxqrc<߲t `bE?5$}y9hϺgzc֧7s# aϪ;{bYaǮ=qGqFvڳwhaǮ=qGqFvڳwhaǮ=qGqj^`46z>15T{bp_w.67/?bnI\0{}O,\z7΅ϥe,8ɯq~}~Sq=租~~?/M#_L5s̍\c'V9]`v؛#G0vb׳ e0z|{ܓcj&>5v%Mo?oW΍>?}~P~~VS^73/b>YC sm_a-;jաpk 70߂%ܵn@E1F=/D׺by9r租3Jwy~OL1X^ԜGK.ro#?cxƧaHK7e5ޤ :f{]y`^l[b/_ծpgnFZo 4ZZVgdUm'f3(f^N<{O[ò?O^m8WC$ɛ!fѲw(b9 8>1{^X'Ƚ@kcvZ]?ݧwKi/F;D%*`C^ܾm}q|}?k-㳡s!ܰC1FB}Czp^ȩsqa5*7[VhZV)0 xꙋg=k3'&6? l›azbxs}0cjp;'^^=Xjݿv[/WP>?}~^}jv>߲-ggx89'nKm[{_ؼ䊑c9,g<^irsYs_;|Kqx?b`m@+ @++罞 s~g &.\>3fOr.5gXաF6&S#7c-q#=}1rKl AGQ5p֤hZVh<s9ws{c<|,1Fuf仞[yo-8:t͖&r!} < dl &> k8|O~aַlN=' k`*fe,sbLeϹ_n'&K?180+Fu<1 zя3#Ӄk9<1Y[qVXi~ ȪO{~x31X<z3_7Zӵs1Z4g⊑{&\+1$>ligu*^52voξbE@ brUϛ15֪5,3`Tl]zY徊Z'v{4k#jjݿ)hUkZ?XUO>?sWM3~VxX]bwҕQ*'sMlψFn ![.jd<VU͵VU7Vj_3gk85Ym>9zQ&V<5L* WQ;JP2׏0k&܌g r=kp3ުPH[qVXi~ Ȫϗ8?Iyq5c׬.G?78FȈXy7NƠuKZn~;F U۫rj-Ygx?3F֯=23z2a_Yr!WZV u,R^,>emWL|qƵkjֻ,oZ|~K>y~e>3XG>U\kOUnM㛩8Bmr9WW~+_ʯy׼k^5W~+_ʯy׼k^5W~+_ʯy׼k^5W~+_ʯy׼k^5W~+_ʯy׼k^5W~+_ʯy׼k^5W~+_ʯy׼k^5W~+OG|].O=֭bFucwR}9@?&6Y+^ngL]br=gmjqϞgO|d|g={2~'>ٓ3=YϞzdlgOg}ֳ'cg>{2>볞=[?ٓYϞgO|d|g={2~'>ٓ3=YUyUծb5[fa6ap5y;hhVZsVoy[яי220g=ԯ7ʚ+λr+ @+ | ;0 G_ 8WR+k&VhZVX :\)[J+{7n_q+ @+ | J}hK_9|ޟI&@+ SsK8|{zKnjZVhZTdax+ @+ |!jZVhZVhZVhZVhZVhZVhZVhZVhZVhn g&IENDB`testng-testng-6.9.5/pictures/new-1.png0000644000175000017500000022133712551235562017154 0ustar eugeneeugenePNG  IHDR]D,[xYiCCPICC ProfilexXy8To,c'=AdߗlYc`%I)*VR)$f"ٲZDJ3[zy|sous,|@?H&j`mlԯ=8kp,o0, )- 7|sORF[QC3`@0G)e[Rp9 xQ Ƒ0$Yk8ƌ]vqzRtGb%y{+M$j}^w $+0 <ïe8f?rhÉ;zV?ܢYA=r;=mo/± - ~!YF.zk P ChBnOSQibisB7cY2e8Zxo^1_~`dTAN"C3򛊴J@Ն#jE4ifi~S[DAaѐɴٺ9!kf6^v'9 dqtvlE?L &'= ':<-uYsߍP{R}\WēSiW_Ξzpܭ쌆oe'u?=7ATWs#B"bز U55j=zjLAM^\imjni+j~ûٙ%۾ץsuPpHh+̯$5c{.v\m|y{l'ON>}7}_TggJ/~&BŋK=?WRW}7fˀH*FA ϣhj [= ]L 9l0k_}yf?B˂B5"bKQRyKq2+H**N+5)g>b*}ȸZ50u' =̓ZZS:zOIc7M>{hfcIr6;k`aaʼnri8(W;󘗁~?~"84F &4> />qTbd(Ѯc<..|=>+J_ISSWQ1^tcԭwbfޗΕyp0ODX#l!O1g {) SRXn)SwIH=3FƟ[R_85K4/ԷƶzyGWM^>ꁔA!ahdlUkbcOƫ'g~Ș̜X9? _gqs__-(~(Ի|qtM|i 11Aa2" ɉ|">QwT}ܳ* [6fC,W''_ 5Vb8zƒc)i.鎃gpr2E˫T(P$(q(T:,wJ5<hs Zz]:XS , 1Ff&,&Wl4/[Y Yg'(lٶ%8su<dW)yE|d~y_{z| Da}*&LBÁynbd/ەkW>:P>hb:6O+t|ԍ-Lfb^4X7g^Xo' QBDMCCyND,'#{ĥ#q $JHɽV(}f@vz=l܉gʋJs+k͟=e}T|5ݪCkw|v8a5qo?BϤ~M7?z/XX Y_w0oIn ;P+0DD oHud(9CYQ]p a*A &jn`~ElZd:vLz=1 3L6~6l~`Zqt2Vc'Ј-W +#@PJE|tĶ$Fj4O&V6SЄ_,R;O8\}ESBvNA+c!gX-r-|3/w8&D|uSr?%B F 4>%tz,Ǟ0 [|HԞKu6-7'3\nOfme߻ϖ{Cr#bB2+*UeˮW|Xz[KN>|`0qTUϛ1w:G&ݦN[}ʙ"8k4=ւ‡X][z/_++U"ɫk^k777\6766ǶTm-llP/Q a4v_ܓ Vbb <H6o-8Bv[G7ƺ a/MIưƇ``cF,~~;=.Er Y" `?2^붐B̭` Ph7"O;6gbp7Y?@ xw &}<^ ڑ#e?ZRc^莎/uϑ`[ہ++}mYxG^ofnt; ûѠx/M8y %Eɣ4ZRXHP( T>Wwsp ?Ap [?r殾ݙG2Cnݍ8`98#8@2EGaGEV7Ć}ypGpz|bYoKRX=KC]d l#;o%|ͭw~tȥ$$ͮ~^;#8@6"dO[tr9˽E\d&q^;#8@ȗcIzY6\4_-ԇm;Bm#SeGpGضd#8ؒ|D!-/z$ua['6tIpGp>d"9qPu>l/NI}Tg",9u NmX96A }r-FI=[?lsW~gcuVSm󵶬rwfI^ۜem$k|:*iþBxM?lxv ^ߑLmqa~qEC_NcC]vRN me&g*kö mqmJWGpG0BR7S;2sm+6ogmrd#)d&gKqbþئ}QئOR:m'աNS}/vRC~IuTmKC?l_R8Շa[?l'ũ>Ta;)NV:Iqö%աNS}/vRC~IuTmKC?l_R8Շa[?l'ũ>TfKi'{x=SQKt1qI6Շ5 uaۦgS]=~*sV#[??J eڒjdSmV}.c]/lmm*'LڬUOx"k|.q>_8s ?>~gcKV굦^eCqm \I,#'39y}~2۪SY$IW]>5cK_w'߿?!_|[93jxm'՚ShImw m[eu0m2meYjӢZzmT/y|<qXIoNMqX?|ta|tqq0Nqq:88]88uo.voN:7Ni;7Na SӅqڎөX8m?|ta, #CZ}qviSW]ck%ڶLĮ"Q(kqlڶv KҗtqEEAMMMhm%^GpG`gG~`\JX+q: azC%.T YbJND>V2k'N8 a:׎#8#D 1T s1t-XʥIIRrEY GE*GJP_US]( ;$Uo۔.$K)WK׾mkqm'`]e֣=RlkkCss3֮X݃Xhܸ}I8|8 +g-uuuxױaD _~g}PSS.o'\z헱qp>opcؐ49#8; ro^$HJض\juG kڶ5YcEakLEmCYua86mkM}FR!agXȣxvW:G̚ǪUYX!睃Lf"I˕K.o>ۧ/$"ˣM6a-{アsi3#<<0lT-cahiiU`h҂'Î͚g&wGpvF=dޯEE"ċm[ʹM?KX[]`?r]鲤a[uHɦ$*rq.s߉vO'6Yz{p|,|ȇdċ+^Ikٲe5tP 6 wE!YrȇJfeDd=~[x!' `sc~\̓+SIcؾ_ \2(ڴ&5lL?|*vG C(٢:-eM{SkZ팣>cɕti'qPgưVJtj먹 O*!Bvmikr( TE!##ŕ+Wb]vIWuu5JKjϥDeE%wGIedRVL~Asڲ [6z3F]#c+"߱{G&uzG`A`Gc`Ævk/ӳ;#?"ED+EաW,Rcu>%]$Ve֡lkB>ӷ/Fɼk66T 6ա\F-Rn3𜳢>HHF1=`\ڲOeXJ&Q.0T|TS'(֥xqchnmĦըPa} <73?^RwvZο~F]\E#d> G]5IyGҕ-%FJt3=PV?ڶVP)tq2,:)ڮ8;'B}\M]ǕbocD* #֭Eߞ)kh//Bd߂  Wj%AyWZe_Þa̧Sˊ\JZзJn.e+^g4Ap{V ۯ":Jc~?|W~y|K1{[&rGo xt|x8)Ns63j1amK?D]lv(B(VORdYئT+JW 1*+P#\6H%rr*U\ /jo"n_$YReI9lgZԺ9 }V8"]BxgZ<MTy+vs /_hpp{Zд 8'&-r?=bGIkwoLGOg~w Fӱag;ʂ%83o2<4pi] 8Y 5,$Xd,k[eծDmS=}mmZ[['9t MCU6HL5'K;k{u2XRZx*mI >擽Vѳ@Y*oףoC#*P"g+n,$^ꛩ2ɳRa_!heU. BВB}Wқۄtտ|8q&F4V9E&,#&<*Κ0oiH^xmQ˞S8@V{q"-$[JW'CžSŞD]?#ZBY۬~Sr6e[>HGlv߼Cb![Ed3rVz5jf_b9<e%3E2ŕ.f!b^x 3:|._߄rJQ-q}d#~)_/نͩYjUf41Lb218?;Y4mk`MƜߎ{:\"Mk:l {fAֶ0q|-UynܯQiKm²+Q:0Kq-۸ߪ|AV?߹667j׎#"Ag^SRE=ۺ^ uMි*QT4>s+Dd_(SdToe,d]#a"<+OpQ1<.֮G1 2W dͲ 0CZʡ=מʋPV\ErYQ-V ءc.] W6rWv7ɗR&\3s1_f(oNWu\W8nplZwl3S&?̓Ѽ~-v;\?N'ߗv_#  N*` zOy/l-ͨgY|Haф-.ƩmEWk[]?9,} l׿F#o5`2c99D)!+~Tя]|ǢOO6YRXQ9#jȚgXw/0r=Pe\~g*/0 T#yzzyu֨QXڌ9xhk=Km6,+U9{&+wײK/##0cƌsdKJś2V\M]8ưЮ6uzQʪcQHmme%Z)٢̋JeRՏ5/UV߱wylg,$4vq #.{I)*+'ټ ke"\:/8Wp z1"o hclKJclŹ$qʼn$EBD[.[:2'ԯ[.LOṷ3nuGpv OdITguzwpԟi.ΕthIZmlr&]:@!DHcϤ]8#$p+(S/(sKQ8kqvY97JM&D&+15}B_}yqGpG WX[rkuq] 6%\ɩK8XXq~ʬ#nLx8#8VZyRKZ(WsVu$)ҋz'rXӗ}f\pɗt% ɨ]'zۦ,kg^GpG`'GEH $Yd!ZAQAu*(+3K9fGwH&cj[k)[ĶN6Ҧ{qGph5,[(,š,^â<*'ڎ?w.+Sm ]~vGpbd-r[2-EDiS52-=`iY||HjfsaQX80ێ#8# cOYµB(T^h%V9r VGhV\q0m&B)RpGpvPHH\zܻŕ֑"`Be<^u"v'+ }ĩyBHW.hXW%ZS5kGpGcDيvAҁ0)P(a׶[bQD %],k[6m6akl["ƶ^#8# p,3'[9;Z{^r8jV?XM{ bGيф!bEclu8#8@<7ȖfYlj\(fW*s9ʬzmgK}d#]Ih25d hRL^#8#l7uߖN%Dnz\[2UVAAâ,I{=]ڇFiQ[sN)ڎKxQ}\]tuXz.%!P?ٷ܂^XfêexeX-\R_[olX2<޽#8@%w+>ynXOSk4m[[+Y6u%?jBIne.:G:sƝ5 O/^{ IDAT1&2UDUmEyvDwxE`ɦzPcս"WUFVJީ#8ÿ>Z4l^͆7|1qc+X"Ghj8r?vAs$߁֔9A;I‹hزfŻioL8T\rHSw=& 1*䳯ǒ%̾o>:gO&J`ܫpڍ e9W6tZٗq'_ůN-]6Xi}H{/z| _5/H0mdL<ӦMg-d0GIk0y|:g:.OƜ|6n;Hgߺ=FQp ?GpG wg)¸7ʣB~d(.%"\<KP2ff5wȹEݑ@?kVڴۏ;cxjq]5¼{Ƃ9WbCtEB&ߥ󿋽շ܃[>{Ǥnοj-)[kȣ#^, u;VwĠ]p;b̙)yפ_ GOnQZ'N> _983g[5MY_?>WM]kg9K(4y gqP- a3B[9[n{qGpxh8ij0acƺH\(.`K3F&h }-7z+Ƕ;%6, mqm9X-)8K]שX]GR?1WNʼn;WOyx˂T&_]mu?_p&.bġ㜈󝅋Gf~n~ԁs 89, 0-h{%zh>}.8ܾNpGp5?(&wRlU&̣(:GEp8䟖o_0G-sΒ~d_/ǘ淰ƙ"MOy4I\5_ãsM./-DŽCGtv>GO9$ӈDftȡ͹75]tMM8BU']BX^ˋh8H1M$]K-T|y.0Gp>*kCTlqO>6TJ~֙8noوF67#D`s`,zj8#{?StQR"]XV4x̒%âqjӶvY]'&ʶA uVrXӟEVgvt)G᲻ǹ֠Yx/ӧ p>~t\q̙ɾw3X.~򼐮qeW AӧKWj:utyH8]:U6뮚+߇/]ʽeQNWUqpim}aeeh޲ukg`J;G4yV\kr5IQ[[+Q-BZQS|<<-hܰO9QqFq.($mY򅳵xG'~{b|ؾ^7G]?>ې7h5zDک5.kTS ]eB:h#c[k % R!aY~!P#=c+㬓[k uv}xk_7yv?G};?d䛊ZڸX/Yg\115'UIT%.Z1/J:\T.2G/hE]LkKT:Q)䶯L"0>vk۱rie dRt7i$}Gǯ_m]옥B‡])욇kGpBڻmQ> 4("^6~bgG0WMWᙿ&II.*&x͹.te\ke:+ky8#8SLh{IIH3蔇1)YLaH]Gp:蠃$֭ޮqXT,{0l=as 'ZSE}rSV%R,+\wO?-$YJ"7qiraVfN(+ jI&j'ƻ8#81۶V[ˡD SYjEQ*٭-~e}u/9z}+C&dM--]~(;Z8n2NlBBm[?kGpGH@{?b36T'+vl+d)֒Jz^tp*ڏU,,7%)![ M$XW֪KA}lYut%䬍:Δgq#8#S!N[4 oŘx5rJVR^V@V$P=,:URF,buqCu5NkQu*֧!F+]Me@b}sGpv:>.{K-]oQuM^+td-!f~3ֽEIҞcVspGة[  ˓R!TeBq9D*wb#X+MHJHv2Am衠l*Ic%$LOmklj+rᆗ~$`TפIS+L2h>9%N#8# FHW"6 r6DI\ J/h>,•J5˩rQb_5EEu-B56>eOG\ۄ8]-L.lk׎#8#@SS|Fde'֡Ǐ6ϖRҒU4xEzY9+$:y1vVlN U.N+_^Sb,6O{?d~/ t,ky%C8#D+]rVW<:,}WhEŃMe>YsE쎗]CQ+乧Ķr{EYDú<#;?)8˩ΗtiTfvRV-Οz/#8# p#}l%[yyt¼|+->r2`|҇H[[ӫ\WO %W9C-Ŭ%]vua[U}xpGp <2,Zږ);-J%/Fݼ^6hK U.9^ZO6?TOʶ͸>֦VI.2 ۚSV}ļ8#87 *7m!ْ=24W7խba\%[d׀l{}AL]3-7>c]< FTO~BmGpG`Cr%A{ `hq؈lP$vQCE}o2oxUrEh`ӻh) GMTW%>FT6ճ|藵BlIĬLM^c3M$Gpr9E *ţo0r+"X0yO4xQ*礆4[?LL3'^cs !]:d5yZYc~^;#8@O'/ڻh,E=on-yz(UV#^Bֽ\"Ebza}64?.4>cLOdm2I2M8 7:#8;$]er</no/tʊ*NJSF2'qm[#zǣ5%d4"\\-K!dʕ%oO.ܒP~6eGpGAJ|϶~"oV"Чo|HՀKlOEٷquLW*W #?Wacm4rWJM#IY{hm{8#\xt*ǛFKhq+ ْ;{?Tu&>e_(#Jq:MڨLk|&9#8;NjBm\V9SBE^ @]PkӚb}>'V:&%%k}|\8#TDe_dߖGFUaDVM7\ 6VG{*+tUF*![2d*vNҠh䛳IMN@ٺ&j;upG-W1FzTJr7suL^Ü6)$/J RBeK-6E{W(T/[RqEɫ-ҕ4$I>vou.;#8;e{ʄmmˍo)r<߹g-B~B8DpA7܈ 45QRo;!SJ8:P64-ִ>k6mHWd n}=pGqhmK`o/V~ MͧMEdP+eFY'x_׈rTVM+ uBSr[L,,2_Ȇ'_eb>xc*KعMV{¶x8#84$/{NbwfwwKZ+%T6Jnh[֯nɆTK;n~7NK"EH:P,0Yt?ÎmY>I6.@rPh&W9.#8  WQUU-+\ :޹.-+GyyEbyYZ"nX&Cb!]RZRKVZvM Um7#r1h'\ETFh ٜ:F>]&Sq9\: NʴSpGI\|XQ˾2ywaxU\$KV߱D_rU- /Jh[XT\jn)lZ KWzsU.yoU]mCQtlF.QLJA,2>%]vua[T=VVkkGpG`'G_Q6c=]Mzf!_q K,y?bT :ʶ1廒QUM`1_vxwE0 [S BQ\"Q^v-zeNyR~ V-H%a˞50a˹huClcou.;!+s Z=ewJ#8#vY.!؆LFUR\B|Rhz[KEBuP^e}$DG|Y\mBd|YyՏKڊel%dU"p>}Jt"Tlg;}Gdw)/.1|33z(4’} eMCGYW]ֺ7xցA'S7{pG؉ źk1hPSU*҅&Az.:5o/LW#}ɭMjj9V/ŕ6ZZ[Dj!BRMhjEVDJJ&QVU */Ꝼث&M?3XDeL&feki"x8#-tɾ+y-t"Ĩվ㐇"QT~-iG'ӞmeXCXVQuZk͛kWݵ-1&gUȞ1"%ċ[Թ:SqCQp؜BHW5YMVXƫ׎#8#Ё@K`1 aw/&wRyOcAs{T|EOx ( W0+Z-՚U,>"LIPW+6O6JV葦zӦ(U暭<+VQ]%d*"]vdq1H;6%?Ncr5>oOdm2I2M8 7:#8;<ս ￿sNHL=5FMjD>M| 1R|hX^U>}P^])zUWJQ>̠#;9Pb|V_R?v2l Gpj³ys=6n{+Eհ 7bz!X#V%IUr"ʊ*,m'`"߀&]ȩd5&}nr_ᢋ^.Q:ձ8.$[ۥ9N=jqoGpnKDծj6WF?j= ]uQ/CI 2w|fKwzW:bU{C&]v`N U9W׎#8N@O{"T_6TJ&N{[ˎ#8N@(Qf o;M6l݂HWd n}5 vGpvd:^mwI6l"!6>eOG\+sdG킵a;#8#6w,G!6ڬޢo}>VΗtÿɳrGp}χr=Pl9?)>Iq9\: 'هMʴSpG)o'N 6O[a;[Y =KۙbZ#O~kspGp\'$@y cdS0qZG۬5:qRzÚ+dԱWYkV\w#8#8 ?4>5y |藵p)ߢ)SMʌ5>DrKpGpvnBaшjW-^ !]d5yZYc~^;#8#+SXX]\|N쑾IWR6$ %gGpGȂ@!d>'Ӥ&dɄ.;#8#S?,/1ΣPe$BM4ٶӾvGpG:/Q*t%䬍:Δgq#8#88?h~⩷>lU %]b I>wGpGq Er S[X&{tف9pvRW_^;#8#"W5TJ&N{[ˎ#8#![5ǍHWd n}rNGpGH@ G%63M)9o8#8# Q86X%]yu3kl㾝R+_5l{ڎ#8-簲''5.:_ҕK$6[8곗ŸhpܱpS7fJ߼ۀ_4?xrn_B<˾U|GpG(sXa;wtTImMVqN?rL9[QLjqHUDN ocvX/7‘?/#8#!$zqPkx$wtA¶&hU)p)x{ςk]+^~6bH =>܈ QoOɓ1y)8S .[&pY>"wϿ_߆|"<FOL~]?pܾhs{+GpGEsSB.t ``O~Bޥ=D7o5O⒛o)\GRaY|/xz Ce,U:XbW)"s&̿{{G㹿]4o9~xo>礟wo'i _3TrGp^D {6er!KOT 61+3VGٶ%7KG xy2X|f?D'6* xㄞ'S?|,T-o~~[&@ $wOƨP%܄N?g `r6x9>,>u=,?GpGp{:l_P]4&kuVx+IkN1B&r$n:w*y|Lܣ28W>.y=&`#qPB{J5JwN~|#8#ГXNׯ[Y'4>{t%%kIPR|It6|wQ"ۧ&Gm? c\<„~)44p&6u 򵨏hO%_IwO/bR믯Iz~])xu l+.9#8@!dJ,'Ӥ&dɄ˃Ǥ;xʑ{E} S+N: yT.{įOW6Əѣ_vFݰ+å4<(cqWO¨QWtZ:Hѓ)z-EOqQGa-F8#8=@:N*$lzOx\cvUTM?6q}W%6mBJHG|7JяAi`xpGpB@8#:m$>E]k lX]SrTړj%ec,FmG `}u}v;qf\X/#8#MIC9 k:L|u"uq:pGpE kr S[X&{tف9pvRW_^;#8#"W5TJ&N{[ˎ#8#![5ǍHWd n}rNGpGH@ G%63M)9o8#8# Q86X%]yu3kl*GpGprF@yFRVV$TzdDImL[?y>>,z-YFNO(.n=pGpz6y^) =rve9"OX`ea;[^YK*$¶& R_P}_~|pDqq{ A#8#{\Ylnv8SDdDP=)v@cou.;!+s Z=ewJ1w\OǰaPSSMJWz#8#гpOPWW+WFOnfy߿O?$>9Y2DjժUXv-6{kŅ/>}|}N'אs8vkluOopd5y&beMꬬsqG+\ܜ=\-Z'^ .>''5#8+`ҥDrヒ%K`*.~:y)¬?..>IIHӤ+)YL̄3Nŋca W^vX>G8}>إln_kY'6Ӧc^wGp>z6l؀~7oM^I缯Cac2iedBuaӧO#RK0MuQ2yAyu(N.OEEsr,G#8@pޟ|M^bͶx_KP֙xR+.8&gmv5>Od;.GfUIU-cv=af+am8O\=}]|Ux ܆ /njþ%iґḱaUc{[:;VW=$9]xg^4KY:}jaUJ` q;h<8 lCW3Eָ8ocLߘ>:f#8#PhZċ5Zsy/$DkOa;Rȷ&%i}|"=>͵T=yБPS_,{MCKm :X(^aO3Ua}VFL3 GX w#rV`HA@P  CmPsG]!C%qC1rT*s sT * 2T0j_DoOc HJ^pVaCk1GoGGpG[ܯGŚdm.qq\CBUC۽MlBv9O?Rk6Q{u6{e&κg1H?_qP' +j5sq9G[NWctUd )Sli2/9%Q戔8r"Yg`hs3N=b Gǚѐ}fJGpG g⃒.%\Ŷ9%iĈYIW8뺩9q$͎N̈́S塝. ?hs1U_g đUv^?>M$?u ye##eiVH?;䆴R15u! -ô[#>wK9W黨wI 7ŷǜ7]+'K cpG'>VTQO;H%gtG-B/ S C{v\r6!f0/W|ml.ǮXbϩy{ņ9L=1wunBY4Cـ.R uէ*y#^i@TctT*+r9oIJС̜m>2pGȊ@܉|IH>FF{v g{])Z#L5mq.Yd2KzQ^"QcQfȶʑ;˓jh-SyU!PƩf7qcΘ]tGp@l^/>R\%OX2`eld.ۚ&Hƫ^5Wvm%.Y91tWqygKlyO̖|pGQ `Tʼ@ DP=)vRcou.;!+s Z=ewJ ~_5]fMtQ>nʗGpG->NPyD/{9SBe-$:0z=c?<^^GpG`G {6 hce~0bLYfH.ci?^;#8΍@9,qC7ūAu!+]d5yZYc~YT ?lk[ܒwYpGpGPVurJ..>IIHӤ+)YL̄c'Aµ6K7"YT^GpG`@_U1w-?lLRԓdie[2gµ?h»`Qg\YAsGpG`;BnWRRv|T:s<$l1.G-.U*VB48#8= rW[e S,+]%Dԧ l %]qD)NYu)q.>^ }_;$ϕ#8#}"w<y}?ru8 mYYwe!N^:8]R/ַ7]q#8#|<;9|Y.k,P?u>albI'i'e}UU#8#8!x[l\j|Au 4M$۷[]dO̷ۡεѰn5;ϫiyvoK>^xo>[.8#ldqrl V$MvӭIJK,5> ɲuy%l9cdPpXix.^z{OpG-B/ ƇN|[y܄t:Ʌm鵚b;pbԩ߿XOPoqhX߀֯Ǟ ƭ-5c1sUx~LL"߯[W^| û p@ގ#8|y(6'f"9ߕ.@rPh&W9ˢEpxf(GP~>ǜO_tS+ ;vݢa=pѥf&u(FDOzAȳhr<\Ltɱ1nJK_E/eN^GpISA?)>Iq9\: 'هMʴS㥩 q 7Vt-{mmxѼC9 5c0Ax2Zx9fM,!/jނ܈S%o{ǕS:1e ]Ͽ>i(y8漿mm0km-Oĵ#8@ʜy?Njvua[cU϶ծzŊ|cǎ/:fa}Gƒ7Щ~7,bbZjj:mO~s~&2^0 w.Acw{Қݘ,ab? x.K#sU-rǴ?T56 8#|r8ԫ-hiuKlBV a[zʪضl >r cN6 c2IS'^|=_tG}z;՗`r;I̸N<=dp1 SS9r*θ+z 8 j]Y-Oe:.6{@xaدx8#s!?$>9!YŸsL'S7 IDATw]^^O>_~yŎLEҀpF\J:V$rp^M5X:xһG|2Yzk 0v0.ruK1 ]U5kеGpSX, 'ʅ.g {z/kc'g}KUJ@ (%pE7[g+jyL6snIZ'}evR3ԧCd<5[-1~{8XUjԡqlt=C7nrrrٮ2kg 9ΠಲAs̕`S<85CS`f^Z1`amAJ@ (%>Q?Y'pŝqYv'*.4c͇X֒?K$}joNt/42iˋDϫO>|JJJ¼y&?~ 9ظ٘E%1c2#|VXbkcWM[%P_ 闘m-dArq)쾌ҏ@~T*%PmIė[$}% |&7gX\*%PJ qMpLBu%* rqqG69V8GQPJ@ (%$7?XpK]8+QwYo5QPJ@ (%`2RSp6X;sޢK.L7)7%codz][%PJ@ b q]^#7Ҧ}%PJ@ -mk_/Ee[֞piw_ hu< $a~'Ol% #3֤qJ@ (%. ?/6*;G=<&ηŵdTV~ %?d TbՔH햅^YY薞uFľӑ[6P!Y&'[:/PJ@ (w QhF/}.W1wҜiM=iTWWcڵk׮ypW-Ǽƀ|u}n'`UXy Ꞃ`$Wo^GC2_hCr$Ӳ1`P(_UJ@ (%bpRs>MfX ƌE{AysNcg?ں:l۶ ˗/Ç[SgL>ueٿC]ɟisQV4mv<:#F0bKgQPJ@ (%`n}gi!H_x'']r٧1(gSЧy6V^iӦ!77AĦ1uV-Kfl't*Fr՚&/u4ipۂNXXNhJYsO7 ƬOT$dNF%PJ /!nk7bDYٕr[yFo';l;ؼ&L@߾}# $DWٚRϼ="1|&%Wǫ'gbd&Iw.A |D)q)1q8uõ6V`lv""WՑPJ@ (/[SHa$#OEYIJ0٧x.smZ<׈Asdda*OXZpF8I_&Wuu5֮] ?/j/1Z y7OjϚHz^J@ (%'EMOH!Toc3tϛ\,6H6vi+**l2޽ϟw]^3rI9] G+ g͸">N,eS7!#KPeط[@ tQ,2)WJ@ (%\zK-p[ck Ⱦn{^:l۶ ˗/Ç[.SgL>ueUwXM#Oopٵ#ebT8w 39jd WM߀>S{WGP HԤPJ@ H"S=v)v/ȉ|趸Ÿ@;cm?իWcڴim34SjyĘ]2`=T,|56:n#>.S߀A1?+_ŭ[RflowJpagzD+۱?J@ (%@Tɉ(bdg?%X&snYIٳ'&L}FQ07bEWٚRϼ="1|)`J`>EnYfzǓ][WeM/ᦼLuyժPJ@ [sH*n7\m"+\,OϹ&qv 7x# ;X+XGwdQٚ?f'{vUmك >ce<`WɕrgbD(r~#&CS^J@ (%)b_YH[tٓ{+\^:ӯ̙Ç .ZO5u\FUy|W2`Wfd``tVta NܡE8@ոciGD~N-30tã C !x%PJ m)_OdAPYݗq2]ae#hSK˭3+XE~^bsD^$Y5HK#aՀ=]=Z)Xbn $50&5,T$ԮPJ@ (%_!SZ#?QEi(}r,Zg=DT8W?s颒ȘL Gp%قAٌ:),(lLo%() ›PJ@ ۸&8ƞ8_|9܄>ɱ"bZ)I[OcѼ<:_0yxHD!޻/bР [7W<_Klx7OL<PXgx#4oI&ބ=X)'[<[}544`ɒ%ew,!+h޷hSAB 4Z}E7Lq+z #pS[Cm/֗`PJ@ ("'}DZI\ {̹l쳟yܦmuu5֮] z PAAv9 {Q~yuм| /a g_~FeᎷ1{@=?7 57`(GC~U]y~d7Gth.-;cAib%wv" >WC% s1`ǐ"ZPJ íOdg/ki|iK$=l(Xlvލϻ.Wk^Ӄ+OJϡg8z^Q>oƕ_qb]g{YH랃q#*)#QR>R2*Xѝ%< DaH,AdvK 0tV(aj펜!cQzdP>ל΅Nͪ^Z:x̓XU8ӻud 0 ^.) :ñV[|8n\܈)u9 N OƾChdq˚ pYkNFxe[O?㘑1Y@PJ@KH;;]nY >{;j\WWm۶a8|p˹)x睷N[MS}^Lǥa=X_}[wA}n̸ص^9ڱ'x f.3Ʊ'e\aR2x|cju ,:RƳqh(Jõ#31k~Yh za>qn *y\z e^=ʜ7Kq]8jl0 +v :K㐙#䛁z 3W`襃~_=lX9޵o̷O|t-x]fcn.J@ (7[SHaN9.Z'"/9qdr(_ڨ/×86Xz5M\b圔iV-Kflǜ]`L_ ~0I :PfK#{75~K_pϦCq3Ĺϡ`jḺfo?#18훞Cd,^Tc}vUݧoÐWR5ӬjG9>y89gz%a`Ĭxb|ϥDa"e0K"-ċ%DӣJ=kڣW:r 8X]DSzdi{fBFmOQJ@ (</=A's}hs\<>Js>}"mϞ=1a7bڀ/DWٚRϼ="1|3,{ sd4IqdIRRTMCYߚE}υ#Mc2{rQY5aV9>ddSDf޴(-01݊/-G@;) Sܹ΋ЇWi杳.tHgn1낦{1)FH6mi6F0A+aPJsG@j _YH[oy(Nbe1^}Z+qDv 7x# ; ֑\ %/[!s#)&`g5wcC͙P#6_inł´8Y2G9Ii0^\Tkb5hHN sCOrG3 &oYQ iSR]W`_vf_w I1.94pI2P7 W~cs2PI Ds1ȗMNjCay]߸?rX_%HDȜh;'36{-*}rq)쾌ڧ_/Ι3Çw\8t9k8#x .Rߒ=t!R>83 5F*hsedjZZ1UH5tf> qL#Bk>0%O5? Keweٝk s<{|ݲ!x\d1}d}ܷ҇[jQ߹"5vˢLF٨lrxIII7os's3U(- /*+ )%j8{/ŚƄqMOc@?97-nK&1/8Qspo7|2+&.{j 1WvpR?,T<&a+i_ͮS Ξmt槴w]V (%"5x")8}vKí-7JlmmTNyIQV|6ԛdN>~.!iJ@ (%L HKk'jkI{z8^ڴPJ@ (7Z#Vۚmm%"cm2wPJ@ (?/v+&IqDq:PJ@ (%@R22_]#cݵkr91]դPJ@ (Xgx%H!e<_m{ܥloSax'[?w ~J{v<:׼Vݝ k `b?}HZJ@ (%$?Nc|r[b);cm㊊ Q_x0 gb>o#`/T|e~1֩o,C{%xVT̕(#[B_uڱ#JqM,&c;0|.(9`!PJ@ x5sg+j9銶Ss>s'Қjc՘6mrss R/xiLU#< m#\)γ05O`PFwLzr2ܺ o6`7ǐ|Hl0_M*!=WV (%p! 5;BXe|/cokU,ƫOyGDk0a1Um6Bt)E#bs+럲i4qO3t'݇Az;1CXώȫ7ozWh. `nK (%@"CD[Kض] Sv_vw)=]:#̃*[!kS.;Yy~w"2cl8*o 75͛VsFm1lA];J@ (%@K|)5$rO- lܜcs{K^3g;']:.<>n&=<NgoC7n-7]Zc;zգPJ@ !?m4]1~jI[An6.N&-u3331n8Ĝ@oG&6tt][pq܀P&?% iYiX6ev6e|EtPJ@ p?XPyڳs9q87BCހk>۞y~"gPZFQIgL-K (%hWnZg11q[tɂ.MmQy|iiw+eEi}p5)%PJ7^ Rs>{{9W3 {Lse|ndK (%P~ 9dqucƷ׋r&1v 9MFx!5\{ネ'58y`+~@LZRQJ@ (%y%` /v{c-ړ.!٧E1(g{Da1hhh%KPYL-{w,!+XB y->WᴯIbn}٠=%PJ//!4=v)v9r[b\Ovر?quu5֮] z PAAv9Ǟ {Q~ =?A y7\6m!.X\i}vmm6,_nV1y>>ue~ KCr/Lp̼S{W3|'sUX=kNa|Ԧ2\6Kn+7%jG (%O@j J6|/{{"_/FЫXYWʏf}Ǐի1m46:xiLU#<1bk#q׳Moƒq ˤnѣPtn5H]ۗk01ݱ{ŇPJ@ (%`$?dN4_bƶť2Nb={b„ ۷oĚZs,֔"1Ofqź)+ ɗ!Xeø_?P4;"2*GpT6Rķp1(%?.9n^L(}r,Zx;uoÆ Cǎ[sޅ5O!-"N0;)݇1iX.4tNNgamW~x #k"od1(ݮlF}{C:VJ@ (%papl6☄$*܄>q9?ZLB>?^䓮ۑ?u\!sD'\͐QKw<{6gd~לEMˬܱ㻝s@0v[јĿ4vPJ@ |/Z֦&cl_q+ yn6dWL\L79991> 4 $Fhkl2;wF{# !5 )I Rz21!@ (%O0i8/"1z蒅 ]`ll4iRR͛Biq6~V/*t2&JJK &o5R (%@,]ېq~yjKtym7I~V}PbUEjPJ@ (%XMH+?r9]v6@~TvPJ@ (% X,;G]^Gۤ88(%PJ  Qh/}.ˑ1ڏWt5ˊӘ.jRJ@ (%o3}s6^gR{>ɮPJ@ (%pRs>iXƌo p7aXml*%PJ ^lx{.HK[D^ >-b@i># , <<$k1pii z(^J@ (%X[;DNo';yX׸>YC6_W:8GUD|i_x*J9UP8y@VL鐌nYY2n0ļH/%P_(I0-F{9='5YSKbFm?c,^~g\=ɿ!ȿ^Ծ_b{4o2Bo׵Y'`)x)s”BA1n\n>T>ƕ 5;o :\ꗣ׬?=j'-o‰=GZe=->%PO^zv?x7\m"']&bx}Ε6|kK_ r?>[K_ȥ\|RzE>B~3M ddjƙW|A\R>uNRxaٔs<E[]EH`bV`bׇ'1$Ez3/ΉmK (%@@j H6|/{{[.be1^}*+?&:<߹8x`/r:3 yS>FU/u32v}#Ζߍ?@yڅs7`z4֜>H7;Bqb7n5F(_p=JTZNؿ}VND6RJ@ (%&9/TBe1v_%B<ν]1cu iSl1dv{̩Xkh+o_pP]f 1݌F.B9y3JB@^zupN;]gLl= S:=KgkɊ\>ivEёPJ@ \K(G[E(QE(}r,Z?_W1rHwSѣ]_.]0'IBt)Eۛ:g=_Fi(.&N87y̡W9(9q~sGhv?8 r嘼"g K,pr tm=|GE I5)%NMhBc”׋nBI8Z-&n._t?:GΈ.竺 5#!aKf[4hrpnpo8}am`c>o96(jC_ k ˜C;̿ E[qt.sERPJ%kn[>e ]~l^XIII&LdvIWٚ?uZ GqsOpV/z8ZӋp]F;[rD痎. 0L,\\B@e #|Wȕ{"NoBd%Y1x.`WQPJ@ \0ܴoNj ckzD6snIZQعO-js?Ļ^߫:PX&qeybB6'ў18q .9aC0ajZC$!4]AKK ݷdᇣ&!Ŭ9aLu*%4 d^Oeweٝ֫={37wdsE9gcTb t66G\gPZfQIezJ|ˇě;JqmiIBFw+ң#%P/[tRkyjJtEeLBISD}PJ@ (%D Gipηc"B"^Gۤ8b1(%PJ  Qh/}.ˑ1ڏWt5ˊӘ.jRJ@ (%o3}s^ٛ+}œ=u՜響9(%P8QHxI7=!5"v=UH֊.yen>WCH?K (%h%[OxS<ث~Η~_/F$ܐS=l WpɹfPJ@ /!=v)v9r[b\Ovر3;&;KEPQ̅szwMob%P [SHadYGh12޳EzM, }97F|SMշl#nT$XxbW,1 yF74"9 I}|w916xlZ:="wRC#v6FSp{Qv y漃15@ (%@ؚCN?z#|&"Mr++moYxڈ#Zs/F뚎U~<Տ-g-,OS_ ޹3R:?G|}v>F<=W/%PN@j Ť_YH[EW>ugQ`[lﻅ<>:Uog1Nū4\ҿ+~o]D#́_1c{xdl\&VǺ'PֹN;R{gᱫb+S5Z >Qk4|d>G:?%+|?urY7sj1^׎]DOv'AB=0NGxr'r H (%@,m~/1cZtɂRL}'/>vWc.6+mﯢt*?РLt,+\v/~3zdNjkP-ٯv7}iw/Ǧ۾+6;->)hxg1Wp*3Ѻחй9^=Pz3ǜQ~ 0xw ]l(ߐڿ3j"ҁPJ@ (RPǵ mrsOe]3S. ]7{Hpɗ}CFuWk_R UFLqNާx݈'I|a9=kj2Kx{x4?A7 Ә{iI#:rJKGa/`ǎտÎ*1~Ot2R.@㘩񊑙ݭ:zd2N%JZZJ@ (%|?<mܲmJqŴ%* rqqG69V$GLv|[/\.chו,7fOz|._-ʢ׍tW\z)ݿ߾tǏ/1v{8XUjxsr,~?igyisC'\z}^$|3 8\4e>i;񪉍ftԈcP)r$'|}Xm-"#r}g/.s:}4%&+_$ofv&UJ@ ( o4\vqg\fNPusc&YnF>OcMv;lH/GvqstOm\c#:@^B1;j[p.Wrp0{׭^jjPJ *?makoӔeAta%PY?Yvd\?Rs>MhXƌϛǼi,|kPJ@ (x zBj>dznrEwZ+Oc.Pکv G (%P@KH;-ktDD~|Ϟǎ:VJ@ (%8.Z'rO/9qdr(_ڨ/×8W1r=C\{ネPJ@ (/=AŹ.F)=kyE! W~Uljm9ELKr+ 4RTCẦӯK0lS\ObO.;: ˀ_.}N`˦ a \k]zY*.kĬPRvTol%/Vwc΍( iCμ@6URuw2\H8K%Pq?.9q.2۶mqk[t}}yTRR #kvHu ,:RƳqh( -{"Z`УswaB` t(ݐ#93wݯ#GT0CAcc ~9|v-o7~2gi/{Wb͌GPNeן]+Ppv|7M܂g@eU0Co]ҽGPSsV x}0Ec3PJ@ `t $TD_/f⤏lrpΏjy6V^iӦ!7Cr_!MֲUȦKflǜ-;t%ϕӁ[G[)̸v9)`F_gsxuMa[z?wף!^arЭϕ&V-J9303w!rƔySX\R3&t=g64l\n] 0c6|4[=FÞ\f `&LyyvoUh!ƌeXp^b!P1Qys9q87BCހk>jy+9&L}FU0] U3og=_Lڱ $o9 L**–#ܜ2q܂,Z&N=}Y5;vμ{m@y^c׭tΙcǗat^曓[ c{8ӄIĒ5ͽYEiكTcBh@E f`ᦗpS^9{]L2 uz%w'GpMN((#p~"-pzsPJ@ Dp!5DZn)cc'b Η&6ۨ:uᄏ࢘`I: \o 0b.\\ihf?;?}J#"p2u(< (0qwum[g21h 냴1s)xh;f޳x|x}9%2]O8G+~j<6œUwr80`mnj ͱSE_5j 9&Cf}5ʛgpzRl\)zl`x~gـU'ѐt)ȼeQ}zpP (%Z+8C2jKtym 'WK[׋sѱcG9lSȟ:-#<>Ǎ WrfOD 7흏IW vE7{&wgcqdJ̺Wt/׀ΙNϟ6.f/OoēYww}t#&cd5O:.~%՜dM^(5 ʂr\’ 䎘a\^f?7ܧ8^mjsWUu6+9MFzNC=q!''͞ Z,#F{Ɛ z.ɓ!3"NkPSЍQI Ajꑜ"8t,xL~V& e_n6>.}&%%a޼yɉf?Sl\l1)Er%oDI)m/6ɮPJ@ (%pRs>iXƌo p7aXml*%PJ ^lx{.HK[DK. =l(LJ@ (%hC^Ci9{S_e&"h瓝}6_/Z)^9_d9Fx!u\{ネPJ@ () ~g!mn^6;DNMU,ƫOzG[ӷdJXjr]A"K~jֻhӛ{>؊ws`HW}@,'[SPJ@ (2eɗ~i듮MG*2NKk׮<:{E%UA 1/1 }]{_x]#V E9⼕85P3ŖYơ;_յtJmB{}+%PK(G='HTtQxZ.Jm8?5ILEE|Mx6lѓr^JOD<#;"M!(2} cU5qb&_+Pf@KEGy"OPJ@ (%`фD_ÛrJn6.N&9fΏ۶mßgL0} #mwޢ*_Ǔ֢rr#kKQ:Ie#boaʥ}:*%P /Z^EؾDEW̉l^XVKzjL6 M<4N٪ctN6edt Ν:lOnFL,[9'saSJ@ (%|p(5DZn)cc ]`llrRoJzU0'QBt)Es+럊zznZ3Oœv_`bwբGη1E*[S`nK1 WiLmڏV ɺs7Ɣ#Y-U7dQͿG:\SgÐjcJ@ (%bi [ī_lv+hr x!鳋ǜnmff&ƍk|h@Hp6WWEgxg#JGby@kAnFƎP:=h>r+%P.x8]LR[Ki('~Kb2*QC0ogc~+%PJ[SHa|-F{]! }ʡ|iS _~XmPJ@ (/6/=ATb+j]bx}Ε6|V (%P~ HM#ClwmEbe1^}*+?&q6gd =X{E?O:KdNwId"¤ɱkbMP]]kk<8ߋK{-@c^h} c@>> \mni0/IߓzP]PJ@ \۸%]}ݎs'z&l\M] 9?ZLB ,[ w]稅QH)W8Cѵp}ߌ+*ĺ5> $aߪ)P GtUl,⧝ }ab\ VnD,:A+\BeEJ=Oo-i羍h7-c5ʭ5|z's- VPJ@ (`M-OvC㸮DO." ټ擱^1 m6Ƅ зoȹ0x<1zS xV8usU-(Ɛ;~.E_DZwl? >^WañĪYwbge I;o/x}( 9޵+E=`j+z]7[`l>~`.n9ɓJnPJ@ | i .Zj cR,pk=no% `6ٶFvXz5M&1uV-Kflǜ]ͻ F7|Tet#I੗pu|Fesd 5~0eײ5xd^<<=3G3F Ya0̞~h+.'d!~=ptংt9fL?J@ (%>b ._n牫m/$b8^ڼ߳gOדڀ9Bt)Eۣ"b#` W55s Ȉ܄uGy]~ubDVY8&e8LƸ[nAV}=&N=JKĒ5ͽYEqAnp9*%hXMH+Uյ՟QX i&MԩnF 6 ;vl1MNBlSȟ~K̽O'GCjAr˺,GyG7x؉i-ð`9&jʛWR](JAba4J|[|c-[gb԰l!po`^ؐk7UPJ X{};G]4ۆlciϯlvOgWӱRΘ':VYp},aX<}j& 0+e\ 0zt/sOVfϞCQ2,&UO0:<b;usMiqyc򱨳4v'{$̛7g?Sl\l̵J*cbD_i϶m-ѨXgc~+%PJ[SHa|-F{]! }ʡ|iS _~XmPJ@ (/6/=ATb+j]bx}Ε6|V (%P~ HM#Clwm-x PPJ@ (%bHDȜh/m-dAPYݗq2_J@ (%h+~%2u$*dA\m>9q' MMXlV (%P6Xe\,!c9?Dp{ȍpi_ (%Pnbi 7!F|5}JtEe5P (%Pbi [ī_e|1WtyMmgtPJ@ (8ī+FedI,GHk?^.+r>OcI (%P JC9+yxEIMcC/s'^J@ (%KMOHUeW 9 " D FZ -iv=Χ8tSFDEI* QX% RPW5{[osν>@j=[^G1?M6Ots%ҟ[AX|I! B@@%A?9>z'K^ :]!B@"Pޏᢝ)14!] z-B@6DNGWz?;M?1ak3s%B@ *9A7ߗt r:kgB@! "9EǽN}x4*MOcBڕPP!  ?|M]ˠIL}.B@A!Жx^k&=~I'}~1mǾ$B@!0hr>:^œ/M(| >oMu9 ! B#%ANB~r=~IWA9_?[ʑ_! @ 5c,^rcmўj ĕ+s|%B@!hyM\精/9U8">B@! !-rsܘ}"]qM+i=a% ! B@W1eJJ׭hwMNB@! z@W^9 >~:>z3#M=.B@! Z#@Q*/՗k%{%]m:+m'ur ! B-9>9g̏vӸ%]~\hsVC IDAT>3_R! "Dheɒ.?1H9ANd! B`chxJi5~HWn6q~b?17e ! B Sxc?NSOAA6rڌ\I! B`F'J-z%!]uqvO_v?9@WrB@! q "9X[tq%J\1~I! B@Dx}^KN*'x)ǯOB@! r4q\>7fkߠHWd sZOXB@! ( -"蕿ac}wٽRu+c>]!B@Wxa|y+̈aSϤ%B@g <:K%?Z^IWNJD}{\>jB@! h@Oxu4ncdI:W"ڜ,̗B@! @D>Q3?ڹqc.}u mN51B@!  %.9sZMҕ``O̍qB@! h@{Ęyu9>C8x:jP}н6c1WR! ذ( D|}~HW@,'\zI ! B-Sj|ޗ/X_WAddJ:&T] B@!Ѐ@?uߊ t DzB@! m%ft q'cyKR! F ?裬%k^܄r>NvY_B@! <9P$'WρStO+B@!r\xN<Ƣ%7&]~`@\IR>z̧_R! &^|5|.SEJ+#^+|ӇfL5S*cIB@! dx}-rwT0|}xf}u4Ni9sFs9Ǧ)ZS ! pf t7&nG%ct |͚Vrќiv-GWUíJ$B@<H kC+z~?b>{%]~:k`='dcs gشilkmD7"LB@Q"GxF3m3 ֔@nnK+Wź:W"ڨ+urOhCikl4lih [9ֆG[OO! B#Eu#sxh7 ݘ?YΕ6'Knc=k%6PZE| ! B`=Oȇq{_e~h9ANGB@! (Ǩjmc=~bnB@! @"#|̫EQzm䰵B@! @O ZMKCd9yzu3OR! m"W^'\}Rt&'S1R}J((B@VeФOOO&>KB@! h??c_B@! 49Ae/aN_t&qr>&ńB@! 'D?z}Z ~r\ԟ-/B@ Ds 1e/hO5cJc>B@! 4 &sYߗ*UZNR_{t! B@h9FS}n־A8ɦ@紞B@!P@[D+{%]Vb}&'C! = +z~?YWSYæIK!  (xuK~ֵ6ƕ6:b|ՄB@!3Giɒ.?uD9Ys+/)B@^|?g~s2X}]dI$ڜCkb2B@!0@J1\s<%洚f?+7x8X?c㲅B@!)<1r|~Qtqb)'uԠ{9lmbB@!a#P@%?FS=8YN^gy̓B@! @[k\%tVGW']! 9ExToP+Ni9'D! B@h_ⰱ>ƻ^IWXB@! @+低X.~5! B@E '<:n1@+mN zK ! BW"(ܸ1{_>Y:6' ! B@ ~ O9 f0N0X'Ƹl! B@A r =bǼ_!]i y5>F[+)B@lPETd?n NGY}^g=$B@!)r5>u՗|/+IWi~2%*׮B@! h@ko_MDd|t! B@ _3yK81o<%)B@A#Q5~IWnB9'cyn⬯QL! (rJK'JRB@! 9Ad<`cQkT.?0V _)K=/)B@@`k>}ɩ"]/aIB@! @&nk4l銓lZ}N +Q! E8l.WUn%},Gkr2B@! Q019ޟ{%]=uc~m̟,PJD?B@! 'J~G;7.s|ץOtA z?t&&C! D?E;SbNiCr31.[! ms1.~H/v~b^G f,J ! 6%>Trho43/uzY$qa|Fa x>cݺuԄB@!Pi>OhZF2>Ĺv}>x1H,S2bЫO#)9&cyJ(YwBr ! B 9 $(}=tcrE |ϥOR! 9r\yS0({ɍE{I+WүϥB@! @DW05q T p∗r0 ! B @5sc tI6>(B@M"^K6x+*u^>59B@! ^y(꽒:όzN6L\B@! hyFs3T_򳮕t4Dчï&B@^G1?M6Ots%ҟ[AX|I! B@@%A?9>z'K^ :]!B@"Pޏᢝ)14!] z-B@6DNGWz?;M?1ak3s%B@ *9A7ߗt r:kgB@! "9EǽN}x4*MOcBڕPP!  ?|M]ˠIL}.B@A!Жx^k&=} ʼnI[1o>{ed^y];wns['?/cXn] MD`ڴie镜19gv %#OF12::jX̘1ðLձRHO D |!ʕ+nz{1]LŅd…FnsΝ4z'߼.]vO)myҥ!nc^dɼ?``=n6{l͚5S13YfV[me;찃LgIE¦buթ8f%AN:ؽωFD%>O$_?=IS| _`,Wسvަ㠹lq%S6444Pt}N;4 /x|뮻ڂ :33| /?9;}toy,b-!-%Hꈃa:QԱU# Iu(#т 6u,H^'7u+6kh=c.7mˎ6^4fΜiڏww^˃4 '.FFF}nExynb m=g >Kwj6xtA@9L`uvo/C]qag?[ ~n˓lr =u6֖/_nK8.\wؠ><ŶAy,7D>קty cQ/$zrX+$Pt!-$dhXGrWW`?9*N+_ZM?g,{_f[m"^b|QDOpy6gΜc ^j.]X7c /_n8e;ĦWhđ$ߴ¾α-Mxa|ߵk/^;2ۇy^];nͮE;W I? }>cOƹ=+7 xefY_&'Ns\,\Y30la$忹-gǼ\o|ve+ivcOE 楻c3 /[n-U`7W/.zh;.>,=Ȏy~K̞sNsExddz>}[o՞g7>>vҷoc3zh]gCb2cQ\w0_좿޾2_SƯ7 {dze⤵ [,0wz6;=Z:[lƯ>LKߒgK;C.Ns^k'>yV]O1uժ鼳vgr?)9 f_gnc'6j?ɶ[k77=.70y{})|^J&tzNɶBʯ^d"^>u"nw~EN`B=g| t2a 9 _JyӫC*n&ڝ_L&ilm~ Skׁ N86veaGPw&靎=hW/NjrKi;+kMv{\pu!5?Kt2kֆY'?^֤CұjV%]z=X6qrÏδ6mMރwV ; ۊҺwe cTI`bw}$ӫwFFGlN[3h6>X'>ؾ+mj#;_m+7JѴMuJ>бਭ^ZCC3Nj?O+͛9)9 [bo/eIf̚ckg +^~lp7uӌx9./M<)MʽJYJJt'mW贈\xr n㷳qwgGvtg]v6{↚O?-1Ǯ6cRk0̯ b &-9m γ~o7h;ka-;Ž9x%чnsrh'7sGƤue8ގepwu%*pH[t1tX9vbBҋXiPb2>GG]:u}6߿k[/2[:Êaklupْm'p]ݻ}^x̡9ͧT[fo_zeK쥶O/-Y6t?IU/ѧ~;Hٍ\b7_3"JY^-y¶[WVY>` >k=_Ԏ~N56l^= ;7g;-lM߳fH6 IDAT֗7RK_{{~ث j/󯵙^by'}㯵MRx[fUd$ 0P7dISvK[~Nr׺C67׍ښ`}u1*߷'vV_}a:/-`{Ջٜagvڏ/"r N8xos3 zC= mә?>c~m̟,PJD??Z]|o7{^koOcn X$藩g%??noضP{˖"~݃Gγ_t mw0K]ܾͶ~ݳ\? Ͷ]7ɡuzlݖ tx䂋4pPFE9mY6/}/Gm[+̎y6#/~oiYmO>~b{ux]tvawή^zv96vj76{nK9g{7ߝiϓwM_!{ߒ^c2#3UwWIIi9g9O>h;lxoOc[xlWU7.`AQsJ02g{m-Sc;?M+:vʏڅWڮľlwvMsOg\bZ^ϼ>=/]hwd}=o±L:-!ƺ8fЁ->,Jbư=U4u[=;}=y{GlEzod]CU3j{݂?]liϻ.OkAcOO, n~쮟}.ͽwֹ6hQ@vi88뽯K잎ؼ_9AN?RUV'Q {-?Xg1 @xwv~dO{[{kvN˭=G7|]oeoĖnOڃ?Ru6֭HG`Kwֿt8 ߒp]enًv&)?4H,[`xCϙ?fLjsgHrzufF:cAKg-}"O˯oy]vQE 쇯_QKvslEz]Җq_<.C _mbcewo-٨z&:k;sGKZjvNmdOwUSh"`#p;n" xv; ux|rm2c/zkl4G9γ`l_;n3m%iO3oN20!lu"O>gSv‚ȝϒ9_ϱ{?^[M 0*7g;Ga#HwևW[:%B}ml?]K.t!vxt4O+v>Ŷ϶ cZo;\/l 67=mspx ,5Ālښ.x Jso3+5=}1_O9>?u?`Mo!cewIsJZ; TжIw~$?t\113.y;μ~Oyc3_};/3V8t k0 _U N;lk._\x}[wc -}הJF1Zո} I#ܰl1F?$A^ctI:9y֭HOVR-w{l_m;]lmI5f|m'#PigO08r+.&"RGڍf6oǥۮssY̎g s Ic;6s㶤P}q{@D[/ʖy#ͣ6+} M&oy/wN7Ol/N/۟x1#C` .&~p0&ҕHPzIdfpNǏY f{ t]=^}ζ ^},h4wؑ'AKx֮8>|ʇ/]g3s}攽C_<%ux [a}02[ew^yO/}hoN Utwf/$u?^m~D86pAA/f}wھz ‘Uv˯io]6{Ö٥_x11Ý.0k&=u8p3uzύmwNIy\SMz_챑Ν.~~ȋ9)ExcVu*5^;w}]w:*ovi?}NzbZGG"*'?@a~c ç zctuuzYϼI.F{U\/:Lwp`sՕ,!-E{\@pA,p`ڦK׾g?{k3.;\jwCq~N&1.Fӣ+α˿$߶v.wP{o}/fW4L?c7ga/줷`OV8QW<*J@`Dx]fq];߾מf.0x5]+/TՕŚMw-^=gDl;? Oooζc.Nj7W} a{13{{k{]WٗJ= 0?6:w|':oOn'vy-~zDG:nRI q^y kK`yJc}8~ӒVFPZK?JO;?*jɳ8wzȨcCuġӎr He~k1VƬڝ_aOس~>HM/-7wnzE NtWJ?'^;tMifdz85VYmFcYsm L_@@^~a)_-uPװ}g:ve+KKtRNK:q`?ymV=n-Μ[=l5U";tS@҂/ȥ͐.vmأ~9hݧ9i_Z86Hz9;=IwF.léUPs?ጤ;xi[`}~}wXWgYm޻=mю&=e!I0's^QnvrB$sASzܒc~Uʳ&Qyx'O=]_um/WϹ7ٕOs~,|E"\]f:>mu]5*'3һ*[wƂ1lb ħQ` 0j]gݑntgsӧ]MM>>Gj= yOIή/'zV {ގ*l' w[v~]tEO`JPf.\le6I̴^0:Ϸ*gVOZtp %hcag=0s?W?A/aNjc(v #' c>uoln~ꗷy{s;!wO\a8H/ O|-׆!pţ-w5ԉq0qMu>O8QCa*l>\+W߲%GksodsqB置s=kV=lwtuњ!H A?|;GqgiC`?b^a;Gf:M~<6Y}uD9}M#Gxࣟz_dq/~H~d&{z$^Lߟ==1~lK`$_`A9>~sDX/wxea<k{f P[ i 3XPx[sl{۶h;/jeHwN6{-{VEb?Xy<Rm|Wbiw3Epg -W\a]vYH؏~lAS3Xn"!!ux(>,G^GNnI1?\ц$:}hOIuJ,\?ʁӅaϾ"@{Gomط[ fWۏνv~3{GTr@] V$$ `ĻB Y Y`V ށNOveb-m2NJGJ.דlxo6.je/o;SN6 <J믓@!Ip!:b$VÆN)4^5He?+G"Ɋ@tqEo]umvɕ7Xq*t۝HUR<ئ ;gYTwEd Hyd8boOA"x/5\8@@Fw"FË޵c7$/c gjx- $&M<քPw|c~wtd1˨hO=-ژ׫iLE@F7a"c~!ܟ{6^crlwAs><..R#0cDˏB;h>&Q1+n>@=RB:)p۔'k4ճHWd sd*S^Izjg L~pb5i~yԦ[D+1e1a/yJXv/sQB@! < QЏ1꽒:όzN6L\B@! hyFs3T_򳮕t4Dчï&B@^G1?M6Ots%ҟ[AX|I! B@r'J~G;7s|ץOtA z?t91ǘB@! :3JK<9NsYҕbq} ǂ<2sB@! 6ppo%GxncyORWkz?;MO${>?Uc.mI! B@Tp?~w}w}}.>~H6'ۓ,y\X҅B@!0{,O;]S;qn1SJB(%]3DN:k|KB@!"p7ڙg9v+ใߣG2XKGؘ=_)~~2^G+ ]M!  \?No[ne" 'Juyn{+N߆czr'Z>eKB@! 60r?b\Gw`\ /a.BmIWWQ28Q1Xn~A|.$aй$U ! ؐX|;\ \W'+re08Z?o˿.ئkK+~.ՄB@ A?ҩ3.7Cڵ2|t@(Þbi#6$r?ؐ6s=B@! jr-ߟe4-#p GCd mH z,Svԫ H `c TlE9G|lIl1q).?[PyF6..>rb PQ]L ? PŴh㉘QO6@yXOk8sƫu!c{%]0D>rа DhiA> œ6POjG!hS?hẉ,,,,,,,,,,,,,,,,,,,,,,,,,,,, 8 ?uK0F}̃DD5R<}h 3ak#A~ }yy>hi3J*!Cgm!};OHhp~ Ÿ^5^gkUQ_zxjQWG}35_xFk^_55^Ϩ|ƣz}xx}<^5^gkUQ_zxjQWu _y$$C\:}G:H/hܝ\'0`uL봽zn \a.'P̃qH,8b=rX|ڔ_?(Ȍo7X#J-_<Տ.8nY8^7J/Ook?ZLqڐᏹQJ`O?ڝ_2rxѣ|L $O~Gċ:$ه'a~x9^Wq1?~8~x-5 ~4  b)XJ˃Kԡ:ws:/W~Ⱥq1ǂS">}.k1y?}kj PJy%(TwWwvV~qRwW+T?S/`OrѠБKo*^d9̋9sEzI,xu NRE5y?Vv pf|>M1O1usv1R@"VXΎ>Q  i+чLb,gG(?贈C&|h1uHtZ v!>:J$:-b6}Qcн̅Dc^ԫ`z%]V@qE8iJA||NG>el$ yA- n1cωq8>8\T/>hs~_}>1?>hskXg4R"ަ/aV0\]>ڐlvd'q$9^GS"18~w>IDATG_7m9~ʔV$7 b4Տc+zG@m<h9 "/ TÂnj蓏GtH)kGsDMrOwXW:%& r:c)SZYıY/ɗEOY׸)/#PeUٯCT(xxJzZۯ 2^u\N;'g u},+?c>c!vh/8kYH5ITMs`sw(Dxw~`z$^BGC> <ʎ>NWSwtSEFI_@#Yzi-G>x8H Mc@ 4~ K JBqby/%uZoWjܜOyrX|R_#۟;Vrq+Wtkܜj|Z.7r9xEƭ\n7^ѭrsq+Wtke>$4P⺎?Dm cØhC0P$Bq8A@L >Plse1>t¦5q~U" }5^iGE{[Ǐ?폗t>~076\㵟>J}6}ަZ4/沎~H쓱V-1J L u2V)T'S ᘨƀ1'uL>}X$6 sh:~t]xv\~ڔ 9vI(1|h웲e[lKXN9mGԑVd~f_Ij$ 5 @f-㔨1{i~z9bsu}Lb?' bSI0{&uLg:r6Fنtax0xt4I18uư$L)@u9$6Vyq>Fٱ:}Fc>ʺXO&č;aT~#u1?}>ps:ak|sO%cƜ땘;+ *(~2A|| +NRR|l$:F?rPGk!}ޏơR9mE?/:tߣ=zu>c 㔞dGc/|ؗCcw{%]*̃6bIh'WH(mpLhAn?O-jT?O?uxz?pLs6u$Q̅-XCREI?:C?oϫ՛H:DOSĄI@@r(G>$*G`#c?,hQ:_zt! B`p䮿џ 6}%fkus<~ 3>&HXbI\2 @~!q\<uĐ|֖>h~^C~xuGOGxT?cul k;{>yx?RWUٌ-ے. w胍l1H,{caH/Bh} CS§&B@L=SbD$Gmy:|36s(}1&l,hrx+-b!$D>q2y?%# 6d-t@8C!cOԩ ! OGu{G>K>`A\?pv\7seWU ᄘKq,tJ3uoϥ6r/| k9 W| 6r>'rFn_h3ܚ;Vr^\sy%z̃-C>sG14d'c|EXIƾcGO"ʓD/H'H^G.k I  胟:Bco]u9u1wè.&Gbhyrl)Ʌ~ч\q}J}u9u1wè.&Gbh+cK{”󱿒w}#1k KI>ӣ6IwhIOX yq`Ӈ;rb..uńuH]L??8rяTV砖 %s CcN^%\3}kź D2c ~H|YGcrѼNH?.Ƽ;aT~#u1?$:c٨Cr)ges~ٖ# Ęmꔨ%t4_ٕcC 1(;_3'Ƽ]9RɯmԄU.._+9?rGF; lARgm/#z\|-cPWGGOvynI: ;Iz 1M-7Ǹ4Oiq?ģ=z}vN!Θy:=`Ohx1fCݏ5\́uرhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh|a8(} #QKh>'gWIO\+胱^$s}'@>@g9>i߶&5^gI71kx5^ocx&kTǸ:Mxq_uƛzS7I_:}oMu3$}כ5^gI71kx5^ocx&kTǸ:Mxq_=ע$duڽJ΅uKz. 2GD&$9G.?hS6%УMQ~h1B@!tC̭d9E~H6PF?mȘc].#1umN.JC>4\\!Ѽi}˞~51WMĤo"&x]Nu aAy\Sv2v/8>΄`#W}:6uϋ _žJy ! As61ucD!_::&Qg#y^OY?cQǜ:[~¯UO7:~t<ǹ9<>#1,2[̋ 6hշ5xcv~ٌE?:ls>g`92|6 /Io]C9&1~u4DŽ_3Fu¯؆/MK.7Ø%Si]䦫hg]Ni),B@<069muEBӦO/]! xz!+i?z2I/cW:߇t! B@m/uj{*IdǞl}+$B@<,Il}_<qN}"! B)E)!W5~&g:B@! 8O+5>-iB@! B@! B@! B@! B@!džN0IENDB`testng-testng-6.9.5/pictures/launch.png0000755000175000017500000045350112551235562017502 0ustar eugeneeugenePNG  IHDRU׎YiCCPICC ProfilexXy8To,c'=AdߗlYc`%I)*VR)$f"ٲZDJ3[zy|sous,|@?H&j`mlԯ=8kp,o0, )- 7|sORF[QC3`@0G)e[Rp9 xQ Ƒ0$Yk8ƌ]vqzRtGb%y{+M$j}^w $+0 <ïe8f?rhÉ;zV?ܢYA=r;=mo/± - ~!YF.zk P ChBnOSQibisB7cY2e8Zxo^1_~`dTAN"C3򛊴J@Ն#jE4ifi~S[DAaѐɴٺ9!kf6^v'9 dqtvlE?L &'= ':<-uYsߍP{R}\WēSiW_Ξzpܭ쌆oe'u?=7ATWs#B"bز U55j=zjLAM^\imjni+j~ûٙ%۾ץsuPpHh+̯$5c{.v\m|y{l'ON>}7}_TggJ/~&BŋK=?WRW}7fˀH*FA ϣhj [= ]L 9l0k_}yf?B˂B5"bKQRyKq2+H**N+5)g>b*}ȸZ50u' =̓ZZS:zOIc7M>{hfcIr6;k`aaʼnri8(W;󘗁~?~"84F &4> />qTbd(Ѯc<..|=>+J_ISSWQ1^tcԭwbfޗΕyp0ODX#l!O1g {) SRXn)SwIH=3FƟ[R_85K4/ԷƶzyGWM^>ꁔA!ahdlUkbcOƫ'g~Ș̜X9? _gqs__-(~(Ի|qtM|i 11Aa2" ɉ|">QwT}ܳ* [6fC,W''_ 5Vb8zƒc)i.鎃gpr2E˫T(P$(q(T:,wJ5<hs Zz]:XS , 1Ff&,&Wl4/[Y Yg'(lٶ%8su<dW)yE|d~y_{z| Da}*&LBÁynbd/ەkW>:P>hb:6O+t|ԍ-Lfb^4X7g^Xo' QBDMCCyND,'#{ĥ#q $JHɽV(}f@vz=l܉gʋJs+k͟=e}T|5ݪCkw|v8a5qo?BϤ~M7?z/XX Y_w0oIn ;P+0DD oHud(9CYQ]p a*A &jn`~ElZd:vLz=1 3L6~6l~`Zqt2Vc'Ј-W +#@PJE|tĶ$Fj4O&V6SЄ_,R;O8\}ESBvNA+c!gX-r-|3/w8&D|uSr?%B F 4>%tz,Ǟ0 [|HԞKu6-7'3\nOfme߻ϖ{Cr#bB2+*UeˮW|Xz[KN>|`0qTUϛ1w:G&ݦN[}ʙ"8k4=ւ‡X][z/_++U"ɫk^k777\6766ǶTm-llP/Q a4v_ܓ Vbb <H6o-8Bv[G7ƺ a/MIưƇ``cF,~~;=.Er Y" `?2^붐B̭` Ph7"O;6gbp7Y?@ xw &}<^ ڑ#e?ZRc^莎/uϑ`[ہ++}mYxG^ofnt; ûѠx/M8y %Eɣ4ZRXHP(Tq6nod eREB&Pm}tn֌1v6H>(u/P> /InbWpQV^?zhM?O+NQO{?|Ǚ9\Cv_{mSCnv{{t3֭nŌa]X7U*"("("p!D yv]0mm) Ys˵MݬL]"d#m=IwٚT]sNv񇓚]]_{m8,Kcҩm{.yҞm [iw|b>.fN=!Aooـ+~z}=cFG?1G?GS[=ήs=uioˮX.fL#5ܥu@e6T"%&|w1.Ō|Wj~k!׏^?Q֮^zo}0vvXVgׯ"٥u.*e >I3rl Ę98f\[f+~z Okh}Nnvů5n8[g熓]kNnןӹ1fR.RgirBŘt;J/A驪I:ٸ{7 UgiKt"("("+)Ǵ? ~O8=NtWiCȞHnl.tqlu{l\s݌ xߴqn툮^?nHD)֒Ѻdkբ9:Z2ZלblZ4X'[KFSuVdkh]sujќbl-kNNY-S%u):Esud9:ZghNN5X'[)֒Ѻdkբ9:Z2ZלblZ4X'[KFSuVdkh]sujќbl-kNNY-S%u):Esud9:ZghNN5X'[)֒Ѻdkբ9:Z2Zלbl>H7뢳%̿L?۸ߥl7fI\)-{I`'sb<3Hf>۹q-VrIyŹ5uq̴+~{ݼFBGP>}G?#^BLEr;\I YuuljΒN:)&8m3uc)unVtOIKK g3\_M|vddxtuDwuI]::y;:$.bl<ѝbloNN6{NN6KX'=OtX'ۥS͞'SM)f)&vddxtuDwuI]::y;:$.bl<ѝbloNN6{NN6KX'=OtX'ۥS͞'SM)f)&vddxtuDwuI]::y;:$.bl<ѝbloNN6{NN6KX'=OtX'ۥS͞'SM)f)&vd+1\X)RXѝ$L{}YK.f9Ű'H3Fl46.H3.\]"]ֹWgP9VC_(_[b4[/@k$OSPH(^?zP|qB.$%P}^޶cE?D{L$Nt2;jXjtpҬK,ۤ8ħRPE@PE@Po!vfb>;ItTus /xaY.If,Lmsp .SPuu^Ywqlj؞={NHH-"("("(x<={}Ŋ|\*f")G(8Hfƈe 71Nu9IIJlԩSG^}շ}MMvϡZE@PE@PE@PHK/=9gΜu+ eڹ)7qY%I1bk3cL& hIN'9)\˾1cƌ%iG"("("(@xB:qDL:Hdɼ8>qfsMa_Sn\u׹:ם3"9'>33sL}}=۴("("("R)Y:1PEB)c&d!m1rfs;K9ݔܞRg=]χ_|JRS} %!#;111nBn¶mPQQƦFkQС4y[qk-y_WJR* G_YmgP"("("#՝0`nLL.MJj3c49ObMmq8-fN_NҴq='eƈΒ K>wb[aRnZ ^g$:NYحEJQTTǐYkCInwލ۷#1)IHLzjkQ]]Z999&c~M3 Ǚ6n6JL%i0lssEdTbuM UJ n$yfBĴGc2 дuEL3`-MOL¿i&c0Y]廅ҥ &&&"*2 DGE:mŃ_cŦ# 4#W)' RYIUvjєXR=`sfwskR튀"|+~OCMa͢?B;ЋD#3>T3“)i܏g=P+[ypwB״/Ϯ\ {_Z ])6\27.kKSk#كӿ;Ӎb_SpC#gT("-! KG3)3sijnimfL3ߪJܡ908^,uѣѲͷNdt'R*,aG͈B,,kEU58' <¤gW"rO*Ϣxx%/@'aR9IԾ[Y Dq9HIG 6gTb$ǠsR$^ιݚT"(DesހI{#y_ǯ_'>!QEM1y%tzwEJ/zE4h}fO5-0AekL$\cJ'b^đ rl>jwR&ǒ܏SK07<⍐B|+hO hf׏F$&iqHHG֐miQEE SSe1o4N^j<;9~ zђүV?M<d̟k,K^A؃~?{5?|3oc-?m؁%{*n'6~𩷁nfa~&RJ"::2Y[+_Ľs^z½v6-{`YO~L{?VܣOJ mGab)D"ci(Eh팢~ώv+C.c"oR!&e?e=nuS%Nɉ?F_3_SYC! ]d˂!۴:E@FhH|5$?_yy~Z5H鵏sN´_uĒ_cYƍ=?wSý7&WD}x7l憖> صfhiv x4,+7G&{_f"ǟú飺>?:MiO.hbi"lZ2\?yt۽wz>E}~]񣹸ћ8{4*Wٷ 7$N1,Dn&ux_K@#s8Ž2ETl›11}8yɽqp<d/.G_a; ˮXtm ./D<}ǷZ;HT xt F1篇XKۓKc`B-ɧÙWi}O6\C߃)糘8,5M8qzy$sprYӷw=⑄~Sûѽgt~?:IVy]{n:9Fu!snWr,?+gut~n {Xڠ bI4C*@u^?ej \~ =Z&6#S{JpsaB$ĔcpzGDM͓y)5 ^=]=O)'TtE@Pvs>!4C˛U;?Fk !Hf(cjdLW+@u-g҇O2gD<-(jm@V{^}mxj@:-*jj1h Ki'#+%X_b`ʬmƊ00si5LC{X"}8J2X~86v7Z" GDR{~YSCGE@Pnxܗf;6="^[\"bW=6ރʺQ;*U Hà)dY=6IwPFwӣ˯Irs"uDMw1?,¦ !xK}47P-m"lqGLxLVE[6kL;0y3dϰ%AcDu+Gu^tL_!olPa\5DFŷ)mc>Nr]Hi zi0l[91bϿ8ALd//w IDAT~b"bH4Y38 U^&ծ(@`ƴd/xiFo~<6cfy6S.\B$!L{0 w^z =ăJAK=S#-d]|&p|viE}]= l{{žUsmс%9q kN>c98LyƔAB?y#xdopCWcX 4z?oVmNΧ~b֒i'dmDXFkBn o>F{e 2:t~>ŴGbDlWG mٔM-ݼ=}X~XEh6 |ۣ>Zc5Z\*ޣ>t/mf2{GڳػJ$uIF<}'Zl#I"e%oע^C0{"aTkJ97b"gBߗ'PͱjQE@8v`?25_^\x (YoRsuSUu.v6b*K{77I>')0Zbq%@H}~!)V_B">`5 #2í|>/vScI)cb8'T 4Cpѩm9= vl}9fۧQWKNC6~+"!@[%KZz/kAbN͍RNߟG7hUFR,1?\G/Bca>QD:<}3r{;efn:쮫J­o-B_F rq#[i&?MAehYxCmv_" /WYE/MScFk)/Rk}fZ([|2&xOsqΫsS# a=+: G67DuSO];|=?F/MF~7yCoi55@4۟'~+[)"(veS!۸up"AS<V~^g>A.扊]$L:&uDYb6`&ZO^r۸g?ۈr-3JZf[PR|,Fi/u&sQxrϚ=.LB&?S֙gAetNAЁС׮?sTad+5wqvE@P>bеooS_#"Rh撐ݲPSUKqHLDю(LCneM^bhZ)kN=9ג/%!ÏCRyx#RӑfiA <} ShyiZUbS:}zPCd2ƔBwbO~)xdtG<#K\q)hOVYvDo};(iyoj7ΎGQJ%F oVin虑̫ib#~lt"?&ACtiR>׬F;AC&"1‡nA#W(p~$t$vxTbzvK%t.BEi^e}h)]&_%Rѻo6[kaC{<>-"( &MƲg)Ҭ63:RKr5'ul.LMi֙xXˊstӦN}' K) ɯE@PE@@x\ɣ1sp f8Zo+1FH]igyu'-:K=5%퍧~Ö6Þ("_@ui!KN%Q6l"( ̷$gϺX X{ankJLs@!l{Yע("("("pbhMnI]fNɕq+I>#)}2!4Xu29k)2ų.uqB(-'|Ntls1msGZd v} 8\7\}ZE@PE@PE@Fx)h5_рR䴎x%b xhc#_$ +)v l"~.=Ҟ:Ȁ8N'vI󅵋MbȥEPE@PE@Poh9]5Q :6ii9Ztx!fh춓J2!h[}#܎$֬c=l1c`#@ȒHb؞\@@("("(ׄO^!-|RGᤁhգփFt(LCKtˆ&)a K9"^v9]E:d-ΌiƊ́c >-"("("|-vFvHˊ-bSE,ϒf!19Q޺Vih5Fx29KwHcK8-Kپ&;IvZ95"l࠸uf>h4mAU-"("("|=-ُrqiAr\>پ{GDDc! $Q5e^oGjuMjUߎp,SJ1օOEwH;"[śh8 ũb'u]ˆ*[GYUghc޼2 sxx4wX_P;PPu\ޢ=ؾ}ʎ!`VE@PE77~8zǟ|6vA;/O4">] mkla}m}hÊ"("|_3>}pRfH 춖O6`‡1nX`Lp˕-_. L|x9 </iuGxIxwc}89N>/ g1y%cR[e0%Xakh;\KX,5q}Xj^0f潿;p>O4|M("(7ᷯ?׽Owbنxxױ!o#;bLu V}!/]Ș+Оfc%Ϯ|񣤲^U\fveR~>/B._ãHtiOv)qb/q͒`dg tQ=$БDJGtdщl:у:zџt4P:N$:Nt:F1s;/紞:d]0O?v:׸ܹС r5?`2PITnO/`)o\<}.ײ1 <ǿl /=# 8*sbc\Wʃ/0ܗk,O[e3v%_4s7aΆ`A?=wX?}e~;.8gҘ261ٺkFrб~w V]PƄw,^1a]+ _bruk.P4Ǐ>?w\-Z̵^u|Rɝȷrf\ 3+֬/aW_|W5:.zw?\jiv,5Xiz6ޛgߓ|k|KhQE@PEA[럻/u?̙ gL??g ; gS&_u+km%'W,/}¿L[+OiϷoݲۿ=y_YG!Ru yQ@/4<~̱k1bةt1gc\1c܏9 sA #2Wdܑ9I3s*Gc!Q#^'6iccA8y:̛˜Mjc__z:zn٫me>|8^=t' W?N:kpIXl~-g|/܈7C л^_]4Ɓ.B`j n|aMOe(luJz~Runs.{: b\t.S (+.CYjnj&\ʻ)0@tMb}J;#Kp :0qP,];jEv|B/ LyU*"("5"m8G_؀HNUHZD2ݨ][0TxԛW^A=3mBjR :d`xAdoqpa>׵~sýѥ+*FZ"\CD4mԊU0Ler-3/Z?@pS{GvlOA x}ܦ.盺:ʒGi> -b4%/h9q!SGv|Hdɥ2O UrnC|/V=q Ξj#[Dƺzy? WCbjKn-Ќի73-ާ4^-1^A~coU=.V#TkZG4Ywzpu2hw# YT<n={(n%ӌe_K[S("(!oybw~$%j+./'ȃr4D6~|ĥE!=%6Q),TʋҚB =OCQ!=7Jq؀JކO}8,O'V|2R:>0S0Q &CM>zL]]M-F!:eP8$έX7m̿Z<ɑ|I}v][I!gmۻ1}p[79Y:znKO*CZZHǝӱi)V%hkF* uYWDU8V/+؍ݻ Bߓi1O=gkWt2ͮxi刣n-e˂l!)=yF5)Hۂt~x{9w`V@|:/Զukӝ0&dq # oҤue@-Q^"bZҞM^Τt,Vҳ!p q+i"Zj>q;WeE>8^Aۆ"("p&&+~ǯ cłɿg]I2 $t Eu_)YHH1ԿvtddgSf& 1 };ы$_u'f^3̟<+ 3x$:9mhjN3 4cH)]t4IFf]~LǛfkG/Of5O>/U`}6Ke%Z+wxp݀מf6ٟ_d6&YSyX`H zei``ɪ ȥyxxЫ2O%>})fXjɇ5m89ϛ:VSqXVc'~n)Yk IDAT.־zs[/: ^}d]S.攮J4mfM|8Tq78ŧ06:i~&BAnBݴ ofZv`I';6YZZ3! A<\zad4}(6BK5X8g 2 Iαo:٥Xރi#EsV}҄)m?Fc+MCDA"("(G]im=2:wF2wP|e  kH?d$"ک#c\jKha uևJh>SR EY)[UYbRC<2.W.~@9t?]4-H],t*7ZK{#GCU<1)ԗ *tnWaG9 KGcvP߀󻶴szpfOƊ헴rd_ZfmmoiAc$n^h.ciA/.&4jKR|Ӛ"("(G&"zQDF;#*r:#vUo7Ĕ%1E{\~ӓD%w'r 7g({bjQQZ[]]^_K'QQLN~ݥϋbC3dGI$3dϒr̊t:MoƔrl۰5 ׀1Fr(("(*Oy"*5ם>Le(%ՕHI[L/[n3Ű `%zvNa蜐%%m*ŶBZK;Tנou4;G%- Ӧuu/]ބ$ЈP<ӆF?ݯM[RdI6gLyn3RRx%6>;{mN\њ1"ˍ1pO7͖ N7ա.i\("(|S|cHtI¹F!16bKwEoV:S;@Y4Nr6|Wѿ#CG<냵{?EvldE"fR;rbԐn{QCIHW+Dj4nFx*g=N_>;^=1pks_C&\A"* sho6miOR-bjvbRۻ=:fcۿϼvpQH=kkወAym%bǾ\6t,ٌ>rјx"_cq(nEe!݇J{tΤ%~tMOEFB&aM~f\+کy1Kn g漵^AކKGgۖ}LHnM#hl6ygYU c9De @&9WJs KsbC hQE@PE@PE ?xTOqѱxO.BMm vBjZ#:eSJZaŦ v;sih AM ? tgI1#iY.>b>2ߌպ"("(""OpKa-u> #?kf Fld i>߁%ؚ_@0 66*@FZ:fG&Sf݄X3 k QTE$7؉d"koF#ip4J +iGl؛O~AiyǟAkq]3Rh.0w6~zhwap|M Lɉn/͐ykm~17ZaiWX1}NDbD`c{h | e 4_YX+sn'N{p 1ٴϘLi!rQcJ0t*L H>XYIX)njӺ"("("(蔝ED0<5zQ)MԽ/=BL|;Gjb G,_6R2SzwNhmhE6.è^˂RtHl՞R!ؽڽ~]Y{ioЬ]hlhDqгQB?ӹ;_Zo|DJm+Ŀfǹn5pj9YgS>ґ`z-IP7+BfJ-|14:$!f1LL3]h) VЌi"SVN O숙Kc7 C#cjdG}tKBdTbDc1Hi|89SO$uX:k3#~K[Hami_fp $j́0N'hi]PE@PE@PDК$&$yɡC -GDEK> sFBt$"A3k/1^p܀7a5%m\ (BR2p|̸|R&6؋d)RJ PC56ici#3ImC&&b{fe4%"r Ŭ"q&Os˨Ǻi#1uipr#utkO튀"("("EIi"̔$ZGD+QDN;}6bBҿ[&bhc#/52:'g-H7Iv|pb.HI!xWpHNLB#H(Adb2Iv>{U-mjUiY`uNt*쩷%@[wssk@C!''іU("("(5cG4117X yy4** ŕع?}( o=RL=ږSшǕ#F!6&y{od4ǡszLn.n<4y~Ҧ(PDt#ᯫ{X&xjyJB+{λ!қv~[>@.ͪ߱zxv O3_9RuDG74BP%LĉP~S("("(@3TB+;ruI|Iiul"()/)Gm"("("?S^de$酕%+ڋQ U5X^$Вܔd"|Y)2 )8=g cShC$ZLŀ~IE?c_Y>)ZDfK4ZCy6l)%rGJl'+WE6`\3pk)khYp#xi+o܆&n~>blЭo6("("(QA |lY#= ~dBD {gl/$bx>ޓ]RVzr>߳>j..YX rrgA>Y 7^(- V^٨{XkjHyi1ouI-e98HٍBĕYmD뒑OuEfюSj ǿLY>=m/bhll"$$P^N,V)qѯkow徴 pL\J JƠWz4GK)I9smVNl3c!'S>;J;!"dべCZ"("("FHv?{_`S1̘1>()F&AJH(%pƋRܸŭ-"KBUr/7\IՄ2͇33gy9:{>s|Yguۿ9 EN жqKa‰TNÞÜ]Pe'~96ZXuA QxX1tϴNٵ/MoFd   @uiEt6$ lzl "yZvߥԍG~YzG)MVuEY:c?:J4j׊@yxshsY_<,T~^yP2 Np+֛6UW._ ld   xaBԌT;21|{Sg3ѯMTA]sO ?>Ny>SD4;vuC^v2Q5/uR)NAD ٮ0zŌv-ndL2Yn&kS'eA@A@A@lؚlt];DGvHjD$#]Z^FucF9v;6|mNEzz6jW%v4rhãOцF.TY"nԦ%8XEJ\}+^7T'RZJR&{0)c!HFB_VGu/1:j>PCֺNʂ   @Ө,O4WąS]݇ oDANaEߙSyrM?~5:ĉx.E8}8#b(FQ5y:U"1Qux:--FfF] wAd(^ވxL^"TP93ENM^fW&T:] hod5W8o},^SޒW$  @Ů}Qq5PxDGGӳ%8Oz 0zTln7jğnKj$l:6}oAکI<))]wG].ͮ-K$V*D89ZJ+j21 '#W"=a%-կ1)ymKh$I北w)9XZd[삖2v}r. sIY232ֲ&gz+!en$ĔP$  !!_w IDATɳ8*A\|V%+d9Ӵуs@v^j}uԯ^[-eO~'!;fIy(]"ĒsM~T@e]EJY%1ۚD2J$Z [(M2uMDY֜T>Uk2-Qa&ֲ&D5AmA't[WA@A@p q+ץH`tL4AebIEBL ~uzש~^Jnl-$5 0#i/">s-9ə"DA()p)bز*-ũtuQPk^3dۚĔe숖s·e$ɹ²$h(ɴLG4A@A@A@"ώ׊Sg.̧%QQLQ2$&U,^ٸ9Ft>ܵ7ЦH g#}C~TD)'A傪*R%*ɃixʉdžݝӊKL,0r,Rx輥UUIЩԛ}HYA@A@ Ac#zR29uFS!!{^y]Ǐ"2"^쓈#RU""R77BpځW]NxRMH=HWuRb~Z8?Kw~U>S_949.*  @H& GQQ1׺JU9oGf~bDD2!d$s:*RJ:TWRZrRd rR0DXEQ}Zisߴle˺72;`;A@A@A@#I`$E1V*@9$bcQ=: g2NQӆ5!0$ZM=1 Sl1x*#"h(S{LZʣRz1m7*:ɵ1(b䀞逖YXH]A@A@~X ? Fn2!)2F㒺 yiHDHQ5_s6UVlС: )ib) XO'\Fvj,3m2lt?ۜ{E$svx\'yE$}  o^LRC[eX/e?f,|spgng/;ϒ]twx r^^KT_&E,sM[xZ(yetRnIrm+   eB\)5)HR3nK{Nǁ-ESy#zTCP= yRϳLD-)Q&D%!UVLfYG7m][tܪ:^j/uA@A@A@*rZ.,x(Ì"z4$k)e*RsS%_V=Pl}Cx啚9+ 6ZǎYulĔ13NN6։:ڈLA@A@~WF$f p%U3.ڰ3?J'kUMwecV]u"<Nuf$7`;;[;ٿA@A@A@!#$)iX0WFu06>^Sf3jU.I!|h$yX.#xt]eSۛei[-\ژvRA@A@A@Ek?5jqQs]=CB߸fA=3lGkLY_VqmgjXw" QkMM2Yn&kS'eA@A@A@(JYtR0.D76QbbcHwA> ɲ,ş R9m.X[륹о<ꨵn:f:a&h   68 eWTVqV p%)[ه9[ڕ5:]NϘ۹vԙN57,  @PpԎj0TVMs4?/O=Oy1+_35u;ٖuQW1Փl ?m+   Kx+*9Hz)/u+vySyyWW1ոk릣Zgʴ+%A@A@_>I &Haa($R4Puvv2==k{-*/+1exPi'd 5k\d   !P*23mMˆiRۘXly$qnYdWt\b,ֵΚ_F   @g`wЎM%r-z +2˙t庬֜L}mLLLu!3i=uԫcJD    ۋ粕Ly ;mTQLVy,-yhQA@A@A׎@0ʴDՔ1FZnVVQ;L綎yj/:A@A@A@BiXfǿdvc;۠(bj:`礝t    tcSVO V0(bjb:̜)׶    tG5yUgʴꂮwҜdG6Vq[eˬvRB`>{B  0 -Wd96Z]Yu,*1eGL̲Cuή>v&d|\e%#=)HA@A@5#`wOhב_ymXoX(LFe/:-ut2Шڛ},xA@A@A@(NnܳigLyvќV;Ǻ1ul`(Zlj:hYggr3Yۘ:)    @ŬҼh3`VGut,nw OKV yn&ãzRA@A@ ٕ5:r0 h_b4szFS!ɝd=T?loڹ"χ3|>㾲.cJR 9AVPQK_~j,j;#"/'/Kaݬuewǫ-PA@A@*Ϳ2Nen:;oP z ӎcm0K|r-.((R~mE8_TD{U`ɩ"A~4@$$LJIސgrU)˶/6D7+Tu *?Ѯ3;TM_!%A@A@_e_ٕ}eS&n:uLu-ȼHaxȻJ\,W$uKp_٭g3ϡk#Vj:qT4A QUV[FǮܲ~@6)#ݏ%ٗ7jʓh 9U-OW;٩lV%t#_"iiJ؈@A@A@~B_vv2=27ݸt/嚌)4}6#(/'z=->sRxUz.]G7 WAa!׬QkzT22sʔrs'wshq7jll~Zjv5N>c ^CNӫ9bS;+*ܯԮ!vxO^|5/Y孆k"2A@A@A@|JW,k2]R۔N:پ2Dz- 4Q52<jr9tTSl;PPFDUA3!P'ՓM˼tvg3j :UH)~K|; QQZ 077>bw/N56ܡ"-b8bZLTFb{&!Z\3(dytTR Rb+t}}|ET~ؕhF+|}>3شirrrKGժUL,BZf褡  G@]@oEtiG]6|ɔqBwȩYO\OP.Ư&~BM q:o-6hfhn"nZ{W`]w6,hiqlE^5 pʈֹ}ޟsRޛҊ)ՇGE1mtϪ?8C1)eaÆ Ob*$A Fe˖v2   rssq񊘋ɭ40eiuv2l϶N:ݟm^Qt;;$u6aAa"lY &]~1mOT}yS&$&|V')'.ԩuU(dE{/I{̟pjOi+7Lث~C=sI@ "##%4HA@_{ N&]xZ(yp,`%ZiIrm[6?eإ& &1她}or){&տ&v?ڔJ\yekbEjn ;ǹ۰۫c<׍ʏ詸~]R Ex/u/OUTz"<r[9A@AහOpcr4iVz-ڦD46LڶY}1V# h0z.ܨa?QZ`"-gNG3)QQM@6lPCi{1}a4t qc$jҷV2] z"7GJ#[/D逷UԦImZA@A@DhheUR#NN6։:K%K,DmпǵD:=DK?؊)f12]G|0-.%+QI1IG3ۗ'u2m_F-}&^rj 09唘x/ cSAZsSu}/:8{ 3<0?Cp:SjCDtcc.7EDUHcJ-Gc$ܜ.}}~?\.<>SD&^ k<ћxBK}=vbDmA@JD@11iiMitىZCno:hulms-kcڕ(kW-!/)=ȯ{-#~J ߩRxUjy"~Xiҹ?|30-Qc2ݹ8y.nU;w#c ݧ-ğć{cd[zW>^co;Zkd\R$z#hW=hW>]9ވfo̹ɮ7aL.Kmk܏ڔI\ szuQ+!nq=z)jDܶ,,q~m043i>)Qbxf|߹ u|)€c0uO=V":ycgu$6.u0زwKMc_Nbp0ؒjq5vq>7wy iWIX>%y@^$Go35TnK%  χ&/&23 Eە;R8KOVN6Z{"VZ}07>y=:iz#N`8 톏Df h…uK_az6ҕ$˿ro Y:sm:ńN0]JYɞuDj9~3'|}.⮬67jG6E?`abWt>b2O=vd~{Lh1+wmZZ[SSH~O5H[7\[7_K< ~I 3ԱX= c=0A,ɍ:bu\7.V޵s݆yjk)p{|kՏ)Ew>j$CǂhT໋!_Q_4<:99DJ;L 5#$>KD!FA@ PY[6}yQktt,n  ҄[cf:f*G6-,u<[ۓj5_T 1-IfӍ|r>BLW/^ӊa.uEyƕ[xr|9iuc&S?[€+ePs?:#-zj̊gN` }y"Ngʖߖb<5~$u~$N ׭}m9KnK)0Z֢h Q3'ON}HKT)X4EeUK?~'"e80Oo4xx0A)~=9SEe)E <L^fW|O븮6}yvIp]N\~b1UX}EOFw#=iE%Q}A41#sKǁ8rbvqCYxөA:& ط&}58&4;꽎#ͣS_yfktG<5Mxr̝cw.Y"B㳩nr?H>w끜4*^xR]I6\c)f* ʎ̴Cڳ=:tyESY;Gd쐓ٲ9O?^qǎC~~~GB⧴UZG-h.hܸcASNTA@A@"P^tߦ4?`^QtRM9ISm+,_`iӦhݺ5nF)$ACΦN¡C3kСC/cbl:2dR-!={߃rÇ N8"|~sI  @"`ǿ츘$9֝cCauZgSA:;{ԕ(ERR`FJKĂW ]]n "Ua ybÏ?G2܅@FF;;w*|^$A@A@A DB_V.fmoN@SֺYfklR7ILLD}w;pC߰0򣕧L;w@E18Z@TUEXDW˗S/3|'[nEeEGMy9:|~s;I  @#`2{Zо<7eknڗ([(]l4Ѹj+*L]o}Gp[?}N/8saӜ^UU} H x\uU%u}- 6<0,ľr5vWleSplV"9: #4?n0.#oU^}X[ճ\L6b_}HTL>O4kLRι \   "953Nenk Y^T;jGPth[gJkGHV>ڋޏ{o{{QP`MĽ7~\=]E(8<OZú)H0k7nƍo#u"7jv`2αoA|Mr2V=g$GC.cjZ.2#灎 u;GF͉/XmhkӇw[h)w*2I)u⥾L`sI  @# G 4dW&yQ3eNlH|9ovl_qBFZw>EӛqŘ C-<_uO\3$)Z]]HlujP#FB#QZh6}OG]׭G:hX45| J)؂SXDORĶY-t8^R{Sዮ %?Ϗr廚rΉLHy B9vO;!|ӫ+aȂx4,SO&iQ0- [S5 5B7Hv.Pwz|s/ EQpg]AbG2#w蟸%gStE;.&.ͮ}ttLt۝,m'@ڛ@bvt;ׅDQf<=uڕ&rtTϟW7畕u4;weIѸY+5o8E(-jb:[7Ǐ,xBHҟ͹֮]믿^=9 /ߊ<~sHҗ`jWhx]֕9So։Y g_Ϙ{R=n"ږ'ھL9/<~81 ID 4BX2ض?-4a4:耢^"'hjKhiZDeZS&QDjm~?w:f7>pSH%а7ֽ1QkO|N O*(O6DZNl2-+͜SQYfw^˹RD;ܱ];Nk2[f=^ݴo۶M/}Qܷ1z %rڥ8ɐ.tYT|d&"qV)FDC'vIi!-]wfff}vf&(G:yܔ$=`Ld7۷b<_W_^+]1q5nUcy ^yۢ<\?#/˵;qv@m~viu1>LT@k5jD<#X:bT*T&Wڍˈ-{p@xxT"(XA?}YIdn,hL!`r+0TXf ڳ=:tyESY;Gd쐓`IIIe|CQ'~#(]6t%2"iŵG'3R*>w(u4J6lmjl=3]kWU0zU ? c@>׷ņ]晇?$c󷟿B:uES#:Zut|f:w*_tởb _m3+' G GMNGH %WI+QY!rˏ%zuh\+Ъo/4f` "-9?W^ _MJًfN.Zh[62@T܏'~S2 "DDH"H*O毲Iiims% ݅QvMʣB7uCnڷnpzX]gJmtসP 9]xLE ^()VUƥtRdIrm[7N-jժ'^:SԙSF e(T LF|$/VVՈh)Q9ߎDN9%?[S&Q$W\m/}?ug}|:~a{DTT +hN1ZzjqѨRFrI)Or&B"x<3_:uu#R>qэqjd>yOtS+Lew98aŰ~!S׏:vVJ]?s4xn9z5/òkbHS,ypL¤y1/+%;?RaEe"QҊ pa1u5 R }+NL)]HɳY6d.LC)s`^Mha\;:.@a Ϸ}SSğHxr^>EQ(J:2u<.) -Dr!"}/UgIY!KLKsڄ2Ikې&ǯgΜ9^7:rDNC@ D@GIy?4nX=sZ8vW_7_;MNYG\LyL,_aҗ4T =]vB7*z@?|p/'~^TNܦJL=kޅ'DNC%v3j4&ftTV21vڵ/B6:v=6qgtݐ!-ޠjQRYkvCE!#OT-QաO$FS?ʔ&ĵs*Uq".*? }j$\YʛHQӍ9jҫwQzeرI 6ԣ[)R$ʳ7}b"ñ%m #q`a9Oe.c ֿ6 8$ @`x]9,ic*-~y7doT6-`Cd "(ڈ1^\|L>ڶ迿Gر2-8V)RCyK7VfޫQ tΡ;mϒi]#JQEe=+n/ L}Ǐ'b:?[=1oOע0~4|~>{C${wzm{ow"nʂ18qxxf6tyHU?t vKUo});s6-w]G`IGtl[Ϊ:5{ >Mpfl8Hkl!-5h"LfN|H{`/YFbB,'M\ر9K<3ājk#"{u}rw'{z}{>D`B:y;dۦUP;>EՊ\שUh\߳%T۵Dο!\D?RFF>$oCw,2 ڏ;~ltPfPt[gܠf1X=B I'C㽾+1O ;>`z sUǓCU?PLM$(ʵL4߹}&EJ'son|P+w{=\ۨ:?</O6&5e2uϕ25 Fu#<'OߏO髉z;>5 GnX D|hO=x;Ja؝+}=fYq/w6Vn_oZsѳc7xt v3hqS '!퉥i`ܹ8y._a[vcü0ugn(20z&󧞈M߬H钝G5z^\`¿qXhݠdvN4M 2{'hwF k趑|!񯛱H:Ҿ3iB"l#4<۳3B {3wƦ%#ݰ^4/c7L[a%0 Q/BGn+ΦU9/ 6m>{wmS˜ IDATޛڪqtΟf?'?ώOW/595{Ф4?3 a_2UxHOYmy#K7̟9=GӯC}ek`wj }{? ]V又Qr՗˫8^3J\{6 Ү˷|beCi>bg(vvoYZsA(]G쇩zw^{"c4Blڍ?mNIiёҦ9 ݪe̛ ^Ll[mqhlLBNSCvb˒HO.jf[gE)X뺏j 0|T_+?@8/q_3gӟ9_ +Yݰ2ε̮i'eA@ Nlgϯv٧F=vKΝ2Luӏ\Gw}I q*E5zMq՞yl$F<<_VB4]5j;U:tLCHNzt&r 79GISY+ &bm}j뚢GQӧ`ٜ{QԒRڦwwjLt[^r-Oɦ6EV9fxs$|u&uJh_. =m*?8[kv:윍NTv^ƨB(v 4Q}=c0s(M >iV5;"λaj/[' 2,B5XZ\uJl9-\; 5 (l܆>!c0ixq :  3}Y4l [B?Z>gvD|۵paq76I'ƪQH:w-r޴w"MMS^}Zsga=)mw몳ո} nto&Vǃ#FIi=x/12~)*V,@aCǜgpt\$MZNCiל+O˓lwa$PAFџ6%󔵘vV_Pal*}aJeN7'Ogb˱"QJ*ĕxp4DkҢ&r bPK}Ɍ+RNJxt4-ɁGҰR-z9eiړ=CS🴉|ۍEM+1Vpd}/ΜN t^FHY=Y-4"Juԟۼ[[7/םR^>_lR V F"E 㦥ے`hi}:+@^ґ}#]=6W!{u C ?7tg0| f gfV"!`ǿ̛+Vt]Nr/5/ϩkuZeٳLf{S.eA@`8KyH7 ԥKđk Dq%{ggz(j)JW@w;Bp5U_ o`iy؛MweR3=zvETH ȩL%m]LZ\kt^|IYԬepNER禕{ndFN%7)ɳ%yg jEV# QtʥB?$bXv|AkZݫLAoxUq [N|Tu3[l\ϱ m*V't)яDJ?7ݻk]B{m؆n,Ɨ'M|ޥ#:^Zn3>W/͎j~'vĻgaPMQ҉ĺ߈|Ǖcݬ|h1B{_e1~JܞT>߯tn[܌ƃlT-OZ؛w7gtY.ܲĵ}N8'9sbCW-aM~ڿ#,`r㦔+}6ku[XyUꁯ3O?՚支?rG{$|P? z!es؟pEEK_fֺ)h*Qkt,n Df=kNrdW']~Uݯʲj"7)5mMxK앖fӱhy@A䐼JY89~Qt]Tm ?-}Y탊2RιQTNN)O[wz>M__ƞaoyѥśo[ƽO+Qسfqy6u.7JWWRbIdBrr2.د_T ȤĜGpd,R݁!*ZbBI~ջѼjyomꫨ^H?@XS|Nw=]ve`׆ _i箠hPفۯ#p2%)<9zYL=⸗Qc'Mg7$իrѸWVϦA,)X+_ϸk3sK=؎+,Oh9ƙ|"Qm1O>bΜ<Ey3 ٮ1RMJS}Ф]8^o5qm穅MKbN{>ۃ Zu(7xW}<ߋx>NKs8I?;]b}miM\գI;ri)O: 7Ҡ>E_@ 4_r?JkK(ٛ.3]J` UӖ]ڟA&7Gگ\+GTYfs] xq_9kHǺfD1mԍ:9a仚uRw63W:{7%Qo~, 5]ݑ;HG9@%gOKɻנcЭ I{LhM(zsWwx:ʠAHKep$y c^g~#w4aw9j~Vzzخ%#x5h*5!NCi IxI_f^$9c\b%s%oB7 ;Fy,V 'VZuħ%rBG`:펌G"x3#yJW%Z(3SGނMEJ|wz5^h?}Pۋ)A^FNrņz7?$z~cI< ÓGZwETo$|N܆h6RϠuHăi]ڕw5\+!ztQX3ewFj/%K/QIG$Viwh3=ŷRhc q/l7sJ 9*ܹX~ZqWݮ מ1#eczbmD\>l;(OG?7{b} ۞OK-e ջ{aңe#}8RjnIJ\D_΢laR8u!<2|]ȣyU_tj0 '6TxG>TŞ={0#Rvn aNop!*>V]46G-vZoB#i>:g:w޲I--eg Ɯ梞iveSvhMQ?(ڹ݄64X K_H+ӗo(=fZ81.i{:5]vgHBӴ-.$jbڋ&-++8w3=z.Orשϥ=4u#gJ,>'Gkm>gY1y\|@!--.usQ8гgi)/?jd8j͡[5? ۿݵi _keNs+G=5QNJ@u k.? [ٕz)]«stMHHx^< 9!quٚʧJ\**[C3C:i):[K] ožNFV Gˤ:hҬ8!fQ=v:v./#&+)y3_bW}sD'"E aNYSO>EUbpWFHՄtU,_z+Zڿ +q#~cZs< ՞:w‡nBJoƗ<h]~o> &Xrn!gihh(UҿbכegX)-W)YEil1zzJ[2ӴbGYAuc${z1T/K^\ld'ݫ |GtIw+1@KJ4ZOe`Ѻwڐٝ[)IxA@ůtwk\\o\@*[S=I=>]:!}ۥ6:=\xfSO{z׾es.SS䔮) KscÄ8MRIV1ʈ1tީ)=Txh/ƇDcsZjcv#9MS5\fT^.K&e9߬~r >s*N'tZtc DR+j;P EkEA Kŗ?KȀؗED)X[" \&2e4HV~`'jeV.kۮ[KcC7Zزa2A@2o*Dsߔ.fk5'z%S(s܀7S%o:`SV=;ѥ{Ou":v@0]L^mgtmR +v}X91!)u%a12-RLJc\%#[tt3&&Bǎ?2Y[|3NǒuEܐwHCf`k7>ȷ[2ٟ!!: fcHT (Y|5.| ѩ9$AHW/_S3'5,de<+x" N1faϒ)3# 5x{TKv.RZL'\28Ym!OAoؠWF·.H: oտ3=WFn%}`x ^u[7iަ;;.j儹ɸzJj]gncc=dݻw޽{+ ;w2C7\ۛR,x OVn0ja2w<<})x]5WEÜ^g,F*(.@:ƽht"i鱸bZJ:)LM< zyԦWlG8t6*VsK0 Ÿs11vb䆧`ɄS|i6;9SD~ ݣx4:lF3{mDkIR   @C +ec!k Of@&i >e|% tWW*ݻwG׻c|3\,gUAůz 7ݽK(, ޗ!lt3|"ht=,,AHhi{p) Ahp;wK@*BҸ*7IjEL@効hkohnjCXr+ƫaÆgN[aѰ]D  5/{5l_z?׼]ɎRz&f=zmDn8꫺2J_9 UU2GVREѼQc{[*| D|YYnNRqې[E'[s:Pi\o:xry)U%Tk!H0H-  >_V\XSV2WM澕=:oo/lǿ' Ѻu0ٷ {,5NކRo:-4A@A@A#(2s1k^.9Qs_']{w\x:߮*+vzUq8q T:݅g9+bx  @yU[=j3W{~Urjw0;` Ћ/``{+.  \(e7A]of_]g+`ymSAU zblz9媖iyk,27g{œؘgقu)XoNxon.mg\ލ<7squy\   !Gey6iz_"^OTtS5x+;A!ps8}w{Gdb>-ז,GT|x#~]=CL3ugf}պ6C~.aKs`B<]VmnNcm/7 i=GA@A!_L~U%"~ dW×߱/s( AM#GtqYiU@91x{yˇA+^Jţ8#sBD܄QkcDL1|Fv odAW^>pﳸ{qTmÀVhEwKA@A@p#_z7vӧTORCЮe]X׽kܸ~tCd{wz8Y'KjpowSX 1}~YF1}dֽEE۞nDQL _]*Vq)Ylׯg+_{~FۄInQ/..  W< 3فlﶯgLujnVz;˩J=nٜ9/_v.$|nWyܕi]Y܆䄊ν0QZGD ^B(!Gǘ8\E>4eEV7W""/i5(xe4^M"1.l/<؉hNɎSݲ_]t5I=Xbl>G+]铧k]MϘ  (|q.]m3SqtUkJZTͱLٟ@)ovݕ_z)8KN©S(8ŚçPMiwq20g;J5G7$䦯2~|FUl*,)Ƿ߻f\qo[1E0gLTY4A/^ƒt=i88Y<iTx7-?[ !0^#C3zmpߋ>"9={I6yV  _ސmeVq̶V6"v X%dL\菍7Kl'ػ_yl(ݩݥEh; [˘asԞXSZ`*k&X`c*BJ9Aw-r5/EnpkSztf&G qL|cc'VOƼU+1k68Q3QSW4֮N; lt!0jZFv!]';?1iSj=|U)n6f yaX袏WW8  ?tneXۨXɬVZlYS X%i%cw;6 >n||9rt Hkg1bF%~|#.Ś jĉkz ғ{Y}2sp!b5;e֯ft/`n(?LꃌqY8L.:`b xcH99y,{0<:Oǒ~_TGš~T]+4)::OЖ^.ct;]Ѥi_V6mJkRA@A@,R2_<-[k]o$L.WMWgH]0b=~Is. p=jLu7^bb*fMA|m#:jnx~܍ar^3pqtg9k?y[US>q{q2 s gFC(F{>Nzvo]Pg&j^^p`w) .?hچNխ&"   p9g4<+ecԯ.1'M 4V@}VLҊY~Fi~F+^IÑ2p>?y9:EGwdၿ Sc%/iZ>tHF.Fω _M$ ExM|'&ġma؂'#7@jV4WLp[6p0FVhcF'9igj?Ցmьg1u#4w4vlևԫCQZ7HuvuӖ3g^uig%  5)L$N'M.3ŋ_}? .}e5mڵCqxG\v?ܛ|<5ML=&&&joQ6u? X5X1&SZ-u^U5VRVT):89 o$ndžqJX+=j߀^;ZR2\_+Jo_5Q'51m! p P]B b"矫uII rrr'`еkWhWٳgo>lٲf­ފd58V"6Y+9YQQ}5u涕٦Ow{oF-؏א> LN▍cW=d-BЈ.$4>b!ҝKI (DGG#$$a$,Y   Bc3i0SԥKcE>"n bѢEHMM}gQe [Y76j +?۳NųkZ%b%ֵbc0!e"z] R5ovSxx[|;a })†ُ⮩.2?n6_OFґ=6չ#w6S`\C>nxm|I1FcVz-oǿhX9~ CӆaJJ_gi3MfLL;. |+'"5 sb(mr 3#~M]Y]088Xm  \Bx5:Rz ̘1؊ZZZj@Ȳ2~{t&=4^|E^C {hf75.UXWG/J=IeIre[o"5t~¨~O+>J۾O" e Ӱr=H@ *b"6  ֹd{6&c*bSҟ'-mtX&&-Yq|d  7; =jO¤cxt^tN~3b-+%ЮoL[A"_~4//ؾ;bceLL涼1`JK/"a C50elZtSyYgnkݯ$9YgNܗl_Ro` +5H)Dgy+ݰXyq)^:ޟc@~E[cB82Ў Ln"`Az "85pH)غ)q>L:#[]>#{l n+/ m@P-EA@A"PTT7W^5>ӈJ%%~ }sz 2~2WWՋIhQQ!6qqq⪫_I{fcǯaF8Y@d8=1mnc1مMগMx_zmq^pX#Ʒy}K$f%!z[OXsW&b0cŇiz|({ޱt61Eomټhgv:5X$VĥSR5] u?:ZA@A0:VIi/.tҋ X]?6$Mw=/CFZ-b+AAp XnqͫD 7NTX6v[yѓ i1JmZx;λ&g.5j9z ݅ cVLIrR61a簛=yJ9ȚoΝ NWW.fty4Uud,.K˟ tj|-u6ӠX e6Q3甩Ԃ'Lf{]Lؓ˷ &  `sw###p8\לл %uN9𩳁Νe( FdlOc38{ߘ˦mqTmi#WbtFIZ gEpxtXݥ.?N{On_ּE#,s0Rx[ ~x=M (f1FY$zb|('C ņ͙i5!rc_K>s0}":9 a](ڻc2ard:~9sK3 = +{ A@\S&V-[4*bʸ_=5( tؗc‘WI sd/]v4WWk=˜59f=buV$I]/WnA.̜w".sg29 j2e#{.tpa]v8m,FC2J2'D9~t"pmIvinsi@0{f b&b=|{G]i9\!w[/C!HU+N( XxJ;d,%\?ϟB(v~it < '", IDATʷ$CA@a@"VLJ W&:׵:}~?s}.bJ*%U1elc%ׂ5T3͆fsR0}u9Qs_COBo]y+|wrHm37A\QNJىJ&#+3iNTsӛd 'G]:Q}MDȁ \˜`)}Gv0YS0bPa׮-Ѕ6c[q!p:'Г[ʋeڊ3CcjJA@|2LR^$arVL9  0 CEȐk?%?/ʌU]z^mmtK7ƛ5IxP4KbCcЃb8z ;oň;{幘2WM;Ӏ>a:MڦH"|xne-:/j+tWmվ6gVɩIpªmL#COyȂPګ@W2%@So4OA(9z,7z:]یǞf#@_EGooFÜ1}$^\ƅ^HZuU`CmM ?c̘Ӣ]zޮ;|vqW[3d([ țKHQ !]9~4 : _Aiͳ '-4DoGl!bڜI."#.LV+QX7 s:HA@+ ަט0=}ql0ziU4e:Zј_t O<@ڇ>l9xkL4iv7؃7} G5GbvhFC{=Fb]0gki]-rk8GqzL+::)pN WEJfRʫ|qAAAHu`S]U-I'tL٩V . =+ DazR sё>0w{5߈h#WNsG87;ܤQ+"I rb]6b}LGztL mZX![y+ "?_cǎ7NUU(iq [鼒MMeؖ,ўQ <Вjyq(z/CODg'mCvx|Y~cag?e*b5IUn)i`Z--gΜ]6bZD)LE2+_{u'Rt{5!]f˗Gd PoplNyi~94aJXBBi{'1MZJHL.8'Eh݈.16hO_? i_Hn7i W$|IN7࣏>B6mB|3D,t>qgcV'1S'3}eyůtj2U>U}2WOROHЮ *T~kfu0]9)-TG0VQϞ5Nck  W2ݛ NJ+pIc[/,ޞ*;j oqq[oϗ|}uf_;}UWLL }@snr,mM!/])+FhL{POFЋk!c4&V:3qKZFPRPXp hՕDEsb"A@3^{-|x Ru-[Q);w's)c[ϋ/ΥmojzܛibjԜ4L&lq6#Bw45F z57FhN5*בM^:ɭ)=UK)zD 4<ԁ̀x ЬE+\K/%Rɋ e)oo 16mj;`\wu8p233'˪Sfw%(Hygu)o??l" )bjN&깾*u폍Ƕ_ZJ'{(?\UӊS^mZ1R>"J*攝X7c8V#z>? m9DWHJSp=bnP1FU4ĵVm-)bM<_QbZ+ @ #PĔ+Dꫯ63ҥ x%_U ٞG~FDŊLQCYɬٞmt*e],~ dqp;k+8ƩYv>ڵɓꧻzOli1_ ;GƨY;09,䢴]4*Y1!bKĜsNJEPիW=HA@.oxPG|?ɫ5rF1US=]]t/ﵮGނI*;]OR+Z())kCzK/๺)NǓ 矻V|[%  "6c֛m :é&yD$|uDu/WYrrqϐn[>]dK]~g~tGqI:a#o7|n9-'X^Rи#tnXA@A@A/ UJƎT%*&)[%Zɬ|t*2AҾ}{2Nq09(~=z ݅ JǵkŴdq^}RF"&v30*O@|N& kRB{xҤhSrK^B>ΝEl'ի+Wm:⇖|A#K]+L8JM,#$tӉ1\'ʧ"9Z$VڦYBc0+H|^Nc1O*vi~x|s1Eǧ!4<~u/FnDxtXݥ.:3|r"8b/=3EH.L`]ŁA1Sb[QPFes FYpz!s1#o;+0oY ;5Ԃ   PE_f.f7}zyWHޜGѓlc~֭RSSKQ$SҸZ㥟0վQsĕvaE(lps4-:0eC so.Ōi0 FJ&xQ]_aCI!Ȝɨt旆hgOURͩ}d&Frlj/] + 4,tq)X6jwƄ2s:QD~r M mAǑ; e̱@YSW x 峡l+ A@A@A@Q7DO"okX?LMc7~OyڗW&YRrHm37A\q?m% &r#-1>sNDJMt&Ss738Rx˕U>uX&t/=|OZ ;  T~o(e7k/8]\SM[t*qlm敪ǥSjPu (%R[xUɕ@˖-qY=gW62{A@A@s΁cՓR]U- WEPU_OTtSu0qJjҴ*FUVj_W42yA@A@BW-Zf_VV2@[U)'ȥJW۫ 2+_z+ @-!8g-D   pE"_z7@>U=WOROHЮA@A@A@Y|/]9 l>U%>m79붦A@A@A@&8継uUV2U;iǬ7vLYI4Bc? Վƍnlh7!mLXo   e_&(ҩطV[MSsjj2&׺ܶ7~DȶhF3Aт^͍;P\G6AzO|6RX:vLMguƭyLFAA@A@cn&m%g{өxuMS=YDd2ن&< X5X1&0VLiфڼjrCf\ٍЫcMS! U O11T   At2_<-[)b'L.WMt~_+~B+|J"9(aFna6^Gn ]^b_g W}ƭ@Z  @"s4Xif91ecԯG$` dfJςҋ.x&rNǓ 矻.Wq-xu71 s|Oc̞ HhŜV59 N-1>{ι E40 >XLc0v=x^olA@A@A2F_)z1,f]A(15''inc7"0frqM"=I_^У5 3`;ΧbfTG7"qR+AY) 83;9{()q"giZaŸ$-m wt Hۇ Pi>! J\}l ._1KAzGÅ%zynDAtdk>%eeȝt}}h߮IԻ:>ba+HL+%qh$%DFq}8sA@A@.+|+6YW- zBj+]VDECe4{3sI|EuBxh0h˜8]!гQ;11Y`  kA_ຎmAZLteO@$آ ja˲9 BCcjn̉X МTΟ~}Ǭ(6cǻsY[E`B@ 'n YL+G?i 9h0on0El}D% `AS, +-p<%Jex PFHA@A@;.voEc꫺@- Xx)=AN*JfS<#51Y|Xp 9D6"c!M)ptI+"ə\ jyX#c2(YVj7fǃX a7텏" cH3ܻq BE\nl-: 6[ңc,2:!c NɄi)M-'=݊q 1{pzCgr#A@A@KˬT߄Wg.}FOB͵ljE2)5^jڨ, 48J6 'Q?`c7nh ? O[yyeen[?fA2[h4{J a&-%ҞtacݱھBzoDa ]+Ɛ9c= &z9ʤU˫Ҫ)n c .,]$us!26"/4 糦Of  _fA5"*2e :{ IDATZa*x]WNqtHAa)UW^lkCknNS^CI9!(mIi͍*jhgb_5pB Xw:-/*[XRS\:Zz  UFzyKSUb`jvcnk )]A@h0kD'>)C_ Ew6m*jgzz~cd'{ؼa졳v  oΥs2nP>J_9 LN[ POgL4v:m]'nF{aD'j?x/,#tdTަJߵüȿ@X;X|CW.-A@A@OztE:u[+g\v X%dL\菍7 @]#д [b&H~j$uq! :(!vAyNɳk+]FS6R   йcnܭdVl϶v:ϲ)b'k[&{)+s7m8ъ,z\Li 4AR)   $t/ﵮzjp]OR+zY&/c^0r8'~R''7BBu"g#ڂh+ځF>;fQ<;VA@A@9{<ͬ3Gm:]1$'b7̉қe-vV^,{CF#7uJ^$E#1c;VA7AOP  \yUW6Jyu5{ĔvI6:+_z+:}cyg8nD?@U[DQȡrcʐ(v}X9<mrbC02+sNH8z(

G IG0nո&" ᡲ4ȴqUWT6o$- &ST=(Vˊ] rfÐ7'ds5AsV,׋=~EzD1Q y@\w#^鱃H B]C>wJ &RD 88͚53VKr\KA@ ?XuT_f.f7}Më}uN5'jIm1uK+b6]cCFO2' \ۇVDE.dTDW;sQ! P#ƍ+FҐ  \6{+~UOˬڊ)WxԓPms׋6_ڌNju݆Ez>x0Og"v)o;:`$LFɋ)   xE@/;#]of_]g+`yu "Ǜ.e[k_.7i'p]vxg1x俽†vR 3'.BaȥU]8 O@!IZm }p63e;˻1QFq\ŁSQ8]J-   !GZALU2ejWv^3ɨ>`7_ zua9:ix%u=ZA@A@#YZ}JL$l^!mA@A@A@h@'q7'חkQqNm@sſt)7vnSwSC'9igjIW+3g"44ʧ Ju7ڕX+;&NӦM ŋᅬ ǏDž P6mvڡ}{wףSu}szn@rov41nMF٘֋W?'`!~rN^%I|jiVu' @T2xL$?q,))ANN> 0wv-Z8={Ö-[0k,zHNNFP_Q?E175Zo5EL VYt;;%3)3zW%.Ƞ@TTryNPf% P(,,4V:IlVVN.];}.FttME||<^_-Bjjj>PjˊLQCYɬٞmt*e]STO*+'d'LR c}F-'0) e 4.3c{۰_ zh"n.݀w?ue\ 2 W<ȊZ)=AΘ1ZZZj{~Y?K=:\~/"V^!C#7mexZ *׺>2}\wMy.{u~iN7Գṛzs9"v+L~f~95iT9"pƯ%#0A@{C缼={xweC''7BB;?{_PU#!@DUC]0GZ+ J _*i횮K6݄Jt 3S+,єMIITq{rˇb3u<3<3p9yf -V)ߋh5Wb.J))c;'4ubSggmNJq-ʲaګ_ࡡ3Q9uy'P{OR}JGekIQu֢w=(6W ~8Wtp$,J1_GQ~zz[ay!Ҡȶ֙'Jo'_ >3NV-l#ejB,>5zOxrr}K&x_ 7@K Դ\~.43h,¸Qlͮc!wܯ lοtRk:|GLi1F xW?* )K 9f 7hl&/%.)zˁHqY"`ńw T(VU'"g6_\+W-_z(T]ĥs4VY,>;_Zggz0|wNI{.FK[/}9m6\o} .m6|~2wT?/Gb<ݕ5wj=uZnԆS1U7LQ^m:.2> ^ޭo#LL:ri1#Ce15off_2a[ì^T$܋8_NRDEQy٫T-ؐGXY%,'Y6J+WGN`*a$(@BP4sӱx15JXerVEdnGNFG… 8Vk!DV96]_{\tцs_},6V`nXP -4bxtzz/ZuM>ͩySqYɩ71J4y?FMݿdRh[2zؼvq);laATdP"RXπq)(Qb Ls=G ʑ#".;U2dےKH@@J<J9}ԩ[3984ԙDlXLMf#MfE71q>>hѢ29;4{ُfL76"vzϓjؖ &}:#\YTݟPm_cԆYIƯ'}<;,ѥ7EE<Q o?AH >-OjzfZ=ô15,M@uY2_4~|ګǕ8w4kz•G_K)wAF6(]@x4`ggk "MU}\=i9&Iҋ@/Za``|9!*Ch|;yi77V`)2>Y3ZzPH+:>8x;sRph)vLШTnHbhZMn\кzwsxRF"z`3Z uڂ"3[޴N]9xyZ<nǚQݭ^9xե~`72^o3UA1XJJl/(3V!Ue1#]C0ss"uʄCgPz=͉&A}FQXF;i~:cp3>cc@Z6$TV4w*b{MC Hvz&t6hlL^W4sty=GwOnepm9= R4_SȻ-W*b,Y-+R٨EH/lEYe>CڎK>c =k0frh`@`,&GBpP&JcZSA3h3J*qlk4bwĺ&zKEق^0°x"iN 8Fa.TjH2 cv2"{\t}N/m ߜսrY|/ zz.i>'bӼSRYQ98AQ=/RZoY1J2v̈,yEu -E{߈Wf/}ECbG"6o¨pnt60y<؊*kC'2%0t/ہtS|3[7ϖi 9@Uy2е^s/1\B:ǪF)3g)tEbJĄ0Y":d}yC?T$ߗ(Rח6 vwD_5wX1J߃QR.\+ʄI-ecL<>@\QI7T {CUOe܁~r']GHst'{[]¥}8޸ > gFoG#pS"VqcipHq8y( #iDr7z!կ sl _&j#t|Ƕ3M4T֋+8-⪢Qqlkφ=2{/PD Gv}N @fP =}esM=ݎ4Ų k1zE'c{>' dticHGTs@tl51f^`b#{VFmЍezMikPF=KQuţzJ041rKbتh1H[FvsL[TTx7f A u IDATuwDo9 6\Q-ev?닚M 吕ImzQ}\{Ӝ֠ 4m6$PgNN1T]5cv{ & S6{YH$Ж-[*l6+R&bsJe0.R %=@Q5Ux/_F\bY6xrm'&@kI(y tjs6ڧXPʄf.¢4y8,\Ψn/oNR.90aj16c9}RTCv澲+Oqf0N7iF~8J)i6Y̦iym'↧W2d,󤩉caDOԊ)j ̸qxٯ hIq׮܆.[ z(qG5!g<{g }2nJEʦ튒Jz_# f+_K|0^E$%>M*10n,喀Å|f%`alOn UаM4)mH.,g`ְl|(y_Xl 3oE'c[evP#46bWQ~{rED. l0ݵȣ4/|jN _>pCnޏ&gc3Tk}q0ڪg;)BZAl_-\EvӨ|(*O*YU++1>{Ѡ[6?OıYKgXcz 0V4U&eQ}ܘ;͵k7qbgqnagc!3(i?IN{X%N0\_m=괡4WCE>)\{P%@"﮼I QASFq7Dod?aMhߵz _Mw;-0{کp7 p{7aP'*{(GJOBd϶J~WFTΫ=&o?}-08=]}9 |*j¾>e%Jf%X9e:.<}>>Yӟ~Iđ`|^ƽ*׵p4g ^S XAPEZmS˄8|(gD@zf{OU:t #1'n*fN}5)ۺ.pG9B:ʪbszc-%&redT ^KAWV)KzZUY:rzȝnU"}21 }U^yoNsHGS7[/#FGBN1<<1a)|8:;u OLŴL\ox c48Ń4nXqv6B;z+2S|mQ?EQx< ѴvxiKv q%LQ?PfUv}UnぃuQ[Tvg0ip7Ֆ*u2` \Z42hoi. G[MؗţBLA\bKҷbww/ҀDe;-ݳcyskXuuu# sl^zZO96wR;`Bi65Fyώ $ `u( -yFBZ.F{p8t3H .oeaTSH {1fĴeL" hd>{w}SGiN|#vCȨڂ*&~w7Fl kg}B}rJ/BwOk/F {cej^ZI[&(Syz*qdzm˴2yELEl\BL+6D d":WeB.zg&|gߵ62<|ˍΡNzBZZ&N kDF[N}hN\j\[߃AdȳD@"Poۤʷ8k+;:mۦ< k>-FGźuYiF~hMggN<.]#FjBnv^!Ct\9;s`}~1dć:yB.|q4!_ݞQKDWhFq|ta⽝b:ժ-@y""PzBSq0^g g#BD1C?@CķL0y+|PXnn.6/ioΣDG#88XI;#\ƽs\ۚ+ T )5+KG͌N"qDRkFWf=@.VqNPq2 hsiu۶<ڜ-#˗H^>׵ -FvSL˦!euʄ'}A>dxf-1l4v] m05~ Dz"U߾};=K{zޒzzKŃ<τ=k֬Q>#(0>7qquߨ]novZ#jªk,Z LDdT~ǭv:&{t3ݻC h29eSaj#7lM@(\MF3 hU bYD6C<خ]+Dg@3ot~h=عs280Mk\Rs\eU˝ :I52qvSH%DB '{5x-h?y88݄oJL#`֓g}5鞯1Ug 2{3 =RlLH$={Ez"!H$M~6äS!kO[?M+-2KjYm<>~ELՍrLI\޴#q1|}=>> vOݴvK$D@" H$՘ސT4m ֭MG[F?r-.huImk2)ݶ, ! =5dtx(Ds~m\RbeYb`O-S2nPLOVp;v]Y" H$D@"p0WqVG ڼeT5DmQ=jmGyzk+se2-9^3ߟPڸRbF 휜 >\:AAtԽǃ 鍀D⽶>`Âar4=Qs'9%6]թ|/6WuP( r Y,MH$D@" tƯ8_i󮩳FSyA=S먞L] ]AJ#8|BJKOSgGYkZ<~qt{ےѱO,e8G'*T\$df*̃!̟l^ Dͩ[JG@ >;}LpEy^*.Fzr}F";hpyd^ոdKySxRgF(="o:D< 6[ɎmJ}HQ Kҋ~iۨHCDEV1Qadۓ"ajD+m/.ٛ.Tm:نDr2v`Y<4ŲQ-g5G`ϊ1 .mH@x?BiT#eucՌU~; GZoD 0;rmFiU%mFlXW@JWp4{9= R7"|]=c1zrD9uD@" H$D@"P@}ik-ǜ_˛PmZmuuiu_<Οwy*/ q%H N'q:|֟ $JiBY`,Ab-)K1ֽ|: -OR )Gi^ O;>ME`2J| [pT8 ͈> Z^( kRʱ)6Ξ ⹸X%o4cr#Qv) Dd/&##2ݼim{#;s!~ȅO H$D@" \+j^|OqZҶS}g|.':"=uS0yB{`>]KgSK/FH%'N*jkq< y۳T{G`8܇Dgl:fF݋'a#ae1+><;9:R,1'rp=pcD {`r-GRPxg`\\3v}D?,vCD?a0C0:&w(aQVbO>=Fk^$PȸD@" H$D@"/=]=hQpgCp ,YÇuڞ1ҭ>|۷Cyt "D@" H$Fbɓҥz ;]Mi#vڽBهJOtvAf45o,SvdzYuD}EL'chOO.K3L+INf\?zMI$ sQ~C! ,#Hn{=_ia}@aBi61k֬St~)~G9s?|u5wy'ڶmO>$|i&M00_-GW|B; ݛNӓh;@K:ZYӜ:~["4m~IJ,'H& %[&|M;^I_Ν;ѿ7Qvmٲej*.]RW_}㡇Btt4kM<9wEӴyڮnm:25JLbV>Ԗсپ1%KJ#"ה54{K]]hLe@D ((lVK$@BLth&+VSӹs:>&  e{!66eĵ)+8_#em޵Y*]_bʆ SU:D:ڎ 땹ni]?P_ظ:K=xڳԞV}FlO)//ǿ/|w͜{_QQ]bȑhS`B+"iA,+H$mOxJLgqrfTUZڟ:`i7o֯_!C G%uDLFn>FF:3Yyu's^4? ʌ9ab,y\G=␾P(ߏh5yMK#L"U|*QQ.]zc]T?:+}_;*y#fMiPoLdD@"PABe.0\9_9~+Oź՟R1l0ƅDRs7ZO7#bn!jqQ' ]!㳐Q5jbu(L]k= 2g>\)OE)^#(=e IDATa5htgɳraFϕ(%͊JW 5@^F岱 ()z'kBxN]K]o$ߔy#w}q6mV%m駟رc/{#nlBkؔŠkFH$@SDgBegggϞh׶23= a#RJJޘYpa?мys;C*j "<<[nUhוl_z\Lii$aUPmU㜧ruЖQ5zRu3SZR|IKL96]=? }L*`}ؖ^C@<S#b݆DnNU7zm|R3#G6) r.7yG\B%R Rv虪#kX}.KV<;G#zquy^7:%,îOM,0`U{`mZR`tܤ\4Kr"oejک:OEU$*iѓ_ __$^|y{H D@" Px/?ϝ;{w0OXz$gj"W{{Ms}u7}O~xwssU8{ϵlDKŴw-Tk66Lm::ڴ/uGL&gn,&kj0=ӛެ̚+dE?G*P;!_v+hۈ܇3LP)pꅜAQZUc[ۿ#733A a*Zs U{p%R%={" ˪Pu>XCft{$_X>'7lEgp &ΙI3`Z*'NMvw*}+2#itOe[9t -.+Sqօ֑7ѳգ&nYWM!qĤ#g63>D0|^'(O^_g%Nx@2z2 ?_V3cy-秏GQ;7{#ĽK!Up@oOD@" n0bBwӉ}"m'"g6_V~  deqܷxyfbno҅|5RIY8Gu|6w$~bނ0`\|+ N^k+rN[ۿt?HMel+`''ovDb]ɻimj^|Otm|BLEڳ0T-W!ڳZm^P7,=x*{R z{XdLD0co9Ξ% ) yPD+7_w .IGq`yMHz)^D;;x @'Rk_/M)DLJg1gaT,^`< x }EFg3'@)XQbG E[ 0aoB!K2)NY Cm?00N3F1@8xߋZU:jQ{2xv_pQ%FW&Σ|p *[`<8 +?|R]qz^$*yQ#_M9ʪ(?~!"wz=*#s1V|RMNysw Qkmm52&H$ Zha'?aBD%d¢q[!~r+{{{+܈I ˨:(eyFu[~zUpW(g^7©u}|޽"|)ƅY=Q#\J 3Oq ~OF,*/ `$?OWHi >,-LD.L3m՘3j NMf:!ϭB5 6O)i[1Gyn{QK!>פlUe3Ԛ}2[gy5>;5p)ފeTkuu-G'M9CܴD?Ļ)iu~xoy7^~y= ݇Vn{_CobB, >$d܏eQzjF/Ħݿ]>-pto[-ӰH|rx$&_$”C`ˁhsa'> [m܁XL}m ƘpbK2~c8M]R*H$?L]esAy{PfB{\_|3|4S},߆,r`vsC>bޟ,4?ڋ"~({ qӚcPzV}ߠ izJLI8pೈ3 Og Gsf5Y st+:jW,YޝGb:W+V؜&T}N"3qyo/sI^v=xBX Y/ s0 `mjC)xFl>]fƏBcc\!'a@VZx!JbmG2r)U#Xpr*3]:bAz.<V?M۠(tx> Dj滠W><"Ԣ&Oٍa-!xY&pm2H$DBY~n (/// jP\y${0t$<ӫF>fuT) oO\KpqA|όߎFlD\酃ƢmN G/GaZj.f=Q8t|jFkʡxmK}h( sTP^ylxQo+-Փ^j yַ::(93AQdEZRGk˷+6vą<ӯ=4M;eDޢbݦ}0H$,+i D#K0Ɣ^Q6Pu>c줔s:=y%mdy{#F6ŒV>ԘU;`1Zo4n.p?V-nd]u]Nv>QP]3TfYyh1)reSzYKp CqiKڴ+~=x($ئ<,C'5 S?bLi51y UNmSن^ ^ҿt2ṙ?M? W3w ۭ=JllD1ҿ>@)!Og;s_)Ό 8ġ6RWߌ.7x@mruFq|u7e\OT)V9@GjXkYQGyJMJFh~bn}2Yf&>+ q Am|d6Ӌ~+M_I"]=h#M#0Scl:&/܋懓_aL0=/QV`ARZcʕQ1ɴ)Gm dUҍȵ+YIT~h4:-b!Q5RRo+ DlܼlY5 猪l[u8YJv$:`dd7³^u6fϹUVʨ!뮻R(O# |p9|,ޫ|Mٽ (e3A YhU%׳m'R4+M_Di2ċnЅQ𹜇׿FIhݮ OZnc窿5 JD@" sז29!xp9-Pwk{Qai!"Jp쇳1{paPeS<}T%y7Gd϶ʌIU';/Ip36+1&/>Ptt-)apGǼjR~_#ch1P 輅;WYɈi*T%U4.7(65Z\EٛrÍLus?~[YWW-ꢕs%m\sH D}RZ^8kW]~L[kPN]2)Y@@ro|cǰyfoXA!x¤HkBnz뎠D*GW707|LL}1uQ_´S9!{1XU$D@"pK"r&^s;t (AL9Bֆh~qK^!ol%ȹzt AK]*V*jgc*<fzT7z~ CoLNw:(T|09)ҵ-ِD@" Hn{xMidl׮]x(ϼЭ]~={sNeq`<&M+wz^T݈H!WԝT˅n8O_ &G.KM|iD V)OyGSokXl o]+!/rR_" 4M= S<,󑜜x>5]~a}G"&FJy6O[ukіVbZ:餶l&}LAsҸ%9%.lI! H.<u* g%Hns&cmڴQf@M!uշ_J{GuL] iWI/ UWhT!Yw1:ԭvK9KΓ.oMUno - 准5hD@" H$2rvTFKݸj=iqn0M5@OǙLW'tBWFwCoH^ԡݵ 7!|?mď~%ʵ'o-jW$ Iߏ 5d!:yo2Jf9bsg;ʱihd5Y{P9u:_Ӻ7,5%D@" H$bBOk\g6Peh զYUm:yz,Wmu f}|s."_ޤ_vIHG(V?Oq*ۂ '~W\9\̎ {N "ݵ5KF(װJQ͵QQHJq0x,;%H~iהu!Zֽ|M-y)p ]ܲ_)H$D@"P_˿\L[^F*|ڴ8hrx<ر0J=S ~k‹vWV$ok_ Cx #VΌ w-Mo6)b&ό $dbRΥ _[#“1ۊyy^*&#+}h7fSJ9*KN(q;Agהu%ӵ^׸:Ԓ߅R~L.K'D@" H$C@MlX܂0~UYE@P(hQ6"gBfa%cXGO{]~>a)Z=c1zrDk凑 ,k/)ڀ^*J5(%*+XWșB@TAxDi$Й-ꅢ #U(͝^ӐGd DBdtEDtMakhS]Ĺa6 e^$IΎn+{^ln6.V2 .@BqxfVVby|~p3>cϨ% tmcα2T^H'rwM]C0ss"UdBơ3xkdAR,H$D@" f2Ho<-װz+ #BY^}t ==ǥ[PE] {{&#(US|)tŊ1reܽ_FBLg*X"s.1Iň`ƀ=e~oµH+r:L׀NğKrmg>x..1VlAI<3%WM$rg79|= ѬNS}_m"x9/EIm*as߼\y1&vZ#_ѨOsXEgi}lk?4pWGx9rpFD@" H$B.͙-TCcAPEjCEZ&ęu ~/sǣ;)4|z>Xzk$s)֌[`pSUEx C.fDKr+ UAٕA5{zuB497'¤X.ڎ*'Ӑg;xB$+O,صTq@jo/4uؚ84??lTq[TE*r2WO ) DI <=}͏V1 mLDBz^Je00ت~-D@" ~L{ IDATH$kB/=]=0H[^tnT^g5,(j^pСZ{4 f|iS1_(*OTʰRR^4nV$}L$f # VCk3JLF+W7hg}.WqSҒhje"%:wGw*ՅIaI^'r'#6&l,d1nʼUç2G4&yG ; yHa"͊x7 ;6V~i¾s愼C Q}P$l]Ԗ֧z*y X0#Ƨa("11I[hG{V9ٶO)#ݼکLzͥG6#B4 +h*o5EzgSBsۼ6 Rpq!;W0F51,%s>k^*H$D@" H@mKssu2*o/2!q -3+rg?Y?g/ΡNz!-- 'Nt]=sm+UxkWëk4O=:= 44wʕzxn6Ժ.6,fY^_h1a|fsj'bq L];ɲg2Jxzyڕ*CyyTפOֺSm+͢rσádb * _g|M XWrk@_aɒ%>|='=C'b[UU}O:|0ڷoONbNR$H$D6EbɓҥriѻVFڵ{t=ggM8$ 9guezr+0B&,q+Frhg/''..*?eP@$Gs)-0MR'u쟥5f5SSڸTjC9ɌF <}.z}syxs5Q:C\VooO:k _fL 0&`e#R}M^!0eglFyYyO|+w BO !Li[Ξ":|\G5HR !sbۍ&`ٸ%dE-`L 0&`D@_Flfd3*/0˓] (#df7 FIJ1*n1~EAbY[[{YCZDuCb2^< mcL 0&`Ud͑NsWow_^TmD RUI.}+Wܝ:> 0&`L 0&"UQQUU#}Req:&`L 0&n.Z0bVaT\"ErlF|̣ y”QSfA>yFa`LJ>}DIUN `L& ]B2C`ɮ|IéSpEX5*FW^քjU_H_Q'mr_.7Ԉl&ԽYT^|ljfL T[[}Ƣ]r\ 0&P5 +J$$rĂV®]Э[7[{IZ\Bo۶mx7СCNj5f+G%RQ<{g&Lڀ,e}'}fTFՁu%i~,V[?Ywa@LI$|_ R+^L 4 4GMfL 0[@vv6JIΟ?$NiO&MVNUVE1o\|1bDn(;@9/#-F~؝L:S> 1!;Oӱ?M-oXz@lgW,y/¹s!/cgҁ. {}:!L׼JrTq1Tw츲5yk刟0#@{rrr_ȑ#wPsssѬY3 4Um YwNw] rC1&4ʈ)MIIiӴZ ŒBz:"~qc̙HHH?G;?rU鵘Qv{ڤ>P&Zj}c%\tW~Y_. 6tIj |E > ]?]D)wn69nA `s L[wWں*J/s,і\T#@'GbҤI|wEƍ<'3Fg%p+g`霜Mߥ \ {JW3?ߺSOA\UxSuQZ=']SdjLN $\'1i[~[$lu\'fE5z@G|V.kjʰًwi{.xOޝ*@_^&-Kڠkzٝ C71Z\N˧ڎǿ214a<-l3'l;Sw/'maZ2 wZt:"I @a ia1Q `mM)8X?g/yb31(X?5U R>9  @HH=u:t6|}^NŅT\o}vfL 0&4jÆ h۶-n ME#y`T6x#f͚E3kWU99 G6mi&%2K7KSY5Ϭ.!LeFUh/{Cޝ'vlψMŅ6Zqѩ-߫F.JV1 Vuv^Zy(̾~3Xg:mGMУn6v18kР<8 `S tk0 'w^^V-d, }ߨ~X7M cb^܈A18fyrpFtD~;5LZgЍ}l.ޘ :r UzĤPsq]$ %t\gc^/cӤ͏bꀫeY~tVFWWW0J*@ej~rO>_<>3gR}չ%}[EX2}=!Q֑:0Rōg(U|zƆw ѕZG@K0<8kaxOEב)$$ '!yXD wʩbĵ~$[ ג=_U'Y{O2}X0&1)x0!LNn'w /VUI%}12Moh}hq[¤kvr 蹓ۃVB'=_J{--$_*Sz[܏ aO"N8{t f `L 0&PqHp X,u"5!J)/##K;>YW}{\nedDŽҥN:x{G22ӓh lG=zO~Au#q730ȼo?VI`m?3y6L/}I7>wUrajO_MQy7ŵQUQ9GFe6j,u A~Qxݩr E&P@jbƜd 5ŚO[H D.|nn3RvkBj[mE#ҤsKMzc8x(ˁ]qLzFQk?p()#>\|1`N6w{lB@;n=J ==]L %җ8UIҗ9 Rtc hQתD}EV,I0r^ "#`E'Dc jsJ+E#I1drhI>a rxkaߝ6bgo\Qy}|`LnH߿H޽MFi_Z,׎b]ak<$o_ѳS}ͳcvZ`jY_؉\Q=ߊڶcs|huR~_ߏ]ԟb&| Ξź+wWs5mOJtڵkk|=tO+5_M;̺'˛]aV6h&*uT+ 'ъkoҫ,*gϏƐ1;J,?$/ᓱiS|󄰋1J, x5 VR0N^//kHKډ5;O"!PV 9؀ѱY$%zPSr_3\L=x/~Dj5j74uYx}h .m`ud|ڋq\`#iZ~/1o[Q[@hq9.nF“&9*}|"Kei ZsyYʩx? 1x#wb>q [,HO&uc1{I/ߋ?E_ml?q!w؋af~10>;Mm>~6v] aO?;❣K׮\(0M/q ą3J9_j8u۬|QwiQڠ>m9*oaOM4 ݉Owg?sbD>ED5Fڊ$|׫%TO2zKimgoL'xo=F9$F|6 qmmz@Un]ը+9;bpfXCN":Z1?eG4 Ւ3mUhZ"x D}Sivx>Oǫ$Dᚗce7%ZUϧA:#X8n|!`FL}x|߬+Z"}j7&qE-M\苛)DO(KeJm44-f+|j$k#8, gA|( qѠ1CvI[RT3EEк'c۩5?Ԅ n`L$@t^6̀"A_c^x~3{9ޭO_OXYW VBm@x,Gk _~>Vş&G˰piP4u4sG♦'0xBA^}ƐG6b1oy]q؉S% .JDSZߤjW|}eɽv:% _h?|O(´3OayO4-11mu1G x_Ro/\_de?l1y p؏9ҎZZ|#I%! '<4ՁEM@Fv.ZEl@x[ܞ%VuZSױs7mj)^Ock>\L f`ԁdoX0o &P0Ad]3.'Mݡ,m Kf)I٪ArŋoDE; k1` l 0&CD(t*Nvc7%zjb} GfqM6)lf?Zƣ p!YWl2[$fNyzx䣽rI4k8xh ǁSx,چj)A0Q. mwv<48^947z_BfxH+{a/ҴJgSo\vM[đ)1V9~ETmeȦȨlFWcw_^jFA(03ݠofX":* %bT!9Նm.͌f7}ӫ`=g4bJK^_~uеkWdQ*f1-{ҞNꃸvr蝼Xo7XZ*/!_,V$ṁ7FF#x:&'&N\;i3o#+,%.&c{1E`L 0&p+oǑ#Gиqc=$䨩Gp1f5= :`Uƒxmc!&l8r7SW@QRm-CPy~r1 I ,.Sbʯ $PZHPf".'}Jh)M:tĥ S~vH+뷻//a6)Mjz#8w&FĊ4?1KEy˫+5  ;M4۷={lT ݹs'u٩fcS!-fgB7z8N.Y?*KGYYbkqԧ[O^b%}ⲙ脗?XŊ1+NĿ,qʇV ,.)&`:_GFFW$֭[ ift.fù(6#иutK3h /qMI5ɬj4Ki<}G_qY @J'eKuFzy@#@_ִ<ǔCvA̜9]:UGTT`]Eܱ4z#qYz+Wj"Es`LQ:9~˖-Xl GH\%UHgKiG)]t&Ntq!>|3WRQGQ׻.y IDATy]+7)505mVJwT3*(ߨ ۘ苙i-"4Q*_ C\HҔ_HVxw|Za4Ҭ87`Lj*@blݘ:u&T۵kxF2?3~GڵKNq#}E^R}tLR#j@1#SfARy35߰w|. oL X EhZ T\G\H#٢yj^9ĕL|ͣ&(+u<XUy鑜 ")) sFޕ/]Ðs=*"Ja61vc׆<3an%EOJͨWiw.aƕ3*F.sGF7Zƺ=oL 0&P Uy>n$BBBP&ǝ\mfӹf~WyѠ/5-+vYL:,hY.Yyl/^_F+|Ot Z;{.jO'}Aɋ¢B7=!Kω8.nzX`ڶmkhg#`L 0 @{HG4C=RZn8Iޮ/ӗ; îY>P&Z\ڦmB~7ESޑ"Rұ(s!/l%vqXX"كCsP;v4-2v"N_o;#_J+GVB4`L 0&p ЧjR@eFid˴3E5niެrӝYfigU &Ȗⴄ@Ro ^$F*-\ٍ_6smˢ4qAEFMao%hV碏35mt]+ĕ0x$l"NCa%k,Gúi"s^܈A1b"nxH|4_sR?jFL3 =d 0&`L 0[=}_FF6Tjye{"ŮN3XX錆;}Q~$[ ×L4w4:F /ԥX іR sԤk>bL 0&`Lp|5~3'˛]aV6h&*uThѣG6eKm 229-H^d߁0l0#9xFcNv2VkbmE]Mi/JóqB!}|wlx[ TN 0&`L 0[#iҬ|QwiQڠ>m9*) T5j;mdxQV:G0ȪmڴALPm4?$/ᓱc\@ZT;-1w"DOվcb!hAb1J3ycL 0&`LV"Hs6A]-S&-L-mrlu}LhI]֚|hs$NaJP¦١Oū$2/l"f V{ %41тHڦߎ=jͲD ŃPվe]»s!pu%VeL 0&`LJ^'T):UvzF>6mV׌f-mro%g|7k֬F Pv(SY׷ +璗/o#[  (,| >O*-=0bmc`, P=r(,z-2yHKI^[+P-`L 0&`՞T fT,Og//ak2[͛VI#=ST]*cZs /E]Eқoi +i#&`L 0&nU~ T#抯ڈ6]VŋK2JxzO1%1bKr 0&`L 0&pPu>O$:ї)u\VaLzW:/[7`6)h׮7*n 0&`L 0&:3}%5}ds= S D LM4Q_QG囵YB+{\!`L 0&`L| 8W(IܗKf”Qd7 ʫuM0DC;@u#%`L 0&#`TFѩ~' S}6 ˫iYI_iQ*}z[1.qQٙ 0&`L l4(((7;jF^7i_E]/#-F~؝L:S> 1!;Oӱ?M-ګDUQJ2,NďdF`Bjtsg%] T;( `L }eFF&OV9$9iiip)\x׮]stsFhh(5j^z!88XU'/ӗ;`׿,TX L BMX-We$0gljRX> S6B<$E8̓pƱ+{0&PZn ݍE`LjpWRoIH۷aժUصku-ڴiSԪU庪JL;v ۶mo: >>^^^U TuQZ=G2m^g׿,T6';A2sDgAt;^$:i4TSRn(:})-xm'c:2jS?xgn7S | MޘL$) /x#iܐeͳ쪫hۭߚ =p5ς 7e;u qeQ!n &Ê\gb4'''_|9Rt5W6k  oUSܹ L]W´!sL 0&PDF[]#)))6m65?z}z+),gi#77~E̊ qʘ1WIׯF  -99k֬I0rHDGGbȯ#+V8WV`LV%칇n:y5J% iu+xm@z$/? D}5m۶)-T7B_^d=޽5@&;dwV4mÊߜK҉߆jb"Y [}k⡦g9  @HH=XGݺuѿ :TB&PScA"2&BfBmذAaަ͌8]qMtƷ녫^9,5"֝ʉA+snmbh|@E 0T8|l4+H>ԣ.R.VkЈjK4ǛtZb F-NZ,ez>FUi߿d͹1.VJkt<>|ψkQWZ*u= 0&pï^T<Y|j~A>|ȡXF / N,;5 ㇢0ZnDp:@<=}HT{yYpwbڵΎ@9_j0ϬKfK%NvZpxΙ%khlXg?IEj 摒 qmNN&֬<[^SU?ܐh< %QxzO Nn߉ 0&LiVV6}7<<\{ G*.îQStOUl`_ޥ;гX}ԩSoHFfzMmHu|?cZ1CXz$U;Nf';>gs;O%q:Ϣ>~ %IǑG*VBtj>:2ktRR=PIWMMV>b%^{KM5ۼJ_1X<ߏ_q+t|>$Lm#7l;52^u&6֬>[W1#{3Rk}Z{ YE܉WK72DP2v.ߞGIP+*mm,5\F6HOOSwC|ɻ%NwUCieNTh9]'uwOSHJƜqq>,٭ZM/_6{d8&en?gX",߼mx%Zl\t$꺰{ ds 0&@%@ݐ f9 s9}hV!>ڵZ,kNb]aꊛucT|kFDb;c"**jY_؉\Q=b-cs|huR~_ߏ]ԟb&| Ξź;i5\M'd@kTIe^5JQ=z_#CmeUYFAKܫTc9Oԙ鼽:=Wh&Hhd0QfP|M`{D/x/Vߗ4K=uCe/D|SbSݤlLܞ!_MxEKpP," ֦c,| ?Ѕc%ۓm'NGʃ~dXs#0= G@B|),Z&Ȓbg$qXIaz9:$W2ґ>)0d"|,h3=~/#0{HyC _]_9w7,BNo'&.Ōq=>xco1?n.6}$cעOĀِQ/`LGqyRatY3:Ӈ{嵯쭧O[xXg|{]C< 'W_MF^]= M#`O3:/b;89VŰQq17GM40NjE1zĈk3$Dx}`M0fw7@ex#m_TmetL6Gbd3*Ok'3ܗ0U5 F FY5<5:ݷLAXTU5!(T?ˑ<zo詭NuEmʶ}&_BodϵK Sm{|S?Ffu@XG~ ?4F{,('M_.Vd IDAT>%"m4ܦ!xgh;aCﵟC` @+P(L?/>i#4,|EcXyEW$GKANoEIY`ZnfJj4<^Wn=rrQSfA>yFo`Ad%LV%An4mYG3f9jIU0kKЗ/u֡k׮#􌩷KnM:=&G⣷㑧\2[OAV'><Mׄ>Q ^tSxwt ƔB+4}m<SmAMI8-Jƨi&`Ձ~;9ƍ#88Xt^7zY=ƠpcI{pkhlĵA+jx1CphqO.F>AF()CJzEaB<1%ϯ-T )tܺDEtc^|qԑ|G/D)O^Gǽâ85$l2OݛI:ȦofRߴߥ޽+E(tI&Թb}gϞ8~&Hw܉nݺiv*Sjib ~4K%"KL_/>b8{8N,#Zj_r¶V%cWXY=!wabBSe(mXXj1&v|3g`֭43Hy_!,,bMԗtN}Ec/ SKhJ/q11Ċ(dՏܻ-3ady5@5-#?+m62˚{<3gj\(\ZN*#**J;v&MJ iELi2hyB]zn1+ `MS|*]id|`LQ:9~˖-Xl8:Kv$pZFKiG)]t&Ntq!>Ut3_FZ\;CsQdi:6'U;苙)=RJB┦3. qo%bX:Gx,2%o 0&ʰ0۽{7N vi7iѵ?vnA\*k1}y/0?VSP?Vq 0*L'KZ]46t7RQ#uC?+Ⱥ4q򕚯;2L 0&`H@~ޝʹZn,k4lIII3g6z(R5 o=ܣ qzζ RgЪ@Fid˴3/05k(8 *#Y}lgL"VN!ݍu9Q1&*@Y)wFb,$$DEkKh"}ܩնo?iq ogu^Tv^dH_3& mVpG`LOw=$h#!EϞh)=Y]7oL+BJ Rc5PڤW 0&`L 0!ʇ ekdaIՐYURR,ڌ97*6&`L 0&(MRմtV,owZڠYi&`L 0&(_) ghqWUK f#ꫫ`L 0&`Li.5z&Wj־>Mn>fL 0&`L 0He[SQYi7Gkch+/ajQ&ٌ+yL 0&`L 0&PRP7/#QybljFA(@3S`L 0&`L L@ojs\ݗ0UQvզvRK_3&`L 0&#j4jUi<}T> SGAR z5p}>pGz>fL 0&`L 0cfJj45HU}G<ʰ 0&`L 0&Jp(_y[sb&LQ׌jgkd1&`L 0&{ݨfOSnE`&LFܩXWTӲNF{i3*q 0&`L 0&FHi1o̮3=6 }crUTӔgOvuӗQ8`L 0&`pU鵘Qv"L 4rfL 0&`L 0'2{2O;]'UAȴ~s 0&`L 0*Bׯ_GAA"af5 {xH9r57|4NyFLa*;a/X{yCH_3& ӧ# @;):QB;UVa׮]֭zMVZ.UU dffرcضmx t*]pEdˤ2G{_vHwoTmL 0*MA_`U@vv6J$fϟ4ӧI&Uuz+DwVݻcܹO1bĈ2Pv)9;WjVL2 S5H5 A4Sy5_L T4'''_|9Rt577͚5àA[O傓+aL 0hՕ?9RiӦiYVn;,uD&Ə̙3~%~,Hjb1oz?+L*%TO냖di]u|@U%@'DwѣGFiKNNƚ5k0i$9ѰX먪_Uo1 #gL 0Lq;j(mP.x!==x)^ ]Шi۶mgOiqJ9\j>MvKNgMeMuF80&PIȅ>9  @HH=XGݺuѿ :TB&P-+5kkv&`L L 6h"۴Q4't//OPf͢ψ_|5OT}NN6ѦMlڴIQ?TR}PUmԾŢ51YFAKf3:c<1&pIkŊg0ZlQtҢ.#GϦ4J ' <%=9ދ-͝px Zd.A>fp 0&(:_zU,N<5@ϧWzEjԠKlq|'N|CSuW\ I 1ǒC˂;k׮wvL? ` ZHө>2fO 5bk2F&+W;i߾=h::X}qv4_*.T'1N;^E#Wcx1M7H'-GdH$#&`Lu$Lc8ڴUqEMR^FFv?}I}{hnedDŽҥN:x{G22ӓh lG=zO~Au#q730ȼo?VI`m?3&y6L/}I)O?=D<|||M ?㣯-8q8W'<'y8$'`L !@$Ƴ*hU"1=OUnmuuc|X|2+)͂R}U;7*6&n2B_4ͅ^-E)M)i/>KE3i,: g RUPyuHZ0nkXb ɽ۵7,y(2-p0?X+1& yiT@@@SןϽ,Bm/,9YIIL 0&nq42H7IҹFHI?%FNEčH,|EYO~3rtշ&~d/L܌ 7 B+= }zoƔ)'WgiAl&&' 3w[ܼAZibgk"$Ey8uȓW߲4řT73j7vo&LFܩXWTӲNF{i3*q 0JH ((HkH9,HҊCS]Cwϊg>ȇԤHP<ŗRbzHh&ƉH޶}^O,^)`q+bYz"tĉ`h-L?&` s93ZBAtY~c<ޛNѻYšuŦ!SNQoK~zG>ڋ)D#q: #ǁSh,چj)A0Q. mwv<48^94 = V(L_?viu+# 7 "$H~X g̮3=.%>P15)ȟ/q 0JJU0kKЗ/u֡k׮#);G+EA1bܮ=}Zɸ`dAӁX":bJX9c5[O'jp[P6{&`՛~;9ƍ#88Xt^7zY=L*Xm,D1?qmP|~(Cy(*O.F>AF()CJzњxcK)np-T )tܺDEtc^|qUbcRv~f965Ai8@$@w>4iM+V۷oz٨;ǏΝ;ѭ[7Ne[8? Yb o-҃Dacs9>39cN ,lW FV.-| fx`L!@H9s[n0QF]$BXZ壋5X|u+SI^@SzIѬ2{2eڙK2d'(` 0&PЗ5-%O17 1Nl>RJ_Ň7&`L542Jv:oٲ˖-Sgt>WgIV{hqҥKjK.S7BTT4YNٝs"' {˓9#}y@%#@_$NYΈMW44嗞0K`L 0& гaaa 1{nL:Uڵn<@uk?#vڥ`'ăTL+BʟX T6'egL wiZ FV;eKwcYw!TC0&O{w6*jY=ӰaC$%%aΜ9<߻Ke/C0$s&9*$JMݩ”ҩtCplM$ E(:CUnϩ0u3{1& S:ՍXHH6֖DSm,:7/*v}H_jZo2ʏawڠYi&-Mm۶tL 0&pc 觻e͐gOi r|5M?N33ћ/wWUKU-.Ӻ 0&`L 0NgGU#ͥSZd'U=?ԾS^;郦MuFdL 0&`L 0g#j#nDTkch+/ajQ&ٌ+yL 0&`L 0&PRP7/#QybljFA(@3S`L 0&`L L@ojs\ݗ0UQvզvRK_3&`L 0&#j4jUi<}T> SGAR z5p}>pGz>fL 0&`L 0cfJj45HU}G<ʰ 0&`L 0&Jp(_y[sb&LQ׌jgkd1&Pgyyy W`L 0[][5V%(LOSnu=j#T,˫iY'I_iQ8 "LЋnP `L 0&'YYYkJ/#-F~؝0u}@cCvPc#Z^s 0L ((W^վDop`L 0&Zjݨ~ZL_^v"L 4rfL/YzΡ0&`LPuQZ=G2 fϘ:SQpTF{`L 0&`e# Y-jYʪyfula*52@{yH_3&`L 0&hj/S2X)PSmO^=`L 0&`L 8&`O_M*5M622߭}y S}FAK;i}|`L 0&`˞#EjnTV^,M W`L 0&`L4od3_F6).~\ (H#afL 'zsL 0&-L->7I[9tWow_^#j#jҮNv{&`L 0&qTF IDAT:MJ9}\Va(H D(_L 0&`L 0&`LL_IFzG5[q0iּ祥gTQQ1&p3 \;7x|"\#:TԿ$\ʘ`L 0&p p(_yeg&LQװjgkd1&PdX1+O}|کxŵf} ܭ1&`L $`TF%T?5O#3a6dU%dy5@5-OJͨi&*!,SP`"Ѯy$p vZ"zzl No7͋mSl6݀&x}'wHwpZW]W *("(`(`Ęc$jW%(hD1Dl * " Hg-l?rvvӟe03眙9sK~^߅waOu?4AЮ__\X{sq 7   /:efwBa4rm |bׇGX'h L^_~ >rwhcl5e`vYC֕e+YHV.Ü p߿fWu/@vCq&l_y([?65bƣm%S)aƟ.Üdvr4B^V=Xɀ _sh"'7QIĸmݏu ]@݁ǖ/N#uqʘOÌ&U9UOT6ڵGmLKuIKƢ^׆&ih+q@}E>6-F1p7   кWzmP0 ܗ]u v ]\dkq[\8)j⬺^ST; RZߨ#ȩwgd*Z58(r$3kj0z PTS}4    ؍ XDK_4_ظ1ٓ7lHFqc,IZm07VT.#,7Ǐe=N |Et2:Z^8* =aֶ߿?wG~-[: |$ajO>mqL$H4^ 9Zslxk= Ѱ*;rҚ۾GS̃k~aŬ{~;dM?Ÿ/R&/xÒHHH[A ,8l;2Ky%x'vAK<ׇ6 I ?{dTӞZoz8tM9yF(޵[ěa1Bёy>_0&mh3Ǚqjl~m$@$@$@$_׵~x(E퓨0Iauگ`H`&<#J?(WfDo2 $@$@$@$K_ea͍ ֿ!>՗jݤ_ސ+$@$@$@$@$@$@)#Msi]fv*1u2_fX뜌#H+W⫯BYYZJٿCiʖÒ @$}vc=@QycVEM/{&}ӢR%Ldbbl.D}IUgm۶0m朂HHH`$ ´2n%?Ӽ=V>&6c3|%^b|v7]iNVƒ"ݾM@ @ENNN[<3r   = w+ՌGMnI/eT^7dXR:]GF$rnD8$ &仕|j#\_R6N2đ1$E> f ` Sq     VaKk79:N=v)$m1%ZX'    h~ib*YaQhFNypuF]_>-&qcF?C m tŋ]N$ZOy圎HHH ^`xGΝ;;N5սCsF<_- ;Vbn[d։$t]bܶ: .FgE^p1GOUSQZK{tqgyw.~Ãv3unIcYoGҗ]u>2#HHHHHZ4*,Y'x"nވ̬MnjTf'&^YT}g _f_oϧIH0l$]I,16% @ P]]<ɿ[nEmm_K7CE5\۬/M T (3"w+۶3vt-5XWZ[cce6A r4'bJSyCl>mqL$5 T_OCkYXabM׬zSxʭ 4uzYur THHH{KKKKDSr16bo0`|&^6F쥕䳹d+][JTUScj0-|>]xW0PX:Q_|}}h#*bXzaUFE*X "|3+W<ߋRyX L9 wYC&xgƯ100ܨG%^6:#)ԋ0qpl @K$ Lv >fǴ6A]||߳ʕXrgp_T~|ZT~ؼa-2%[6Lkchպ23BEq_coa$m0?W'%^ku ݀@Y6Pʏ`Dci~yꕘ6gg&s6,\>X<Cv Ƭ*p]>+~4sk1f-XKGO1?3&@aHHZ:E 7׽P d~kD_nAV`iJ+dǴ ޣϼ чXV[%FdzD_گ벜0ƅ-=C~`L"íI[meI$[p/ V7'(4+Wb ?3can)Nu& ӚwfSb3Ĕ[Í`N\ jDߤi?Of܀SapcbbcGXW` G2Kۇm I y"-^+*qN3查>#=#Jc{sfL؄M؈!~x͸怏[f3 F[o6hͣom|mm02^]/*ivS|_߹ eo~1>%I;1.ZaϒHHZW1a*^ګSSF^?Nڧe?W+L_t3d FNYC[*uEvL}Ml>  ?H0$0{ht J?1rφC?ي\[OSNdCLIDsdvWǏ? ]EI/F2h{^:{P|5/RB^Sǹ +ĵu1z\\t]R4z'  uӌHp,}3Ba=j9}:u{mp鬥zvhW?2}9N98G:mKϙͪ{'M$@$@$ ]ug/0 {QK˿MkȠsśrV[֗[ -UFW1$^c7*D'd٬OaIJ=b}6=>$@0JRV[ȼE63.*ٴ⛿iK)xdc DNQIw C]'!IibȄ!$@$@$ygiUUVZ"=MޅmP6~)aZV0;i8e-Zk7Llj϶mpBaM l$ZX'M=y+bu9l!6hHfS}wJF$@$@ F?y3ݺݦ9FNN2_ن÷u)2;jm>b]M&L# m tŋ]N$0]Ȗ%Gw;\ "W^8餓kᥗ^Bmmmݙ5ڥxn;ڒ#'#LDݶNL'u?IHHHHv1kگ_?ׯGii.ҕh;krZ(eAZVYm=#'#L&%g!}l-ƣHHHHH`# MԣGl؂"kD!% EW|)?v䳠b,IHHHHZ ]D@r͞R+ TKT'j}fl%ngI$@$@$@$@$@2/_fZgq H %/ׇ6      +X[, S\OVxz IZ d-05D$@$@$@$y߫|j#~]bֿO1ʼn]6$ @!Ю]z y    (ݺu+;V34Ko6Mmgc*S-LIݤom6 @3h߾}貲fӑ nE@^#߯U3tĢt&EJZv1mKsn $@D@l7h~7m      ?0}e5]c*t=lz.T|}}h#HVW0E(9 Ѿ܉_ǸBT|f˔+l4ld"cH/g4}$@$@$@$@$@$@_Z:N= „$m1%ZX'     HOsg q0aA9Dݶu]|x} F ^j1ێEd։$t]bܶ: @ h][g}kfa D_'anY'     HFվ⶧CD}&OeI$@$@$@$@$@$8X4Zѓajնu֧m6ΖoX D'I_YƳDiЉC @Szu?̏DNR' K~=$@$@$@$@$@$@%MiKHنo蓨0m zĮc!$     H@4ͥRw^uOL0u%mmul FH:ƊNmǍxma 6[z7?}$@$@$@$@$@$@Oͧ|6_a싍}N& cJA$@$@$@$@$@$@qvֶh:-X;~2UTOvmӋv˒HHHHHHh&jܬt당0$]x46 @MnɈ?KxN2lz.T|}}h#     hJ \_Ⰴ ӰIt_!qX-| $F LiRzDunǔ8kmRZcHHHHHH 9>b6Ν-ƅÄihpuuŮN$@$@$@$@$@$xn;Znn['uqۺ$@$@$@$@$@$@'unvEOF%`~gu+ IDATHHHHHH u QWƊ۞aj T`$_<16% @bhFO:M T։Z8[JL$cI$@$@$@$@$@$@$}/_fg϶* K@'jk_4m$@$@$@$@$@$@M DWگ귦3Yl0?:I=0._ @4.YĢ"eֿO´a'taudHHHHHH I4Kovzm}?2M—2EcM$@$@$@$@$@$"E+:MZo7㵥J%KlMKL 4>&6|/6&:_>$f)y M@7YۢxbT S=NڵM/Rm,K      #5̪usұ/v4Zw}nn<$@$@$@$@$@$@~aj41'#>, Xn":ɰuPHHHHHH)hJ:&s}Mg&L&IF&R=b}HG$@$@$@$@$@$0O LI SlIim>:u      O8w0MmKNP>>: @l_shYDOFmNB%m~ e{g۱f1>aMTu:u      +lDK_ +n{:M'Pm|X$@$@$@$@$@$@EE=6Y+Pm['j}fl)16% @t|>j<ێLTFJ(,m~> 4%M_iǪߚXgHT$z°KcN$@$@$@$@$@$ZdmX> ӆЭ-N:M      $ D\/uW]T S7 _fX6 @lc6kqX_ז*a/ik7zc,1G$@$@$@$@$@$XP|gƾؘاJ|Il`=D$@$@$@$@$@$7lgm≵G,S%L$:Ik6Hm,IHHHHHh2iJǺۙ1G%)sgw&H#<`Ov#   E+X,l SID'aIwC @&Og +Wl aM@z l棏HHHHHH 1aKk7Yi'A0Փ$2u;Xk|}t$@$@$@$@$@$@/qlav7.&LC;(ۖP/v}}u      ī\-wѲ0uu:1KX'     H?|u϶c,b|24,$l-u<$@$@$@$@$@$@#`W؈V6VtSO#≱,IHHHHH'F4zR!LmVڶNRb"mK      "+Wb}6;xW0PX:Q_|}}h#     hJ ~]U5b0Iauگ`HHHHHH /u")۰ } 8=[[u3$$@$@$@$@$@$@I_~kc n͖.m      X)ZXѩm}㸱-U4,_fKobXb"HHHHHH7/}1O0 $0{L3HHHHHH nZMkǏXJIt֮mzncY 4dV\u}1ђDsw&     WVߍ>gI0uIMc܅j4m$@$@$@$@$@$@M DW1k:[0a6N241$E>      /dd}ڞPaTONPgcMJkq $G|Zƹݸvf'Mm:A]/^ph$@$@$@$@9۷RʇGSZ|ZnM#cṉugb ːn2m9b|2Mm7d,Mm~ |)//ŋi&[F!fddڵÀsy:7g֤e{'m[o21>a+0[w˰h'   /D޽qAcǎHl۶mÆ n/2z}7EشMS&XĒ+,\W|>6nLtSHFc,IHHHvq"|͛j3&R]|iiO_{ѭ[7nR%{$N0&̚LV%?Ԯ T։Z8[JL$cI$@$@$@$hѢݱc"777T%Gtr|ڷkF^ v8幉>ZDMy=H_XND$:.H| GF$@$@$@$ /[l .C6lX yRu|>T}:g5kږSZ0"Hϟ"o>!{f=&Kǹi4AhJu%>k }:IN2..H: n@ ˖-C=ЦMp)9vKVy6l$J,6퇽:& m<4aHry1hРmsS9fl Qa e,qnĆ777n ӆnMnpl Da=D֭ myEL7W-͛ ^3 IEk ;umåI Gg?r\z+1]vg}0MR~nj̚; c'aI [MtsD^Msi]fHq6>2ԝMZfH1l  <ԾRCĔ|1J>i=*/GjhtV`Od}yڨ=qGAaF$6H5F\/w̩<7djxhL_^.ĄmSGQs.pʩ`'ޜP_G%(1bz{\OEx"HDs16iE;dhv1-Rz,1nIHHHv'Iv#bJ_kjopG0{ïd,yk 8d~aj[.GX-*bEѪhOt4ck=YYYWa,9vֹkWK˪h#̶|F?y*?XT8שׂ1Pm|]#\C.BVb ok12{)pQ,80g~dM$f4$@$@$@$@IKOEJiqn6ppli>{a~er*ǜa}e F|ol*3硎'L²?O=.:m8kei4&LeY.Òz lz|IHHHv"J۷ou֡]vټ@ԥU?l&z.;|0p8(ݖ6޺5jC}8GqK~Uڍ: RTWE;k׮E/Sf?7y8Y7j@ʺ00Yb7oѿQdF6kF2?(IǑsn2m2nvw_'v<&8IHHHvq"~:v\29%Ż×r ;ƌ<%JgSl[+u e&;Rvm0Nh&#;Qee1Ǜq$J%T(_>-fn\h;LvP7Q-:A]/^ph$@$@$@$@.,**BEE-Zg^ø\3u$_⢋~ ߴ'N0,++ Rh<7:Ö_O׹I`/Wv"Ƈ]mP񻉺m=NB%m~ | em۶E>}W_}={DݓK\*p3P$_`%- 6lիjժ6%d}ynR|uOڶK*a>aN$@$@$@$- =r">#GyR)MVyn,t82+ե|/lܘv䳉ccY K|AAA>S7>YƼR.є\n+>XJyi,<7sksfK:]>mqL$   h˼ޟGQ\ 3<7.:73 "_XN~KTJBV\D:.H|}}h#   Mȗz ܴsCFot !Q$z'Na6S%^kx @4.Ģ"eֿO´a'taudHHHHHH I4Kovzm}?2M—2Ec'׮^'/*fg^ޓڊ${3gTWڝ׮ڵ%'vu2̸*\pUx1B%Mh6{|1'@    v+Ҫu&}7R%L%mm&Vo%ipA{qC{7(=*j:\K|L~yug1Vx7`<7ji؎CǮ]ѵk[w3V$k㌇rrkw_;lz(Y0mo~M+kgt6IHHHH[H@k+~|6_q":_>$ft,NR7[6zhP(dfcUwT0WT/߈XS[:ܱ-qֳu,6DUV\~}M 7h~7t̘q?-kt+1BoUa00Yf00w,:mkU%1Xq婨h yL{a%>un;c$>sw壋"`ۍh)dUo0xob3Wb7?GytXN>v2hS|͇#"_/.\z.>/ wlXE}%ueL3VmG)|v-7-۫1x\iCVy嬏au;ܦ^[Rg{S:m]bzK~:߻j!Z78(W7By{&ԝY @ %Fc}$חezG[щzXG.T|}}vm@eeɿg.^NݻKaX|.c{z3v6 RibNQ?S,7W_9C c z Sv+>l%s * 3erf.]}0/=f299dSkJg3 0kz;!S3Ͼyc 8J;ޣh\uޯ3&_23yS4WY?SqK)E*sw-2ٍE%&#~%n1bչf2_anFE@L/}ˌ'    +oR SD'd'٬OaIJ=b}6=~Ժ\{ǔw(vL<,mov&M]*`6K IDAT1qcYg; ? WXk_ g3`jsdZ[Gr4 Ͻz%Ldn~).}|MO.5thՒy';d[U&$3Z>a]xrѵ0ÎyܚR<# r7V"u* 'I͑% 4#0g۶L8Ky OlIim>:.byl&1cyk7Wڋ bС:t0j".S SFD1;cS\rπ`kWmGhE5䎧(e/N!Ƕ $&!ͫZVm4m96.Gٮ)~#p- ВO—SF 7L橀1Z4L-\:3ƒ* ?|V!j|p?|:J 5OI:Ko+Lb҇CG`(8Wqˁ3o`NoQã?31rt@ty~3oǩ"تJ$@$@$@$@;@bnmYd0YZI3]e[˶.D>R|6ƖW^{cot<#R0;&\38QRbdyo<7GuEfl#XRBi*JL&ag bP(1!WW`cI ͽv옆SAF2s%=uydVlDF5O\.}kre69Ih1w;0yx{ VHHHHv[aw.>ͧ|D6kU1RmȔڥs]z#z)but4;׈Ff!ٍkx#3׈f}2r6N.!a֡u+QuK.]'#$:{@1OF5\nƳE$@$@$@$@H꯰)?.}|adTvccY $N YTtS T։Z8[EY @<YVv\e4RBa DmmHHHHHH)hJu=Vt:<I0=aX]⥿1X'     H-hKu]EE6CDwLp*zB8XgH6IHHHHH$Msi]fv*S-L$|I[-c];6$@$@$@$@$@$@+RSۤqc}1^~C7 FcX͖w6 L@cŃHHHH |Ml:B|%^b|v, Xn":ɰuPHHHHHH)hJ:&s}Mg&L&IF&R=b}HG$@$@$@$@$@$0O LI SlIim>:u      O8w0MmKNP>>: @l_shYDOFmNB%m~ e{g۱f1>aMTu:u      +lDK_ +n{:M'Pm|X$@$@$@$@$@$@EE=6Y+Pm['j}fl)16% @t|>j<ێLTFJ(,m~> 4%M_iǪߚXgHT$z°KcN$@$@$@$@$@$ZdmX> ӆЭ-N:M      $ D\/uW]T S7 _fX6 @lc6kqX_ז*a/ik7zc,1G$@$@$@$@$@$XP|gƾؘاJ|Il`=D$@$@$@$@$@$7lgm≵G,S%L$:Ik6Hm,IHHHHHh2iJǺ hIJ"nNGl +X$`W$æ1B?ׇ6      +H5-KfHLa>2,IB}>?K'_6ow8l <۷oGmm-jjjO˰dnZ>CΕ|x4% C9G|m2Ä@:A]I6)G]҇G<7 y9 ,^^!.v:{0?bX    A@ O?իm۶\ ";;=z@>}p 'cǎPMG"H7l(?o~ee5j3??a7'?!B3-Ч|ZLǜM@wۺ[Z abnҶ6ۺRY1"?27>. ?:xgQS5w Jq׃5?矘9 @裏?pr!kЦMߍG(--ҥK1g+8C1i$deWr~߁1s.(hc3(u>#m-IJO[~Esgu`Oih-6 AuRb|CDmbmA6LŊLٺ[Z1*[bTnEإ.-eZ_ï. l\g^~Cc}dffbC⫯)N5$IHHH`']ӧw߬edZ{)f.Ymχ즦Qۛ_+s6^w7\:loJT̺{Ѫ\,bUywX'\u)1S+Vp!-6RM>vV| pt+Bnn)bRlRui[AK+Vʔ옾91} +u J$**{f)ǢG׎8/kkqIx "zfΜ n@.uv9EԢ|oXopI'%-~{cu9nmB S>䏞2qgcc#=.`rS*'YoKuK>99Yxxå(fb.<5ƪгKsI$@$@$@$zrOW_}\jw&( eMظ Cl8|^;xq&z0r3mF;19 pw s*a ӌe8hPbkE-ZgFtixj g.M $?40ϕ<;zh>{(*ddWR!L t֧m-%&E,?\}a➐e||ȃa-2q ޘ'?D֮ߌҲrmovY30~p̙S 4# On UBT*j*9Fţiu1"Ip/g=2Qa* :.H|cE4rnvDO};kb^ST/^I].q᪛jA$@$@$@$LZC{ }smCݽ&r_N՚TkǨ,o| ?6AUIJ&I~]OT'%^k#ugxTn .wy2O]K}ꅜL#NiCZ\|gHHHHO@d3Ɓ.F8 Zs, #aܩS'?(X5};5}(eT^ijJM7Emrc+Smެ8GoÜSN%־[0a>q_gqGTc^Q ^|ZߌHr ӻ#jV?WfO=12:|T}FZOV>9=afMÕbn8mۥ=8;`ܮiHG.377., S/íI[mMYv/ZOc/7ӃcW>,CѹcRgHHHH vQPRRR.ʛDT3V}#+.1"QEfަ2=rHNk^p#J.xޟ7U#Qzb6:o]Y~= Wߏ/Vr>i_Uv7E 3 [%mk+-xyZrfn> g6wr̭pF4oFd'R,33?/^т'&dVtrqʽKۯnF{s+VJt>6rǽF^2yȿn/z; 5_=v$Yw9Ng*6 f̟#(#9?U5mTYmQa.2r tIE\/uW٩=RLItnem=FK|ts:GC‚F}S6    rr(.T(+Jv!B0]Yp-?~p5GὯq}߅8'Ǹf=|ߛG'jMJEX! Sa+-ɤ)hsN3̽eD{ia*pK;[o+3OvV0E3amMoj[Mݼ&/J?_q? L?y_?fnی _>r$*0g>&6uS[ lRLu(+f[aKg63io3&kyض].ϭ19 ue_F@q #|4X[a'/nqHHHE@ħ\+\2ZXXSkji:/vy'ser26\lkR,{*xq3>5G1Oѝͽ' LT}IaEVʃ5xkݹdlȎ9gfT|MNT5J̈Ffw־t3X^Aq wPy<7.56Gvhc[ۄ\sm0fMhmP&*~f@6}Ɣ( "96;י5"kPj"Z[t]/yT$07D}{u'{?asj^=:RSϱiV۰񰡉HHHI@Qyh\n*Dr^)ͥ\c CzPu4lbz,< _{|x ⶽ۠OPa0ξvT01屮1}+qyn\ELGDipEq-o ѱ>]+QZQev%3]SFLɃD,$)%mn[Qfiksk)6}p Fw +ZZcmN8^wk>n=:'o0'`<לV1\e.cD9+ōK!?ej5;;Mey]e5;U'4o6BۢxbT S=NڵM/RmlJǻ bā{?`5;ƈ!\$@$@$@$@i& yo*cӦMw\{i*EO[W⟝!8 o`H&b??#{ 󽇱ElΨ=>p铋Sػ%u# ϟ' )YTJ{/YxzVkZu\OM7,üxC=?|C_2wMʼ"y¼'9{<=e.8(tM$@$@$@$f[n|%K`(..6B7ґNuFl6;AQavTKʫgvymf7f'\\ht%+VO? p@1-]>{vCN.T*&>^Msr~@H_sya޺Î{T^,sCiS[63C\6?ɶ#J+ʶaՊoqQHv=w~|̞lv#Vn֥e9⬓6 ~еK[Fd    # ;{' ̝;7xDL4L#bDУ av1׈KҺ %R [a!確`.͗Vwh%:~ ;t5з3Jϧ]U3'@!SzddcZi~QWȽ 8G4}%~#iC|fKO:D'd'٬OaIJ=b}6=~\#¢%__24ܬ,0ѻg#7= IDAT]/_s~ nA#   h~rkcsȑxW裏SO5;Ы5-F{oby̙3Iq[a!bWQ]׊Gбdo۶$t bv[wKwn]_+>{E۶VR^3Opac\ku_Py֭Eͩ\c/RZx,IHHHKFWZz+ttذaOqqqpj HŦ ;˗/{gy1"xT2+g?Z>w>ҥW/ Nlitm3H:1N%3"iIL 41ic4'*ZާNսo^{sZ<ߝW˻~q>G?xݿ,?wo~aӟCոQZ~W? _1l՘vqAJ,K>VMM(8MȃU^I[Ԙ~q?[6Wݽ;_y}_[ݯWޙ( D(@Q O~{woX*ewhΠoD>>x[_~7J?я~ZJW?Ԣ/ m~4_>gv/'C1e/MUh>ezJ1oLg=C) Z5h@ݧT>'Slנ>zco??{v?Z~ueSlw{{^yQ D(@xZ "iiF^_g|Ԡ!72fYk5 |64|{Jê}baj,euڅ~S5=t:Ը2%kzeW^}7>ϟLw/{ @Q D(S}['9ioM?Ro2+h+W'_d庞8-γhLyk]>pd ҤfD(@Q d=̿/T9b8XqψQ D(@Q DE5]ߔ~-(xG,j*K |ajh?q +^"}>ˈQ D(@Q DxWx)rro¸ScJ, X .p|pY U}ʋn&TzW^oBka?[jn.\$_#W8~ZĿu>ezzςnU <GA+&+L $\VMrQ1>Wl-E1S!F+_BԐf^. ŗ=iDa5Vc8~\O'gy>CLp|{=˪?ҐO,*/3<|ꫜK~UVAntzH}<iTKE0je9V5Zy8kXh-X#k쟜gZ.Ϗ̠ :8/LF|PC~I'yXx7SLL.v%U/ _jGS|aw  &\p'KVC< ׾k<|k) XbWcjZkfͪctKVH/4_O|>.er~r~r~.93K=?Ӈⵋ&՛NΊO3*˷M500 |X`.=_8TjC17Y$Ƃ/}NF |nc#Ksq0Y L!:vX~*S%ϏŬܵ6Zď~{(''Ssõ^OCOsS4`4;_H,zo^'GWy⬎-fZ<(zC4t y Cuke>knt1rp[SNz.''ges~r~r~Nz.'y=IJ BIJp|#f>5`>T7Ź%AcZ ͯқSdrS5rh^@Q D(@OG%Y bGRG|7sA ^k=RcĹ^ p|Y0MC9=T+ 5pl5nKFkX~מYO???~"s~r~r~;3Y;?u'LL+LMj-=Լb | 0=xWܙԘ-j!|A*|0 Spa\M(MyV_мF(@Q D(><h`y彖|H/ cyA+>XZ*okcIjV.fA,. #PIs*p.ǜ{)`k؞(@Q D(sRe7ҐUC|wys W _IIJmmL)dn¹!V|~V1O(Ap깇ѤX9b@Q D(@S:CUXritrШ*g)9ރ{akNǵ4ތ@ _ !s>Bs*'9A^wG\tix=!sx[0'`p>wb+utn_lŲ틭S?Z_z8`XrIJK1|iPKnOZ^Vj6٩1e2&,7q1b5n+`Q(!9ij0:|+utn_lŲ틭XOֽ>G͇z$)A0]4CNS3e0?K#aÍ]To6`C8ƓoN* 9'ܽT\UƩ?)iSMjN tTƧN8贩XO6q;)iS:m*VwRӦb5>Ut`c'ba~w^ۘ4u1HNV(ި0P47\b¹qwoSsר=~&SP"#mOt6S8IiogR`zF<~ˊs#yW |׬!NV9xkcI%vI"Nyx@T-𾞜b@NVy|8s`17ΦJ;}N8:??ݹtEI:?r_>1Shx,_{gvkcEt"szތ˛.~ ׀'_9pSA^1Kd+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1d+;ՁW1ŗ| ,=b0R;s3Vcx1e2L ߔ[s3⪆K&xcnb~⺗.x/~(׭.}WL=-kR+׸m foo۪\36\3UgfGm fos܏~pV|KoC>0'UN<5ȯZp7K&s_71M_gj:!}̧:bYX5kkV\8 Tj^^5~ Tj^Wq[WU쿪WߺUWgUjzxz_4ܧ/xk-sT\y{G;e#7Y>oS#ZWX_ ON8zC\^_YKsc8>zڊ;KIi_99gN >ss9)}2?SPz"}G4:Kөŭ8jW}bkrgf ,Ax,c:vɧ7`K5kx|}(;ollAs~r~r~O3OMڧ>k Gy.a񚯜w/ʏҏPU0r Xqՠr?0,s`CaBIDATpuR^kVǰaE|0ZXq]3W'Հ_~+ڨk.s;ְ.ӝmXOO϶ұr~r~Ώ4jKߦ•u_j]kN&N%W;^}jXq5×_<7Α?&< L:MyutwӄWgM:Mx;W`iϫ&&<+04Ntc飁[ktWN 7֚JM!wOyg8,6 D(@Q D(Z1/ܵVsiP v^۬ujk5 eNb}+׿5»&bst)Q D(@Q CH-jI[wjw/ݢک&ŋ~v~'-n-jI[-su:R@Q D(@Q D(@Q D(@Q D(@Q D(@Q D(@Q D(M!BTIENDB`testng-testng-6.9.5/pictures/idea-rundialog.png0000755000175000017500000017277012551235562021122 0ustar eugeneeugenePNG  IHDRqB ;iCCPICC Profilexy4{s&qS'cq̳y+C%NIm Dr-喫! yۻ޻k?{g؟g6@ pbHbx\g;@@ ( NzyoD+xĬs F"{5 dɸ5qeYGD&v, @'66>0~ӟ`М"b/@GN(?}y@jA&_ Tǰsgg" IiYyET4kji[,^dckgA+Vd#"WZ&zmLl\qMniv'%INٻwi3<}c99?=wg Ϟ-*.%.\,K~+/rU7oݪ]Ssnm]ݽ>jhl|iӳֶ/:;_vuwzw}1~dtlW>T!U X:&f -prrvq]eW\9#-INٻoii32e>}4iSʕ׮]QUuV5wݻAG 3=oxeWwOW߼}IC\Bj@YUM]cKGWOb b77w%^^>>~~3"$~Gn'O/8SX8QRrbiwn wh|iSsKk[ ߼~?26L>L  €{K3$D7@-A< hAư-\HBN<&B`D0H"JO'm&&Փs Wy%*M hYA'BA!A`P=*:L1sbbc'$\$% IJߟWMVB\̟VIEUNV=O#aZ,&WNGFF& f# %-mZۥw:9e8/uG7_m-A1+BΆF:%:,F!5>{^ObƄ6[Ŷl/ۙ;xAgd ʾt49' Sg Φ'[ZbzQtR}Y^įwݸ|3:&n`{=n*̸eq[`ۺw}v{_P0_cKO|Kפo^' T>/QHAs-+68S*4 #'t '"LdeD1JE2'vIOH_d?r y¤P(MT)KAk+'&X.$-ShBxHHIOf1jŢ%ī$b%Rfa-]nrrr &JJss2J*Ū՗iXWY@ZЭYўF.GT_opp1Iitg,.ʹksPsLtwQuMZ}G'˫gogr &~i(5kKc#9-LWĆM9[¶-il]I!:)}J*9ϒ{O\>r:Pse%(,/ʽfvjJQ vF{u\E[~o'뱏1R޲`-ጕ=wшn)[=IܵdЖmev<ݕ8Y(~_4Ƀ9AYJ/mK?O.,7K.10Xz+*4uVVNQs֣~o1\?,Yzd/Iax \0{8ӻ*āyPȎ~./r#9kVGNL$>>e1]:,1v;m IDATx{\U?;{w5Q@K--O$J$ oQV>O-G0i@S LTT=;c`]Q.%|w9gΜ΅BP(& P( Rǰ,ַ  BPd2շ  B<H$OֵjvʕmB}ƾ7&`- BYe΢z i F//~M׫T盟D/=#8{[jlos'-"| FoMF›xdL< -[ 2w)&P*?ޮ];_~FeW5)VLzoOjJzXH!1cȠ+|0nM}lT?&ZN1ww7o>QF;<YS<ϫjLVXXȲl=MzB &b4?q kZ{v;+y׺2 YKkm(yȱ=<4i w P z'~.iI F>LNؠOc```#7K$۴?<^_Q.#@MKosT闞)q1rq)xO[p%%ņ"`(iQ+e$}2ҏgeqoe=?3o4QԨXܡcJ<}v zkV.P\ ;;>9a[|䶚1ܵk={%*VZeee#k.{vvvJ^q1"mM޺[o1ܺW-#zCz2M`xK$Z!;eVV?ܷ6n;͝C^mR͘|1ծ]G=\~uv%JDm[ #ˬSPzr}oH ^T:=^u CT}}s,2ɯv|e`@/{v ?}w)7+NJ#_0]S@#쿕17 뇾ڸ-9AAUVh ^GwARiO0q陹C(UnَWwb`7VVr|FO90 ԨQ* JѱΐUh-49cA_}DL7d[EG~lBc8VY^ q"UWUXS2mR/wɜR cG'}5@ץ -}Oqc qJe{F1a#q*%.Gx @Nj%WT+YAXUrly[{a)I~АU`-2{wWbDo4Ӂ-o?l"8 @РFL _h}]aRLe}p:RYZR*`UѶݯLc""jSçM~&OV/Aj(g-MRYFϛ7qϨ>bv@ q?=@#X?6_?݂й[Mj 3';mAw,e'xܻ5} oZL۴;( * È'!ri?hF;}6;7yT 1{c*Ư۸8eѣ72?ãG W)e[[:U,X0DE\]]oOgqڨw/H2fwΖ2x{^ut[SG![Tã̋zaL6Ezxxp Yi+D_\33DT2s|K#[B !R*K8۵ιsm7r1fr -mVHձe"Y7_/5{ݮMѮNJSa%{O?+9r fM%NLPJ8T Ire^܏)nֿ}~.:׸W.8_v"£GȮ܋zxxx~,m}c%0I^^I^wC!gSɠ`\XWǎ];p(Ȇ!^:v+baL|gE`s^^^0 ~" ZȀa0L |Acx]};w߰r Ĩ?[P̸rfs@KS`X֒wa15uԚ5KCB^3{bz=;;;^o4IS[$J&xjNn|9w^08kXo<io޸IK1uK>qQjZBNZz;VO6ɝ&!V.-K.`I`T"|X/1#&A DL&d47D磈@ѝKǼiZt ^.K7Au3TrE7-3oNt'W ^奯O{\]9%oyeF{]r+Evx[TmF墲Kt7mխvz}aa΢{Z],./LlV4~_s.zFBLeYg|IW^~OPhȌ#>#&LͮTXlPղF[0_%yqThuS;x7<#1xSE9%yZkg%$/uUZ[}sOoOT'`Һ￿?vEkO)N+((x`L1]jdx⏟nrpph֬:u+((({nϭ7ek^bmO9]{8/s%C4FOg^nYbn?${pEE:@.n5 @QQQIv''֭{. <'ky>79>9K,fajI/(I~m{YorNk/%iDBNtrw'E@127&LJ a okv<;r1ݧ?y<lES+A@sy^xJiS磈@X \h\>ʹ[hNܭbXd$@MY辒DŽ^~A1|CVWu?Vpoo:3zM[,6t:K$|:zK Q.~%rFG?6WIҶY.(#KJ KsS+v>w%݆P ͛J1 O[b]@҈Hy 71GU/+3W3u[֋k׮.!g]]R|g_=L ~^6w\-|z+@g`@"q )r UzaAPTz`0TM,!T޼XGc)T*UT[Fq%/0 c}Js죯u}F ?yuƌYԮt^&%`g-vch sZmJ|2C;?szo"6t>ѐtE&˽k2iW=:rQE,CZIU< @*,ˀ1n"c%ʝ?\x šB{9wKxqHd2K.݂{*۾LY.,nsW Aƽ܅=e)/IanF \.zj S=@x}63 B^H2}\ \][_0w*J-<-{V#z~W{/p_ R} =Bv=ՙmvn;`hJ&U=Z0Rt͛lV@%swf8ܻmՋ%;eHLگ Z*rǖl}\Tjpϛl"JV>X2t.LOL]tA̴LxO~O}"w^XV&YkaTl4X;& ݈C;L&ܚ7o.|`Ic,yuJL?jd(xȽvƿ응wHc}`MY(uZzgB,nruՎR9Pꇷ]˚Tr\.T2c$woJ,Z1u N}'{Y5,~y2b=y:ΠA0c)O_,㩾ݳoqd*.6ٜce2 $f")u=dGd֎[xQyO;~g^_yﰢ#~zrw-{[T V&*qwl±/\U_(t';Xs!L&-y;դ{}n9AfM&詈JW2-FW̻ AIɭ&URCѭ5q_풗W(spVUmJpT:u* A8/w1d#,:@9uyyF#DW:8+Y]^!Tj%Pu.suRڤz gFI ;bʔ)mV|M @tphҹ zxD]sTe-w3j'Ps1[`-YuSAeL%]?uTΝHa>\][<_ݫZ-GX~GX`Y]v`Juu:w\o2eU]թ㪯 t%e-=&޲{pYjd2B\кu6A%o=Xr3dUՐ@6D]a"@>_oXܼyy̹lPu5 NI=z4//wD0 آE :e^^x1c.Lv쵕 OZƳ;snUKӞz5ճv*~'$$X.(?32fgW, [נM@ZRLɜU֞UFNtm>y?U  FQ;w8::B!ߤoѾuD"i-g) c```N̔L&suuupphy IfzS8;::ZIݻ6/[ܵe_\~'&wɰ\.ZVR= =!v:֥M'=ɩ~וB[jJЪ{aua{zyy_ & BP3gΤ9;;o߾Ak0?|}@P('_7U GNڷo3"Lrry<yx ciD!1iixXӨPo5 7Wd2RRJU:E,ܸqBT IDATR'''M&`-$4&f ,Fz7QTYL47S( NZXBȃR( Bi<,@ B4)ܝBP(S( Ԡsw BPyw BPtNP(JSݫb޼yO—) x1˗/7K^={lӦ]}BP(J_vRBUѵkݻ;99շ! BTJ~~N B45hޝBP(N B45jw믿.\@ѣGv}Y ~shۺ|ay8rUGWַu ByҩR)˲Ν#plbi+fݗJa]H ӧOPPunw 'P US/I B<̻L&L&H!ugHͽ5X+\URKDZJeNGV* A,?8X-͸7\R$-c ;u( q`rr̙/gpAP(- .0⏺1 ב4f@Br@5"jWpstw圴X&6lڳGh=4 G˛4u2Ө/`坎 cT*Glj~'LRfB7:0;a9\) By0R+ P&Wm]l?Mxo"նz HC픍sE\ w`LԈZ}"B2z\nK~Z>`6G74M^ ź,~Nr!#% ~ҍ;7Nk?w N#U BU^pҼkA's@xMuF~.ʫ) ByV6EEE{dȐ!u2?XFɂ:(5!i9ª5ϟ?_oqy%up6+,,!pvvP( By,coo3ϤZ>iuIcDmnҷ~;D٫a܏bع3bg :zef٧5$2 C+?Ii#t) +WH<,.ό^>?سzȻc +Wya^C{a܏W1?-Zd덖}fjUCA_?/ڗ@'w1}|FDXӁU+K8JAtu>nݺ9;;GoJ<[>F%$+eZ& ;5GyntYO,樾dpqqQTjzˣF*..&4o<778_9I" 'RV€HY-ډYXJ?/n2YեT܈pY\QQM!lU ;88WA1 9E/i^O=[1|尌09aM n ]1؝+hYTkF6@tۡffT9GvzdP[R(sV'A%˲gJO<4ݯ/G'}45&ryE._:sgJ^!Ӧ>hVT-![dt...NNNvvvRdڵG9rHBBN#j{{͛t:Gh̤ڐ 7-RޗVtQ6aǓ$$_`;Z@nh4n e/'DpswwwwhqV{N[I}[͜Աwfۻlds |\ra !)6@|,k"6fljW|ti?Fi){LbknuU#%nRu7Zm?:(꧓S]o_<|n"5risw9ia=zT,>K|hH.n!eEbGҢ B2lĉ^^^^^^'Nr\T\{jOED> ~9͒b@K?74d [.,4&g[% e.x 2ki ̵͢P!V<>8ʎ/l8!:¥\9U՞=z?/ B Uipw;W#Jj5q׮]Rl֬Y;t&j0sbF [~icƌsۢ 矟݂ҜzUwy*$0wm\"KۮOfM(+eض)6x}?.KU!55KΒ?-M VjZoiwM÷cP(JgBa>V2X7?앻[kWv[Mi3GQh ĭ}kmvX^Wzf3R[X̻vT*i{pYM?eX+V!|l'֡؈Y#/WޢYݼ*6ԫwJ府RH`] g"grnz,2dL_u9>;^EWak.K3@sM1_?RlժUrrx-00RT"'''wQTZU*׼<Ưl[*nk.۲:yY'2+,p_e rBc^رlXGU ϧ<7657#Gvtaz?wڅFq[6pbO y~^ʻW/x,fkYeg]=wT_K 9w:5o)H9A$3#p;R릩wGeCb)nJ_fLX>> ahhlNuj  s;dlk*n9^x^1N2D5;;;[\ @ m[/mS( 𯙫{+Bq}t|Rxܪz^hVוB|٠< B4 Wd 7OߦYM9N4˸ pH;ӿN,P( !ӘPU~#4nEYFrF9M msR&6㷜BP(IʻoܸJ2uzxOZ=0>bn^><|bK5F8m0+*jzr暏&trlޜRqG B4Fsss .mXb3_と{8EϧMgFO,T{^~>6BP(JcdժU6 y|۲-@xEps%[~h}W$-ﬤ+D0kBP(lCY3Ֆb7s.';)|E6>\H BP; +^uy748w^,㧹 ]kF)sGjܶc}4|JCP(59rdEdȔDqyUrHOĎ}ʁBbn 1 um,Жe]}g84H9OjJ*a[u.vNd꠼{50winmlW:^'(džtR?9]^lI{P`7M3 ~P( Sޝ"^;|>m!9,h|B{ly=uGJܫ)/^4@Xk`*cu 9}:BP(Lő1uǼ=ՄE89:ck}"ܷ@~U[_uB'f4?Y0w @<81Xv s_ ţP( 1Z@ݛ7?Lql,lkmv?W=CV:瘘o=5*@w| ,2p S ׳@lm-lV]}4񇬶SV>H BԒ{EzEH CsSߡKI['ǧ47&ˏm h^|O~UM;?ۙG :i`wo}<}}b) @`Axtϟ?ߵkj߸qctttnnnMvBtZ(YVF]:iU\ [>%9Rr[NVQ7BPM`xb/@hpssPfQE999R) `iDyLJVNKxڍP4 ة'  B!mBP(=NP( y 8::d#o BiƂ%K++0 ˛J>k֬{٦M;;:2BP(GKqqk̃klC@n)4t|Ii#λwڵ{NNNmBP("??rRZXX(Hāa^qGٔaBHQQQMwM B&( 2L"3xeY{˿3&5ͻE(BUƺ~`1BP( qPcF1:}v|]p$ èT*Ɂofb%a2JaT*i2;7wd%UDtBh@R( !bV70<(ŋL57ZK w$'L2]eGCOt!RCfJx/ 7.n~nw ySFߵKeFM+{\. .( .jT<]NyMSDiZ%;iSfjfiFţTɻiuvv,˂˗/vyf}3?~g|繃XzB[mmۧR.[EGy}[R*~`O7'oÃWwB7#/EE=U(+o*}6c5"d:5FU L&Baǧ@J,7死^!wt75MLcQďZl@u|L{!:i*i]?YM!*lgv H:9_XXh]T6.i[snU߸й_?y\2kպ >Nr>ǣ5S)B:5ɣׯKg,ׯ_q/8jʬ~rُ2Μq܍x_^wg ^=FM=y27,Sy'MBKQy~o{i?fÍ2yaq~,^y0^i15`5}#ӐLF:Ork+ț鶸FXX[~w\VX3cdͮ]=QO'41/lwWtj\|W^ BEQJ۷ׯߕ+WN8aPdZ0~nQuoRmo/||A~ k(Ms3k(֔yVV즛ЦttKjuVp#[얖xk3j4qw ^dwhtgTXrT yaK "Dy8^ve@"BZ˪8-NZ3R94ed7+[JJJ~(???Af4@lZyi۶U57OL5WKxīnfjpn?׆]am7oXOCmmP*4|ṍ>W=\sTF +\ӭM$ܷzvvl/ap[[o[Z|gژw//6Do03Sz`'ʖV1oNj[f`07R C^?)7& UJ]+5 ~\0;)Q'qһGՊÌ\ ^MU@rsͲ+VOTbfQ=== 9+/////ZY,=#-?-9Gu՜/Ǚk,Y}d8zQ{ôUSuE׷R'VC84Mii x|巧i{/dN:{ ˲{?DV]YGݘ_|r$0y]3fٿ2:$@^ށ}s'v Պ@;vx:)X~pꭡ?;k{[ieVKòeؖv80zyy)JJJJJKKKKK9+..y^6k֬E1 㐉P,˲ܖ_>&`0&} OI =ch䏤1?JJZ|c&;`>|rt4y1sYlZqEߨ&Ii`0䜖uj I/l\ŝ 3mdsrY䛦ۻw޽{W\)iXes{?H<^p\1 \g7 ˗g$%e:ݾxh!`H~tl\`0n1Vf"4cmU*_Om4jS1Wn7ecY:s>gOW֔_8ZA>s}]$jԺDL[𚚩 gfkBebFRX`C<`ݱٯح`Ц<|JvZgP^]}~^1߷/f~y\rLpph^,Ķ1RFjk#: c1:+CC^,n49;o ]t o>`<_$&+ʦ<1cbgJJJ4JbYCVjBVU*SRέJGuWƴG_m+> 9ƍ3^~ߚƸ`jd=zjgLz,8xX{nAHIi)wLQ~%{SJڕpld뎙+%[vu8-74;+?#mCq,Z'L66"4JbHoY,aneHb="I"Ls__wM6[l4^R>N4ѡ%wX2+]!I13#Xk|xji];b4^cjkt1yf|Vqq' n~\e[I7VpN.WjԡDl }dIjn&wGλbδx6)Y$EGGwMz#j|wK./A< ";ifYR*Ղ \E>,."x5 XW5N& v}^ri{ΛeVOSkVKURTҏkeh4EEERqkRmI@`Y}Z6vtd1|<._y$/-2}w;]η/tl$ƟOӷd\d3qbϼdHӲxAL-odȖ-Ӄ״!KdvzCmfԨQ[nݺQnuH/d?r:"{n-?rm{epw/ U+nYs~3]"{?t 0qe"tx{1Z\pvqC߽(V||+Vf7(m+y'w*ۚN᷂̝(MwXS]3oA͍fl|j/qaO^֦@3;~~wQ{zv2`9j*idZ2Mof& VLXQf[h9km`?;vlad>>t:w]}W/eoP1 #SRR>e cN>Qn֬SYmmg;[Q~[[j_|&5|nЈwo7WfVe+iCdlxVӲv[.N3YNbyrKk#ӷO3xVjX<_%MQ+GT'LX}ۻ.b2`u:m Պd&ZyM};?5ag|fK3J244ԩS~СC;v? U*2<7 ZUZz(kd$yvB5r@pzW#%e@įr۱UBw@˙'v&N]>iA#xA" ֧"%*!iY-Dy^3O,#gل/iߞx!6 0i=3<+1fSݪuZحݯ#lЩ9_ֱ˜v5x^V@.CSgc֬7n+&~BHKx7 IDAT{,bӵhʚ5k֫Wg~#FG؝4eeeeWnݤދxEbnzϞ=eeewF飸;iAX,JYf HegJMVaXZ-hۍ]d1 SZZRXVٟ3߿6z:ģnowrR9zZPt[܃+^Vg~ x5+Kݫu PsΟ^6eZ^^^Ւf3x흔9͗ ()W@d\GR7k VTf͚E8///e] K/ES2ƵQ~3,/?Nã[s @Y|<-o:}><37?Yrr,OO $R4_BIsM5qn%_?d2Fv=C[?>ὂp1{FI|n7o맶N~sn֝( T*Vqb;hN,lZZKR!Z^}G>x=g7Y}:D3ge;߈wiQ]Wլf9ٳG}=8KK\F5̪-++YZyn/y\c36`V83XJ<ƶ[3S9A@}3:b\Ecq]&7phl˦93mE*`[Ö}k(ipNfƐͽZ\ƒr&̯ˁ>>%ҐMɧ瞵k`ko|wWi։_{Cѫ>G瑄ŝ}P(JAΑ>HӱR @0#cP3)|Uj$ T@~K+0 #gYYYyyG@`?88800i .xxxjeMhٽ#wyzRP( R~je JR (tp ǃ"t*TJ-]t,,u|?Oԧ\ђ'Q0< `yOG7KRTGeY/JVRUmnԖyǯ'<׽JR! zYs  0jSNX \G ?1!l?ɵ3޿ ^e`!WeѻBm_hՏ =ɄUjZf0֊LIc_aZfHcɖV>o(J+ʈ@?b <_^^^XXxтHsss/^تU+F#E7޶;l2.wyq\yyBPTQ ʱr)XWMy(l\8GCC^ׯ/v}_y[-3߭r=>[|{x+{muok+'unia^*+GrITto*ȈWez/JRi9e1_V5˕Je Hf{{|Xto_Hk U'WNQuU/W*07^ȕ~_o> HV"*}廓ƾJ`J|[V4U2wZnK+>o*J[8%EbK.poq˗/_|e˖:~erBPJv)4G5eY(=}S\]Sso3*γV, ME4/;4T|DfVeγoaZ@]'}p]i=68YYRcuU_veٗ ƃe5!/ݯׯo96?v`شAɲYNJxj5<~\*uPnn΅&x,qSoSHy' S [ fW)0+*9ČY?cXK9ۧt'}Uб*J%Wڪ5MSV-jJ;YRI#F jaeNʕ+g'odh-WPPpȑ~-Z.ڎq ϟ7Lm۶t#T7#Sg9n]V3Μo6<@-Yn1g6qeMxlő?Z<ﻧ+r2sOԿCWT~-U5vH& ZJ`D#ZVn /=ގKQ=] z:U4 .j.X[,Q/_ܩS'CԊ( ƎݥS ֝SN0gII IQw5~zcoϏvZi[ķrĞt+b)((MLTںEקnܝ$'zkE,ڵkw.^Ȥ#t-[2 *J: 8kBNȋrwk׮effv122ywRr~h4o߾VR4ܸ;0JԻ:qqqO>~xvvvaaayyTbŊ;]`0oߟ"fdYQyם=% fڵk']lȊG [SdT!]gimU٢inr+n>nVHoI9h4^^^>-%nqwBaZ;IhNnJYQ;44%o~d&fZhHOvAɓ[ΈB#P{++QO!(=WƸ;f!. !FZuܝBHV=,2 BHSZZ*IqwB!p xB!iEkgz:B!D,uw !BH, !&ȝ 7n]Br<ۮHkcw#B*5zvC&Yo߂^J > -'0t”7M_.xeVJBiT*4ϼt] wZ lx@%ܱoު}7]W[]cݾPa=rͦ}t5!4 .{{}#0GwrDKf ז}RNqfZ 밐c58y𜙇"qpmjOoH}bи5֪jxe+@!X,M'.OlE%|0r~kߚ o3oN9C!P7ǥgzO\}FU2Say̝h1pPۭqYcЯGK3`쒭Y´AgiRd\cKO~d\0`;.~1(Oiӷby/(ExioI9vvrwzmR*`:r~&"@P8g Ҕwooc׵2y,+l%0ŸoY47xuM~hQ{zvQ첊wd<3n2Ki3wQĠ pU.!&A@~H3"rnZ)`p]!l#\8c{Y*z]=ol:o`Ϯupg~ )/5upc "2KiRletHv˽x^>[ji_6S^$M p7?ܧ_p[>6}qi O!MwgYAݥyAj&xfpw!*#ڱӿw\#Gd)=B acg/ڜې H{wtO@NW՗ҙnҡG#\MKa!~39I3"rq=;mO ~B!_ CTPPpȑ:XVQFc.]3 Rq[0g 2tcBM&3ioT7̬VaMfhtp'SU&Kd8fbxtZ'Bi:JKK-˹s碣]̼j l֬YYY;k&P.ϗ]L칯`u:]wXm9r'SX"4k怂BHcݕJeTTl8NR븻dU,VpB! ˲Va^PPpСz+=lDBH~0w7aaa3.'B6ݥ|@XXX@@d2w/fVBHX,*+V8KV}Nv'O[5~wa Fcll̻wڵM6^^^ʄBH]={gM4gۺp~-ټl2Oz;='''***&&FXVWt6E$BngQQBo«wK7{XXoKww'҈WICm[.YW*9dsq={]3UXoB!wJbYC(JJR<<K: 0LiiD^EZ/*䡃 ?TVtvyyyQQQZl!FMbNP B0 6ΕXrC6Ғ¢i|{3yCsgXnBH%Y䭂`1~~esR3rϚ5|P.!ˎm#xOiݥV+0yBH"e*`(^[,yv|i^zt@qww4 ry5BqwB!ϒF"`k9gMIodwo@qwɾ 97LBiEgGU/**!cFV9{Yh.w\يʮݝ wgYB[U1ݪ X-2v33*cqYӣΜdhQù'b ,뺃.:H#xB!RXx(D"DV9_.}j(. %SanmIkQܝBH#eDQ+d5NAE0 FŲg̚7T$.BoR1:n݆&#x),Kh|ef~}c'XI҄.l@qwlV5E%w'҈,eI/Z4ƇyD]AJU|:ȯ %B,ی4*y_K\6C7޽LQh4vQ8 !4R}4ĵZ<a>Y1eii<}j l֬-g'`hZyw8Oe3tÙݕJezӧOܞ*B!uQXXXRR"Y([uOS#w~[۽{K!Bnm+f6mڝF=n4"##5gPܝB"<ϻz~-l6jEٝBY=0LAAhݥN!w{NNFS?%B!M;g)k2fwBwo(qwW^5w>B!RF1***&&FJcߝBۨT*iy4)i.fj8B!J=ݭVիWbbbܼɍ'BY,wc&**Jպ !\Q/q8b~wB!kGP(ie9!R7Ґam'SB<_)ֻ;vͦ[='s \-)`6K s!4A .ϯ+Og ܺ>N:6qV ]vٳ̕#zٵkB=?^oܼf!h(qXS)*S;g_hJkE58sg\]/[ eɮq\Uq<8cUKWnlC!֤;˲ ~"%|WꮏPBU-xXhV;'-;{e>00Pӭ5]7mHKt雎UռiW~f.00pټizi}g&-ٚY< Y\-CYժ&k]zi7:Ltz]O<͚_>cuMURf_!9c*!ۥ>T%+>^5޿n{bqq;/_ IZ:f/m}PʨNy;t3I1gt=Y[yj 6>S5vm6,U׶,{x ,s RދT:S9uЉ]BE,3*{T$(1z 0qM{4_CnzjYժ1}K=~85cSlpzC<͚OYf:jyff~];فU9wsV ǿֿ K!=c=3z,˦6hvg-7wg [6j,)DF"o %I>563`\άABh]e B)d% 3ȲDհ,:[.W7U˪V@Jjwyk)uBcrbC̈\`\T~_!N9!:cYj6A!ڟy>m.R`c1#֙Fz蔅 )keY9!=;{|;&s\nfW@xL?ev#B׍:z缒7{lBgq޽jh4t\u3wDKҒfvgk͕GK:ڼ!'^Zi^0a!zQV "xR$\Qiiw huZɪʝ N7o3a4'ڒqͼj!22YfnvtjH‰R6=ѿKa5(ݛ:.KX+#l$=X`T2,B81 %N-}ݴx8*Ъ-[M"6 !$j=ژHإcȨYNjpVI}Άs\>Q;?%ur[1a-GСj5,˪T9rHppZfƝqfdzZ>3'R' +h h4eee%=] ߭wg{o\1ζۿ+w!4qi`2fg FXf|B!w8G|wB!w|w999QQQ111jj]ه̞=LJNBiP,Kaa믿`ٲeΒU*0ζ|ڴiuF=|}}kuf^;߽k׮mڴ=U&Bꢤٳ>kҤI~~~>օw me˖9}V; "իyyy111$h__[!rK؏< ԑKK]xCvi@[\\,_{)n43Z3n3O!44>իeeeR֣KneyEQT~opP3wf8B*eYZT*yW*( UrZj*>tc];wSj̻9A;!`,30 BsP( I+D:mZ* i5 jnfs[%BZ؅+W[BdYVdVZxAP==tه[==tjܶ}]d}Rĝ8RY;!E곤a1#"x^UC $,β읟g^j2 S9 !4Rs Bd  aǢHig=`Cx[?<XQxUB)ϲ]$os,cxv ^vllAh(qw< "nošeoB!Mah( EXXE""@bl׈*rO8?]O~:£k֝ : !4R>"|.i ̌X`3/ZAEpa)ҙ~Mϖ4Q!RXx(D"DV9_.}j(cZۘ_<B)[%;˕YZQTL[' "bYz3 OfM*k4ݝ oHD~ %BBߒ8+0;?O:&Bw/++7]tq:Bil}mzy|OyӤoDZq.ѻ[֜f͚9ϼnv'HI4˲*uwvkIWO>zwRY'Jqw)@qwB!}%푯d*w&'iچ6@B˃"t*UYCUXpeQ. vjqqu{ (‚byR@ERj 48&3iZ $tr93s@7666KU_|1}Coj4=*D4x={nY}S@HMMMOO̙s-|wA8pWwf<&9z~"1bՊήsw/¸[6<= ?ޞ;Gq :tĈ6oGKܝfCD$#e~1bDujD] :fE ;@h'$$$I>:cE)".B'M@8WUEwχ;<&幛Q.]y}NEUss0/h{' wR,NDS2l=9}Ƚd?iaFDw?v.p oԉ/z=vV8Q4߽%TbjM=_Db'PN⸞5Sr]ϯu Q/ydh{'s˦GJ'gtp{Dt`G%YfMo=,I21U$YC i-X*$!I4#R,KhG8&UNݔADZ>;י̝%yUo9v=UKnwܾdԒ,hM]ʷnY~3--͙!*HKKs:n_|InеZX]9v״zU:*U9G_%DEo s"U)r~c@FO$Uӿq;-EsFN_NJco>9gD_a3&oie6lc 6ƾ{|b >x%ƈ53De1ٵh{y΂ ~'S>tp޲9>޴wSEխ}|@޲?޳v 3&c,$En#oٴvKK&7ж\w7),{e+k>?lrp).*{?~>5nȵ7RfcgȜX@wd{9mۻk;@niD-ʼ<Q銒AN܅ϕ=逛DӞY6=wo?]Y8(u^"Xv荅#Nn2QE<_hH?bv=U.Y0^'"Yx)F&qD>>тW^>~Dz:ү&z\rը9mVy*}iw_$U{qw~wtכn T/iŒt%WOylXɲG`Dd-;&]DD<= kk\9b IU;N`<^V(j,D@deYB֘z`+zd-M$ˌzSDDB2%Qny$TEj-@dUv\Iܿ/οWd/]|Y'_"8!ޮKOT^lC#O˖m.!"hmosMXu]Pz|C'nв/{h֣.z=kd僺:;ha7j)Q鬙S)E-;øl>hdDW3.EhU팑}9TR|RWh cQ A4fD&ޖv߲Ce3' ~H3K2QGwpj CT JmbC)mZ:a[(/_A9sĵ\7_ߺLm r* o0 =ADd@ъwG~'Qz8 [۷oȐ!W}fA:;K[=21=;v,wXK-:{$[6{;uvb6-p'-3-pqK,*[uN^Y%I${رaÆ'C rV _dOz(o6^(/fݝt*5oO^ISM;@\|w%,;7_͏^yBAgDWϽ2f@m!q̙{_F.EY#nt IH=3pwRRRd9(VXaYlAPU5h9sB)#1ݸUW]u饗&%%uQ@ccW_}Yg޽fkMx`CQj;c,|}wΨC 6lXjj9.@uuu=φQ>ք6`S;yYǏonnCܵc,ʟU?>I(Vḻ&ulfY,$˲dRUUQ>,KD - f[w#1wBQKk1xMUUQEQ-d""QUUQŖ;muc>, _R7u/V.YE~1qw.,ޢkzm<|w.k:~_;qwQY<8;/ҍ Ԡv޴&bwswY6 vEQĊrj;(wdw]t߆744y0z IDATdZd}>;UhC6K[}60FRP;~eqwhć6<n W vݵ~ә{Zם]vm2FiwՇ;(t=m<|>8L=1Gkf]{JOyl6up cu#܋;>m 1bK`(V ģSc|>_0 ySNɲt!=f&۸7669r$%%y/m6>f̘]`={߿?_k3\&荻A|5]"ן_A "[&Vwgw޾ tH~C@[gK 2zeD 60~$ݣ"Gqwwָ;;qwу!΃CBE=0n6; @܈1wm:$ pa;)@@p4bC<C DF{ܝ1;csB ~h+p];;|b6G*4t<|Cvsi{\U>![9]QB!׬}[ ґ7f߿ԵefmŐޘ'x-DD-O.*={ٳ}ӧڳe%o'fx -x<=}[_+U00IthW!?]۱nsv6o} 4@s('zΣ򧯯IcA1Nce~ܳy]}Q؏;ץ)es?xheiM~Qv"b?-=&o+aaڹhgjQx]| '$IW%ɣ5,CӺ/Q&>^8mex۬b_vJsO>},{qǶDkzP""ڳrn&z?0zzR(3%|P@ow:ӜGutb~YeYVT(̷NaZnl|,Y ?3ʶrD?k)F+f:N#kŻ-??7cp:<l:'ZQZ*6I3/\AzYJe|YXp9ʲYf,tɲ,W?p(t3WWK43kg/۝N^0W/3/8knIqo7e;3]~Ǣߺ~^V""Y2 oO~x'[j/k~ɵ[?dƵS{_^xsO*)2:~)flܺqԌ)cT{t$gTYԟ!"K7ھxʔ\~EJ ^ ^Z:y;Wݱy衍~kퟖw$}qw-e.GT^Y#s 9eтW>ckU dH&=5s2c!Z03Q~m_?dDhC]=fd/,M,;tO^nGTr^lLwGom4;Y7(_?0t70OY ,Oc=עi;ڎ}<_?FU}ٯ̂}leEMRk OHV"G`G@RJDo;}'"'7ф-5ٯz~rm|$;D$ڄtc,UPVTRͼ"7Q3qn֔u5#W|t r&o_@y rJK rKJ.<t_&Dcl>8Ȧk Ѻ›,y#ڄnDdm;7[x%;ZP:ͥDOAhK|0oeSmWV 7.ξMHo͑ |f yCK2l>pS7M1&cVlmF-{JM+cɦbPr| %'cpי¤ 7lذN+¾}- V~DDtJ$#(6551dd{aZ1wgw޾&|Ar=/~ *,&(|;Sx G{|>(Zjj 7ܐzs7: F=z[:?v͵u0Fo=FZ$3bEQ^ hkjjjjj}?;}|kvIom\ y"^Мjlzm^ )*TeԥyWDQy^o6cƌ+p#+bۙIz6-w޾{$N:WE1h a}ɯ4M.9=-Ս[dEfcx{cڷm۶o߾[o5( OoZSN#ڴK*^5k:Z[d ߌ3*cMMM,yܝ۸;?%hc`DMȊrˎ+~oDY~IV SJ}oQєw8!t 9Ydfնd m}nzAg뮻u=Q|hYZI#"o}>"7CU}/Q&Y܊X]Uk JǣV+HKt]ÓXp95UC@jqmgͦ=% -rBB(lbƑU68&Wv+~p'LFG?%+^痛fSWODR.J=uޥ-OLʿMY_--(I`?2?uTuiرcZZ_nnn6ͺdfqw>u<*( L&:IMQMH'RA QWD- 1~W_EG]5!Dt7H4oVYqDH/~媑]#I߅8yzUU%!!h%xG(pV@ A|'LEUAZ>޷'rwԶ?TY APFd%3oZNDA?f1%[Ϟ-K( kJ8A;~[yvfs? qwLx>wEQlӺ*t7%v'fULԤ'z Kz @JHHMD׿~_={|Qu<[V-1wFbEQ[&~oNJTI&U"(Ola m侗ߔrRR>{P=QI#K8TՔ6zWמ֏zv3LA;Z#zi n%&&voas8S~_EUC=f;:hwEUo5$IUYTUM`Dy'.g?iZ;CϭNJ_rlwk~-]Z0u&/7*104,nGn…{o>}Od2|>>j~|h nЫW/P]ЕKU(*j"H~TA~ESeI^$3Of𢵍s=nIf6  GnS7 +~]9t{^^gΜԳ7L b74 oqwf|bbÇ/2~q>RqD:_n.)GR 3}m:4XB\/׽ WC5]Ҙ|='Oyq=#t h2t8؜&Hfpܝ,|7OAJJJEitܼobXE #mbZ ?>3#G+N9(@^[[gGo!CVeQx'6膨؝v&qw~t\޽򪪪Itf8wVkjjjzzȫFddd~X7wyb2ѣ333}>_ԝlZ !X,T"6hLEpF[a>ʵc >|ܝ w@h̷wG 6D>;Nq/j|R|>_qGnWU\1cx^A}UUK}כ\j߶ ґ7 }y]X魼Eo]݅FƳeoX-;ő-۲[=[XwD1j=sgrD0 u?{qwUUO:vM&Q_DY۴Rݎu..}nK'سI2ƈO__EƦwϚ]3Y00~Q.eNφ|Rq-u+{:mXkiw,v]Q>q.VUUEUUyiC$9$35($yقI 3xaۂZw %IZO_F-Mco=ɰ(E;'9L/{} ?E :q=ߝ3W5ܭ[=zB(Jsssrr$I<"Uk˲BeYHŪ%UDDd؈ܕK-NDt'\T_TNDDKח?ӟHVԖTWx:{1Ӯ%wjєWrx7??ef9i ɿϫE?9j*o>;G-K~1hjD_eYVTR$Yl$'%I.Lkƾu;m`({w׍kITv՝`ӗLJ1k[ߜ>Fz^^2\q+y^^4y;WߺqѤj ?yA&r Ul!( IG>z/frDwﮨgYW Dфç( fW2cL[>p&HMZD1F@}g5nS2y>ţ+kqB"q;hOĜ6& -G5:z "Tːi,d#""IJC/Nw]|vJi6cj?Ghb]}\Z|k{xW-kSzE"21RUM"5 DD̚JTAtD9ob%w;wgC=/UUEILLLLL4L猖^E֝u$~,GD֌۞;uQͯ.Y詩=EDI9s~Z7!6!#xD&Ü/hSc-j+(Ә3iTxGnIn?C#>c?cmSWnx聫mIZ5] p<¬%7eh?jdݯz|I[,w͍Ǐ'8NewN+|+#b]E3m11FԯĹYSgv֌L;]65w,)-)-!*)[Sh]K;h]MCW}Q'6Z݈jeZ6Y!N,/SǶfNK팵) os*FT:v5h價+[,=c/@cH滷۷o߰a: KOOX, ֨v_z0UTTٳnj=2:mI$} ]i5*11x qvwݻwu:l6JEY^6NZ~)EQ^()@lwECy+ΗK'">[^(F#v!Z)uAx[؉'"QiWŨwPy]׮y`g_Zw>a.km"=;YEQ4ͼE);cg=xExgy>g)-Nma;Gy?ve9|]QxXg>Drv3A$ =!1Aq 5c(3n=1'h駟>|x<4=|@hqw.WU׿5h[v]1nĮkt]3]@ Vwkx<|ܝ?bv]Ϸ,8Go] yt8߯*zZ]c;"w'"ɤB&[=Σ @L୕6nl6w|wΛnږ(G6|\޸6w:sV|Xss3:~;=6N<Ѕyi۷݅=~6; KLLLLL䏳!f3_gK ěc;|w|V#hb iwG Nsg$z|y>qwx;@,@qwqw =滣Cܝߝw;{ĝal6w:Wwm:$ pa;)@@p4bC<C DsЈIܝ1;kfG9{娯oll<ЃQ=55 555==qw30qw n{Ƴ& qwmv1wll|w];Pk]E.8wqwqe‡%_,Jdw.[o~N&55. [NytqwlժU;,'Oo:iӦO>k8p`#|>_jۇ cǎwy~3fLty󉢈;-cqw߹cX;ۧx},5\%M&w# Uwu'"UUyeff666~]tр III,gIn⚔|w]UU~7:Qv/KUݻ755ɲ|kjj޽{kUQ^} w^chM{ ҷo8p 33 v8qnNQIx hb   A&-,uuu1&4zO~eIcڱz޺/d2ETڴk?/?HHH_ed2iqWì?X58@DD+7f'Z.JOD>ojjo:4}tժ$r pĉF~D&/KGD(&%%#An.n%eWSǏ7V~A|>vO:Qwr$XΫѽ{=zh?@L~|;W^9+lj#͍䐢(*bXyu:k6Ԣk^"  zjFe0Y ATZ曱g *!zuu avwAEaL&+Bccbn֠   A|$fOfꮿ}wC|8gO|F{j2TU9Qݻ799&ϖl呉1/n֝`Ozvcxm6H1d2iag+7SG*~36⍷.mYG kH?4@-nW%Gn7 HUUu6 ~֭_~mp8|,, YzJ9ңGYyܝ׵OC}g>oÇѣj5yE>}z𦶋nWm6[ݝN{ꕜזeyEشiaZzd2V+8Çvm#oEQ-:_]vlkؖ] 1rx7w7 7z3x/\ b&cפ !h$@$@$@$( )§ <:uxz;ZB#   A4'P[\.8 ֙7 qwx;@A ޠow7 qwx;@ARU?P%)Ql-9-4~gO<Xk=ƾ}5b_#{ m֐Ȝ ׆>`k3lwBQeǎ_}^^dMw{WʟiM,$d:JE:]we=Uk=]]ٲd70WqK qvo};Θ.̈́YD9Vc'㺤v`HUSNndt7 $&&ʲ6~Qjޝ?,$1}Y9Ģi_{m`!%^|]RS3_$I!9zی2$y2l11!2SuȒa$su,˲lft:Y3*]|OXvӹݭU[A/ϚrK1>[_5eLag4Lcx޸oP}]Z{D62>F3,.ܭ[7u @eϓ%''K@DD8p-eg5eYo(kŻ-{*~Yewc6h|gәʗNi/~yoK*Ϭ{z _2LE}kpX?l//<+oݸhRUIKD$ה[vb]|uVeUU7Dr%=pG^twrƭN(2vMfɀe?ZoKd܌2fs뼜D5K.>~X;`ILDa{y"zrƭ:Ymz|Y&O' vϗU65:o-זgnQĀe?ٵOK[W4,ڡ(($յruuu'Onw}}}sssBBB|9"6ЄSJ6%"O;hBě}]7w߿kԪ.mτD'~lCV"Yh/2` oTZUfۆ _2LP:Xehb١=D;j%&~wQ鳏o;ˈ9gi;NZ;LhjyNHHlIW0y/_LS[Dp~C2"1setbJΨ$aJx`nj2,lX,'A 1}ݥ9Ì}ZM30H01Ƙ=0@"G2i} sei՜5 1f6 ${>7gq9hOs߃D^bFY63x<M(d./U;2|u>8)1|=Eb&"e5FX3n{u3oZDs6pS+5dzSDDHbD$S=19(lL[جp:}n=PYAsV1ƻ|w>z1L&dYn;ua}r3hԩD>̴JU EӮwY3yJ҄k'aCI|Tej ޮ-F`djIJ_}u>8F.v*ulnxhM.Y۝%ȫoTոXQ-h{v{jxbfx`bm D%yRYv? hj,=SYvT>SRD4kܠ%"*+Ty)+&up{PFDVҢ%ó~5KUPΨ$Jx&^dX,IIIjZ,ޛX,V5))))))!! ֣=A2g3&QƢ ~]Sy\'y/,J \:9 b5zos? _2LH킴: "YY=vte^| } cvM9mÌ,x=D󈈨lqNFԯĹYSZYfdcb*υ |f yCK2l>p(+J=%y눦d ~DHwtr3q9P:ͥDO1+hpb j JbX3KUUwyd(?~O>@S?/6+KGjby rJK rKJ. / KƸv!}tt_FU[U}c=%\}m EsތJr&%"EQN:?՝:uJɩzJNN@!dDC- { Kot9a@9΁.;gV7 qwx;@A ޠow7 qwx;@A UU1JoPߘeyb~'˲W|3DQ4L1l2DJ'{.U⾾@WRE>/))b0L&xg(~sQQViASb⯭,@ 0e%i׎cPB[nhhgS< ) eLb] m2Afa} f$ ~};$zمGP뛛+++'N8vX[[[Xyaqwܹv횝_ Aá]Ȼ  <ϷՉbWWW[[[Bq!0TP\rAeF*}fS $IDATUWWI$Y zz3C:E"SɸJBzYbZ=QNnpDبއ.C=ph$^-3"V(um9Uӽoa88N"h4}S;e}U7-dS&8V꪿-U:xMpT#!Dx  %4---1xbVsUBؠswzJ, 쌕T۱#GΟ!%fxԨr}l~ats5[owʏǿw6psoA "ˌ^w6_ȳӠLW) 5BȻ  !NcYVWcTIFuhUbu;so=?kMˣ bzgg?G]b3H]h`ͯvgr87x)kg'' yw즅pyөȦu⸫OE|b=[V+%?*S͵kNk7\/'>Gs^>{ܠU~ywZr]UU'jl^رLWUe>BzvjqCqtQNwxڶmе)a@`]x 7Oq&$D qvc IZ=!DQĩ]R+,ߍ}˥1S? ga3]a]gOLeHJQWq [ed'Tc{<ȒO^۷$ds?MH@rn# í Ztl2:*c{G2eC֬q<ۍȽ9']qĦ̳1! [bۤ3kơ]@@`X0ܘ׶i;4;u-׫CU뵵5u5ֻ5x~ʊoˋHRu]nڕcJZ]UVq`dRة!0OO0eV7)= _|~o"!T@[/ό +|Da`EB;t7=OlL.,+;$p33 mBjiEEnjx¢׊,:Lz $.K, Mm<3.lCpΰT, Lu߹"Ȇĝ/Oay(_^w^yw!)i@D;4VF8vUsNz{w+̮_"}MUPٗ@(,~̋^+fuJ4ZFg)VdF8.3}*NZlΎw @(L6Ξ*VN d~Ws4]KGDӢ׮vUO'<3/{N0g7z$dWXY~b=@W*c6kfr¶c\%i>śꎻZϊER'_* ^h~%+Xȑ^<4XYnu7cvvH=pOygME,)2__+8m+`oE(@ʀ4D6&<.? jBW 9߬+&=; >Ke&}$9¡g͗,)#B͒'YV0Vgú@K 0i|Q2ô:2?çk]z/G>h^[xx[wg@0֝zBQ6VR7[lJAN\9d-̲f~'#wgSG0@JQ*o;8BT3 bB]@@`X\b6Y/ ,K 3 j{VU36GrQ5!ږ 9op?ܱ.,ˌ1% `MAr L۱yV+oT\|#:r]O|o}ll2!eG=,*~}m/oj9@ q/|+D+#?X5j٬ Ι݀ID"ѯx%NvqK ^1'K}u^ʣ ] H+"Xsv:&#t_5;W q*LgNY%#D9jZɭinnniA_GHIENDB`testng-testng-6.9.5/pictures/idea-output.png0000755000175000017500000014205112551235562020463 0ustar eugeneeugenePNG  IHDRd6J ;iCCPICC Profilexy4{s&qS'cq̳y+C%NIm Dr-喫! yۻ޻k?{g؟g6@ pbHbx\g;@@ ( NzyoD+xĬs F"{5 dɸ5qeYGD&v, @'66>0~ӟ`М"b/@GN(?}y@jA&_ Tǰsgg" IiYyET4kji[,^dckgA+Vd#"WZ&zmLl\qMniv'%INٻwi3<}c99?=wg Ϟ-*.%.\,K~+/rU7oݪ]Ssnm]ݽ>jhl|iӳֶ/:;_vuwzw}1~dtlW>T!U X:&f -prrvq]eW\9#-INٻoii32e>}4iSʕ׮]QUuV5wݻAG 3=oxeWwOW߼}IC\Bj@YUM]cKGWOb b77w%^^>>~~3"$~Gn'O/8SX8QRrbiwn wh|iSsKk[ ߼~?26L>L  €{K3$D7@-A< hAư-\HBN<&B`D0H"JO'm&&Փs Wy%*M hYA'BA!A`P=*:L1sbbc'$\$% IJߟWMVB\̟VIEUNV=O#aZ,&WNGFF& f# %-mZۥw:9e8/uG7_m-A1+BΆF:%:,F!5>{^ObƄ6[Ŷl/ۙ;xAgd ʾt49' Sg Φ'[ZbzQtR}Y^įwݸ|3:&n`{=n*̸eq[`ۺw}v{_P0_cKO|Kפo^' T>/QHAs-+68S*4 #'t '"LdeD1JE2'vIOH_d?r y¤P(MT)KAk+'&X.$-ShBxHHIOf1jŢ%ī$b%Rfa-]nrrr &JJss2J*Ū՗iXWY@ZЭYўF.GT_opp1Iitg,.ʹksPsLtwQuMZ}G'˫gogr &~i(5kKc#9-LWĆM9[¶-il]I!:)}J*9ϒ{O\>r:Pse%(,/ʽfvjJQ vF{u\E[~o'뱏1R޲`-ጕ=wшn)[=IܵdЖmev<ݕ8Y(~_4Ƀ9AYJ/mK?O.,7K.10Xz+*4uVVNQs֣~o1\?,Yzd/Iax \0{8ӻ*āyPȎ~./r#9kVGNL$>>e1]:,1v;m IDATxy\Sg7ـMA **ZV-VlUch8UmeZv::ҎЎ8Vwm jBUP 7q!HB\p}INγޛ_~8EQ8_XBQ D(@IJlccV5 ԕ+W2f%R@Q D(+oF`JKKەT*' D(@Q d2JKKA @ Xqq&i^w@ p?q^@ pB,{@ @O!+@ ...@ H @ Y$<̬|^׽ AB./X-UUUu{C t|q@ h;i=P G hzF6hQ>rGVwng70zxvն li|_+9OK.Z&u#m0%{ccXlZfक˿~'5[gV_b709rv׼uͭ2?`Ͳ~wflGvV¿?,͂igR&GP{DHDHDHDhUȿt;Ȗڶ[> ~3oyH/"Z&-r/3=FH%]K5_o֌Fa0OOfWw_ Ͳ,FbHEa)`0.+~5꡿O?ǡUɝr ]X;3 \FUޜtQ=oF:ڮ:;W ];⛷t35#ƙj'B"$B"$B"$B[B3s4|zi-icy%zoeTj]a0LhkJȕٓaw rlY|eISXYẙjb1X/^38k3 ;Cg_Μ9SXdW#Xnz.YOi\M#fғ6۰5ž{Īw|:ste-!!!-a;}O* -@9[e2/&4/x}O\07us'H}FuҲf^9bOY3p~'>Y%m]{1n}T͎vZ;b~ճ2%즫7\B[;o{wԥ}/M k.%66g/\4MӶf*l*ì'4.48@ {R@ 칾o:qЦEg+`ؔ%poڳT3X|L:"$B"$B"$B"%4? !caUx3ó7iY{/oHP_6ꭽg"`̧מJŃѲ!ujZ74 ϗ#Gzz|olǗujQSqUQon46>|⍸4݀?;:Uk|:꭬SɞO,}x׶=3+(E?L.uwp];ʹ۶ܪE3 q̻4|G nXk,+n}o B"$B"$B"$B[v4,2}OnHg&c̪6gjtCije5y?Ve\ndV͚IiQv*Ѽ%S`[`[nf[⩶~A)3^ q-YL2a,T:wPPo z]Tkg6htO#W^3 ұouuW)E7\XykúsVf@YJ`9Cz i{g}f)>u$_XcݥSVwe5,ks:m^?9׮:a8 1cr̥7Wڞv4k57o!!!iȲMw'>cGxsHaU"EVF0?\bl"X0̎tOލc;>)I߯6*;`5ЁjmӨȕ{fXZ6쿼7q6r$ mcC3މ>Y;ݫx4"-`dNY/xH҇>~a6n6\Lr~;ÚO@./[Bԭב 5id 쮦#o'muC:aqz\tOP @ i#-4ͱ>o,ٲp0+Pױ#b`ј./xN{J'n|rQmgnNfi7`P}Uzc70 c G}!dYohcf3?{1/kn`z{.Áb_f˕5Wv^!y^^3foQknA#ҨK JLq׮:trתO?,r  8%~淬VMDHDHDHhYd&c#[ߤH fDZ,kUر s 1O[u޽}Ƅ1e6@e{uѓkPqnt/W^xҥы^Ɛ]&9P|~ȕF,}lB|}e)k36/Z cX LۺuYrO矍aT&y]>k7f;f>aR>×6 `DJ ͅF,3,s,t ˲vii#οbYKu=5:!!!ih24*3՗ΞdGhI۫(I}}rrM lLS5MI_V4 KUS5J5u KKݺY_;Mڃm"Ξs5uܗAFK[5ۖ6=Gͨ*aX9qMÂv\6'럌]"XI kClkN aTU}PWǰ0_}y$7ю@rk.["$B"$B"$B"%1?I)F`?~L|x|ڛSJVOU/,;r.}SO9?\r]%@ byfc/^oXFABA!/ga{@ $R4h05RyY JJ@ <-@ʾ@ }@ G@ n=@ £ YY$@ ,) HtGj#h4jUVrN 8NUH 8HCCCIIɽ@ 'wg1444<1.Eҥw1ɌoG2ʗw/Z zR 4M "744p%.t.J/ᡤ ,jk[L^ z->VwMbJ{KEfv'junA&?EFimZJj`<\{"]jK5E@` Z"aem۶ruuW ??]q&77wƍ3f "ᣫV9=b\|}|77=&14lcOXZFkS.N/~{gi2)1'oic\836%E%$";F^ڧO&#ЅLLWWFh4{݋y%%%wU>3BeQ'p&X(\!Z R_ Q}2ӒFˁ2iw_ `2>SI[ۧmKMl ݱzF̓,A-/VruZ9Sx̜"[xgNoMmv>JQ***=gi,5"D_~}-+`Y793{>zhSSX,="$׌ l2h~޽d2q;BG?qIo9ݡ Z1 Dkb1WO 9Ci,~\TVgۑ N˭`EB'*t/JܲN@Y,XuWUjal8i`@_{"'ȚMTAr[9_|}}b/(d2z@l)ם9&E,zT -Z75ߣ:^n2 i-!ep$BRpB(XT]g DGay5ƻèE7EH'FFޮ9 Xbj} @eL^[+**()**0`:,9VSS-_>} `D% ~7j䠱x]ǾՒ[r zo/}+FH$rvvtr1qWCתS(z5JB])UA Шd2@)K)LQx{,́RAژ"gi!$ V;tUzj۠h/h\Aill5cFMӜm4y|B7lzGJl8:YjW[JV7JC-:9㌧3bh;wN!L&H$rqq1܃L آg|rBG0至pw &W?͇MF,(1Q (՜F>gČO}D /ݚ*9rAr&^kDJ"fs0??0ӧnjN,>BX,njj`2BaCօiuOl^"ª3^Ov :K:>,9ҩL(#_y5?)a=-Җ>q~iSKmn>w$D4i'MEۊ:FWY_`Jp0fHj5rt#OǫFG,ϛ1:hknj o/FFFxW'O}GN[ ;,η){zzup5o珞u_C-=uS}3 +.rrrjjj"+6,9(tOwa\''8l< E*Nʹ)1 q%%6inDLJH%iHXuB=(5רiS>z%6MIf13VP.]fK䭍VPpǝ (o1Y$<||ʢzϢ_qj[=dgLPs*\UVuU&Lwsj׎yleH*HիQ)18X(5MG`UbdΫ/~%\#&LBW׬L{9i47*||=px O_A5l{ iE[R[Lh4]!o;&XV~FXYk"H$555,KED낺d2ۅ,Er(jĔ?}oMNoǭ丕7UД4,)gC;%[WPds$V(iZ$bbq_cH@$nˁBX, !񟊄P2X0h0\1~`?.`x蚟w'dĐNJۃivx+wJny?  2%C#݌}Mrp:+^K$ppŪ##۱_> ͝JZg8Cx(ig7 [,*tn#o6ؿç_1ڥs'}sVN"˥E]PTngТQ+e d2t:VKӴ)NCy+WTWW3 òe% xD(eTUUT*)D9mQhb4ڦk~B9 BT(B!8RJ(y5 Rש}I37iܚP(ASK 9?{I$Pȵ(P|ؿaܬfdZ.wDήbRPy¾C'ǯ{U}}Tmk4_F#>(@بjך.>{UBWw'37[ۂҥKOh4uuuR388xСݻwX/7gAAk||| D"SN[~.opX, H/[j־3/叾_Hw9+!Xpm=x~iP聂>'UJ [Ir#/Bw?_(w8  YY~wMF?n<=B(p=^7ˍco 0~ IDATiK)-P- UaO?3P(l껆[ LL߻NNzVZ,Ƣkn񾺣Q1LFݽ),, isVBWgrԩ`0bV[VV~{8s~EEEuuuϞ=d2:MoTQ w_) Vo&|c^{}G͒y0)Fq!.y[lX9GB rat/h񣰣KVZ풝?M/0v_7cB6.9X6,+ƍX,K! ~%E"GD"@dSS~ʈq#+jbEZIaWsQD(D"T**++oܸѽHݻ  &Z%???<<Ֆ87LgΜ-˝e2D"Ν;uL&{gۯjU*'''~mսl.`2JKK:YcWձ,\f:nnO0u.n.4Ùj4u }SRFw{߾}/ {Rjoοlܸ^wH$ gϞ} "၃__е>JرcV?D h( 5FDhcpPk 6'_d%^eワ$:oSY U['])/~>7N *i v%0lC"kL\B yk7,DԌ_v1cH/m{L#-EyP(4,tz' b;*Z,SKQ "$$`0F6SCtڇDz [ERL&JSw @BG}h׶˗vYm?qIo9ݡ Z1 Dkb1WO i)L}auVIാ&/L9E9'ܸ]ES(N|@u1gt7v#i}˜X5$hw413fnjf^[;3ةqxn ;7 cMϯF^[Z1n85@\.7n} ^ҟPW c-z{P>4j "'bݿz")oo9P*miP iѼcz%Rs(m6 ՈÿV8[Fnӣ5ywu `0X&3oaqv@x8G݈|X 1(2/ꘟӍG*&'';sğ7w+T\TyġoNuus5"CIܥ}¨iЃvo){; 8@RYŁ;99ݙ@PRRGXغ( +++br-QM&B;@QW4vџ7$aDAtގZ;:9noqݿMᮮC`(YdډC-O`ּ*ssYst%eլHJ:䍰!_%E7NE%zGÖ7uzw y6jS )-rB >W'-/;`4ʺ@ <<ɉډ' KE(fq]N$- ]ݞ|&vm@>I[,4}}a1CP7Le֊19kWo2W[S {9rXr̠ ŭ U*}6l$vU}&q]'gNx{n}_ZFί!+ Ug-T*ROY`\a!@xi?00P 466544y$ o/b}}/aNn,EKHt:]Ƽhr{a{'D'$D$)ѕNHNxp߼h>c}PTN^MQ&@ybÎ}ʌL\>٪+7ӂ^BDBtD"MNN.je^X8KK<{CDs@Ʉm'ya5|"#Sv];~T_eddؗB>y~k.v[agXdy:yEEOAQԆձlZ:PsfʵP@>KK57m](*!evEPT¼mh\.vlstEً)*z B&oVW*pܙǚ*MYv97D !:>>>"H$ ڂv?[l D~86];z##qع9y>wIIՙʉr鲟 NhƲO }p9 =Z:L98p(sSt/!I3֚J yPA}4հ@Irh2HZ⊊[2tE r+8cg/+sNT@C兟p0//,赊;w%nе̍:.QfرF;g~Bձ+9k>_$[5oJPmiSP|h_j̮J-뭌jjTY ˃NKz?vf[{Ugk|"8\rsߑe4[JU6neÒ/h [}E]̩ӆk8@=ǝdvN1;("]2G#`M>SvWm}M YW,>}FFt<,›4m:`4Leà1%tSF[ EK?oE,$`M 6d//H<t|y*7Z6N:#ӿIGXlގu ,aaRj6v_7.XgZ)Z, ܇ߩP!n3ZF~2؆6Svh8n*')]帛ac(ի}h24MY4u_|uZ][dh]V̥#gT\tuwNtE g(6ΤHUQ맆T'LxS72:]Em57:idujNWS h**ZǰXF]V[ FSͷ }I;_ `YFe-P[өuLHb [LѱНy9&Q9iɒ%k_0`4V#LͨKٰlMmFAZZV #FHem|au*h45M5:OȜ1E+EVwP1btj~Jk(lߐ]c*7 ^r5}VGdrtl@ nO̊GVTTpgi,vԴC"Rܘ~P|u_q;|a}a2G̍R- JQ MQ5wglkW{<bSURUN|dž|6:D`|wbK<Fjv`%0s7EQG䅴ɋ2>Z IgtgŨM )+RcE#_qr z)2b?U [ҴxzԘP;&u㗺WbVTKc9_:>;BUUU999D cnmuETXY3fRg2eo@,(\?֡QYn40($&YbK,-_)F=ճmk&#E9`LѾ ?\Zv!KQ222JJJu*--U(xSǏ;6???44~ ??W^"˗/[ޱ:Zfe:L.޹ #I:RVC.Ji!k'aXRke-t&VVe:^7h7w lNg9ћ@ <8p; @,Su…C4=jԨH$PȲl}}=EQFի m>D[cx1h+J[D"UK> PSL5$8 Wx@D+ڠ 剨~{/)0F$bꆢBl^Fsj6P-5q vL "Rt_0gxT["an6΢},CIuc,EYQs{{H*TjzR"uڤi//w{yun)s':8T`GobD`lll5c6|h"˲ ӳ[n^^^wtK||[~nnnv8O-;jpBjR(ppQ=zrn1 @w<)L}f|VYjJYjp>` V$.yXu 9RE%UIm(3ץ5qcgrU*Jn1p%zCaӧO357#yob=QKa{aHp7@[} 5B&I PΔFtݹ["h(H'FFYf,vZen;пAu|p<?"##̲leeD"Dϼ̶HI-ƍ[r}W'ԕXEK8;A& rв)LQx{,́RAژ"gi!?j94w>m:dpI<6:h:LeIaa¢.<+~DPE%~2Æm>w++^AQT5jlIጌNS)͞(V개Ouy|il YE}Sܹayرcǎuvvo0Թy6ձCOH@9OǒPMiy5$n 9iԘonL)n6bXed/G{źW 6/o=eg;\j%~Jrz-ΆYbq,,T|by9"#N>K,zV{qRg+5?ř[348OFM&#@J,M&^V_Gߔ}СC}|| :ԾrĨQY 7*7g7b;"RgpM4p4-JjmEj,/b0%yj3U9KN(S+*TUV!FWY^ֳ .2[=5"::S+]>Jr.Њ(M#J IDATrRwqBttDkRelNHذ̀ ѻ u6FdxDK8OZV:lmDi5s|%ދ-^@QaƕC2j#ub9N>cG̎3p8-!@ I֚Ŏ?aV]0fBa\\Mqqq^wlثzjms C@ʹ) UH,/f%mIPޡ?@5&CFyNJK1KҰ*C4]ޱKsZVGȻ-lWjn莩J 4y|}P9$ Wm~;gn=@?&(rr֝~yi9hgkF+(2Q:erJX#Vv"f)ֺՆXji^[2zݪ9Olopɽhlu)ˁ{ؚOͿ(;ۺ@ l`Foܸ{s 'b~>y>{ׯ_޽;WS Ac]9å PB>mds)DAsƍjd29O3~!8LXiԧ!K}5[| CWծN6+wz%w aVTG?^dN+"GV<꤅/X ^r[k0ooD.^ a)Cod^9h , BR>?dv2X<ᔝD̝p֭6dTD}ͱ:;盞/sF_ώJN[ۼq};x V-7"qbk94!*DeGp0u!@ ؀DzliiiAAVz?""–;UF.t7Hdݻy<`~k*8ͩt-wowr;~g8f贒^jnaIԭ[#zO0h؍] pR ZrHk)?Js'Qsll'bvF [MmeDvfJrg+adA-Q~3wybk p}@jo9 |gϲ,l>%l0oܸ1d޻G$yE>>7 EQ^^ѳd+NvNq`Ncz"+ >$g)TTVf<URTZz YZWeʨ(Hک7hϹV3scf_lsַ΍[׶{ܝ5Y 8k׮9rɓ˩SN:wĉȑ#ի.]:x`uuhkn&<_~e777>_yyy\.J2rCS믿 m'rXI̪լetzZ~ ѯ>ZCVUameD4Old{Dϼ|ӎuAIlm5Ў744H$X,H"4M ~`<<<̹\T*-[`,Mk놄$h B[X \A%06uЮO+Uط8~S݆Uçc@gh': k vPMZUHB?.@.G89ssr_ͳ8S,WN5L^Y+d}*ZWÜ+dkBq]påz_|__{ DnGtf!MXir'vӓ珌4=44dZm6ϟ7o󽽽B\.ZhiOHV[sկBgʝ  GpcN}}}F D"l믇HRG.Bvn~׆&8sy|gO|[=x,wUr_NHvbNh@vxž>T*H͛'ك3gΜ;wb,ZH6vay[y~wݵkЯd:XdKUtEټ){~TkҤ]_Y{˖-; /:Zz^O P䈸EN#Nt*V*p_y:7U2U&[L&ӥKbH$r|{Ξ=8fa22.(oT ǕWocg컇q0tXy\0Ρ3mw nHR#o ^)&]e%QTnՉ:u[2˥"szܦbAn uYQ8([HC<[** F­Ȉ`7oH$bwb,XNӣv~t;6)0v__lYKCס WG:,9tCqy Vk<|g:S2Օ ʜSUb}?99DFTE(*ӥYrs FO iwTm۽3i5@ "v,J###.]Ͼbג%K.^x,6Ƶo_rU /E 67}y`I,EF Bވ0vHs;EfG_Y>.)2NKw;5F&嶎^NLM*ܩ(U G뵵OVBfb$5KԍyӔݯ',unn螣lt.@Bo "Shk.{S r")ZҨoIQ].H"IH**P@-*Tw7LlTl޺MbpnhC;/m6ˡ Q}/sepTǮp^ِ*\ifjjU.rKRr4 Un.)wE,Ico|? 5& Ì}AAA>>>vBP h6w~ȊLz2aw_rJER+s(s7M۔OckLy׋>٪6[͔\rz)2K2*aSRKkFF*Pd7jcaΔ$Y]F%itNk*hgڴJ aƬU%=mڪ*aLm QS[5Ѝj "@FaL@c6`NԔW#(*JU젡>qʪ1wG.ȩ7Pk]]k{S7MJMAMӎf1s$Q9wg%_F6%3Vhj4J(m7(,21|rXmZ%FZ%6wW6r79:Chs+2%;;G)ڦ0sN?{(W@0g򁜓.qnW aܨ~NCk)] ÎĘ {43Qe![^{ٳ}}}:ٳϟ7 e<;ΞlRn0ʛt,*xbVZ>gM~Y;3]g [a.o 7(ղ ЦWہ$>):ux>>\ ~_qVVF8K"V 1Qk*u4?X]WH%kT-\DfZ/*U.ʘ&>k K8mm ikTVg>z%:g9;(9`$b_rJm.+soXQ}H!"cֽTƎ߿O;9}m+YdUzmdjGVh,rK>pCxF8Bv!pOXNEEﱺ%?YX5NO8+?0w@kbmV(D6nlKѮmc=ڍs@ %xyGo5wík}wMF}k˱FF8Kx \Fsnu$˜O}?o @_B{w hwU -x<n++۟$]CW^<:71/$o c&;:V˘FfsұtpϚΟ8KVwzhko;Fw3 g1x=8G0 C(O'pĚM{vOQ8.;m==;~>}̮634(a+[1j3c΅bD^RbߪUNS&ܞW*RdxtT!`Uʳf̢+XQ/UPj3oֿ9( ]u:PECc%9yI\NNh@¡.@9ju\,H)rלA[1ڏ(R@ HswSEN |^q+>l^\46|Uon,d/r6X#,_*9\eQKE$8F[,; RDHxgޫjc& Yt?0Pݻʤ.ak3& mei.|ö4wT9l}uKՙ2$Smg0l(WZ0{G{q_|WJR_-HnB8d^y_4B@`ZV3+ =qzcvޓ'ޗ߾w~;Gm=}wwV_YyYt 5h_ -?wYf"~}&xb .g. Bz{@/M n-s ,x###)Ec:441r\#yw1?>\Zŗ^?8 >+[K~wp]?E+E|lB_7S'_d2X/L$n̖E\H"T4<_؀ي'}C|pU.EkgkYʚ%䧯oE}}U-z-y2\~E<|GE:EQpzqMމcyeZ:zڮw|:}䩰RC]mm$EQI;δM y܍[+]W>"9p~((Ϣ@ αkCk`l  M~gʥ߬Vt(0h;NG3m͛#忓"@ jR_YEZYt>׾b5Pϙ5$W)MVo[(նZ`ӭm{`ԷdaRū@'Ybg sgq%kuM̓uFN+ՀfJ}dNh{w44T/+6:XZ uavay˃@ n)fKd؉&Лp1y9 TU8YصwF5P]:Q ZcW r2oYQRȸ[&^_/韪sȪzE拠-Mg}PiRU"?.1WY(ھADi=ֽ\ $x<#^$[ۢlsώ7OQȗ<KLR}6⌵9b2&,: c8}._ ٢Kj?Toӛ!+et[C9U )'€RTurp#s 1/^r%(պ]O= aVD< 8! zs"UBnj8#3 @!\SFlz+mE+o-FDaVfBJK0Z2-% N>H["<@i`sq1wmsff/_ *D ? 0\ t ϧ(ON['xc8DC-*TԤʝ*RЀagRx{=к-u`iT=lcSA$0LU׍6T]͹:橥M4^h7Œ_7#&µ[jtpɍNhR¹ͳȟ(|9+s9[sW!fHl-|}J@ nQ%2cE>ɳ̑},6shsOC:^zs kˠ̣cgebH,0"BSSI#ś;חyXliysڮRez|OxߕlzD>6O٥Z!>>PWW]kȢ6d&oThW >1Pll"YvU'*C*sE3gk>:Bq[ӃV[vfSpo1 w=ti7'<܇<p1<$f]N:x=KboڼyDy}/b*bFk=J,+c"j2z 5 ,o,H@7BQ -B{Dc﫾x6{t%{ֲtd׆pS|BjSD oh?,V(ɮacQ޶wM M~b]:Rć )QqSG fM\ #tS.IPI ,M!4Q̵!gYY)c @U.*4YtZ>;)~y\lV w^_~Z{ZhK,W#tl.6VG]hN֔11P40E/I[;3*`-`\ Q4j Kp@6'Ck s-,"@ nb,zqEEͻ=SޯG σz-ckfk.MGg+i"nGԊJsʙp X;k-&@q[[|fl&rh ]wJ PԲIǠmVˋ@`Jբw6Րkgà p2\"|>ddYʄ,}Z/YFS< x8/׆y83U-{Qsu R" Q&;; a |WoTFY-(z}"jb*4\d&H]Ӵ DhWj]e icwKNNOP[zp 1x(gC<@ D*Ϣ;'DzL`wD__j/bFmK'Iܞ]j`u6B0PsĔ/(?E"bϺ^`}b^6`Z)cwevBh um_,0tO*ާִQDޙPT, O?jc 噊< Ś q4e7f)`v6ͳ8=@ d\qũ&PҥKsYsssDD4 l~{  a1 G{^] #&|1)|u/R@ P(<<<8Mg>ddMHV(W~`?XTf"4K^5b's@p X:W!y9ɟ~X4ۗYqGg;Yd~IE@ 8򇰟lŢctBv64[lsY&&fdddppMt0 "d|>[$fpr-,adH g.\pB3{644HE788(cYI" ɳH PEQԗ_~9yf&"_}Ղ b$i%1\0xj|ɃQ˼s2azfgq a@ d|///{{{{yyyyy###ZT:*8&f,N/K;\2}Z>KC[C+Zӯ,- eo]ck|]+)#\xe9?ch@ |x<__A6#<=nnjj2K,qM3=Q-pڜ޵BQ $r|& v[CB\dѥRΨ蹬J5LV= \CggqFyo'@ <ja6-ˉ'CCCcהMțFFFxOCF퐟]H$:t6R*.0P@(Q]_18Z%RؑH} :"Zv]+(?\J I!)Vp{c0vlX,Eu] ,p$fq˗?& __ +B˗/W dŖ @axqNJ?Kߩ[(S4"`f6߁|SuaWfʎb-T=,޽.;Pj/hݖ_H[K˶\4?pQcSCڢ 2x0<t0u3>?76XW"Qv}k/YX Hxݩ#iK{]V}5PgdIjv=g"|ߙ+mԑ]Z<@ ,Ȣ6d&nڨHW {"zbMy=8%=`霊DEhq/)7ٺޚ0%OY.7'W7 -$I H@ I!)v@Uqlr OOOpY ?GlEg+v%3s0\Ǽpx=&j /S0Zq/%"}|@2&&(sZH?pnk" Ƃ(tSn!"$J;6g3@7NWQji-KGvm 7+Z6H[L b" ښ쪞 X!m@ Ŧ~'?u(ߏS+#E͚0rGG\ ߓ&AX&p!sCirtSkCkgq6Rǧ~* `6价BRH ݅1ar­{- U# EQC6Ǖ|>Mæ"殮ocd /3zg8Ŵma^_b/:Jv|%FF4ܹ1ieOLs @mUj6 hMQqsgJS LK%"GE@yEJoڴ yȵ!7sX{'k\ 9yGVTQڐ:=z~je/j.t+.%%js+i@;)wF%jʜ2'FZϞAK m,F KYzxBc`̥)HVln@݅:=M ˑ}? YLvկi oѵZF 6v445{ +=tSnz(gCr*g$ց61ɳ8\&};j i1E%$n.\p`b,Pc)3^JQ~ENŞu!?= 9m." SBe4D4 GXf`jTOi{I3ɡrX~63Ry@5:b0i,(N 1oRB}<@ 8D"H$7oH$BS |V9cxxfl6vZ 興,Nx ݋//tƴGRIfzI$s/ hѢo L&s/%HQsg aHnEZpJ8:PBK 0;ЮteE/LG=1`c Yz;8=3V/ b00###WV4 Dc{SNۂl ,W]Ʀc®bzë1v@ =![xxxO?~z<;J}7>|8eUtaׅO2gEP|SqbFZ&C\Fɨ$ZXUKuw@ |>;Ng MAq$f?;csƦ囊zIx{[nev{HZe7*(*RJ=Hz]mٛeee*uY^n*{)ʭlE%2R(J%um$EQuSyT.uW令/zFOrR%@ K³@###n#a6]J| wRG*){.Y=j-InkMHRjKW̵=zEM%;0?'_8iWz;`oO.A[6=>|fjjU.rKRr!ne׃ [Gp9]x<_oٺs*@ n/'䘊p#l6ۅ .\~f⡡!v+ b# LpA R,' 0a_v_> _|_(G)dԽ' vUǙoS>(4*֘f+[4PE^#hFqoǁ7WC|_.?,B@u K퟼TN5Xn@ neH"7>;le6?^?44ZZV٬jR91i14v%|WO[ݺ$Js;]?kkOR<}l l2ZwۺH[퀱:;SCag^9]!W`F6}==H[.ܷnÆC_ƍ@ 7%$fq\76w-GT I\.?I{_;E.(*8^۟DQTAZb"cYjkؙ>zoڽ%)H(4NoM|}}АbX,Vb|'F1((ȑU{G9`qUӖJwby"9$.'xcX }P_ @rEQ_2$>D9ju\,H%鱡Jr*ocw;S Vʚ8Ǜ!.,$\* bW|X*O*r٠-GQ@ G@ I?{?ywC~wS" /ӱ[D;KYO[db @[uĬaB\ [T@(}H}FM=}.8Kx<<{hhh4zxx:.###_|CCCϟ?su"Xw1fX ʘh%v2E"bMP᫶Y;4ilgl/Ѵcu0L̆0Dq6ao.E^26^̔ZhC\P!Jit^ lP(?>EQշ:hpV۲?=é&:6AIdRnL(T~zXe\n$Һ]]+Ԣ@ߩ[TER -`nؙ9)O}[j^D!q[ӞYP`0;wd2/Yd…vf ͪMlP$&DI%"D-H$TI\t)rqi8]Rps|gU7[ LYM@DwqҥK|||bҥKᆬK~^^^SEN;@ XH8'{O w'ws^ʻ{=/(翴R0֠s.ʘWG )Ql&MRE&0atar) '[MPTUo߰2.Y@e9ԑB(EǬ{D|PI K+qc ]pz{{,Z("c IDAT"BP}݁r\$3>˛%Lkhh-v@@ LɰSMdg Z6x'Oy_^h*l&@Qk`F9 Af;c6gǾ5[mǞ6}y8 fIXloYyS9| 0N<㱟]q?f '<<(ؔ~E/_jPd2V3^nR6m\Fmճ2ny' tōUύev|S{#zgyۢ/|T嫒2#p޶,SrM̊MGUӛv눇SMdgq[=z22tѼUhy6alً F]X_o5ZߢkWW7![2Wm6<@G|/(Q[IzᝅHOP[zpZE;m4zt[(r c(6֬>Uyj\M"ZaTC/H$~>S7 LS'ԮWrcѥRTd]6ͧ՜";#)ՖmREEV:[wov}a.? 7+W7а ZBif54h0Ȼevpkms c6 {l_徲4VN}uo5s& ;o^TȝR;Rm_V\ {=ޗQ <[L ;Gq2}}}VU^NI=h߶[:)WYإ V7"T$&ʥb_xQbbJQUM0PKs}U;0z >D:4 X(,Pc)3^JQ~ENŞu!5E~9YVr5{h +YJ}D` HUܹ[s ϕֶI9fԜWr# \vr*<_U[ |v5/ZCX[2wڸ:J'v?y l EgR#*=ƄaoǬ,-TT00iv~"i0A*0}99 ˒dKN8jZG^'P(a-& ѕxQ?-G %ga^KD$c3%""07h bb[ŨOG/?Ѱwl◷,{{a4-;Nqg84ͽm@=aAb{בF6-l24Svd']D-}}>׋^㘌.W)U[|M9}±VuC_vKʢЋn.yynnnr nb>;Eo GJBFĝ1w|A^j8.^Гsnߖn˔" FzzvC[WﱻTv=dfa/;~NC 2_#a.͕bLyhγ{Z"dB||xÕ Վݜq@=&n]e21m|#K,>P} jRU]&|P( ^^^0 tAAA6cҥ$fpf"c5rx'+.5t H6uHVz&itSDw"FU,y#~7gy;jcL JF.rDjǚ^ {|%0 >aFFFFFFG`/p?cJ@ \/|rϺk;@ "K;ᦃ;d8t,=)擟?xۂKL[Ix1;R)gT 3')z\0TbT,mhL͌(64@ 7 좐;dA[V<88X,#7ꆂ9~`l|(bg*oMHhg)K?|`C(Fs@Vy >f\f+*]ƦnUS"QO}Cֽ]:&?\J I!)V!g[>?88(@awE$f}y`I?P !ZcFc=w T*nؕX (5yiwK: Z+VҲ-?W-/oTPtEhC 0L}4DMbfa "g",uY@y獴`fz}rnlf9)74i!9{oCG쓼 ckJ|)ɅZ <HڸFZZl^z|Cm`floߌO2mgR̢bGGP8mYo{|sk I 1 $ A0@l#(ZK*=bO-V=y%J{TP\%\EH.{ݙٙCn&|v=<37w6b#6F@[eEQ$\"0$#IQ,9NVT{G3`KJk~A 4 ,6yTstw齒W.ܒ#Ty37.޿dµo=syPvaoOjW}?iFuK} 3ۊȴZfɚ-eTT?]7k/UJ?:|grttg5&V])ﲽc8_BXt2Ă i늒VfmVoWM3M_]v"k/6xn(Z;(_];ͩWK2wx$!jLnd)cFءCP{IXh 5$8]qx7ܒ:f̘˗/Mg̲,qĠHȠk5qUH &z!Ph#g`hP| 1`S+וEkɱw<';>75`\x{Ɏ59.}Z,}vW'^]P7C.SIuµ egWTTYq'ۯW|X[6h̳B.RSܥ{ v/8nڂ|}.}^] [^^/$w<rvSGg=fޮ mYXAx{'R5e{cq˸nYć'6Eqx7e|24n<ɶ6bt|S{^βdqJqZ[[d~ý>ԩR.sB|x\P}Y*{\[KJp6EuNkH{zH#+wز*q̱TXmn WJ[9բyO8=µ.\ckCgcY!)z\6 q}]-;d+wv=nkmrP5+s̳g;m]zX4{mENwF?ɀ~Иy]N Ks|ݾVpq:BQԹs  8p !!!)).KEQM&nONNN+}ggrMvd7ϊxv ?Ngi@5oܟNyN=FK>b0AdHCYu843bo`U_Q"v51j2?*k/}>W\#ztuWD#M*)A78n Äw߷0ubcNf=5}h|xI/XobVDr[x#{ 81yovmXheٛ4? /9;$S-nZVu1 ,Zr/8޷x߆$=)j@pn;e4h,>onYҳs<.fyV˴9ΖVpq˭u> |ʢr}6Zz",Bכ," #7}ͦ{[bń㸰<đb_W~IB'~xg/#;*~F{vK/QnwF@c.ZrLLCa'ҫ*~[+ Yu2"je#sh4y7 gpJr<> 3&998JtmhaB},Qw1/AjN(v)+X*[Zk k诀VlLLL8^͖1B//C' k)t  aYļ#?Y{Y͸PeF食|,2d=2ݑo s'8 W? Uf@G)AWEAVw%%%eeen∕=gΜ趘HyhyBo͞`&f9@?Jx'ⓁEAdD+|Nܹsaʔ)˲QFC#C~BGA[Шgsss999 DnEEd(z/kCв  BgΜOQThm ],|QS j[CQ1ϋnN1O:ySk>{l훋r{WX!&:$n~B=)" #}4mܸqzU"Ls1h{Cś.a\Úd-˪O~^jm\CQmo7\n_UJxl0p}5rX8tK䊷}+RЧO>cƌoK.]`ԩS{[14(" #eRv(/  bY6u<ϧ\ 9 4_ff0, EQGLoUo,+5nyf.EQG_&yy.,} wX]bHtWz +GvDz㙹E]@?⣓){M_6Ԓg68׎ltQFu{ 7{Ej_AAGm&IrիWI9/n.c$hY|hLMQ~S~}E4g|1́B{%\ rkq)TUA*Vm|zӲ I5^8* b7Maڣ ɀa )aތgn ׾U'xco,|H([ҷt~m"[8gx~VL'7BGA[EQΟ?_RRR\\|ȑ/:ҥ7)YNղ`_{m6ػW~R<۟ki͕\5yXȿ;V]Z!M[϶]Es./udܻ|[~[੊{m0_SmIDATpzC;>75`Or/c9Kݽw_tBWdX!c{ xU{Qphkqc(jDih4|>bK'wv;Y w^PER]i4M Am7n¤8!˲t; ȭ5$˲de!+N~kKV%KmmmoOw*q!hZ }ȕIȠ4,K1;=^o d+>Y Bζ}2/NzVn=BhBԄ[s_}+`"’kZ ܵ>BŰͥë茵E;KoztE])ԏB^HMꆆjO4THQ%n2t'bRd2EEEqG$:Ad$Az`(|>Qnjcue@E*dUUϟ??HSE[3>i dlK^ GGy`y`aY6͔ |VǍ܌E?ħǦkͻW|<2s@6|PbBX%+ru;`~QM芡y>]vhMG^hy۩CfS)N,0e1Xg}V^^j8qѣM&$ A ò,7449srJ|  #=fY7.(/_y>33S_ںҕ~L8̳?L>s[l |mnLo{^CWj[올P0GoŃI%Ù*/Իr&͙IV!/Ayɠfkv^C abOz͏~ *`1T|S󕕲,,gߒ6}-K:Hޡ uW#1.\8q0&iҤIXIGYi&fH8R^^z[ZZl6j5  r+Óu#$I'OZn&$IJH6]Ȼ8#87ZS# ^M55do햁3ZkyUy&11VҴ]v~BEy<f;{lII6mvݍVd2 Q1eڽ-_ f777K󼮡" j-fzfEܹs&L|5؁ѣ_Gg]VUW=c#+XClq5&&s.9`oGX3{C_Kg1Ԥ'kkkZ766c!ފr(jmmMII1&yYK2,&f4(@$DeA䖅($MY@e C[[d1dWUUyɲv}>_?U@{mЅw# ~ȿ4>(9R7L;u}d%xz_ cB{ z4M=z4T _]hA$ #zli(,K¢"! ÏP"ɛA`0H(TnΝ9sq<;>0L\iAn/KŰ<S=`0y dYr;(;E]}H&'VLTAne,d!Vh8}nO6X E>,"ÉRzqWпŗ4M4X]]]ZZw %I2e &}1Բ:BQ(,$:/ѿH,*0 }y]P/B>M&MVVVF< /jZZÇO:G%i=-4: JD El6?XWAcD-DY|NlC4MΞ2e Dɲ?e }Dh)tI<#%#uDߡ|$œ9st'i://̙3eee ̞=h4uSև%:^__CAa Q $8@O<9T(*lUҷȲu2u>?t) ən2(),"q%$ 1AQI,>NzH EQ ߿#G\}(eee'Ox<&L?~<)5\AdXTsH_0ԩSf.껯iZȡo޽{IsI~"q)/i%آ"7z_ B}aah>qDMM͙3g|>$I6&ϲhNLLt:#::ZW[{ CwX"DSlkk!###>>G#H-dgQJdbZ]PB6Mb#uGrEFp; %w1L(E;tݴQ 7> E{+//WUjFGGO8qd(I +#CtCCÙ3g\.Wmm$I$b s_qD{`Az@K?3fĉnj 3fLBʌ ndgQE=xS/y…'N0 k2&Mp8jOuPv=͒iqqql6J"poԡQ ;(*)|E֏c! pr|>x`lY$;zP@\VUՆ@ p8L&d2D"ʇ^BLun5Eh6m6QqIuhBMFEٕ$TE@@FEE QFu5>Ey< ={]?6v766FGG[Vd0DQ j{ GfOuiķ/f3EQ 477KDIweCz/dQSSz 2 ao!dPPP` hi>yR3, HA3?F23CH cfRF/243v[%h4+(J  A0#xԡQ h6nܸfGqLy :4M[,ݮ8>x^kjj=kt,k0<FT#롩&#=IF4QI!R\X{'SEbr( rUCfȲܳ83 9CtzzzTTԧ~Ƿ0$˲ .kرDYS.SD8t-AFv)$WUUO CDYԆF)>M8؇QPP&g8ґTvE4X]]]ZZ@L$M2XjY$Ò$cN EQ(,MII!ʢ~7DQ # `0+ E\§iڤIʈ4>|ԩSyyy$w ٞiZN$IDw$)l9ȍg(BGAd0`ELvG i://̙3eee ̞=h4u3ҟ/N~%?ʊ:a(UAd0`")e1t@Z(JHH?9rʕ܌A XVVvI3a„Ǔ 7C0ԛ] AA`}Iv 0YYY4M8q̙3>O$] SX5щNpDGG$CGY!P }Ad0UEj\^h n577zu[\e$~FbpG4=kC:  ,-`̘1'N ×BGEA ̲.^hj@%͞ L֛=AAd2$r   CtYd@@@@u^AA5!0;  rP#,"  ݛ<  H-  H" #UUɍyݡҦ mMq(l ( y睚7J{#* ƍ~]((0FL ȰGQɓ'gggGEE3l4GJ_D FUտ/ ,Ye)4MSe޽`pѢE% šlE@4M妦\YcCRRRIII0y>R`(\(@@ . M4MEafi}@UU0( M{(\(@@ h!ϢZvc )MӼ^l8`xG`$4|CQ QO93^b!uPP'*Adx#˲dbYV4-Ҭ '<_wxo߻tU+НwRΛգܑ9.˲&I^ 2QUUQa9).PP`H J4`%iVCU+VD"x1:<;+@1mJ~gDEQ$V(eYڅB@轀֎>u݀ 2< .h4@  JQVy:Ip￷U=aㆍ~rws%ia#0nraA5Ġ4M[,6!!fO A*bkk+˲^WY: ].WZCI o{qGE]޼?8dW. r<.{_mQfE,˲," 'YwGC((CM  ʲ,qdy_Cmg>~`FUM: UWY1 IyWO2k;rrf'O21t@Mh$yMXU (({-y[4"2|4i8iZb; @Lݏa%22`(1e__ː[;`0!I5@@$AiWI`44 ]Ec&)9b8eӂwpCFO}5^= O<ۻk~ blS5GpЋf ËyA`PQqGJR4\,ڦ{9 yMէŤiΨ+ɌIna?eYQBS~ E!1 r@" qyݍQ`ENϞX0D Sc}>?,%?=orC%.d$iΠ* Mjmms@'եDGG3 ӏHdկh {W :!b`0 [[[/^4n8,"2@" e[ZZ m s+ \L5%vE4%99GG" Mx|?H[qs㧁 2H^ A;vlqqM C(xرFa" UUO8xmeeeݰ755:u… ӧO谈 EA=`ٳmmm$݀<" #F|0IENDB`testng-testng-6.9.5/pictures/groups.png0000755000175000017500000015432312551235562017547 0ustar eugeneeugenePNG  IHDRYiCCPICC ProfilexXy8To,c'=AdߗlYc`%I)*VR)$f"ٲZDJ3[zy|sous,|@?H&j`mlԯ=8kp,o0, )- 7|sORF[QC3`@0G)e[Rp9 xQ Ƒ0$Yk8ƌ]vqzRtGb%y{+M$j}^w $+0 <ïe8f?rhÉ;zV?ܢYA=r;=mo/± - ~!YF.zk P ChBnOSQibisB7cY2e8Zxo^1_~`dTAN"C3򛊴J@Ն#jE4ifi~S[DAaѐɴٺ9!kf6^v'9 dqtvlE?L &'= ':<-uYsߍP{R}\WēSiW_Ξzpܭ쌆oe'u?=7ATWs#B"bز U55j=zjLAM^\imjni+j~ûٙ%۾ץsuPpHh+̯$5c{.v\m|y{l'ON>}7}_TggJ/~&BŋK=?WRW}7fˀH*FA ϣhj [= ]L 9l0k_}yf?B˂B5"bKQRyKq2+H**N+5)g>b*}ȸZ50u' =̓ZZS:zOIc7M>{hfcIr6;k`aaʼnri8(W;󘗁~?~"84F &4> />qTbd(Ѯc<..|=>+J_ISSWQ1^tcԭwbfޗΕyp0ODX#l!O1g {) SRXn)SwIH=3FƟ[R_85K4/ԷƶzyGWM^>ꁔA!ahdlUkbcOƫ'g~Ș̜X9? _gqs__-(~(Ի|qtM|i 11Aa2" ɉ|">QwT}ܳ* [6fC,W''_ 5Vb8zƒc)i.鎃gpr2E˫T(P$(q(T:,wJ5<hs Zz]:XS , 1Ff&,&Wl4/[Y Yg'(lٶ%8su<dW)yE|d~y_{z| Da}*&LBÁynbd/ەkW>:P>hb:6O+t|ԍ-Lfb^4X7g^Xo' QBDMCCyND,'#{ĥ#q $JHɽV(}f@vz=l܉gʋJs+k͟=e}T|5ݪCkw|v8a5qo?BϤ~M7?z/XX Y_w0oIn ;P+0DD oHud(9CYQ]p a*A &jn`~ElZd:vLz=1 3L6~6l~`Zqt2Vc'Ј-W +#@PJE|tĶ$Fj4O&V6SЄ_,R;O8\}ESBvNA+c!gX-r-|3/w8&D|uSr?%B F 4>%tz,Ǟ0 [|HԞKu6-7'3\nOfme߻ϖ{Cr#bB2+*UeˮW|Xz[KN>|`0qTUϛ1w:G&ݦN[}ʙ"8k4=ւ‡X][z/_++U"ɫk^k777\6766ǶTm-llP/Q a4v_ܓ Vbb <H6o-8Bv[G7ƺ a/MIưƇ``cF,~~;=.Er Y" `?2^붐B̭` Ph7"O;6gbp7Y?@ xw &}<^ ڑ#e?ZRc^莎/uϑ`[ہ++}mYxG^ofnt; ûѠx/M8y %Eɣ4ZRXHP("Tqa0YӵSLjC0 !)kf&L:TzK5ŋrN&[ccX0 CC 3EFɉH.#rIHQ$|ߧ],_V!`|#0/:c_i&k8J+uӵq۾.O_( W~~v޿(bs>nm8,U_X.e' SXmT۝mjڰ%g?b3>_}*gL:Q8k>ח}ܾ̈́~ߵua}ʢ+䆀!`=G'm\?k㶙w۾׷sulI'ϕm&2ձh<%-2^>徟ڲk~+k~+k~+k~+k~+k~+k~+k~+k~+k~+kV{,Ovi~X;]fO+W8kӥN"EGT:4NMX8[ e&7?agjNk}}]XՅ}NQ5tun[OWnLi T_tj7_Jߏ"8}֔k[k_r}}Xߕt,:HOGSU,26ګ_\թ3Ϳ+_f?aK龋vOjs缴ĵt*sk͸񵯵?vܷ~dۻ}mkjۦmչ29q֮\mYkQ=nq(nt|S00YT00#U,;6OQQU,*Fm*L^(g~Z6eޯ]۰v,JG9KXIm_qem\B:ۏkSDŽԖu\cjkWG0=mXTuM-1ǡh~F9%Jޯ2_}jYۺ0;S;o)V2yCՎwIYm\] +W?֢TʣVG0?vQm |\y\چQ>ԳdOzKxR7~vuwenzV~W;_}8*ski&mj^k_er:,Qu.pGTk?bG{&3yg{5Ӣʴ^a5e*ov`[W _j>}mVc_Vu6I5)`WO[CծLl_?`ɓzTYYtb!`( g|ɹ7|COtuPQ$Zm6֯Kh8c&2wRʵ/C/~􀦦&_dR7!`@~~>JJJΘ1y:9\J(}o̭u)٬|@ISk ĩ6^jJʗGy䤼l٢cXm!`tA D">c| (y\W%(V[iv)S[իΕSdK~`&϶6klfY1 C0b _)F@O5*(J6~K&ݢ}f^ej%\n{T҂ WG_GSm-FIU>qI4EEEt19n]]~ml޼md лwo^OwyYۣXun U٫ ?N< ~qs0!`"˼K8Y VNfgkOU#^u*rڎKPrum(ϟ'#ׂ} /κrο7dH[b֮]-ms\#K鋥KwAyrT@y%ݰu+eV5 Æ 㩎X<=gY((a@hmmŚ~lmY'MǤCKg.hhX-c_Ii*_Xޣƀ2~b8ɡdKԶ֮t1c[eoJ'ݕ/EnvA09e. ͢$SzSwbX^7t?D}֙h[އO<ؐtI\Ge˂c8p 6 \>XefB; ਘ//>2C{a{-Mux?Ec0Op\Qc<5o?ƥ'doܹ`6z!\yɷ qh'\~$ZTۜe𯈼ƒ?6?O%]m6 uheo6䫉뤴VӆrNDk>۝G΅cL 3 .E7 Ec (@ ˻%ʅk--iKMVjڵ1mz {wPq OA#%ޖvL>\KPV^eߊ$bdw0 W]'N<{h^"wt; [n{7㎿,Lyi?xB\}LuU8j2~.m55 $zgnXCY}_;n{,x.|?&mϹ4aeso~gOJl:: 7/> <,~p#'a9ɹy'C&xcǿZU ?zu/pQA1_ S7_vr%b?@ \5,:yPk/.EI7ITSmV:i.Hc=8)k[kv+^k1ե%, 9j-MVC=UuɖzǭJjߞQQQ| y5ki+@SM Y7W nd:g/'{BNOo .1!}qrn@}{yտ;=%,%pY}|omM-8Gf}xookF{&\ґ{{_pGC g௚00{&|~qqqaѰ)_!9{8Z!hXB,yw\͸k!պ~ހqqC_D<$/8h{b;yʝXȃ# ]w"]i ִT{۫g"o6Yk8-i2Z Uy˕ڥEP݄TF?d[PXTO~t2!Bk9bYy hlBi^ dYG$ڨd˚jH,/BE-/ eE(/ >Bck r:6Kb2+!P|N\~X*<3kNN{}. lKe#pWQ[>c3xq͞$L >tY?Ot݀꽏^?yl ھU,Ĝ/EMh˸wWb #Q!ob|;3~G}+o+zNw58dH 6̒C g(0 E۔\!cůoSN[_>|Qk@Q5mkq3PX)E} _H7$mnru*O۴ "q1A hO س9|_8jXzp"Fkx{WΘ48lY_geR਎)>fkߊ}"1>3w~xIIW ;,O'|xDΒߍR;õ8l$˨U\8VUI$Y:޲ATjo%v;B? V \ Qؾ6ӸɻKJ;rf\._x;+iog> ~ _~X9W'N CY1r@!o_S"הiEvGm]Yp> G;nrlڱ[j8,;4]Y'\C][O>B xIAWJemx߶r$Ϟ$'"D7=7cyEgr9Bd^l>)~9;J{˖AkJ1rD `k]w*Ħ2Ggip[ErE۲tЈ5A\raO._/֭'&/Ts\__]GE:=bDr`,!' |' m뽴I~սq"_q |aEڕi[0~P fSjðyB("x 0O=${^K6: ZT߿?֭[0BD塤˶/9-}r>Ge[/¡G"?aTW$VIzqq">xZ"kO=oO4`yfO|3S`*FM1;Gr1|gJk—p|j'F$&WyC&ږV߳^ַ)fϻ ''>lkƢ\Vn삡7Ĺ?7T}Ǐ X^y0a\vS>ΟXL{( Vռ!JX֊$ls1+G@Խ3D2wk uh _::˟[:_oܜ1kh5 %}$4C 7(0+|٪۴ v XgT2!_M5AY+͢},;@4!l=N9YN=!u\,erKY9ѾϞ1 6XpRexiC[L4ᤃ~06Ȫi m~uV.ވ=' Dl›èf`XݲͰ`'wN&&r}ѸPO.F=}\~у/> ~{n<MI ԋ?K~~-^8Kpg;kph^nOuy7C{\u[{w+W;_vrKQxWŸƟԎSn%SIwm[_,PrB\y&y~CՖk-矇_~.YO_+{7̗U>.9ɩ%Ƿ%Cߋog6PS#9U¥6fg2-n[eZS1:*m3;1O[W϶{POxPΚ2~P;F}HYx=[T!ЂoN[)7ȬZ Ur@DE$ 0ɕv\)-/8> 9h+kwUb}kM[bX%u*WHgX&C@T(mڀ箥 Ckۂ@Pнvxea}Q/\YYQMrA~C9Q#a{XQ@n0W{g oaho(/h1rQ^ZRIصlCkA v(%P<;j [P$w,H,~oeҾD_=Ck*x k_&/_=@~,GJލK۾`jd%B0 +SC1M0,䞅*dӡ'ɛ?"SS9aЈ%7YmKNUx|ѰbӧYB-#>(5ɑmOyuܚ+S4Uƺ0@XQ[m$ elCTuԇJSҥLY;gI[Hl}p=R/-VW!OX녈WR(IU0+MWêri/3Drn?8?0!ewȜr MܱmBs=Glޔ 6wS? ]lyɶ IDATk,k!pyM9ɗħ$Z$LFJcp`ƣ\mrZ6 C0EzTOێQy.fB=- i2q FcՆ!`@:(OXxŕvIjCNq}R%7%T51֤Uӆ:+!`@&(G۬YTv%W)˗Kk~PLVgMJ~jۍ2ж[o!`B@y'Zݢ}u6*׾[Sm>:v:u ԩC}Q;;ZmhhiGlB oi!}Lc!c P$壪Q N6`1TQOkն[:x77am}+lNmY1 CI .ޅPQ m,5 u?DIj߯}{֏EFWIRbueXmS.vȻT\\Ռ7Ƽ]!`;cKw+m=M9)9\Zwe_}E2)KT>aEs}jy<ռV6/'ZJ6Nw34!`@|۾&ʷUMQ?OXp %V^ekل7Ά|@nR.LÝʴvcvk/O;sۯO~o6D/{w7?W;ĭފHƋٮ̯}*O\'\TNK"Bm?^SSlй+b/..Ogmm]U_k>y4r|CX.gLI*Ýun_c^Z.Uzx ½}AW◕'t%]kƄh[7׺oA-5C~!Ld7Æ È#ѹW:?nI%%%eT 5?3V9EkpUE9mG\Q8N]&nqQm7Yڸ\_6PoZ >an(ě( G$;K|~,q/1}X#04io!#@2-%ڊ l޼9 ᢢ@GA{.XgYxD?W(Ymth)Ӛr֧,dBD/s':ڦcj/ub}|\T3ppZ!߾ʖM^-M.UX1 CHJ$U,Qկ1O;EQZC~]^R\ɶfJ|݁&a}g퇍Jj/*I8C t'~=L:Ԥ^6 C؆adxkeCe\myg Wm]uTmp\m}n~z"D~rnma|#A~1;񒳀nxL:mQU*:Y- R0OC0v"\bgXfMpSs*WLwtP}_:Mzm+ѻc]"q'R\cO ~-D<< 'wSFw7IʹkSFf`\ M˗/Ǜo zy73~fNhޔ5~xի(h{KƫDyT[}YںڙoZ;hu' &:AJyI=&bzvd3Jqz{ҵxg!`t"1hРN '}VteNc%29t59&&֧NX'Y|1y:cŊ)ɗA OUҍ(JTWn[ڎ43YKK\y4tJǐTr水e(KӾ&}Ի i, C0vH.+_%_}/â5CGㆥgqt=%_?`X"*ڝ4WyV[o_W}Ź瞛r3 CGJ2Z+*RN[Y+GՆq ezNQM\;?>[ .q2WI2jӮ kƌ6m=Xgy&ш=xc0!`:XK+*9+V=L)&׸|eK>㱄&5!f{tHP&k0J:/snj hK 淯`cXƋ|Wl\r!`;-%*v(.dIL#)jF^Tܤd^؞u-y" )Uꨘs .ՇH'%Pg?1W~ӶaC-j$y@K60Yb,!X(%bdYT}+Io\>0. H̏ӣ>O;PBb}ANT9;LŽ$p[|s1r@5[aʒX`7^bE)V։Ext2.촵!`; ;9iâu?G$TQ}]2lΕd|`ܡ޵?w})]k,E 'MbY{ wex.8/?8 |"v!L^y![Ҁ:zڥ9 2g|!hK5ߙ{aΛk3rdN!`%]%ZVk%_mgRE.6.td{U(dPa62fyʂ$W*Ne#;bgc&≅°]BWN8BRq2L B(([F}x)V}ْ;HT"ڦڅŋzKA4{8<l|9l >)/ܡs$_k}C0 4H?2$NܔeKnTܤdnsCO-X]րO]7uԼc:{aOD*궵`n3/ؒkb MMMغu+pEEE!Nuu53>Y8p'*xNkӭ+M7IwK'tWn)̥<9DN#O"8idwV=S̃v ;|<0o.^Zy\＀ۅ@+ϨZ] 81Tv"hgb!!occ#]O< //F,U0f)|bP :} V!A]u۩&ALȗ5I:g:o}r`\-[߰lmsŜc'[/01ߘPQd6.ԥ8sqa\. \6rkq,f-o3.q|`~Ø ;΄wxXe=Z<0 7`.A"4XX8:>$|Ѿ֌Om>eLM}w`71mWy+OL0&mo ({;5@-G9gju5μ)|u jZOFm-X#1-!d' 9wn}amC0>zH+V5?mMoxQU)Gb䣸p e \Dp34B*W;M}թ,:$f 6&ۏbKA+(sfriu 99jkJ7q0 _^lUWe 񖡦w)z*(-*@^ñ+0t 8p{rVKK׹}w9G`Β@!`WiCQb|P׆]QUe;F{ꅂv|Xrlq(8|uTƾ>`g` Cy]jqqp'j`󱱱/-NU+GV%<MO rM.I/BL__uA@#y ^veVn]C0 vo/Ƙ*+@7M~"Y"9 Xn -٭o=(a?*Pl֮,tԿO& $qQ:ͺ- C>硲0X 桠  Er<螧I=(QCRenƗQ&/钯LS&gyzcƌ6m=< nO[b!h"[{[)ǔ C+9 ,t~kMvwm|MFʴv'2Uqo))+#ά!`l'dK 7OVzy s#sE|{ICrX/ߧ:Luv3yho ⒨:\&﫝Osj0ЇOSb!Sho N/ne oOqbolig<0ۤ&lw5 *ҤwBF yBw5(So f>ms䆀!`@ ON+ *IN;/WA5xr2'%ȔO:qS杋sɹIR&uFPP?E[PsOpWH>24!`aѶ˹e&愐rd%D,`9\>b`|]ɆM$Lq?ݍ*&QG8taL,Y80 |KEBf C0f.}LbBVrY=_䲃os8*FG0R9:qDh'se~\u;Rv5[8E5Zž8Oa\knЦ4 C@M-|Zd}$?+"'l3eI0#$7W+_?IMOֵ[.e;ݕo*]2qJ{(zafo0 C vF~ nʣgERCl%Olgg(wtk|Mҷ W[ t{]i)P9]w!`d| ?)kXHH+܋qnv[?Z$궷y蟉}%epMΙk_ \- MS- NjVrĵ-!U0 ] 3 lc;s4\o\H<Ê!`vƛf^*^^-R./ mIـ.dT2V!` H86X˵BYts0n/Il'8|930u+_ip^veV]d35-3E CC')W|spȹv5"A 0Qd[ve]|%_7)7@hP'iҩoV5ږYAgN!`lW^n(+rl%\g#&[rssǐTr&e(KӾ&}Ի ijR0+0 폀<ƊSeVo3dR2JyGkFjǍJ35_&ʴv'2WyƵ [un)@!h!4 C#Fn~mR'EC"zxI)A-QOUGdKQĪLkߕQՎ O;Fq RǻROxvp͂>sa]cݢGp|,$@ʧqA|k]07>..3]2پpŒmƆ!`|X֦Vhh--X@mS;6!5kL>h@]]kQf>lO;D%m0hҾ-e]M\wm)aNb6_т5uX)}hym2mDrrȑ(O58CC~\qb7\t-n?!yϘ4:r~0 C`C@7!%عyB,qQCcchj~%rf\lW&&a27fN $# ,nmwK*$ꨒRG`uQ疂ØUq 1)q3mNpxɑeO w Yҷȅ#ƌ) p"Li7\uEz!"C๗oĿVnūKjhn؂[Ѱuv]6./gŜ(wӉwmsuA1$};-lʖr=}dJsnǴ:4% Dc0?ބE%aO`|Cb_׈Bnah0 B>x&a*"ץ%m(;rSM<#- C7n(, By3>lޥLMf~.}P 7uK g屒45`?_U {m|Ѿ֌Om>eLM}w`71mWy+OٶL.34 C`#=—x d[چ-(,* mݖO8h>BQQQ!|}ѾK vӮ3!ߴf 6&;mBۖpX0 ~&橃Wc xyU>h|m݌y1qX3C fyU:sUq9oM:Ҷ%%ܾ;Ѵ7CC0 pqq1F^k,7[5551gE-[]]9zLUYKT 42p5iWmy=tKJ<2Y?T g!`z $DKoVa?*Ki2yԿO& $qQ:ͪ閂 cڍ|z50 pHJ$\[g%\.s60~ O|`ĵuz78;Uo)/6L[S!?!`(hDfJlr+ ʴv'8eTtK=9;}W8g!`|ñ)%ֵkGg .q2WI2j3s Py8Ib-܍1'LĄpHыbƆ!`|8DG'׸|eK>㱄&5!fK$2\$|0[\(HB(ZQf$Rqx~UP)V& WHf:C0>"%RVeQi6Mo<[ 7iWm7I }jwK[lII_w5_/O! FSU9R.OO6l"a2?N|T+_v~Ewh-Iv2؊!`+TuN=W'dt̟cq\m):E˕s>jC0  a:rG u,rQ a]:Ӟh.D<$ׅĕƺh)ر(0 C`".fE6ڹ"t~ڹRPuVZYmXe!`vImʘ2!_$`?$_R0WhZC0vh|Ѿ֜o>veT2!_71݁Ĵ~_Q<6 ض236 C`gDkĹNaߵSyupm~|k!`!+\Ήjj N&+T$|w'曵̶:s4 C`W@@l東.W'ɨNek[sZۖ9ӂ!3!Is)&#tɗ*F&ʴ:Ͻg]Rg!`; a?*V?]Y&ШtM IZmtUm[ f9!!1/չ\涉m|a24|݄6R0 =>t^1dup;6>uL%3/萏 /Kd=Gs4 C  ե uĪji&2V=?-?[6^{ C(|}&}ul 砥9k*Ɲ[4<|=G9!14L)ֵkGgK%Q N4IW~_4~Fu+dKґc CxwZfY8eznBL+]Yf'=<ޘ9 1`b0 "S\M-m|fԄig?С"M:].4`RQG:Em)p٨%{; 'M:X~)}&V,e{ wY*lLSqi^E!GD҉2l *t̍)#-رAyx#ƠeAށEXS9\u~9 xljp>w,vZ10a hԛۂ!9/4_ _?lDd~-w`^jMR&p-p rcUn]4\3b`xoĪ…ie>%eRI {528$[: ێV''ӥs0!`@G\oC/:\oTBDkD|'an)XX*ۑYKZ*vFifh@?./cvQMv7$};-l`ș!`?Z$SALx/ktt0^Z R0hZ,C0vX|Ѿ֜o>veT2!_71݁Ĵ~_Q}A<)QX=K0@_1EDޔw1q`f\3{SS%%1O>d{$nj 9O}u}mz9t:!`0Dq ?U~mN60~ OwӾ&}Ի ikf }= ҽ7hkkg~,GA~^J "wbo9o5f/Kģ2uKk_G7·''[}SnGcOoM.3}3zEhJqu#pPkk%y| sҹC1gr%x~<!"5gՎC ե uĪji&2V=K|B <Gg>XN&*'?ܵ }c?zY߽ф۟K}Я1kDcy_\zm!N;uڂ;e샓ÿXb}b# jI.evu3*mO^XGM䆀!`ÙP;([&i7jXuPiM2Qq䢂|TCq1JʫpEȩ+*HM]L3}`UAWe _=Ɲ0]5Oڿ!`ls^ldQaFZcx;HiߵSY5O;WYQsދa0p8u*S5xcS>TKU%RЂ{; W=ՊO|_K}lZYoΨ샓(O68 eu%w Q' U>wlf90ʫ/W^ހq=Lyixl!"dIq/kh%_wTtT03'>E[0 R?x]VS-%[9;<p0VVJB؊?r-QxXCgG6[ϖcvnă691wU+V%キO;torrz u)3x&4m?؄Z0 ]G6r0 _?t&'WP +#ZFuؿw}oeQH?z ڱbT5cQpG GO:TȅMD<,^΀`~VAo;cm->1؉ILsx`R<.QҞ2!`;G0R9`{N Ɇ\?)Gj1_z\BeY.nI㾥MrhF*^. c^<_7 CA0#߆:_54"ߨ܉0I.iO4Oנ5lȣ#CL? ouܘk]yTSnUg=C0 \!rR63J'ɨNek[sZף\\풤ӧOrc.EE$I7 10><=cI94ƏfZC0v5|90cFpu6c,f0ɘ8b' C0`1VW=ZwwѤ44t]ͦnݺXw%8*Y7OkQn9a"&܀ϖ Wޱ-=3_u+f%-a`:tÍ L gd:C0v8<:6/wo5Y8eznBLAP?{o Uu t+ `D@24&($f\h53`2;F4D,Q[L[$& *($ B V?o:f=p9{=׋7_9$!ܚ!`@"@ޡPqz4P,)7/s^a#4(N|$G[|rLtYkD'7V佭V8C,zE&_UvӉ}ۛ9 C(MsP}l~7&VJ%>}y/l4>T L IDAT"[{xFYNn"wl[ݒ9ׅ!`q?|Na.:sXK\bW7iu^D~BTSSjQ՞Ӥ]lէv\`LL5SςnZ>Lj\(f/7 X52cTn ,MFU+#cɮLqKɒ+wcVWlؤ!`@iPNxiMWkwi&ӹ!_-$Z~mYfMDIo`CMU&˥n4Vv7fp4_H:efΔLUT)MSoz}@57HNifop7wƻ+s]b!P, RGG+v:rB^ 1d~)=cen! ӭ[74iRrRAhս"sJGV"Z)l!\v槙0 C]!$3`dC1wʯ6w̘12bO~ËOzHY0 C`WD ?B1p#?1W~|&wyivį/hGA8{:,0 C`7B ?4h^һTuN^W~Gi'o=\[`i> `!K @$&Z 9d L)[MƋ/)7ݼH^d;vȹKt:&܆!`/>ЦĞi~cZGoWP+|0oĨ3߷鏫:=܅T$_vx̿C~*0裲tGw%S%!`# mJzueN;jy?M|.Wޮ۞v+E >~ֵb]S,)-0 C hΉK:R/w"4A?mڢ|XRuw\}TyzC5mwxlϑꡇIyUhI`%\R0;Lƻw2e{R["(0T?ׂKI N\O1`Sg~I%N;w.ee#dOf_XD翥wrߗ]V -)( O̞AWPʬVK Odoٰ\.ܿqWr\ykE3j8ڰ ޼s6-eheFm~wl-8ysqi?>'qr6eZM4n=ku)ڏrQfĩ2h ^-wv?'%"_%'쒂d[Rpó3}+?hlMK.ic%qsgΛ'܇ Y-eҧ V%ϓK'Z6$ >|2KeݦrU+rܻqvF=IX1mvk2\2nZfOT.XSLB!`8&?agz+ַI{UܠN?>.j=**ϿA~䵧|o$=M ݰ,ۯܭhӗ;EQΖU^ztw'&'SrG[bx Vo_)o3-27˔}#n%¾K?J47TKvrzyn%É2d2 e-,1.I'~sSǻ5C0H8<Ř,>C>OK~g9qڔq~W+v^ݤנPҽGLƏ"?:ҐN(`,dGȗCΖ2snᄾy8ٯ~-/Uö`X^x%YL>,;2E~80{:ٲfrJmi`U'K-]Tʔ_ȵ~JOLV5^-Clh4C0vU;g|+mh"QꝤm8ܭʮ{gkzPi0x\]=i#쒂'Xpò/q#*%^7e)Ij1(t9n2 G;ߍP]" _,߸8w u5#Q˳je[urԼq3VFr W˨ _oy7[|?$k!` 8>nzruNOA XYC%>}yM[ ?)3.و _##K |r;BS5zf`Mej";intSMnݗ÷ڿfΒȕbA,[X!_eFJje1y!2u$W>XpV NwyU| 7#^t C`Fs ~9P.kdGzI _ʅO]IAo!~]ǎm]w}*5aIAΑwliz,lwK cM|Ϛ)7gܲnΫG] Mt.Z4i][].N2Q~*+5ԆK.O/pW|NwAmuunyĖ#en@(e]KzvPO!:U#ݒwkE%qpYhIaE۱nE#squtPZ{ttC0xBDJk*)dɆv$ Uϖ,:+4 CÄ/(KMG/w'iS~OmIDx,h@b"G~bh0nBzGP_k!`!B ?4h^$뼸z7$<Λ`{?u\M߾}_tPxb !`(5j}C}!Q/:$Q\`~>mhB{;p 2uT9ꨣ}'妛nK`n'ܭOJ?.oJ| ,h@ mJ'T\߆Vig=1 z`=1m?%m&UUUe˖ĭ{Q.j2iکV(,=~r]"|;X\Hl!3)K"3C6e!G;uzbZGwc9XRGVhK*n6H5{跢lWyg͹RfG>f! @ќ)t 9mk 1mmkqvQ/xnt+$mQ&ҹʌ%"qw:+{gTTnY'b#rY7=҄e dܒI!`@ARr'8M=M%$wj!Hh֛]Rp<d8F;^~eI%cQ_"3*n9X>"5cɬVȣo<ݒ-hti.?2߭CP qK.pKUN +1"i3 CH?>'qq4X|1( 43/9iΘW~G]z ᤆr _RwlވeztRE;Jwyj5h͢H?ˬ~,f!`@DŽ>tu&V iWOJw%(䋣Z~g7on|~mn-O-)22`@psU^[=&-:!`c[r|m=zK#_mi tC󒂵nI`́raȡ$jC 7K7D̖E2U.#]VNEzeIC0 w(Q'ukߩ&Vϥ.Ԥ@mBD_X?|Y6Y'Zo䩯%7 W[-+d {3i!cP7E\ICYD/A421NRЇo3XRߖ5kDTo 6[1K E?z#\!Mu X?`0 CG |o6C f#|]i&;ׇryq9A?=cݒ d:;lIAe` ݙn!D I.8pgnk$>ۭ|nj##F(7F~gϞY:0 C])y T 'O6#!Om0N%ǞNnց!`n/(K @'ijtutC0 C $E3TG$9:1mFK^mI6!C0TCO%kuN^*M;I?Ϸ&XcWXR0oreSVC!`t&JMZokN/$?ꯐ~|ڔm̛pKcC0 By6%" :l+r'A|['JM\w6/M0 Cy6%y 3 a|;~N!cG`h9rxl`|x7eOHtjfŲ=}L~ke[rК!`@ hΉ=#_]ҹib:Whh匟u䒂 ,xeXyfcieCϪF9ivFzT4i ftG;TfX M'ɲ_I}gHcr˖u뮒RI_:W8wѸX!`@GsR1\_JNpz2:K. I`/3.j5F|}Hq eS+S@ [) ZBЭ!(%{Pi[hq6\yxg4,Shk,k!`?>'qq|X|1( 43/9iΘW~3fj9@,2LkY;PzV1zVn!eύ'M>Y_4Ns~80"o,xToy¬e C0D 1!Bg9J`rWOJw%(]-'K cۼbhu#3M=M2qjnLpԌ1<!E cSi:@ci_;uIq~ 'cl%7oFS.)8)e VȄARrˤRvfv/3pYdK}wC:&ϬS&\Jn9w -wxT`]BWt4 CHyUqzR|k/&BI؏o_%CV" ^*( kZؼ/2ኅtwmLI|s;pή|4jBy)e s!S C0|B7sP}l>i!6!&A42-ɧcfO-;{I`["킃c0 C8B\&.9>6C f#ŒoI_ʅO`s!aA Hu.}q8!ڜXu=i'ܐ%`ɠ C)y jB'ڑ1,0 C(#pW*ŘJofGt?ޏ'ڶ`"<4 C`OF ?B1p#?1W4~"߸ $u^S.`[!`@;H?I:/^"ߴ|;o:%m&)/@Ҽ3_lux!`JMZokP_H~_ibA$ ϧM;p1]rIbvj C0ڋ3)ѿ7Pur}Z!\aQgoW[Rp?kpsYĭ=y2yh>Իb!`Cڔ%ҙY6e!G;uzbZGwc9$;eI-d<7;S۲UYҀ>}29~ƫتMr|/G6eclk! hut$ߤ 1m-:nߒ{nYAzEFI670 C`!@ќTd /%r'8q=M% ;ȶV.lƭo0 C`'!I~ 8}X;ߤA:'"zX\?Eo.)!#(c.]"â3ˁO%NO<'Os^DUX!`@8&?a^ [դ=4ة'ZM3>'eʘ>qɬj?fyJ1[derv.桴C0E cSi:D?owFMG\O8)}%;kIA!W?(mdrInr_<dxVi-si!`tJ' 5ϒrb%_D;Im [>2֊,YeQ~ن!`@SG9Iz>6X D9@O8IC-f0 CSH$RK_dVN\mΟj\A@ѓ[Mzjg!`t!"՜s(7idC;%YT̖, 6+2 CÄ/(KMG/w'iS~K`(ik, L[t%f!PI49"-)ig7!#~^볳N_Rp˖-%St.%ZfOUI7>e]8[Ə.I,WkH]m!`$柴l\}\~/&:]`&Lp,ԔeD|n̹XCYsJ6 0 C Rփzj[-|v[)۪/(^%.[&;Q%ᨴG#e|xprL8i6NsӶ!M #X!`@['qDXA:'"zX\?E555c۠dc75Jદ7Jr eK1Tsw 3.%W*d6/ƊHd퓥;M+,d@2! }M׾[GYʛ*n`nߟTk5B.)2ijC>OK~g9qڔq~ IDATWQK F(jw|;r#Z1p1.">& C PbqzQ,)7/^; M>Jߦ`K _i4Z3-CP!{0`۱cG"A q |tq:'IKD(H'}÷ `Tg?*QdC#U$d\ 14q)t||rb7ͤv¯§ro! @"$^!٠3F_2 Hu.}qC!ڜXu=i'ܐ%`ɠ C(  T/IV$hhB.$Z: )y YZJ|i H. 7 SN:*'|Rn(|i[qK v֛!`;)O) ; $:M/(K2-d0jɆbXmۢg-%H`Y0 PI\qD[Fбђ#i>st.)Ց?IOV!mhX/)O[\RpNJMsڈ@(`IX!`< #\A dH@E/I?q00 /Gq D3^{|= mJ i _A |ߦ?^ .O] iK %_,wϾGVfMjStonN)ᄇzt2r{) 劊t/b #FD۹>Ц$/a|;~N!crA8'I䛭%=Kj]_%-rV[(遳!`VO>i_|Q6n/.ze/.߿z衑{t5_gNIPJMӶђ\#_|J"YRNnEǍų_rX #ߒ>#3Cؙ`ȑ#}eٲeiӦq: QnѣGGČS?R/wדa>ԙ_rLǶ%~V&3.)x巣%/."HĒUcdAH*tk.$c^ fL(e׋L"]rL=No-`N;ciCJ^ pAPBjgI~S 8EX|1(:/|NZ3VHmK p4_$+,9S2UXC%n~> 80 Gh:9J'1!/:Jĩ2`MZՓ҃; L0>.)Xǩc=V,X O'I&~',)X^鈷y\78q4 C`A 隚t=/&टqbLs֣)?~aܴwFMG\O")}%3&R?5{@s+;lIBв\C0Z+.}7@D CaQ,)7/^; M>Jߦ(uL%;W0D@/$6+,sLیSMwsP}l~az- Qz߷5C0 =/v+'?$Ns+r>+u,.W6BɓA&7sp~}(>%c!`;~ӟFy~ׄ\6NΥ/k䶕WK'$1$^R0SA6eOBv,P'.*Tȸk@G!#Zl=c/|VrbuM 0.ioɆv$+Tv reRQG/5Uer+Sڅe[\j<ך!`{ 8(G?y+/~G@|J_k`bivD;X_RwI j;Ԕ}eͦI윩r%ECYsJ5 0 ] M){j~x/ي[%7#i>st,,b2KuVӟ$'6ku,Qǧ+*Nq`ᄤJ"7ƞ|Ǫ;尊2“dƭKv$hd|jq8xNXrGڸzqdHf;r!'!@җ$gqFt`g|9$CIzZq:'O/yl3wf\ԶA}$Xb!P,JMZoWsNŅӦ&T?iV%5#WO^<հ\=ee^[dKIrSrw*%֗!`@_w(7Pur}Z!'A|['FM\|qJy,)ذTʖ9JWkw`%HFjpKi!`E! mJ:ue!䛺S'uۡs ;ȷK fjVLM:P622wo we6zV>v6T:Q CP @ќ)) |[OӶђ[R^|r]Pt-CxX.}h^;4G6;%]guf;uEK wpPyƍ%q+>FќTpח| cʝ`LIG'M1!Й_  Æ j3Pjg|] Ú"r>1v9ʴAIyIkuƼxv%۷Vm!!Їr謣>oDҒ ةKIq1=N:ז,6+0 C`OC cSi:@?owFMG\O8)}-A`Y!`{"Jc|+%CR$}oo0 C(MsP}l~GD(H'}÷ `ApY!`oEϟw֭V8c~Vow.q<~5oro?Pn6[,t`N\t^\NЏww^R0S4 C`7Gċݘ4i,\P}JfN{;EK䶕٥8'77I-ڷ.)X[!`8i!aq駟. `M"RIJ:|)ן?Ў|~?w%۵Vl.nMO}SrAEC#N$`J_\#7XC1xи;|Kz%ae2l]@eY쒂/EK N2Fgt^Dz!`(3׾SN9+P&G(.|XSO/Hdubf~|q甤e[wgd}}[3K# )os"nܪqIm.),[}xʭ!!vp=:qnE{h㡤z=z{QIy.; ̒Fݳ]뎆ۅ!k"jA)$OMx뀽 Pjz[CBs(.t0?6e4RvwYRpܳvZU}ߒ+nJ C`" a5qGs>ЦD|Bym jm=u6q_wXRNnEǍų_r:Ў| z-0ve@񨶮.wԋˣ i_}vckQj_iU|tAIq1Ϡ]UQ&nҷgX/gk!`{8ռWUWU_@KO19K9~ӒmN6eq=<(+ܣWHrw!TeWo!4 CwU]{C0 C @(0N~Ci+|u'mM;|O C0 F㑧1JJADɆv$10 ChG4UtrG04;ن!`@$E WTO'6kutC0 C $CIz̸z|N 0 C?DЬo+U'ۭ:~>m@ C0 v# mJ IT鼐 _A'z`=QmtC0 CP|MI^B!y׷O- !ԝD=1;1M!`B9'N/՘Q?$_Dh~LzGC3 C0:b)˝d6u4 C0:|NSǹh)ӒoҠqɰ^3׏ C0 bqL8Zg2ַIKq;u#Xa!`@ǀӜu h?Ϗ֧%_v`.)Ώz=<, C0 "@ޡDqzX&)/k/jbe>J=a\& C0 b9MsP}l~7&VJ%>}yY3 C0"9X\am/rY'%_=HDs榭yg!`HrIoh>|ŒpPܐOi!`!4a<t?_IZ)ן?Ў|~?f!`ܕJ2 _&fGtS~70 C!H󑟣c |Irdubf~n!`!x(^Wsx)(B !_tI|ڔф:ϳtS2drrSGUܰW!敷>5F&0&3Ylׯ_/ZJz-ٶmΚn1nnd}!CI'$}ȸ#&]~K'eK} wĘ{=c,>=>=J_>Цİ|Bym jz0G?u_c |޵9I$O$rd~dIگyJ^x _}tptOo!`ޑħ {Pl"9䒌o (婧?^>h9W^tW_~Z?1#SLb;&s$4Tw8*8{ZglWϮs,g=>l۶-BscC1M29w=j$Yڐ$ZG.$bx} E.^ $\-KF !*ʆ#HW #{reokL4pt{뭷J}}{rtiN}qT/m9Gťh ޫe5Cs=#/̜9Sz;-/잣45mOj9CSNi<7oY!i[-"p&+]ō'~yL䫏I$`$$E $GI+UN7 }3住,oO?5:ŧ_?;\wck{<WeKVy?ɴS9ʙq+~"kyWۧiD)Sx+]La;jwZ |oʓkc>UXGwlwG#ҝ3gq0Z/?r+U|^eٷH u{}{[auVv;uG{O0|3d~0'|NBǩʴ/- Z+]sGI'erаAOh.Yɽ{?u3&R "y罍z-wLhd:yG4 QS]+EK3WN򗭺kC:տ?Ul:rVhEKCCkzcɗ%ix/ٯ^!J}dۥW&ֵ):>l[\1#YUݿ{l $m/v yrӋȏh) o5$k76J#L6%GK%>8:F:cڇӒ ةKIq1=N__|]wGL&wz~b~Axw<'1i 1wYswޑOTrom{tGwĻuh~TTGEѣO^'z^96w(1B4:j4%K~Gw>-7o*ݕxŵ{E0>bR>}:䉐C`]]EqսYDoG9Zn S9Xξ_#sO_P˺ȟRjRaA8ڭqW=cY*Uyҳ{;H{Y諁.%;K!*dmC'ܹ]mYU#o2o#r5eGtfb%8g';c䎄wk 5vz㦻9Iz>6g:$|:Ijm$^tq{{z:z '*GT4T,HN$7&/H $A.J]Y8# =ݜwγRyνw=M҈B]O6Ge?8])T)GG?BqyȷZ(7 -|L:0\n'P.|:/.'߳GOBmrwq6Zw׫OM;⎿$4O}xF8Y]]0~IBG?!w塥ɘAKwOc@n{ɬ'KnT7CN9׷Ue/|Kr;xG8X%[ۜnEÛ87ظx A[lBܾg]&u9~4X'O||OUrFEoi@)g~ ?#T?.+wFÉw5;-o.8ov~L$RK_,m+'6/|s8EOZI27c~I%kkd/}d߾W=kpMF S;, (Q[7?!<_I'~*?84k}R Y_~ƽA "T;(ZN&OZqL>doyew'>E|yLѮ}A&{ m>/%7:{:WPjwlmht0+;)gp;id/OoCפ~/ePn}@h({|uot F#^\ZQ#7F(m3D)jj¥ _D ~Jb>yvrE/8/|x䛛3[&G|b2(9xƭ#3?zVVV"Ҿw[#`R3J~)/~d/Ȩ.qg}Z>5Y'ۻE]#f|fl'ݹo}I?y᎚3Z5v$^H~7ma 9ܕ{dw] ~orڑUw\uN~7{ǢU{鲦h?zW>]>sursM; ݶNl@^}5IC }%՝G?u_F\^t9:` ;!UEr,oW?z>;{?o[)MϻZesGrGwLk@"yfy"N8Q 枣BA4;e6ȆV;jU4ԹTKu;(vG㙪T7+Q+̵;w?lp7脻xW^-=PtoѣG;_\pFA! |v'* 6DIڽ.{ nU wPkV%| եns,%~2 GNhC7ĩ}9?yi;M}(MgD]$腡 _*j%r)t8/jx[!cFG"#ݏ~]?F?v$bʫ{Kby#fܝOiލ(N:`%ԁ-0.T;VL:7K޸]+vbjS֩5ћ㮹rYm O? ˮFْ?q .swzEf}Q1:7cǎVFvZtg)Ps3活z񫅍7Fl'pB-0.|gg?Jz]#ݫWѯxzOmu&Y{堚mӱA͌&QD6B*;~:{٫}:} {qyqK?j?^Pֹ'Gw§a@3Nn>we86ޅFNA7׮]+/Ns3F 6̖l믿.=/Ncy䑹lQ*+[.`ekeeC#gklq__~/zw7Q|,0ӿ;toa43mʸS 6IO$j+)?E|9wQ2GB p㋗Ë"'_?s"B ׯ_/+W+VD .XZ<oh)Ç]#k\oG*ذaC&a;qp+ua ,9`'%8A/M RCNL.GI$c-Awʑ'jXVɟ-ɝn?zc{R4EW5pTWMs C`"p.ƟYڣk#/ ou*HWS6Xg-< 2q~_QX$%=ŃYR@\cƑq6, 8}dCec]|EF};"7*A ovdFGV G;q `GsR1)˝d6uwHtm 7wCPin sN|YX#GҠqpgQg,!`"Їqz+d.oU| vFIqV50 C(8O19K9~OKėN]RzIyXf!`ECtMR^0^;}zM!`Xj919Izhb7nM>JY}֠01k!`@, xq)Sx)˚W6Rğl@=}~>l?f!T8Ռ#^;_Ms"l?Pr n~ I38@:~= C0>xy9s"}rD Cs B!ez?\NFׅ!`@Os3Dmqx9l$cϸIXB'|C ?tØ C0 /r/W璳 Fߡ?9;Fzg=w~!`bpjGmE>nnHwu-t|~ B7Mǜ(s9IژuH㰭!`|V2 4ׄlYL !>6%ut `s鰱Y: z?f!`F`rݶmOǍ1:mIFcIzXS3?'1q,ࣞ4瑴!K ]M@2}C>v(7c/C!_G;1ߗܐϯ Pn|e(7hrC>2uC!} :ڡܐ |~Pn|_rC>v(7c/C!_G;1ߗܐϯ>hZB86~ >CPYsG hiqm#5\x|ѩODőI,Z!WM2%2Ċ>4g ~ء]sbKIY}$b#I1{tH#AbC52Nk 8GP8sYXBQq9Hj>?? h36c6;ja=ܺF,ql׺g'+>(g~@@?gEu\vs_ӆ4觭s9ԳLcC-Swj1Va| uA'R:W'~Cg)Q7-_6+PV߂g?{@k5i;wg`lnxG yDgo>hc u / n@q9o$L0ϡ_K5F?A7|HIk> yVoE^?< 6A"F$ɾ|>GcߴkKjOi+|ѹ&BF;z0 KM1.= bQDh-)ƼgH()f~@ 9yD?~xncKc/u̥GD2.i]QOobG*¤ #>sˆ\Q-bDoOc|Ar5 5G1[} Ą2 49VE 93:?<hh]!}]i^RAC 1ꑣ=JA 'I\1G3G2t@t cO)CG#ICܡ3]7}c18$sqz_?/ӂ_#ɾ ?9ȶ6prMAgt4|$G4%_NR?!88AHjs!N"O72ec6~胎cYOa>B4 ?5iϟ쎯>lmӯ%u.>Æ1Y%s >|*$}/Nͩ9>԰ ڈk;9hZmE>km'#շ~>~N矏mH6xϧO<F.SsiCu~hZ)%_t]f1LߵAG.6`c1f" g߈ÇzO\h}1qGŪ6g cA6u"c?>Cx0jϟ]2%;|~3%O'#o:ں?ԠO}xb6[ZeG#NNOTCb$Qj??ِL]ZqLHQzı!k5Ɛ_l}Ӈշ<6_Ǟ?|o+3E#@Roa l/?u78Ǭ2ډ2 b>N鼸O8t!lJzP`sH\Hl!7ΦB_}p^" ?{gzb|6z93'R`~؏:΁6Kli7/Io"@OI8l같 q I~š![h_NX}g}Su?x,t͍~p i36%96t8 \mF?dy KZE|SDZ%we>Xc,Nje |4z)ϔyiV'3zNtKϮc t }9EuHlh6 >6kE("aQG)rS2q(9Q1>  2,G|3dÇң`ƵtC0 A@GN΀D\OIHhq6cQRs_c|s1 :&q= }&SP8b\ C:1L!`t,HIx&G u\.:mv|9&Eq2ru-t'tn~?+B-h9?Oq4Z׾(!`t|I7}_,"hy^GZ<ؓ_?|c?}DGrQ"WPqc0R7%_t)1I!$|<Q }~_\u-ӄV26%qϣMWGGyqϣMWGGyqϣMWGGyqϣMWGGyqϣMWGGyqϣMWGGyqϣMWGGyqϣMWGGyqϣMWGGkIDATyqϣMWGGyqRA%kٌAHRPGuA/9cGϺ<|u!:!Ff}&M2EsQ(?O2/\9SPXH)Xgϟ ERt]uOL;&1Ɠ$b$ʥuk>.ZŐ/;`|9}z#G-6+Ls Y=Mc=s}8v\~o3/NWG̋~o6⤟quͼ8v\~o3/NWG̋~o6⤟quͼ8v\~o3/NWG̋~>mH8q+t7/QC.`ѦDaF cֳz" 0^@XI'`б1t4ʐƾ _5N`h?r}h\tϞ?׎9ZSޑL1ũsD1çQøO?|>-5"߼f:%C eNsY`=jd!Mq+TZ} b|k՞?#~d1JC]K}}kSy9چm }m鬥)kӒ1֖͜(9r,K[gϟ<{|^?>an;Cs9PZAJp8v&ybcܳ[E󜳉kQm?/7s  8ejfZqZ+7b$sM=I8z6q'm!NC8iGq&M=I8z6q'm!NC8iGq&M=I8z6q'm!NM{i'Nάa5OT^Ԙc%VY RCOZtA{͹fɹ\Aou9J3=o~}q>?֜7vƬƚ]{=Zֺ{@S=0u쯰穒#֍yW=<U'o*tgݯJ>+݊1UN+ѽOUUN+^n*W_~"ܬ^S93v=4w3{T̻7PDIKnuAϮYM?zn8iY8'NC8iGq&M=I8z6q'm!NC8iGq&M=I8z6q'm!NC8iGq&M=֪z%N矄9ZCjF]54 DOνqV+i3>ԋY?~mfyour?755go 4&_m?Qwҧkg~ v% %ahegnU_ͯϛ>iJh?o~|'I{Ԙcs}&7Yq/W:.MC#s5ĩ+բJV\k~|n~xVI8Wf^v)&f+޾S M 4&89VJSΩ$gG_;ϋ,KyO忪Zߥs=k~o]gS' _/Gqxz8r ɞ;ͳ 4&~xٙ#9xd6N 4&owWiJORwuG=@hM{&pr`;㻣M:a_TQhM |^=,_?WS71LPU8ej/=4淌hbZ~B~:?^}e@ ^9Оgt&ON[?9>[hM 4&@hM 4&@hM 4&@hM <& 5ƙEuIENDB`testng-testng-6.9.5/pictures/failure.png0000755000175000017500000020761112551235562017656 0ustar eugeneeugenePNG  IHDR"YiCCPICC ProfilexXy8To,c'=AdߗlYc`%I)*VR)$f"ٲZDJ3[zy|sous,|@?H&j`mlԯ=8kp,o0, )- 7|sORF[QC3`@0G)e[Rp9 xQ Ƒ0$Yk8ƌ]vqzRtGb%y{+M$j}^w $+0 <ïe8f?rhÉ;zV?ܢYA=r;=mo/± - ~!YF.zk P ChBnOSQibisB7cY2e8Zxo^1_~`dTAN"C3򛊴J@Ն#jE4ifi~S[DAaѐɴٺ9!kf6^v'9 dqtvlE?L &'= ':<-uYsߍP{R}\WēSiW_Ξzpܭ쌆oe'u?=7ATWs#B"bز U55j=zjLAM^\imjni+j~ûٙ%۾ץsuPpHh+̯$5c{.v\m|y{l'ON>}7}_TggJ/~&BŋK=?WRW}7fˀH*FA ϣhj [= ]L 9l0k_}yf?B˂B5"bKQRyKq2+H**N+5)g>b*}ȸZ50u' =̓ZZS:zOIc7M>{hfcIr6;k`aaʼnri8(W;󘗁~?~"84F &4> />qTbd(Ѯc<..|=>+J_ISSWQ1^tcԭwbfޗΕyp0ODX#l!O1g {) SRXn)SwIH=3FƟ[R_85K4/ԷƶzyGWM^>ꁔA!ahdlUkbcOƫ'g~Ș̜X9? _gqs__-(~(Ի|qtM|i 11Aa2" ɉ|">QwT}ܳ* [6fC,W''_ 5Vb8zƒc)i.鎃gpr2E˫T(P$(q(T:,wJ5<hs Zz]:XS , 1Ff&,&Wl4/[Y Yg'(lٶ%8su<dW)yE|d~y_{z| Da}*&LBÁynbd/ەkW>:P>hb:6O+t|ԍ-Lfb^4X7g^Xo' QBDMCCyND,'#{ĥ#q $JHɽV(}f@vz=l܉gʋJs+k͟=e}T|5ݪCkw|v8a5qo?BϤ~M7?z/XX Y_w0oIn ;P+0DD oHud(9CYQ]p a*A &jn`~ElZd:vLz=1 3L6~6l~`Zqt2Vc'Ј-W +#@PJE|tĶ$Fj4O&V6SЄ_,R;O8\}ESBvNA+c!gX-r-|3/w8&D|uSr?%B F 4>%tz,Ǟ0 [|HԞKu6-7'3\nOfme߻ϖ{Cr#bB2+*UeˮW|Xz[KN>|`0qTUϛ1w:G&ݦN[}ʙ"8k4=ւ‡X][z/_++U"ɫk^k777\6766ǶTm-llP/Q a4v_ܓ Vbb <H6o-8Bv[G7ƺ a/MIưƇ``cF,~~;=.Er Y" `?2^붐B̭` Ph7"O;6gbp7Y?@ xw &}<^ ڑ#e?ZRc^莎/uϑ`[ہ++}mYxG^ofnt; ûѠx/M8y %Eɣ4ZRXHP(+Vd^yl]z͢Zբ71ߪMzi]zZ2D1A!R<Il\($$!6ZYvvvI2L|oG6p8"O8>eA̧-c˩]Zφ0$tT7 `ѱ߳GVG( 18 'lʣRҧz ͳhFg/`Z)d2GZ26L:Z Mny?1<݊C<%q@sXOWN~y\q'/JN:M)g`X)z9y}<׆ߒxsK:XiBE)`ob]K~):9hk҆eثDiZ )if{l?-ך .rB.!#'٧"r)G~E%.u}{)cE<޹.WJ*·O}9#iMRpy:wDA@F!>n2Ҡ;ͭ_vM{ʎ8;;񁡶?_myv*̮tH:J2s0!|| &SGt|T8-ztlQoXl,4jh ;oS\{`?b3Ij Trqu0QU23 ;^mZAkz!@pڂ ݊K!= $ DXl 'BB,U-N0AO e829KoWgd68.xBbFE{-9Y:Ov8V[}9+W!SF~߰ϻ]Xpa޶Cjʫ3~Q T^ G|C]؞0B/>Jh-:fhy΁%wM>PGJTc ,(52s[& 4yQ(O({ڠCkje2cR\ՁfCz5ԢR6拣: 4^Ikij[lRh9#%#3B,`^yPn}0VZ(!*o.Bi4'lXvSZ6ԦQE]DSмHc}%At,Ĉ20Qz22XZГ}ŷYX^%|y-7ꇓ= \)3yW[c20{,mX- O4nnisF뱋>cCT=CbYx{{sj z]h^|sqҙcq~ʩx7!Һ)sZ-NyWm"e%;3ӵ ԊM WЩl~ fʰ6&[7pGy2L;FÔ9XKղh&N+hmyXDwHR_xʚe_$" /aONiK Ia ݚ(NK% &Q R?Vg" r-^c(˄9pt04ޜ0C7^z!A(L`.ƦV?-7SKul98e9Bt6cplYBEqy+@}->pZ9<c]IJ}.9ȄV>;x`Yf dRF1x.F dTQ^2.(j P.{刭(UJք#pFӫZ(UsjջJ(e "ƻ9=b0lJiߟ=̩{P\Je#'ܻUz%spS YrD?$Q,>ra[Rc5]uM!nܮiK}bB[v. jWH"K(Z&8I+@6m6rDEtJO xUǩ"Y'k? )hd)| {4۷<k]K|+ֲO'Vrt4ѾOZ04bSr0y(K`ˬOWQ"ULP**ELܑ$K.X] 9~Li?=x_ϺB"gϞqԌ6D{iA ;1Dz &, Vx 켃^|?0*(Acr,L=ŀ]&N5\:M-JdMv3V`n^-k/=X28]A+@D!X(/?],y6հF\->˻m7֙3gW׶|vJ1(1E57MdOrPd 5&&6_thpbI!Y"(IIB4]@ݑY{ hwW~2 bmYN[KLIs$eJH v*״G$c֨Ȓ!2Ɍ!' 674mS CAcC5Anume|Qi⓻cQ0i]Q3'!--(*R NUQ"2B\1ɅwXAVN49:Z;g)*vϺb e@Һ^He )^U5x/k%$Vڵ Ɗ0gc 2vqRnl^K_ozaɡ*p AJR=ˀZAY0.79IYYƚnM^ :W;UK}M8sCxh'*ZO~1 󚙝Z}Wwowme]tY#ߊkjVJdklf[TCů۽;ԮZ+Ο|Na놝1 DJ?-~e4 \{y4*MԮ?M;Qd "ۓ3Nh6rVq2[!ă{J$HQ *+g5S5U‘R5UJUӽщgr$$2;t1s^7% 9_jCh:u&DjqjՔ"hw،-{eE2$UJD&˪>v0*LڥV(j3H#25YB7s˖-z{[ _O[kMQ\w\x9}??dTJrcD2/ޛ{܏E!l8{uؼ#JGgEU>^v%/O<_{wE Ƴ}Cޞưq gKF1vL5J(MRMuk>|FXW1g.K!LɾkīxYkC%nJϛmS])k҈Rr6E,=r dXc&֞%ګuښ=j*|')v zõ27tMySldղ6#o|MHI%<Q#36TIΡm0 %H͐ɽqŃ3>"r9$|'`յ<}j\F\sɜ@MYk'斋JC>RߕN:we&=P5)K. ܦM0_$k=: e!^J]i#,@eտ$w3GdhxԽ!6kl]t)%4zǛ~~qkTZX%sB>Yc*{d 8YaQfjUҽ?1\ f\GH4UMt?oտ]{卽ٟ%[@"QB|˫4o&C7Ur+Sn+qy&Psωvѭ߈}844 ޜ)>n/lܶ裿=xp>;(xBcA@ޡe9筇~!t0!z@tLz੫'\/-f_韎Ԯ64PvKp| jEW'zQ5r Eƫί,!WH\/SC .tV'[pa*K<`Ā*7x0oR.1Zw.gdPd?x?w<*HʏT D(.}A{jqM7Pl0V\jvE'Kg(t[X5ֶ%јM\AN5_Zȏ?+;U7Am#{y]G> r\! [ͫY{a^/ (p(ߌ/L D̕OG(nF+Łǝ-f&MBnr%GiCd A9G/뿣fn]Ϡ dPfNs'ĭn ul@ R~;&< +M"rnAGRH4²qx vAHp }5XP+SP I(w?=;miZa-|ũcv{++|'~-uZLb,]Q.֠Hc;jo~djvF1fi}W A@uUnr~mL"/7 fqAx fY/52A|TTB9(XS-^V6kP#5[3@6-nj1Fnb*z9[)4 =_k5w?EݻVf3e!9Ey "2~A#lzuQYM@'㳉 ># }EIB|$.LnCRHA )DhVrvS02 1-Ŏ<6v\(Cr%¢r}U-.Qu+$ruGbG!3:Uհޅ#B `ط %zW!Cx&2k SRwIp}Wci;Ȼ0wB9E >"-Z+#5%7DK3tݺ/OqUS ۶Ž]0TBt$N_g^bHoAc#3bg/ͥWmL󷥪.EB Bٱw2l"B3 1 %wGCzY޵ IUvTFf@{!rz}Owd^X5,R_+w3T/W^3}~{OHo6j,8JN'S=(HRO-pJ32sL8Ҷ_/ed_x&4bM@| /b:אa@5$""(<*wf¼i]&g% E֣ZA M7t ":|i t+^7Q~!6 vFJ'N,ߕ{wȲ5cՍc7'_.!)Ym!1I"T3f:>\W\̴`8L^brou''dÚui|炷CJj0^4 Y%1=EW [No4?59xqm[Ed6Xb9+Fҹ۹^ggC>R*ޓЫkt dEhck[}%Md҇>3{U2SSKl#{g՗ho'>U2?6.=3j ǚSu^S~B'1+{p?(`f&!?uy<w O X8I /W?`EP˟RYv^,*E^NKeHP+W/e31:SΑ#Gdzwr}?}cezza0:xdҳB7Ll;%߃/:`dg p Jx~"IdF3d]^, =pfg.LQV1n;gxؑ#ۏۃpXa^C-x:ulٶ~ڬjztmў24eJu:e4 6T\xJW},eQ6lj8e:i ˾$jO$鶰A3Z@-3vgm8~-Iev~m" Bz[&m=ʐofN2m Ҋ;PA{ (|'Av&N^|˙lRz}'[sukmYR+ɶ%b0hKDՊj:k7ZiO9"P5_wE{ފ/Mʴ2p^X \At=UkkZ3\P eXkTZ}P@06ILMZaj ťmY6]aoix%tԪ0Brm[𞕫SoGs^Hg64WTic!ZA)gv X,ꇵ}U{D?leW:5aDG7V&Uk }\:|N=~]銐g ϊ| }}/݀Z]cR#|,j\ZQvVO m'5VZbWC 4j3.ţG6=?  jj|# Ji3tNI80\}Z'|jŨ}x vVwS;8a3*ڴr3lsh@[o t ow!+L@~ Sz>N",lϐ3|zı4ƻK8~HJ;@[Cj`3A_hjT{I\@J+A"ϼgEѭwj(, Gfqb:5($m @U,A3x3j2e&FCLa-,:IxRXC|rN +6$N < gTˬ6IЬgY-<,,0cn~+҇O AXK-HF,-- lՓӿ_lVۘ{K7iDS DA ʼn(|ȜY ACUSʵkZFŦYoiI'A "Ym wń6,A @ Oo'YԪZ8D @ @]_HA @x>R]BN A @ :>XdePB AvyHIA @ v I!A y]cBRA @ t®:)I A@&o>b$ @x?۷f$HIy # &t?_7_@_P/QI A)FOv>C\ǎ1NU2J?)ʺ:JΈI)_|HurNE2DDE;J)Mu8"m^N'-kZ {<*)6R+#WJ(60JEH!@*(E/# 6 yٿxRiO}!R{AA uۇ2ં3:YpdytZmůN#9UɎ\YQ6hiw*sn颡2+F[pARP}YT>hA7?߿pc%UTݿ59ݘR˻oWPJg)b6ntR7m-y>ye$;x?S 7AIZD}sʲv JʤE5#b9&"z ?fu(X!۠U:nGqy'ЖQm tMGoZ$ ]ǥ2II> qh!'[E]ZQU87oq*~?t7`g0BVF&̍>y[г E" \B!酄/"qM #MuDZ5*qу[~\&7v&}OmEװ!F\ڻV] /YqޞQUg~͍y)YY\Qֱco˩eʊcG yÝeW*Q(*`Q[t^)uq:ݶ۹mXwnsԺ9w~uZ%Q.nuBvgEwyS<0؊b14N |)_†\* A?ck g=/!}WE Mx,V80;*UUrD MfY .~1P+H3LԄez;kA|cL _Cf\lzf ),]f۠{7 \{1uI=oO IN 랎.F> w_w33{c\T*\y^q\S!ch}:3ܕw f'4>g``/]WVVQK$}9H]\JR.d1t11ɕ^mJxdqdLfOS(p G=X@!jdj}#T|Nn{/-rp|U]'P붟YvD']BƇ x_G=@olq}eWUMe }F F(L՘{ k1Ii+gƂJ$i1s֦4p]eعH_xc]t1JWdff8^S6^z.1GQC_~ijT+:z!ya ?i|sjƚ7^xob]qu_snuMŏ?9*1mMI6ҵHU5fvi*7r,1(^=u,~ر{b.b0{5/{md)'Mz vT8oXLDm7i)\C NlZ4rW|oY.pZK|p8t;U7ws 0l.f\m HW^΢ΔN*Kh ^-N<l5㕞8< ^&U=rӗLP\^aIhj{ǎmش;B.ESChFkg lmS(dGK/i{N6be_/T]\3OT[թ{Ţ+1޽:ulN 'l4 E]~}'_~@T.ZP96C&JZ.6sT'pE Qa+S_͍E f{ýY ൺ$pAnCb Q<ᬄ|X~ Twhekh]l[*kʒ]|!P_$M-:kqW٩ؽ<ְM/fŏ8 UX>;eئ{6G~!2txkD?Te*ٙ1DjnHHM4O±8K=T~N&;O~gRV̎KVQMДrlE"9z'♍FhcwܺX! [c-0~y]@&<[=uh h_TRW\9MT 2 *g./ E_^Yc/'tZ|5ie"yVjJtNW z2 (V:[*r gG.qm&۬׾aMC˅lH@Ȥ%0[KL,Y' 0pyBdp4UmmW{\[l?Vf\v߈.݅ pNf ة@d@GD,SO'[dTg>($zv1YjÝ+{Z>"NtRIoe4,Ѭn))7ϊˌ+W |fHzMNZzOUa0yo_ߥ𙖅3@V^R=x̯, ьHmsۄSvv4t-P(?juX(6}KLP.G׫[:W(.U| UF_*xszX;4mY{ؗޙP),WJv"Xr7ZG?'+x|vw*]ǀ^v 掉-NVm#8ޖjITw+;a+ã]+:laϣgΗSA-g<󛪟(`v5 _253t1<8dS[dk*7 s#JEEoK„* nU5ǀE^ _7iQ3ʏ!k L6wǡId+ϟ/hk?i\Zhҭ7& Z7 ='#KO!K VJ@./:++Ezxϧz];Z ՇE w~[ocg6!@z3}VHqC7,wbfKtP+zeNggޣ,RX>-Òj5z^޵ ǰdEͧ  ?~.g'swvp̋Hgu䅜L;vm9*BًFWsZwt]q>ڋ\? b&##hv n >:;:)&eL9B)) 8/%or|,`iRlHdy(pf80m/œG03!@>㚹q4}opw3-FRֈ{,#UzR5,hS{[V #òBr8یz cA;4~z0ȔK=l|iĉJ|@SLR^o|vAT2e'BXAIT^q)N}t*ંbcV˨$YAFv Njv~;qWDnbTOv s} 8dH Æ[ ŇӀK$2e2^,2¤i!mƁ'[C(övk #m#"k^l𣂤Eh͑H5sHƸHT#ӹH)MvUSY e ؛*W_˗CBB3O0W5?X*iRQ}Ӡ)Q$)++ hS`W1 N 4?r3:Rfب)`ĵīڴY42Ҏv}\uP4ҵ˜'2%Nz7'6ky=`!֐N# J#fg.#O jDŽNgCb|B<-{XK7V=4 Zja:cPlgi; 15_oDVF#l4\Fit^WLxϫJl#bX b,mj}Ue_mc%/4Ȩ'{B +z(| zOC)! >>sK)`XdKI̒fW8̫UxF`(-jQN?cNϟA @ Fӥw676٩Վ*52`]y ;[ؙt IA @ k3@A @x @;ϮTU,} ~a!P_ Ӣ^zҬxT`y,>*<A @x6YQdW9VvNݺ//}wTU kW3>ݧx6+uS;;Sk-kxlPt] mT*%ߤN&5¡~a.TߛLb@b1pӨ[?z SioLٶX:H&AA`oQ9*|01Hl>fU ՛'N@)5/ 0r`N&#0&&")9M$K,`yņ/Ah,-*VibAjrtƷ`Q3fMhl˾Goɑ^v+{.-6pt6e̴YȊ5!hwFΒ 㑽m.]'i5uEgC{:2 qgugJAi@]ך0\.,t! uHjǺ[W˜110yJVǤ%dPP]hJEi$Ś՚_yJE爱p<HONBzB:KIJK^AOps6TR2`_*\(a5^v6y--|Er9=m$:7J`F|GsTڿY{NGz 궂\ׇ}fwkG( Ke\mDVrpŵ(m%#&t$4a!N6ۙ+o<٩A{ˏH+k?v^cfG.X7仭o[K"yr3=U>/Vxgјߍ9(??"i%<~f<Sd;zxpVB~lRxGS;N -̪*<(g0-nߝxAf^E֪f;ϢS%:cƺ޲hdԼ {,-+ !Ʀ{8kmMySm+e|DeIIn^蜔yqs}ܧyN AY->f2t jvEIo}w( 8vb pBoN|w$:9M~P O iꈐE / 1hdMkm vŽ>o}ꗜ+41d3Cl|ڴuB*p1}/'>mT?-b+8<7MDǏN9}|"[&'wS50 CI:tӝz/F+6"f[uY \}yjWathcu(pL`?jpPژuЉeL^fzg $`䡸=-KR9'>S|WC~:T^xBNa;~/'+  ߄q_iSoVo-omB@q%VrB{vָ hґ _|bl/X?Ԑ 2hy(\pfl8ьmVحxMĞ"ݗE dzmTzbw54dPG 2ǭ3U^ﵘqH/JE AL$M{*޹dώ_AnECʿ x.\%BK`Eɏl޸fܲ( $ck7#/jY܄tVWuٞ9kgpQ'g|T ZZ^LDrIa֓&V}?%(7==qO6>/ kmc'!C=i^L8%}Ə٦[[XVEEj@ן0Y g_?@ܻô 9\=7Wte-bs'e-D=i4ZPW^yٞtmJ{Q;B Tj#kFU+up6qv:dؑ[Ukْ,A4%K phO_Wqwpo]aE,ydCGZ̞&KFWwxJ"YOwvҔɴ,D[s2~=Gv>nZ7W);_&+ӧŋJsW?7nz)ܕ[ee%U'ט?Z.|pM }iT7 }-{Xz3;"^Κ "&A5~0Z-x] m\bHW* N#@,yY+N NFNk_7֩Z(E 6#p+:[oT!SvhW lH]xa100X#0Ruտli: 0'R< Y$~ [ʷn2k3000000!ڕn`ܠa[/nso);%s#>f,jRh`VjËC[Za@2ܙd6BMAz"?*w<ד/ËAAA!0jCfA+Um#~L,~8>erF#Wׄ LԲ(;';Pl ҳQ(Q[ (Rm%!,ʩP[%vYDPyԋjԴ?/Tq K/hH `Im>GhK M/Sȿ!+Tش2!Ձ#,Sp^ IDATu9°@[.9J^aFP *Y uB8ҒM[]Iq,C{#0:nkpr믿N޳p`d߱ åin,⇼iJo U?6%ʏ-r@sN`"+4LSxW4?5Xݛ*Y T<'BEmi.lQ,әT׋d'/E5Jt"!>+tVtcz;2#ćFL=3$v8 Hבݹ}l9PrҤ +`kAU)FK ȈD"!@=yi36lkҦĈƢ8!eP[sIruK巇r8/d<5se ? sO>@XDn |X~4d;C_p OKװp73B:Mn>u{(kaԡn~fe BĎWvH(tڨ4rfN@"tٌ2[ZӖC7 G@$ 00ٹI@ `.ZpoN>!oUg?3 nB1H5wwD4}C2JZD SNDIY0 rqMB*~B/ lpL >dSS64e}/(TkFL]--hWc̙3ϟoMk)n@00xrBX{vo]t^q rP*dy!R sE(ϕػ i ?:[ZXXj_U%6wFhÑ38K&YYG(>_SxlAa&tiGٹ%6N((CKJr*»?;qМ$5I$-8^S(li'CҺ:X4P)fH#/r}KF{4فYҖ/ O @uum gh^e F'h3rvV(S)$X̾O9JsPLGhbS>">^ fgWpSퟚy}c2 ÚW3BkUՙhG(B@I~^Oeɜ{!)1 ;UQkSkk֓*$xH }EӒe5-H:Tž~vMxTj!RJ T:3?tG\xQ(2)m@G_fX#7MǨ] ê+&k@ry~^uedv[aqOkqnqp\JP,m\6mL{"bzwu~BIQb.swK[q \#iVfKLH߃I)p NfyR\F`/|i(%d~ɞh:e3}("Δ_'krP#LZiИ Bwd&S̕Az"2E8Ϝ(D(.nÕ@D}nHDMx嵥0>$˂3Qp8&#T+~00 ihkZ5vKRmZS+M=U! ,C5G \MD/ʔ@_l̝!;{P0;A E"cJWJ96.93A6GY=pDvZ >xm9/bէ]պy\!]We>Ů>5ɁӨ¿VCԨ4`d1u4O*JNHNk.4**HaB.FbVHU v$4ScWgKi4W3HPk(i!W-y2 #C||ӱM5+T o1gt=u%'s Y_֣硭:=78p @-5 ULH~.j9-5=.jD4-vcƇw"pEgH]KVSey`}tDl5D<h$v<%,Ȩ.R,tb"bh#!s'@JAcgD%eّ Q q(95buJ5 Ym7[uΠוC+WN>-%[H?[XB?VYY ,)G{vssgdflUzف^oc ,׎ ykcbϋ]7,D/S p \2|`a _t.6|j!z96W5$q$T+] u~rڑ> R݆% 0`>-.&gvVbR6s MlKi͔1ԥ*XcwccJ$b``}c upM9*e!o >NnZ|C-7Tbu[ p3 .Uxw[XдV, Ѯ,`n?kv8pl3 ss\ Λa p; @VXrZ]44  `\42uL蹽+ F=S#w+b&Wlu  pD a+QWH3=6ӮaD?lec툫KhM~;?ݶNh[Z "7<G!"Ǽ R&#[Mk 66/W+w"{Xѕ{خ}ؔ DAkWE:k,-1K70آj3 p}*mwv oP,8]^9:*&8< M]Utu1.v&Q;8b0ű˩T# + Iñ#ww K/32'%܈t!ՁUaFȊ"EZE@R W3׺KTc)s 0 o2In8Zu{{Lyuc9!pNwr9UyUt)/s800mvz-§l5.sɖDIFuA{>z2>PU{Ӿ<'R*7zٵ*_8ǥip;<9=ILTj8ȬH|e|6yiqwd:b:sZS4U:;cjp-/p/[y*SHy&t;^>k rMGp?.򘽢@Uo,0#qn  )iEf-U]-0DC8<١I_1ASXOvem/;4;9q[W>̎oYoSGby᣾ =F0FBfMc !pH$ ):{7{4%K5Cwz:ʠ !WB>`XrB+⯨Ì&L+S)5jm(b 4jYI + gxeY24Cmm;O# mMVj M֑SRòI"8t޲huHSYiʌ2i@l`ZsR '?$/D?RQBO1Zˁ=VE(a7ie(;)Ȃ:_ }O"#9|&Vv4 bCh`d%15yS}8\<3YAKX`F Q: `@<|]@z2޲;4)Aǡ΂9 u0R3q'&0gG4] =8-~Stmg \N\obFZ Uq>gsIrB7T͍ծ >k!PPP7~SNΡ~3ep{0d* R1q΍:8jS20j)ZQ.-DPdN-)OW<*o2HXlC禋/8) KἿΏEX-i M*,m j:{B^51q~tu\NE{ŗ@:ټxdƶ6i$贩2o Iٚb~#C6UqɤdH#7ܑDpe9[ckshSbړpBq ]tu謊߃((OzfYSY.5.Y ?aC0VCXq `f?*Xq8e? ̷ ]V-YI~%7N ?ڱ娢L[B@]. GI(c8V GkeJ e%7,X- E(aRayY=)S.˟]  yNS8RK5rfP0+#!{/! 6?[4uqlXVq1 iLqEq:a< \MB.\ {N;Ί Z}a00ORdj-BiƑpgVBQfhtBqU `8?Iq|+V.79;:9c{vVb$- cEUߴʂq\^xNqቋm۶ a3[_MÞ +!/(2-_FeiR)u1>Y:ȑ` A8(XYBXCK;,a>y*:C'ŒmR>U/"9 `!l$ȧ"TR-tVT8I6kTp3j0 cdAݣ~ϼz7I fhո5i'5uK!4v\4t<Й/B} THw)ܜސp0OJM&$ ~~iar(@}o^d@F} (/O[Ц 9~n̫UEV&_m# u-*ilkoMьAu'w,Fo~ v?u(8"Zay@2]g#>Y];JhJa$gV I>P IDAT(Ajh||p87VÓO.mSt63o'pq|;5nU3 GqHNq6N#sgjFZ tӦM G 5f|vz%]K \;">] &p5Y#.k^za~hulr&ZB{fRO0}!=)XLEZqӻnX结BɥBp0å~v"Xw,ɀ!.:- xl8l_Ds)ɐLNniA?/\*%S}XÑJQ$iMwF@^n3r/Ż#_8HA@V('ȱj6(&a5#p vW\sj_,?\\g! ^nhFL(~έv%HԍעRlFH!$x{U0J Ą^@SX~B{/U)ނ{5_m8^BpziJ ۻQCڇukBMߐҧn`L2sڷoVveD$M]1\d  (owpwDV: a ν, /Ϧ^Ơhĸ,ҷk1l;3Fwv@ ӾV AA;$EӼ4')Z_+:pJZ!-v@*v'|*(+Vz?cӋ& jj9#mc{̄7tƜl:FN/ gu(Sq{K;vMrnN>]y͜9s֙v Z{p?U hz5yh:5w HRz'00 σ%? eaɕ`2w p{Wdv!)R/kUJl:.5b'v(FOb" ASFp J̪LDS_J|0׮4jS^ zBZ&TS%=W-;]I*X8!xTt},U=)dvJPS1ɃR4s ͶƈFW@`.q >27^lN ZkSkkCRnX#-% xht/x N7(a>`>SRdz1is{d$$撔ӏlG d0=ZiC~eF(! PsD%-o4YM^(qkbkkB-KU"Stίv%P iN5oL7BP iqE+ zͶÚ묫]H*^zDT hL!̐6o+$\ lqT)=ɥ ~VdȈ 0Z5jC,`M <ϔcݖ)>u_6ZR&Yqa.̒XF;f׵@ZDC2%.cv9$(!n}Åe@A^[ s!Ãu!_!d*{6ZV(aڪ,D[]nVni:MBly "Tk39."ŖegOG grlVzd4)1a<)M.*NK@.552g0gO#QRtFE}]qz) 'QѾg,GVqTqm/F6Ow?BYzl:쾂Img~gPI -M*D{ >[ed'S`b7f2q5]V9++0 ~iЦ_.X;l4p:6O2'$1-ތYo(&0SU󑠖./,v:Èg6ϖNh ),SVl0/0vAInwc'pȄHHa&]s9i_bfx&,=F^-,Imh4HmdqAkj!ZE!?4sԔQ0 NleI0Ŷ|@Seݴ `(eYҏ j ̷Cu//&!ƺ`MU/ؽKiz-JV -`ZMl L<7]@J4:AJ?z`welsp}`DfaʃEj(",H*f#l`/eG3F UMvW`B85T@-6bjmdTV@y,BQQ|RߍAܴ+|0j9^Wcu ⋃])-Ml!ƛ-˙5H}ŵRhs낯XµsOe 3ޒpU7;{SS@/x"Ek1l<\DZ!;CA ǵ|JZ-b= ǎv0Ӫ:-c"7eTjxC -"Vv`oH.&5BXK cj׉輇4:i?πxti`WrXJg2T"^IA@<x]9rJO=cA)EOCԁS F<wm $   Uԛw69r2/.wt 'ཀྵ8vãZPFg6&AAAAAAA`hd kpm)~>D? R192000007#pg]~<g[rG[&PR]Oe    wv#u_٢j3b66%4{ƿx- [bgNuyPG r,4žre/noy_y |\N$G;TfuˏX[qO{|?Y+r_CKҩ~ݍXPHi"|hݡhU_suSh%V>ٷ+>pI3Zn:=Y?-n0uKGu:|ѝᮥ9uvΞڙvamgן+s[U}!0QW݀f]i ׶?X?l8қd]sesvgfs]ɮ7#PYk9s礦c5kdkfpYU!5<ƓZ7󳏾JjCLͣӁz Ŀ,\mӟ?۲\KZ~;u#~Kf-z

5>'9ObRRHx.=|7Gۻo#bj?<폓z{gkro\9u]|1B;sjCS\0~*cmcm}ܞ7 ߥs^?[6`~#ښ{{uiYphh>3Nʵt[{~$sl7+e! TvFC~[p}JmmI[k½ZB jbl)A?h=$7 N 9ۢ YTscQϏ*@m$O#x[T =dA ${6]ظ¾&lA-xV+ iLt!i# _Ю0QaPJvPR^DJXE%͉quc& #箲?YFVg=w*0k~N}3Re FUw)+Tw/&:dEL=\KJlu^ם82i~o9/}KPe;=il?=y禊 %mvfxٗ]c'Neg޿`粺PVKO$81Փ~]C)ï.[s>fhj큕Q ϛ X/UxU>3}[ - ̄%fpj[7x ֙7֟lt~,}M~yn'q |Ѹs2dڂѥ/$ShΏxg,g/J7#Y[6{?1r-lEξ3̝1Qj:5R9Oq),<N+S[a-Avz@)&õaTE!+"O[SR9e 3b1nQ#mKU,LXxE["?vh) XOemt\Xx,rLvRS\V.'HȊ"3*(t~8͚oNUq^[P׉0R%RM`u *ŻV‚ (iehPvXÌo'be4i5[$,LJdT95_ddAa!˖=CÌV%JxQjYpMUd]C_I@/$e5d0h Hö CmkItsrOՉu6%$H]A,+j5MEX7 L#2 Hid#!ʨ0kD,} 'ǼrǶD >U{%8dKi&.ޫsǷl?aRGNKC[hd =='Ou~4?*tl[?k~+Rm7=Hߕ0jOso#]/|u=<>}|+1U]=(psWmړ `^9^݁Nuci[/Q+ʂng/O EDG<+/hZa5Z l`KF@Am*5|i>sQӛBPpZTjiDThNLO)m+WtTԀ['m8r)w%0 tYD N*TGfA<ǧ|yHE۩^3VOM: 0{]=~L=v}3?3Be+pyg5ʋ+nPs(j?824Y7\et=B0GuFڍty"ɔmmIRikԒtţ/xd鍐/!㬽y:<GgGJ7xG%ϏHͯk4 "KT _U(\ M/`&gAL!YT}rk)9ػyh./l>$gpZsBǖqr =|Pھ\~e|9(8ڔYmQ\ܨ7E,C[4jICۻU\RMZ$koPrJ/"+zFT U[3u@n՝M[s%Vv vD p"e]CxDT/lTTыKT]T#Eu5.ϒ"݄ M:gG>;}?]˘UpYc=R?Mac7/vs7~{m). ~șT0E;>5˗KN^$4v3\?ZfI_0h2`I Md vWp"ƱH*`Rpo e(7=*LÕ s7R -I]*Ixkk3nk|wuFel4cfC]JSiO?^zGezϛϩ-zAiƀ>ҿ\Id(lO6"B P\Wk! |X~&Csq:͉A(44:?3qu\L/rH(ݻQ~_>ZكJM-G(wGvn;-An`P*k}@(!RVk0B ((rT9"VtF&b5sf % f\H/WuXv@AtWG|ΰqÓQ)B?T菈ӪQG!BsU@!I"A=҄gJJʉS#p6^f+LrhQ3Ld5#m\3ؾ/j8 )QpZcU r,BrGI;K7[dn AVcYzq|8 IDAT0EF;'ƭUkQDȬ~LylAО<ur[0X!4Z~yv@4Ac!CpU BЦ.AZ$cu~eun!S7IKk;6jiojݳ ^AemOMb9nC*њ-kNPgTyDwo^זSbPKZJϗY<(7}ge\vWaچ ]޾ ^|w+PbK8SZ5qyT8ϕ˷Ѵ)zkΣ =3N%)?3-b(%S;T)W;ַSM.ǝ7YL~DW(<( MlM*mFP9EA .P 枨? ptت(T {5*pс. {Yk.Û|.abrUbu$Q/V+|q+ʹ?/9 H@ȧ׬qՁȯLYX=19bI2$mErV?yt@ I37eȁ¢3augW(ZW ]1qR>8Ty, "2#&kOJFKeuE ǛTsDr7(2C_-y[SBP_K3b$rGDBıx8O"[Y ꆱ:46gPV4i~) œQW?E*VKՆ \oIsywfXssn o%oߑY_88+ W`w-(qvIs߮d9{2Á7{~=%OJ]oUμ7#VQ18.n@.{Ļt(_/ztG]!'zƺ]p`6baC5xz[wOg@:w^2kÛ|IF08* ]~cgl&Q3LxE&-ģnyZv}O>j傴T+f`I Zr2pgǚt0s8`?{7 co#!Qг*cփj{&NR@L8ϑ#L1ȿ1]Ϝ({WNзwy  YR+BX*3JBQ$e|Z" Ƌup}4APt*u/ߍgT)ӳg?$  sBP^Jq=-`q5+Tʶ9޺jQeDl䵥 >kLAޝvSGrf+7a4LA|+ #"I/\%BKqޮ4ɒZH'PVY"T*22SxG(_u(4r HnAg8/g{- EFMLS؁o/85ȃ,y<;~ժz?-XJ=`$oKW $K ByH) _TM8Ɉ۴a;p ?UYaeO%vADļvID|'V\u PօXCct{X"D]6~VwF>F$16PҩWחȦj`ݣq NzzVZ=Q2ol Ry6|6F,fi"mܕ[+O\(4c'$DJCa1UnB;sQV0-iNoK;N!IXX"0=) XS(_Oiinjg Yo[\seg&L;ӷ?SZr)TJ{T&Λax;#8ׅۮ9,{oun'5p|SHː@seXcDIn@q &9oAN8 >\>4u =9<jqbQ 1RlѼFd%h{k?_swWJ_H0@a_}[gW_}\k=G^Gއ~?؞~GdjRZ0rgWӿׂG'.fHW )۰6H A  ^xK_{WٳRd+3fW;fQL R W^b@ہA A`6Hv5Byh?J?ڃ|6I<|$Rw/ IEެeeu4pe4gLU;:e!ܼxsCؚ$ٟ&cXOU%O:=p22PIXhc+Is~#\jue\_X%~M8\jŎ_(Uљϋqv id=6n;D; ?QN ̀<} "6ZeEV}ْ^ MlgQALTl0659{s=ߛ3NrYy3c#)<~֊,F Ɇ;nC<_T$%7n7"kTІ>=јQފ`c ݈އ44kX23ؚJj[[*!W,ڿg%֤ίm1^t0.2OKT1Bc@Pjfӕ–͸xz*1'|K16Y E|'%w{-Sgnq 쳧Ҋ՝=jjLSa|bq@nMiv"%BI3=xF3&)&,Iu+yzMx0JVi HU`awqfL i:eذOH//7 "Px5bFpfJJMݜQl_VZౕf൭R)eAThgۯ/Cos;QUlVQ 8`sdPYb6^jTUA2^͇KZQ7\$=zU(DtƌZp "#NoUpq1#X!^L| QWu!W&[ʪT*xx Y5&Vyw+}'a>aAxgI!7Ш@Cy}Pߡq&z=3휚rwT}؄룂OrO9 g8JAIB׫LcK@J{sk5AJ̃AT'ަU(^4K:pj豻N}뵃ɔmZWS"M@ ,:==嶷Ϻ 'wդ"}렊) Ms np^ 9' Uf;PHe0 #کN9@e;ecN׍@{\bYvm7݅fpPQn؀wS*2 L9@† {8X!&&p %P^: }kp/ eÜ}8PIc-;=)k Us}l Nk!x+XO\8XA(A!eH'pD-t(dp\ g>0U=]w>8.9B@\KCr*AG GO) m Hク|qqh;S^{32۽ScmPwٽ13tl|B%W!gQI}s! N_\+hi+5E A @[uW 5EZAAH Q1A2?;AזTnz~*zӉJڎ˂1d ] a- ә7r`X7%z.9j~~+?tՠfRK9׃Q(h8d%-p$BҸ?pg2.LgcgtL<0GC>|?癩ԡc@Xу6"n$yŤn)S%2." 1N) byАv RI~j' PFQ.܃dz n۷vcPT_!c Ɗn ]X!.lد݅VOYWd>2lM@׺7rbc,`Rx ,p=!?.A}<'LY *XL ҟۏNY6e5 ' G6G_f4H˂ҵJ3tc/%.u=cM/ȅVʺc (/E)Ǭo~2zXI<3|.kAM*D #EfA=U#߇L|u<C(##x< wvU\q 4  oa L% @ ug*NT~rwfh'ݎm-˦ tm7`tzrp硾 /ΝS+B7'ز IPo{^sۛ7[0Q֊MLuU\Ni+r( gDJ=ߠJ}WՆ +Gah=\L~5` ^1|ا۬يS`9o@7r{eEb8Z ~t cq ݮ2nܶ"]bmuZg;0(T(ɻmG˨ؚQq_+osӉt0+W Ŏ(! 1m " Lh! _מA^,p+n}1;4# PEכγydH?V SPAƳfjhQ bXIE`gm-spQs5S`XE# sƓN' IJYF Og{FS $°bVQD<{ueh(V'/"uOAx\>iF%3vԏ[jpB\G;DY!MYbಝZЎ5O T8{_w5tl .mm:WAc1qg'b\.f5~T!2KBwGS= v?t+SP*eH$OY6Tx{sŒ )Б QG%[fa \V[w@~ Pn-(˟e6вE^Ƴt6-Uz*e1ߺ6VGuWx壣*NL:VV'4e&hF| /„t2Nmw pĺE7:8.`; X &m2125'nŲ$i]0utmШ #y12 (47"d?Qh)>>-ʥ𘽠1PݖR"AaevfDtk]4y]sn<pÎ:g}D]ԙ+`Ӏ_^zFJ*N-~pGdUg'{C{ElhX*~c)zI8kll* ]~T%* 0od%0-B&b ܇gҡfGCkw';u<*F\,/k,inH IDAT×-W6=_T VUQaϚ_]dmhrcdxq.ϧqqVCPˣH%B\5%S̳VKPaxA˃rx) ,Xe`<.|ar{Z<7bfay*Sl(L1+ D1[0IW1GY@!@!vM G})h-cW3w9Z:#:,<%:c d6\C0k?r ⏰kf`Κd/= Ǹ 2'^?ȸT9YTʈA 0GfΜ"@ʦV@ ϲ)RT ).FX$RA\ Z13'e *8J. nP7@za=?<@'[t4vA҈9Z(tVK?})tڏ:lq1P謹KhϊX3⾴j4A @ |Pu;tr(KOKLFAod A`r+]",>bȪO_OA @ A @ >ӗA @ d A@XLne?{}IZ"S^I [i}-3}33ܳ~[h~|aRJT ~~a]G5܎ܟ)`zZ +~/gӌqxL8q+!ƙ.a6?*]/BM inͤd̝}1{/l-9{JaIn!؃Mfm휰lqo^Dg~{R<`;[+=|o,% tW.3oU]hnJ%u^z`/==y^1t}uϦTa/ޛbqOQϾ p.?'덨6sllnj V?Q-H~-:!Ngj.{ݾBۇ5D  ltV;YEFH< Wk+*Z ,|vnjVymb5tUs,,F+hTZ% ¤"umkևҦVvC6ZL:u NIccuep&RoZ]jLS'!L|'p UwL)Ga5Gv򸨘Ettڭ fDXqp$C.8#' v(8x5uٸc,ƣHIw\$Z.d\A`1,xgP{jjѶ I;`ZT10vvWNt#6w==xo8-/΋5x]+% 76`27W}7ia]JKM6$O}MPV\&jWTzK^zw#uy =v0<}0ҵ93&NoVSξLCPuL.Q{1!odΩ1Cԑ>5 dܸrp\hV5f_AGu C*kUDÍ! F@tmIBlA}\^vRu[:S.::YQ{t5l_l[u:\_XʋepidE}8 \#S7JC@^ᚦ f NTq<U|Q14mȪH%Zyzkj_8oPDǬBTL|t>e"]Р߿kK*VV WuI}Y=Lk4]q捜h#._\ 8`g 9Mc.of+M™/4Μ74 .'D6A PuFXݝ~hg$+ +frvEezbËpgmFJdJ97[8,\yc::r=% xCz,gc!o#[a3>+ndQr:7Էra@'39ɋBCS6iF%3v'[>r<^ V4nOFpVBsz`/SXK*X"~o ͺ} X5[0Z3uo+AUէl<|e\.j\#./=ӶQLl[ ObV/*8.'>z6 L=QJƒjŒY"`B ȓާ4kURW23kF皡'N鯖Ψi"=/9r梿Gb<[{QN{wu;'a-+`iF*>y& 4WQbJf6YRw*5TdXܺsHsn*:-QU12@(Wݜ UCx Pe˿1hҤ!`(p8C!nUpT8šÐog$GW Tm&?+|n6rް漕!2PBΛfE GzxE]GϰV7Xs=w77QPzs|,,,>%{E}"vFz9ĉ~Q&"cS/A6N..CxnYdttSl XVD8A @#poʟ/g˭+(3e.Rȹ:ۀ0,L0ĸ&a6gDBEey\0G#I hx&Dg5{A p ǜh$fG&$x)j8}?q*3_ڽn.X#ፇd%Jx [o Əv$C=\j)@b2 /gQ~3yga$OαUى[ALJFBvLp;:E\MyV6gcyJZu/16랡xd pm_=Ü[#@[Cwx謯[f3%Y&߆~t/s n^'~ZaQlzP0,q+ŌISw:8f\q; ")R6&eb!`n<)+;ii mۓ ʰǺ\}U cS㝔x0TV1oN~`|ztӁ cRHaiv TU45ѧ1ώP/snHvw  vscPg),a4S>aE2[qYxF*f:?p)2m4 P[ m,iYꬴ"S4RR魓62J{a b24"T#)27{yGzyxHfȢ0` Ȫ;͎1Qm2"Bл^tAiKH|^e*[\ZGVc~ t"*|'4cl<L~]CO"tX3[r#q#F#L0iqvҊ ll+۹lהs{sg@Z^~iPs|t2T۫I+ꆨUKqI:h zU|Іףzȟѩ$`O(a<'Ma.4WOE"@EH eA`85_qy:mpɓwNŨb`쮔'DOMs[kBܖ/ltb#ڟp޸dQmn78FÞs]Q{ۀ5r$rxaEO+*SStu/ %>z(ء]^MVfԠwI'vƯˋmp5p 6cJ7D=e)DU柽bBH($YrC[WЃs [Dnp #,7>9^:Ȋ*֝ c{KĆ5`U 8r̀y_fEK3u a7e>vZUo+pCvFm=Q41t*Tʖt'e RFl=Х1^BG:+6jt8-n~g ,~}guO Ɵm顶 GNco;Ne@~e{ wn%0y# F:UkAh+>, sN^]DA @+jB:yzkj_S8yRDǬBTL|4^H!,s{J=X?4"r` nKX9dvmvϊC߇F)||d%m:yN g,KǙ7aԁz!= fdCm1Q(*">a0i>P)ܿg-%p,:21c`yŤn)S%2."+B;gnD԰á*Bzai{)]c&`'b|,s'ZI=W,o,C: }lƊt -OBG`7/6>ܩה( ;/e%m5\YPe* EttHGA\zw{;Щua;*RaIa`#)t[/%L\ڸ[w'EPN9Co*B[ˁܪĖ8_q-hӑBP~G  y-F [1 E (GUj1P~c8hʥ(tG|2 H8/VBj#R/Ro{^sۛX45O_BjgЍ^Y0Պoy/b8FV&ݱOY@N ",sh./mA5VahqS տi[UTbV#sl 5y=7e;(/lSx}j=\כ0t Z8~'f+@gS _z/>GQVzsCQ<qS!W:پ~JRi\VAIgv')I;aуɶ<71n_rHjCcџdfp2 uW606YFsPcEYOFUv_IDAT -hlT!{_LJhbK< LJZOc뭰&HWo+At(AwBLv=| $Bvij- 5>bP H݃Uy(bc 4=,exE N.6+\?EMʽ땨qхʳVB1Q!O^v{Sݞ-,t= N%*Ͱkv tA=8 Ꞔ-Hn}{Bi)>?q u[w%@+\>iF%3v O}BY2kN< @HFm<~1#mG-h#l0.JHNMb\9< `2í)yGt5I6KՃl bHY,$Z, @XJAJ#W֝Ï/B)JU'4e\vug1??<_.{{#X[ m  Vfܖ.C0 \CU.1{Eɠ7u,^$M.{02f(LYr4.R܋:6G*CH^LsHWx壬rB[3WRف'1qsEdgo*1`Yc dBEA? sl,t'1 ^U-jܧDiB@sE )d)JmPPa_WDAF[uٶUyun<1QtgI a(V. i B>a GFD!ET 8.;=~!BN$e~a%AD&{*?10Hӣ`@"Z.dsBe‘7}O7( A`fH$;@T7"fJDEr;'&0,>heUK4{Մ,yoĊtaZvG8@ |*\+""Cw"" U~ӴUߴ'A jy% A @!@oZ A @X^ȺŗH' %Fu.\f],@e'sir@s_{r`>jƭ\OL;#qۀ71o`6b]9] oA\dfpA&A`]˶= ׶/hGلNjr3\H65AD&vLA ygQx) x]4Io1;\pܼ87-i?-F+vX3裳bgfl VDFܱ~Hбs0aN> [sB \qJj'CIs9+i.d!b#r!O5w6Ze}ϝo/@ihzLϑ`lpV/lJK`;]zXVv{h%Y%1yX(-ZV( htsz̾Nr sGp*{c.~guTu GO4Jj |3lJvii mۓ ];X7o :V<ρ8]2l߱P$Vڄ6wCf1oQ31j&dH;A p'X.YC*2/]PSJY $i}Gza@#-֤ίm1w y;<ii!b=ݘ JegR96.6ҲYFYM,u VhVUR `GL[w%:^lV;C_V;΄XzζTb%!gf燤%n4"'qj*46Y#C: e˭UKI:ibp&c5 1}X"3ܡ"ppH 6usaJZ^-RM~]COB14ly\3Bt6 \,WszqMeZ^ߞ֬,lt cxJWKR5(#!5,ӪV/xlZ2`Axg" @ .|@;a߇׎CkC X|nរA휚rwTb`lQ W)gAP}jIC#k9~Ya6]:ڀVe i ؽS1'DO׃F1t@W315JlAtq  >̌4cts!8t 0<0t{CY(]tOimfSoA e#^Ea23J7 @8l08VW]tzp  .=`8؝ 6.ѕzQy964*+6zE iwo D=@`u`/B݌k 3.4=ł8B!)]ۘ] $;Pڻ p Q8F{3W`=IJuAśЌ8o3k8fV@Yàu 2t :h—T4ҀC_UuPCqİƮ>a/Q5i 5rɒQ''  D@ Z Y1C A p!jzOqUy#'~h,تDd$jvz6'&>Pւ0~T` NTv|_I5`AIڴl 98zn|Hz=cX:μA ՎBqc)C@Te4XYyS1c Nq_0#Xm`L2:}ݍ+) X80YeƱ~{L!™&#MvգH&Qsyy@O֙! 4s`:5`?*%b49];bua;*RÇ Ű{Я[|nseFK3+Q>_RY;eQFco: BBgS 0}xrwr@!w`=Pcy5lZK*f1#0ӅB6=BԯuVzC} _p%hfl3:T5ZqUA>`XBaB/׃(_L:7e;(/lSx} xs1^@mwbq]\U+k*SY!z!yиr߱q#oAuWg @ ^wa#BZ@'{[ ~;Sbт4V1=͓Hc Kdo4n4X Va[ 2]_ _ö+=mĦkPYAUgRULxLjZ?%x;? ¯v'"q`o]#^DӨDO1)Azb,X%KWjP[p[4;2SUbm?Lv \wW٧<1Bbg=lX|=`>wa eqʬ9 ܼ&٫+ۇ,%ZH➃, ԗs9(Gk}> ?Ik ւvdO}k5~ݕb}xQ&WXdlI4B= +bjlJKIkuWh}0"x,A1#9kxØ1k}u>SdW,K , xՏ}^O=¿~ȃ ڡ胢  tdH$OY6Tx{:qiB@sE }Sr/6ӵɐVpE\7ؑu WmP"'>W֝i@q[ @,]Kb8k-4i 2^_*ϩϺ(kxiZ rIOa &m212xlA1@]7?ٕ?-y(?$y.>" HTxx-  *[_$ZGW8pSu͵@tesőQPD/݆ e uq Yb8];ƅEbK1/+|n6}O.}E˸8o~C$1\5%߿Og˭R(y\si)`H\rvuˤ62v/HIJд4Ar*NfEI;R !1*`.BcDq &E2!*Q,4lϤW(S`#|I{狼.P#-.⋘yAR9b px\*L@{갌ޭxE- OAgA$""Є[h!]iѹ/M;6` H L$Ks4KH!C`i.rljPqiKҧb~7<-]@HjtAb„Bz5C#>Jg=J ]D@P7!Ѭǡa$A+oy@Ta]큑a*1uGsh.j\H18F7@gcN7NPܦj6-o s CǠ>>4S BDawzv8 ̀)3ٺ;aW>1 W>aQX^` =RU T'@(B*OEs^\+4C9t.=`c qG_mgEz| ௢|p(dp8p GpHwax8 RLtBՅ|6 V pB* IqjvbJI ww.o ͪIENDB`testng-testng-6.9.5/pictures/convert2.png0000644000175000017500000016066512551235562017775 0ustar eugeneeugenePNG  IHDR6`NiCCPICC ProfilexYgXͲM%Er$HHZҒsJR ""`D `}>ϝ癞wkzm-8 0fFa9f3Dae`AwEZ#QЛX?6_=E>08gd s0Dxp,p%TZA w=08xd YA+ BP<eAP tBm!4=fE3F0# R2 6acT8.+M< Px3%RFQ(/T(**DUQQci2jEѼhIdGۢIt":]ED36H`T1FoL&SŌc1߱X,3VݏubسFl7v;p8u9 Kǝ]ƍqx  Y  G@dBK](6)((U))=(c(s)))SSnRSPSPR*Bu%<ϏW[#b|~A@-NKDAC} L"8 9:B/aNCKcDADSJsf#-%63m,m!5Ǵttttntttmtt2/0<Rz(QH"wXFF#F_,!&&y&;hRNif0?s.s3.mO +,,kZ?xZ^-٣/s0rq8299sœVqU߸ pr-s3skqrpwq/y4x<%` E Y==*{TԖ˼toޖKmK+HKWKa1Ii,+.K-}"G3Kk[/@T8pLG᧢bE%A%W2IeFe l*$ UEpfOjj~jWoN_M9iM>M7JY--wbھڗ?HYUMCe 3Ox*v7ٟ҈ˈdTgbd`gBmbmRb2k*nj~>`|ԁfBff-+ [XK R˷V2VV.֗ڼs[׳Ϸ>(u0١hXӇҝ&>Й߹Ӆ+떛[7w#2.QK+k[O2Y\B^[gwo޿1"5-!//;(:h$X"8=x:D5tJIhMv85y9HԈ,\M=#. B:4~&A;|"ؓ$4HQ~G%K''MOiOJ=:fVN>yLXqq 3ۙYYY[٤2'Ox *斟Ğ <9WO?w_O~X(_XQDUQ4]lZzF3[%>%:eeekg=Ύk_Ȫq|y7++ UUo_PPW^UbZھ:KrNZH^9ܘ"_u:lsMڕBnodބn\iinuhi3niWkqkוֹ|L]T]];co^}gǥE'}}CwM>gptVz:2>okTsΘؽ'FOG&l'N:MN?x/ļ|EpsiYs7aoSyW бh8>~I՝_ؾ\*ŷ72k77n3j USg˝`P_(|yOp@ja,rBll텖(g=[ ԧRKQ%H(ӚйG0&10Sh5/qqr7>&JLAIJ*m'vyvhqe9}4~hYi_3/1X/oge 25oVM;gm^CmNk\N&;L=<^k3>fdrEBKZXH}hRy8OȜ(h1%qxlXbEɌ)tit)3;YN<=9דvJA39E)qgbJKn.X>r~rS j..Ծ4W@E1ě<- mF;;o^A@NhA4-5<VF<g8;Yⳝ/b_ʽ\~0z4vztlkNfnͽT/v^_[^pc'j/׿}Z{`svί @M12a_QdSSb4BtR D;@T*>%vz N2W 2">bK{B%oݐ֔9*{_`4BTPׯԊԮyW5p7_o4`h `11PTfܮ۾`C!%'ó}.5nZ$NҚLjgW{ۯ?0@?=CPŰՈ]QIZ1', EuHъ䔔T4tc|ǩeff>wxNhᓦy /,b)?CU.*Ztv|bUK54lu]6h0y5Z-P+]_-C]K4T ksO>Ob mca裱'E Iϸc/x֫㧃gf$̧{Wpa}R/>Vu}VßsB'`Qx@`u\'1J*9< ~!M9 XHb c Ss:K.YF> <:|)UwEhDel$*I.JK+8ɕVRVPQQR#KTӨҼա}W_wPo@mk+2MLLyMgVdNPYNX]Ѳ>uv,9.t3W[ N=yzx>J!Os'dAACDBS {^9\Yft]],w(ߔp(ؔ|dTc~ǵ3X2>d*:C3z2?/4B[7EŧD8#xs'ΧWVUp&bBm@KjL57_͛-­,۽o%vq~w=w{umw~Ã+ f?JJy67R;plukh2i峡/_YO從!ϱܻzj]p7=@ {Z TPmXQ_T&4D86ޔqA>XDEvH2caXG*,~@T  tz #Y fª`Y' 7JAOaIqb҅#2U 0fC Diizӎi]aah$]2`g` feae ag8 u;ǒ_@`PDɌRғ2e?ʽЫxS%:KjMZ446thu a35?jbkQnb†V. >;vLpqrs[&qyhz{xi&Sx|2#5G2EGDz9&$IvKy>~!c+k!''l{qqpIqYkйh.ՙG77q7Wސh)opu7GFzbchFyԅ%+_ؾV~X{Q5k %dUA *#Ё\Dꂦ p0\woQt(U'*u͉>TWo0l3LHp^ZEE'%҂,{*U,xy| &YW]I"Z m$nޝ=C xѐq)Y9K:<[Rv:Qb.wn)3-`,(#!L!)Uؖa^W 6r Y*g! aM-/: F&̦v ,h, mv:bY8UbZdS|~\!#CË"\bY% $eYOMyf{\)!?$%"O5CAkaQqrIHK9Jj ;?׽j۵;7j[Eۣw^̃OGtL\~zycSI1Qo-D? yo,,6xi]'X{gA~K>  }0 v .hty$ ϣ(mBM)v1}=c&[ |qp crry DM%:ii.ЖqU#E Fmτc"Ͳz-݈cwהO_\OGOXLDQHE2Z^m׍os[#[[䭮??)-_?KNvwB?N|ϼʝUH|bpev:>IA pHYs   IDATx @Tȣb(CQ1ic l̲iM5(6 y*QTR~>;~}1{|w~8}wёH[(--֖^Z2KS b-/ο0lPT 60T ׮]{ ӧǍsH_`i ̪X@:-NJ 8TDW5,nD@p+k-f E9lkZ"(Z[擵v# ; @& [mgH (4"9ՅrɪX%@L9esZOQM iw~ Dܝ__ %|\3c@K^XSE;7%yc EvD.kkMD{CGCpbP.ox/%tͯR,u7=* Yⱽrq GTQjӬWO˛x(B+T[7fF*_e#;?~-32t, )(+np 0yh37Id-嬕0Dalm+FZTòcVY6]$5n@,khţrXtq6۔!buڐjzQZF<. ̶`tpG?S$t}giiھH$n jky?/ grO_F;ȳBc;8(T`uGsμ't_4٠㘹K] tw?< @PxƍdB(,ino@jj`_볥p *H=@*DD+Ne^8hJ>Xj JaAπ |X9~.MJMi-at8[50e%< |o(n1⎉S' +v%Z+{qaR^"TpedݽR)arT9s@ шzS˾[ |5˹ d5%,K}wGy8#!mM}v@U]f| 8W!(UUJ2b:vل(dNcY b@x&!~!`'WBO!0H(MCzfY ,Ъy|_w42NW\^[2XOZ*>8Ԥ c mLzFo6 jfFLm<ZV<>8ZuZ6d@hDA/,ъ3sUf]f\A.,d¹C;dBFJGBOIőLq@T1oDqOQg@Gem:u|kU( +OHMDb4m4ߙeMDom$z|M2=q~u+qhJEHV_-B*X3Q_Y)p M[z2fV0@ ?QA5Gk.e?*oR$X7d\no|?NWb)j`"Еq/:AߘT◇G9kE2Ҵo/&w]u6Miۗ4Ma ^ n)S^% }= O|\('o;|8IQ;Zad3=F5{A=NLsE0^o /庬!z%u&. G7G}Wӗ[NiˬxS~C 7ZT k'G\' dEV8iY+nfĄ,$DL{ O0mCB+#@ TZ2׊a`+-g- g*XPFF qbb" PU%s x\}Kt7޻'9¥=|4H=׎;I@O`c@L $vH$Rxj D _N+lkO7+j3?ٓLj&u#ا5T.a15j lkM58 AdIj&L-Sl <5$0lX-"J)5k O9zoػIFFu#-0)$Qr֐I 5^NݷR &S?hqʲOz(RF[v6!r%iWҲJ-AဲsyXQXZҧa2Gmx)}B7Sb@*xvR63pjD R GM5'Ch`DsDˢCQ_Ou{[ԥJg/>Y)X? uZr`f+uy@ a'箁gw0>UcAa칗.N_ē_ MB%ޝ$9a aϫupWxo'  ;wV'kU 4|{Ml5D4I5BÎFC-VSQD>@2ɼBH^؜R]|]$g3?0O-[M9iQisc&g<#)Gv_raK|q'ϛ}N&%qS\ B杹?jV[jra 5s]M]b!X76 ,$t~(ǁSGnK8P+HB`\֍ 6yLF(@_i6+`8UMSrxVXjngkVץ)*+b1|_k޵ ɰ&=ɞRO+fI,ZT4Ea.XUX hXQ~*?$WO(ȕ&e'5hSjҴ# z1:<~TlVCZYrEÜBYKrrH3Un}N҆ٱ9n|B#}EQEmRC=ܖyk1 bGUfyCpHlN$koy7ɑO\Ym]#M=s~'6`JᖋA-5B|Rfƒc3yIcVџ^_oKDuh"~{l?F^W܌IC+U(~Ae95%oI:ٛXXGUe`fXEM } j 0/Ѽ(/h&{@,CF0:; $ h!AB*j4EȒZNj* oY#3y0ph0B{6CA7 1EY}: BPSnay⸂r-rjb-Z!TFpjZ=SC&mI 4`_&@rrr<<< e"PxV@ 3>Y% ~k Rs$9у|6=^ ݾZT³T9}I UTCGA833s^V&kC*3#k#CPUH+gȠE{JYT4>Z4-9ZzaUi(ކ*6&Xy:,Y> f(adnTe&61e}k(Y?P_@8}%hğZ,@\|"u(\ 7F<ˊt#vT/Ӿt 5dZؿ{`3ǥ˒s2Z>ğcJ#& brX.^&u# % 6+3J`]!~h,`5r7{sW+nsil&VeraYq1<CiPC 3wsшfe,Zlk IDAT]H麃&B353L Heehr@0ŞZǼsh,cy*:$o8Hw2v/-a84ӴCM}һ<T*#cfH71qW2O_+aR_M϶޽I&߬:O-ۙHMڵnomyΙ{k?ƝM z{+si+^ @Ңİ Kn 1!Pĩz %|RFY PZJ !?@# r+~etxBg]x, ])%Ed:v+s8)_QKő3ykPU֦9X93<4ՈnI=AB"HNDA7k哏cu@)Tu =2NqJ8`ؕ%f,yƊbʿ;EZ>V ?lIŶ%S~BN>y51l&מNagN s=WY(?Ws4BZmwѐ--Pv?6 YW*=[v7Q,5K/|K=Q5t0aJ~t$D]:q&W)3v]\Wjz¾jkw"\|Q~- r,eKߨR[0m4`y9;tb+x', iᾋg`71\Ю@~G8hY*wpd Xx<uAn}SH:M"|v5A̬^*o6KkYsL,&5sG:tL|``c`gi<%ˋLj3e |1~*R&HOGg62!Xuz>ia%çGAct[[!KR *mTVJ~QJ۪,p_Y2bfGjׄn6,ͩQS,eY>|6}ctO~&Nܖw'oG4{ڹPpXj/5vvȁ$_m0b9x*.>a@2U/,V\ٽI탿y_(C`ر<iGm}yPE#6t>O!fy)LtTR1xM*^BM֕琤*kqeo׽ߙgGCQ/ޝgv{AҠR"`WjI, +8md1x͝K5vx)nmC )Y &{_*3x(:A,\bHxw[͉4Mɨ~$ؒi7PM)ej2aP wCwu3gNzM )36ݽ?gmH`P[D=Z8MRHäAI@r[c+ ^SWqE;sHW˫_x@E=[cAϖJ 2g'IBT}-Aѓ#[nƌ5k5GS-]; \cQpc1BŏojxaԸaiK=ml\G g]of`^r}Ϡ~m9~۷/r_-Ȓ '̊Oo߾d9t=aSݸhF<> @U ͩ-o5 Us^T3>ϟiYnPŪ Gu6'fXssrs󫩜CƝd&%\yh~_#BT/{>p1O-H?xZC5#%U)E[wЬU'^o?PМk]z}$^3%w;**l] Ղ n8lB[~AdW~S ˺WPjUh@x642z4WV1k13sB?{y} NMXeDpP xzY}%<q@ì[EY}-.T X/X, <Ҕd4ҌUj T`Dc^݂ n9jQa:ښIbPb)ydJL/6Rn$:Lڡli׹_ ڟzz΀Crp.zO&13~Rt(|oZy=N)- )qann֯n;0ykMuK{J2߼{RZL**_cGM؋Vϝ9iܸ+srw">1|bTl@o`㗝awFHGȅT/-`ft,W^>rgIW?)D1D !@rQVXngk<xbQRb2@Ip`1q)lq q%Iŀ9gXMAMgIEx'.,S͇ɥ϶_dtѴqGfhYajd"kšqi\CCU]AqE)#q3/>|b=蔰38ikWR!uA4* [84pr0ˉÍ4%`}2u&Zsnl;n'uFplFg;Ńf1力j%Wa ҢW5?nyc ď8-WL` ˄3 5Vʆ\|?}X| 2i:ź{@" V l 0BTq'#lb6-Xs oOiIQ R x@,IW\kw(Gi|jeeT231pbr Bie~"oI,Jvz­z²p#ڑUQ[_$3NK8+ G((~MME&?qeey~'x1?^....̹yй[#\jS2_~©/nTHoPF3:1-6ʻ(OrHh+LO؜REm"~"/zM qG.aa/EE`()J!.),*AW4e[eniURRc@{@^ DcKlJ#(2NVJ)º#/Pp JqYeei%~ƈv3[@š\Z)pQ(JVht2nܚ@@C.) 854ag6nx)\|- _+Tg/l^9ugԊ90X[Y\)wkk?u9[nm]TVfM+*MW,SgUVKgF*5ՠTȠ) 73voJ#p(:QJ0,TMmM癙I,>&ũX( PըM\i5gd^*5h޽(E7 .͛CKhɾHj3HӚ%'E-ۘM2/3t st4F+7bz7;^[9mJ pw_HT6jk>|i,{2m4r:r` DZ=uH|!0P%=qPQl(7c/ m`̡dW줱`}򎟕]z t:1쐫 ڳͽ ;'~zAhF}:jӢ B@ 'pAi4pe#l!4 *\mu|>y>~({6C>*A}6Hxaƹ0u׎+Q)4O%0pQτ4 63|BU3bCE3dAjUYp!C^!϶[gOW %XPbx,--}̛4tXmiEjcem¨&gUgk\nZU -oF tӣ- Gqq̋jgoES8&_k^.-50 압 njϷetM%ꙚBFr⧵ M&mLL}8Q縛#ԩ_wfvB\>1;fjDK;>i(ˀAXXw!Ԍ[.Y 8 /r'hOLtb9d, 88RPYMhJ:(TR&a+F0X0HUUH$/^̟[$X_!>m٣9.KK A,ӺYE-D >p*>IŠdbihaaԯB-d8\9z_..rAxcՃiYbYY-}]FptM]_E=SR\# ^apd?s̱={fځWE!%3> i_!T# G(v}Oߥ}7b*jL!r*Yz{ů]xᵈ?'/ez2uY}->wޑde9{s:YO0?umS/gxig`gaV RnC N  d- 5nkt5[u))Q"Jj,XNb3{)0m+aQ5&AZ/Dzݱ )o{a-Z?Z޸VɝMITpώ9g60π`hԔV Br8t1J@ݍS80c/ax`bp[V{7`4<qtl??O*r"{q ]S^{HZ܊gE i;Qzz[Cw1.0~5 m*m\-Y柋+Zə4 ֚<h.W&/&W@ʚ3gVNw"D{VzML$J<74f|h&3zƨR aoVR+ZKe[AEaVaT dZTi" h³d`e'gb׾F_冉Guf[H*X*ROzq#TÐkŒl0v3lM?c88?㥄۾ß4Z`de|)أ1ӳ^xv}<=6tk oG?N,}QgiLߟU*W^Ǎ{$wsRGܘorJ DO X+*=k9 B3\scmg>}&^Iы2/DJE!avڪͰ\/maa0xOX@xRVr^*T=> V⣹}! k͛FPKE mQ||4(*>+Y'46Yq4W~!M*GKh([xu2e1u7ftӓ:Bo%Gsjf+ڵvAlL@Zq)g" U%ڋ\_X%3M`c5,~~{]6S2  =nDCymՃF G}}䩫#(dIfv=;Z7d~+zEEʺ-ɣ ѕwV{NfH\>sM{$Dk\ْZ@HhWh.mτӳ<ϼ@i36(eIEk d< ]=]XP!02a S`1e6nzshjfdi K9{GYEHGg1)VANt `{ aY棆ڶ:Y5tjaU'bP)AH]!6 -aA?^̃%@Vi>֋)ҧX:u49͵oϣrZ;kY|?RjOtk?9+DƄ #Hb9Kvjԣ/hOu1lYe{ROթ0N4dDވO䂔Ɩ7#~{rPS~̿tWR'$sh%zQב1MPp9+:z@0uI; oBt\ѫ+qgCWO`ɥsy6uOzVy#" VkaGRc?= ffzܹn4tq5|گOk.WB$0MO%2[LcX j-Jl(u㣹&ӿr4W >k6Y\huu6Kv1> nGs򉚜V܆>3uyh1?FA?GsAX |4W棹:Q#jI5e6:N8h[WAA;>R;G@]8}֔iZr`J͕B鳻pm>KEo2\j_0#ޣV#={7 HhEZzj +B/?'@'(t[%\Y,ԪalE1ԧ{nwvrsr_cZ-{Vuޑ\^ӆO>ד6-T*re*|PrOz}AWyЪrYg`S+;t5/@}?cLE t(D|lAW= l*gͥHMX`?ꬤqFƅ?wZ~їo]7f-+hyfp^7hxkVJ {ƦCӷXMرi~hʦD 0ggK[$ӄac/~-_V[\5һ;^x-vIێ[0tϤ\Ҵ}̘oyV04]-;Ѷ{wWQ`^7 Ljfػ`'98q_%:Pw$ѩ@6&Ơ>7{%9ռ-TH={t?O:29-m4;ءJlaAXHPO}̜P (tުoX9f^uvu|8kOa:WE TeɵL$JejA)j,[w5+N֩>hv`<|* LPAK`f&+^oXS, UڤRVSh#dǞ4nkOX,К}#^(5nD0ng3:pPjh4`ߚ.@RDM^X{ڐ?'ؼޭ2f70 `\ "\Ȓc@S_Z ^!M.h$0A(%q:918ĉOO2>[=t4Wζ?.ԻyO\|u2ӜA Srk|6=&KK-sx#q`re)mЭ9KUV6kfأo.}+p49XZ"G||fC4?)/zn,Uuv]4ѸA}Y-w" I5)4eF #+r0dJP̸P!Եuպ{r'=& 0ka2Ī#*_ c6`-ZfmƮ-tFxnҢYuMb@·+103)䟗jJ„E00CLup+W `(%A맚Z^VN&:! +'(ш1k?0kצK[#)5dB*RAo1iϨG}?ހd -Ƅ '`ONܺYJuܻ֖ϳhǫ-ִ{'ݲSG{ejog1br0p6FD'Jmy^$=g ):+FxP{J<qש d;=5z 8t4po7q`tTUO cdn,挶=5]IlZ=wgƣD7~{! r++u8ImG]qKt2.Rf {v"> V`LrI9+cխ2Bk*2ikmk[ǎ(RsQ&LdaS{M]RwG"l`ȯB|h4+9 EK˳Vmjl P](h:[ |`eeÓ#{ f,  +¤w1aOQc NrU]>T}5}L Fҟ{:઎0LcgKP۶|;"h2/[yL$"{i 6ͷ]ډ4@];va56q rBFUlKv^!8fzj₌hJьŊnaXEMߏثӑ^@cyg$cb휆nzi1)Vq (["g2NIaL?Rz6z@ԊD jXuʓ.(*JS=]O90#p27iQTM)\~ՇN>=ۛQ>;Z^efx^:BKH;aNgYee׋Jg8fJ{4?V-G*/h.JGNa1`=\ז Yp _ܧVOPCÀ}J(#}A}ƞmbd 6z>Dlѯקϔ#)㺜01;.!Qm=ċ¦Е`EhV/8y ԪHk"GY±ڎ_#T[Itsjlp/=,{K;5]126J9-|!= e( (Kt\yoeW34LsУ[BXIXbͮڬ*Zier K`Y9Gwĺmu* .#v[PWpR&5 -ͥ|4tޒ./MXA Q QJQKc8*Tx Cut2q hCaa2.8(d 2# WuT^%I]In)weslyJ8ⴻݺ$_}G+C%udEy_3D]~n^cȗ-yd^C\~x'6Ytfk>n&fH~gq|GS'UӬu+ VIժؘsikM}IUqi5u ! Qp@f?kƎ7 gENԢOZ2a2Q73߽N8mLuHCYx2eq}P^bQ=ٯBbT` V?=< Vڝ߶2z.eUffsJXcĭp4GO9l=($] \?Ɔs (h B׷,2E|%Ћ4nycWk *aa(T@xQAK *Ɔ?÷P1ρow^<<)SbS0py9)(K69jA\Nnhg/7^Ĝbs}.MO*ig -={FeuYv7lڰef"VCG#w,1&@'G!00ȸ^27՞5 jNR܏%C1v5l7#o:%`&>xȯG)R Xq嚚2"m/ 4N^uݕN"K4uv'/jk _nw_WAAmT1C\l|iU+L@(ER;1"X9=BFMU?跪Q׆2*,~c֪j?_GwAI~Vp]sڊs}! ]d!HK^l淫"9wJ-S2hl442(ztQ?UP>Eaekp[Jݾb3X|<"ΘcuzP.PM=4f ׎seDa>kzmkXoJ )@G<ܵ"s)tg>%tDnBR&ǘ(ΘOw߉jCr|/_|Aڙ"ymēæ:o9ټ0 3DuG]Ζ,qe3P(C \lkR\] OW-#((2k'@!,:|,?NGԗbi' ,]=<> f2<L|c/n }oվkٻ#dDz 7;Yuk] N}NP^ĒWuud9E. &npJSlf6DzI/}ɓfx3Sg:{DЙcnLiÈ6],@;b~hXTF!t:BtgTR!LVPЖ$m2[Q0I$5-CF 5axZFCwɹ߮ qm|l]pR5Wvda\9IUˎ9;E2(V(@2VNek~ y 6?+=ƽ$M̉)$?tҎPvﰡ+tO Q>xu/AC)%8u'7\pϘ4;.7%9'vU[CЎ鼱66cy>P%(xw؝_y۹M 'ek40ŷs[KABI(Tq+ gm_`s15?fTB7auwߒҌwW:XzMOl0#UE˲E.}|/ύ:{gN>}  kmN CW\t x躩uEttJUUՒ%KzeB "@?VO <&mmm*JT3gRw?⚫5 `%҅B&W!#ojݺ%3Ky3iiձO:upA͇}Z_Icqq<>=q1`cF{3J0qŋas)7Ҋ3뷿;dStnSd^q/aGL^~R]׃pC Gx.a @ Ǐ_|dBEz81]A @ !&M4j(9 FPG! IGV A л ڈu=7A @%466F+E g IDAT#x$/a @ "F@x #@jEss1# a @5f%*wS])*"9!Sa0BxI1B*lccciɜT@6"%/ c*Hc6E'G}S/]A@@OzhVF;L*JZgk{D!uCskBgFrI5AGImw6ңLbA @ Fz^>-s @ An ,A @ $=/Fx~:,t[# a @xٗwud*%*:(kϞ%n_!k/VX[n_`T%:EIsGv4'!$)sJ*w ta}XuXyJa7*+'Ǐ9ă#dԄ]{̱gBTvKYclqW-ZV@r.͛ioe2{HMAQF@Qsf*z=^9uF5-a6󭰩I(PlN\)wb9EƍXN*U;HN-,f ߔ]N)=Q@A~xZbk͎2jwהCi߆kvP҄e. DU-|_0Oubqb󯢨;Dr#PwZY]2p@Cr.z[)ڊozրAl]uGCAiLnTt`>b)E]+\F 넫ѬܤXc44055ͦf SG+"Aٜ]PJ2Z"ޗH&; wKv{[8n+ NA^[a+/8WD3)' |[1cfA*8P8i^7ko1_yfrzT/Dm9<+%9'02#k[NϭUk>Hyl9 *?'cY/ج\ȂVBJWA/4)@t .D9 K)\ڔPwcK=`ŵwq5)18jS#wau'hayWW1't(]Ym1HY{ Chl+adqrGP_cpvJC3(z_ !n!) }2Zl;SLMzj79'DP|SzsM*SAMJ֦T* \.ommqt|K.\pyXVUU  5x' +W\xٳMMY,3hN|%5P@LR!BxE5aZ h8i (C$9-)#^ө)M/9|sBb~/CbcOw"(M!g6Đڳp&A E$o#K~Fc79{oDl9o!ܜĹ JgA86v?q;x M|1]Ӧʩ>]sͩ7ͼ* A٥@\i2B5 1?~%/"-q1NHP$6Ub Og'#'kdX2z$,·VCn\\[ ]*l07_S|/|c=BA1g B/:B[MAAIr xMRT[?;*»B|,[W OQZ\FP}x+vG0֖UegOxzO⿓h1>EqW 咲J.突hJmpE(nk3ot o߾ĉ0VSSOhmm-z{;nxNJ/^D߮ٮyCQ>zE@ܫHmuͩRMt1RNcy ٬[6tFhk.Kd!!MGv,{?rs{nm`UcV ޻7S*pK:͗jAVz xBqfE6(=Ɔ>&xE䘉lO]8 ZW#ޛ!;/SL~VvV, ^}vo':7G-zDt\˘~r'1B6Q?aj%Msu@# !sy չբ=>A ;'eD5LG˛]k9ĘE!EBZ,EԮGV "zn~w,ſAk{SQ3\Ak L ½ ~ŝkQ;n< C3wl\> r^Kd^3e}#~Vpf5;}W'RA+_4}lnsq,d2O?->l4|_@hӻX -B @ `,e]QX+ .A,Fg.S@RS/_TܸZi kyv 3m;ZTJt'eY'!0#+&{eP[.t_:)ٳ;=AWpNgU-`AY`hd)6ch0B)ؐ1jQ@X/ [/"A*ڇ(KBJ Hޘ$"m3]ZU=24p(L C]-56A lU֧@fS4@ZF_!@n]ts#ެYo̴S_}!#ik61ŤZ K:@G*:`M o9Cf+tԄ7|jTq)򣳾>jE;mĝMJ[#ds%/PYE_䕋Ţ;=:Qhur$.@tE,#jaS~BWQLiF6^%I+…Scg!/>ί4GC~NH}b<|E:|FC SRðV@񛬒 sf&0%jԘ켠\wumD Q {f ;1,,0_ŕ5BwH ؘU :IǎTYp?~#%ݝi>C#?a!xRϦ缛h*e>sՊڤ9B7t4 .v YH{ nX.…zB*Je 5.g.=!$-x~PK}5 DE{cB^p o<][@e˟D" CaB>Q8YԲv"=s,~‚<-[+iƲ5n#usji a/eP=t7z/zt҉mģs<wbބ.s- [ZӭL6Ӈ@gKl[P FS_q>Ou! g銂27yUa"!8'XHF|AaW hCZ<ߴ7V4eQrss@D ľ CxPrm⌹T_S!ޥ9xz,yq1e0>n&bۂMj1zt)&OgAKLOL+0TliJUs6s|D";F2 0D\Sޙzۈ eZQJ}y؞H&S&%Ѝ$T [hTQ1`堯X 591t8$ *TZC&5&jyTmЙ#< T7˪BhfEK?6EvU+12nKOYt^wba"=EH}}atE H##ѯE8u&}5H%K$I E~ xL.?9 =uR$)OhI-*aFD\U .cBP" /KWT[x &;Q%ӂ݊uiy%/P7,gEGjB|תÂKU@PK]ʘlGunN`s\Awu;& \tUu:XǥEkzB]h .EL&`X:K]}m"uy*;(tdj5a΍o6(& D~u)i\ajVv׮Mwvvf2 *B*~lH {4[l tzQp{$m*β%ڽ*P*]KvFF)-`ư4`u\  @]k $ֹ9!391@g0M`U wXg ״sέ΍UNy]`1` kVΨvdjZ3u zR=IudɅit! cԨQ, $ sssZ) 8j 5DA#C0 h# rF cOP+Mh#nCd m#qBA !@eŊ>ffCk#JGv 񬨺,RP64rg.3έ]]K'*ŢಫKHZYخq&A?#!A#ݞO>ٱn(4sKԄ,>u]adT3KRi E@>g4dKdZz985:QKcJ:HiAggAT;ѳj}BȯWܳgЬlaamw!xW(޲&XPYڃ6O*39ݠ".?6ҭ DxtU+ҢB&a(tq%Sp\aq_'D F; B_+=!(9q ?bk+KǎAf$NYt@́N:z'7q>hy5^/[ijґ/d˸L?}:d"0뤶/4AwjtS:A0B;NR$ge5U,6{d5{駵]R"ƍ籫$nG:h݌tRa I}1P%^` %`2\T\O1%.c27pVwa9#S#OmDOMCVa㤮 Y!4{BE$46U$)"$-̓OTt)cW`i6Yl6=k# kw!l2$D ՟ݏD?|#@qPPӗш1 zJZhEG"F UA`=y>7Mf"& FЁ,9+yqڪ^>N^v3񙿥QHk$ ׯtxem;~ iN3Wkf~VJ ^}vkn?U;]fiϟbf>̻gWM&ޗ4 p1 :Uq:2vNGz^ V!)lLQ G-+B\sMNogǤk.#ZeĔ,Ь` 5zZE-vw>ǹ\ `4+ᔳqr[鏎 I ?~񘻻;SCVQw4Q'2A @ ZE#Iz NKÿ Ng[T.xB2,qֶ3Mʶ,D…^D+@H"IZGY$AqBYxOkJ:t=>نWs],HY3[M[;zxs1%"&3T;/"pH @  LCT_/8PqhȬ,9l߄{`Ry>ώ-/;Vi􆏜 ]_gRsgeMdĕٟ럯g?DA@ n"jge_s0H/ц4ia1z=:<БU/w㘚&#EG ZfޗS<<NR]f .KHP=S~V[TL.O  l%?̓q)9-'>Z`QE!!^@KKKS olgi)SiZU7evxJòZ6)JiWSLfKaY?Yq9.8Mylb`˖-Ӥ~J%~%az Ax9[6_ܹ/~u˵3?r%Ѡr;NA "GweePnwTm;M>SD$l<\,Q֨M~W?pDDQFSe&hkDOWUɶeF`df UJaƆUeA 玞󯰢bo (ouhnҫP'U 9& ,=jqs2LC S+]E6j>.Ѫ"̙Oz Tjakg o~X|]?mc=9'] 4L&5e`c-Pq%+o*;`;f z~EI YTy;fV[V͏7cXj}GJ ̑n:/Nl0ߩ4em/~8I~?C}1pBu8? ja'wﳨ,R%/ >S )z &]˩Ӑ IDATi9as^`\#hЄW-]@jؐ6tou^1xbmk}i ;/! q.g 7}d U_ w^ # ' Oz0x܂je̚6Z@̉3XZ2ڰ'9M}!Z!{Z0Kqsw('-%pۤ ^F7_8['0amhq dwh3txA;00Pxc(.E+DoOsneL>f7ۯ^V>ej>7՜{e懯\􃄄i +$[Om ȗ;.vԗ/?t%ȗg}oZoS5鞦q9rF =iKDk[%畤N37M*c(:-tCk$ @x(_ lGOg >/f7 Xắ+_ OF>txzÓ*g?:'iTHR,2@ڰNſI/p|C?g17 EsnLΩ$ @ nx8bDO%;_Yb+J5M9ɏm/}"pC/}7tC5G2^U[N&I'@/GF^4nLzg,o/!ל7eK+{CᦔnHt4ɻPm # z0J`h}5f}4}jߓbJc-۪ pr}QRK{liSM͋ŧ%=mo3bH@-ca֖f\j&Nغ[:`7]7˴nxae[K ACm 5iWZR#I׶ ;]n;u6XcBA @ ГbDYjn_m݇^,b^;W/Kr[^翬 %lJp89" VmRҒ[K}>$a{E%~YE_ȵ}gNj BO%(N@kiM})*⦨,Ç ~H +/ů|3 wq=rF ^\rBh-?#=/oF\=SA/)xCUl}I페̲cqç>`3A1@^nZiȷľF*U>vTo;ruܜr ι¹{?|Ț_z`n7mPӹ?-)o@@1 BUk}O\ŝ3b/yѴUM+V>!@B`ҰN1֓bmcd- Ò?xX-ֽ^x?VqY`'Mj2S<~Xz|>8sÇY>/4 rɆqCL;718q69ɽXto\&r/K MqoӨ4}'{X7`a=(ZŒY_3&m$sٵd'nqڇֶ[0blK$ Lg " "m%7ov[vsL햫Vcfj4?_s2wz[(%M21YiʮT+#eW!&/"mw9ע}ѵ0[g0b5t7v8x{ =تwפ kʷǹ}C|㠈X;r$32eÒMq.n\!ƵA pKM ]"4&yh4!F2 @Oz< &'s-pN4W7TtyMЋ?aioԷ,- KBy(v 1޼5I zMhg`5O$^hzMjҡUY_q|tuvӯlm -'4PFC .,m: ҽOe\f`TP ]~5g3̪,Ykc`abtS:H$zD#dOaJ2tȮ%%!+OM@XVR VvPCs./-X3A @ ^غaϞ;EY\-$ @ G?ܓ: @;"9&4fΛskp+9I4ɎwեpqYc@=Ob`N66H:A @+DIK ?^$LP6Wׄ;im;|}KgP ٧[hZS3w@JIjXXg֩VI›gՐ*x1L WUi /QKX56U>:l/a2l; 11%e}JwXYl8"鮪r|rQ &_Lg kg`CAOTQb< D184l$"@Ĉ 7i @;-Jܣ3U:Tx' I 9 6 R@JK1O,C Q$sj:ByS"ʤHQs4:PfjdJ!K튜#~i"Lo< T3YnR,E140Дe4@ݤZ*EV-a4M В&=8~O IZ+Y/g+B_NlU"#?ƤA^[3wc/*A쏌M;IO`e;Zv~;]BuwOq'pˮ*OZFP |Qy(1E+e"Z a:úxs#ڈIᩉgs^:yGZ{g8u0e?/hi1H!+^wgNQҌʷ'hحU!C<4izO(%lp5 m16 lA!"pB~r=K])3'P 6OXˤՕXG (|1U,e pE\ (9l7A sFtjէV]Jӂ&%H߻}5kʎeܽ x ѓc&zr4 - /]kJG9ɮGFB6!͠N O݉Y%zr}a%_dDcRqa=S/a|j!Ϛ9,3!+`ȧ\#ZejN8B`R -hCNDp9ـc#Т0җ \D_wԆPٳ8NOi'=:'[<*Ά !QrJi儮8%<6!N$ ΘŮ٧U$9!!;%r疝ؕKdw 6E*c;l*k/ikcnVSB! pG3XM(1l@ :U+5恪x_@|SY \]=S6(JJyH \ Tμt)r$͞Qm_T"֬@ e:7hSu I=װ68ؽO &Рi~5ͰOV#L>5𘴵T*R̜ #>/W L _jNj[,dbbD:SU+drbZp:R9n U˂1(6˘VU>=.^hnNjVMFbSO P7/4A x"m1Lߤ 4 a0(;"-ELE\ 6 &jAV]*1,? 9²@"Ct$<n=HAN88ä57Y{^D G"F<׉pI uCŶ':yը/;/ֵjnC׆WZӉ!S5;BCrMZT">/FBXpb;F D @$ @x$_+hLhXWM ݆5b„(ŌꑺD4Wl6z:F`W4PւԵ)_ѱ% x%(6 D$'anQEs,giAQ1Bhnnva[0KH*_K-͛GTKA#*9/lHs$b窛fKy34emnU8I~?C}1pBu8?ja'wﳨ,R%/ >ShIR{Q=n.7?ZNmP4wf`s[^S}Z#ۺ(xX9',!~vnS \T!xw:"Y~F`MCi}JS#tJvOmvvA }8ɔFC{ #666IDKDgH\^]#tEAMShA1H_p[ Á_-ZC@(vQo\C;]9q֬7fکԯ搑0+a'j ^@nЗ1QGA lU֧0Bum@d ghjf3qFIEBsURkL Sa04>}5}h6f;DuS ]Esya? ျK$8r.#0mj@ Gb@ň#2'$$ү4s*?f' ׅ_)"oQ7L)xR91qAK* '>W?,gY!Lz4=l\,G$qMF@{8GTca&=k" f%Um-(-V3;g]aZ\a27ځ ,9Z8IXڵS;DHC:0mZI 5z5WyJ OJGջTqS.'!p&q8)qnHR1B@@SLCJiam o`tjU1Km K]p k ,-U/,G`0պ/ZT}..JK)Kye{z֬Ԭ9,Tvg(!'?xm\p?32k.7,xhY0e!-?螓 FԬc&X Ϋ: `ҩU0,bA@íRj^P BFGy*voKPnPaXpvȕ_ :~Nkfo/M ;f$PwK}G6-%G|2p)gٱeǪ>3~l'~*MzE+ĐxSJ j.PgԿ|/}{T!>p~[9d'xcu}7i¬u'w`s \}Tt0N,lqtDbs:QYik+OdUoӦְ z0J`h}5f}4}jј!!.O !#!dK]׋RSSn30u 9,mmAf‚=  J׉YGT$3"hA'pemAZx1ጛ,@dG=v,3nc? 跲ttn5GGަ#"[4~o54^vXr8csxxD-9)OV-P''-eua>PyY 5{ Q֕%~ CF.LLl x(C^Zf&_%#A RҴnT񦅥esd6+8/V-KfKQFC/7baeM~`9}]Kʑ\XἼ؄Zylb`˖-Ӥ~kg~ߗKx+׵w4@ #McH?ka]W"֦@ՇR 8o T{c8;gw-pQ.{`aD"JhURkI]LR鵮/aYWo7RKnTh!*<aY{Tk\f{fvپ†{O Ďӟw|vZOŇ=,xo9±` kcBlI).%. y1 y=Uvcg3 pn j4lԃm 6*8ku٥}Ac2}e.^sГuP!.zRIis 6glnP?=78|PtjgU{]z )}{ p8Mf@]e0x\ï¯K [-lO;r~=kDTy{c$k罳X鈨+=3);Só\= 8i>8=zB;ߺms K9g3pCP;Z {+Kmjk߆nAmqG)S q[KO; C8xc] lg^ 2<⍿-%|fS^+T.+6*kg'9g3/3wUQ׮hҹj"g)V2_4 nm}H&Io I%j]rWe_Á.䰘7$5SOӜ4O) p \>|_D)J~J`)x [սa)Qk=ⒶjEbZX7g3 p~Qߧz^+g3hUk.9F{r7&\^g3p= L4z2 b7^w#J Vؾ} q7;o~'$\?7[mn͸UFE-b7J^g3p#΀w#Iw-N_9`ʁlJyuyC} &ca}+%ؚa Q)~UY2Ĥ#jőȾ r߀-yO \A]Ag]KUd2/屘/~7b?qPxU]%c*+,*pZƹ$%xnҩ"nYpʏfGb{-@/\v@i4G\al=NJ#غ+ {6v}`|MتkKc{)wSrvXJBxEZc:<9Ë?; oqt1&>֕ӦuEGGAڴqPt#/:izwpUtB+~JR{fq3v/TהmT_gOWXU~⅟ h{*YCIcT;k*1x{Cns30+5K N eH`*^HS  3h'On޼yԨQZg#Ѻ˜sc dBSVg?!m׉OwSM~=]rW'c+ @8RW^Ѡ`CbNd@#7QZup%hDP'<ɳna\u-HVii#:){R_ G jV|vw]9f~/ y}+3wWe|g/~fcih܄~˝v~S%獓!CT+.ONvnm.q hȪDZe,*{P'}=[|=eS5i Ud+ XE6dҧ8y{RxW7ICD!JM_p*8 p7mꊳS>p3;٩wYU5/KeJͽ(zs`L|b\n7H=ゅ+6 3bl*a崳axg1 " /)svz@`Z T,K8qW0 Q ^Qa좋Cv"OTKyg ~=GYvX3޶t"sGTX"ib&N"-3h\0 5Rv;qYa7 :vRlP;ztwHzO?_! &Dx _ZRP*K'v,D$L``oSw8N٬7PqR|tϑP_2w025 yLBJ ;ިF̂o8'N/]aUܔXO.xiu}3ޑr]}3|kYXz*GUUҤ8XUjm3 ^e%].d絠{ٚ]qRZ;}C&g͟1i/bw'rˁbո9qϞ.H TVTzh̏ybd-P:RuÑmb6[g}{\<\M8&>c=lD=G2 K/\42sN\оO\&s!pe:vtsS}ٞw]| {GSSf"kբWS&Tޔ/Ӊ`5c ؍ UJ]NL#ݜv7j_4+: ƚ!bNu&xQQ j. ^];sun(bpZ:Q{kʧ/Tu - EҾGnQ$SWyԔ}Ȃ$|45؊][eF0{ќA+5N) 2BtGy)5u!?5/[:%Fhsɾk~0ZJ64Ų 4;%Xs/M[w΢B媢 p<ن yW'nָxYտ#v"R|آpmS ʲe\=x ]D&w2PnwxprӁǭp_^>A{!:MZz<eES~I?eK竏S;oe[ KCB'<=Fzhb!N:#GGzUWUa"#{c5*. ?[R@Ç ]4+J=9?s -myz^AcϻCA? ;ۑғE=AjPk;݉"M J=u6,6ZjTs%BY!EI;\ 8vXzz ȇزe kxxx?6dþ1DeI]gOohSU@2w.ŎFMم/][U3RuFeѼ$X(Owt xzYW%#ն۾]yCY%$KH֔ʝw>˅s$tp4~S=uYØr4gCt򂊿j7YruzY 3f<=##D۶Q31mn@/PZت0RS5lDKv)7nXïF(]F{'*=Gi7mCƣ?Vx00k 6;L┥;:%G؍CXשƚfTs N.8R/`{ùmyoNT܆D{v/Nf.vC'uOww= Pb!/?]Rxw@ /g-u]}ۂR1g6gg p><׀?1fFLrmad+5:~t}҂,_R Rk*;r ;Gwo?WCm v s*g;rHLI`=_%֒A #jg)yJ$ɠ4fSv/9)6_(&k 3agMsG{%%oGbMBWtz"sxB dy$M&w5ъzHݿb|Q8cCr9>:aa>tK0dZj,\"G&F=W {0:6vyI=3+&iF=Z԰ic>k[Z \/|]n^U89lT< _zj gsd/ݴnJMT>5N}#Ԟ/Fz@s&f IDATFxϭ4WTAh1['O+X6qsx?2Yfa;s\ۻ.T Z0G,Kn#\|xqusyK=7 #{Y4&`Vu2)se]k-gã*^6.ÍrĉT996nH>pZZ|N G>*OvdDgK>AKU5:dji]ʂժ,ˠ U*XVkZNA٘1N[x8NEC+֤2+ p+zdgIYQ(k1j`D$(j]o:Y.j3` eV=&AŚZ/'t\{mB+;(/f+FXAɿ}7o>d#~SO OXY>7?K7Ǿ>t<]<mC;KO|5xX\.ꝕЇ1`5TUbj9 p\95[n'*0hzBi|mG,{*y"c,) !0"; Yf.-5h@ z/!&kۙ/ c5xv;[en@!f"flp0ӵkW!FPCqǍx7?˶L ٤/dl{ ?@)$$G$IB0"F(T$d١ڑ߭[58irod[/{[ BPƷ&% owXfsXXn7|w)&eRq[E} WbdL*834@)=Ē{>*+xUZhh(a/-$$RVk$|l? FBRc)Vt&I]:vC*F@Υ A 39Y01Q a 1quX_=1w ( @1)k@I S@LU*@1d3z`SMb@0iLsbУ !!&jn7YOj #I[<`n=2FuN1mB?1L܍'h69)@}y0$܍"pJ 0ndAN GSXg50@ZBÞbH0  1!na&0YL,$ TVDI, Ln8Xii54Xύ`X"Q ?z <b!A󋈢w#l\~+0ʳ*ppCDLB$!ULfI bJH3zY@ %1@pBAˆ APCb v1< 4v#hCxw#{`Rmݛ Z {ʡAUjcFGYp 3NF)ߍa-,K dm,b VĬ .)n$pZuBd XQA ud!JRqRPb`g:0$S< OX16(= 6*0d'nఱ/MZn٤h#O<Ӷ- "$ߍh '#XdI%}@H0:INYd I C2a86*cI)㜄TB NXj-xr#PL:';P*Hl>0XN:7h9f.X-LJrdTb)cV0\G.UJYTIhR.iJ"T 5sZ!h1INbCiN15V YD)vIf "IJíVt̟n 4IMFkfMQM8H)\h_Qw"HIENDB`testng-testng-6.9.5/pictures/convert1.png0000644000175000017500000017336112551235562017771 0ustar eugeneeugenePNG  IHDR˿NiCCPICC ProfilexYgXͲM%Er$HHZҒsJR ""`D `}>ϝ癞wkzm-8 0fFa9f3Dae`AwEZ#QЛX?6_=E>08gd s0Dxp,p%TZA w=08xd YA+ BP<eAP tBm!4=fE3F0# R2 6acT8.+M< Px3%RFQ(/T(**DUQQci2jEѼhIdGۢIt":]ED36H`T1FoL&SŌc1߱X,3VݏubسFl7v;p8u9 Kǝ]ƍqx  Y  G@dBK](6)((U))=(c(s)))SSnRSPSPR*Bu%<ϏW[#b|~A@-NKDAC} L"8 9:B/aNCKcDADSJsf#-%63m,m!5Ǵttttntttmtt2/0<Rz(QH"wXFF#F_,!&&y&;hRNif0?s.s3.mO +,,kZ?xZ^-٣/s0rq8299sœVqU߸ pr-s3skqrpwq/y4x<%` E Y==*{TԖ˼toޖKmK+HKWKa1Ii,+.K-}"G3Kk[/@T8pLG᧢bE%A%W2IeFe l*$ UEpfOjj~jWoN_M9iM>M7JY--wbھڗ?HYUMCe 3Ox*v7ٟ҈ˈdTgbd`gBmbmRb2k*nj~>`|ԁfBff-+ [XK R˷V2VV.֗ڼs[׳Ϸ>(u0١hXӇҝ&>Й߹Ӆ+떛[7w#2.QK+k[O2Y\B^[gwo޿1"5-!//;(:h$X"8=x:D5tJIhMv85y9HԈ,\M=#. B:4~&A;|"ؓ$4HQ~G%K''MOiOJ=:fVN>yLXqq 3ۙYYY[٤2'Ox *斟Ğ <9WO?w_O~X(_XQDUQ4]lZzF3[%>%:eeekg=Ύk_Ȫq|y7++ UUo_PPW^UbZھ:KrNZH^9ܘ"_u:lsMڕBnodބn\iinuhi3niWkqkוֹ|L]T]];co^}gǥE'}}CwM>gptVz:2>okTsΘؽ'FOG&l'N:MN?x/ļ|EpsiYs7aoSyW бh8>~I՝_ؾ\*ŷ72k77n3j USg˝`P_(|yOp@ja,rBll텖(g=[ ԧRKQ%H(ӚйG0&10Sh5/qqr7>&JLAIJ*m'vyvhqe9}4~hYi_3/1X/oge 25oVM;gm^CmNk\N&;L=<^k3>fdrEBKZXH}hRy8OȜ(h1%qxlXbEɌ)tit)3;YN<=9דvJA39E)qgbJKn.X>r~rS j..Ծ4W@E1ě<- mF;;o^A@NhA4-5<VF<g8;Yⳝ/b_ʽ\~0z4vztlkNfnͽT/v^_[^pc'j/׿}Z{`svί @M12a_QdSSb4BtR D;@T*>%vz N2W 2">bK{B%oݐ֔9*{_`4BTPׯԊԮyW5p7_o4`h `11PTfܮ۾`C!%'ó}.5nZ$NҚLjgW{ۯ?0@?=CPŰՈ]QIZ1', EuHъ䔔T4tc|ǩeff>wxNhᓦy /,b)?CU.*Ztv|bUK54lu]6h0y5Z-P+]_-C]K4T ksO>Ob mca裱'E Iϸc/x֫㧃gf$̧{Wpa}R/>Vu}VßsB'`Qx@`u\'1J*9< ~!M9 XHb c Ss:K.YF> <:|)UwEhDel$*I.JK+8ɕVRVPQQR#KTӨҼա}W_wPo@mk+2MLLyMgVdNPYNX]Ѳ>uv,9.t3W[ N=yzx>J!Os'dAACDBS {^9\Yft]],w(ߔp(ؔ|dTc~ǵ3X2>d*:C3z2?/4B[7EŧD8#xs'ΧWVUp&bBm@KjL57_͛-­,۽o%vq~w=w{umw~Ã+ f?JJy67R;plukh2i峡/_YO從!ϱܻzj]p7=@ {Z TPmXQ_T&4D86ޔqA>XDEvH2caXG*,~@T  tz #Y fª`Y' 7JAOaIqb҅#2U 0fC Diizӎi]aah$]2`g` feae ag8 u;ǒ_@`PDɌRғ2e?ʽЫxS%:KjMZ446thu a35?jbkQnb†V. >;vLpqrs[&qyhz{xi&Sx|2#5G2EGDz9&$IvKy>~!c+k!''l{qqpIqYkйh.ՙG77q7Wސh)opu7GFzbchFyԅ%+_ؾV~X{Q5k %dUA *#Ё\Dꂦ p0\woQt(U'*u͉>TWo0l3LHp^ZEE'%҂,{*U,xy| &YW]I"Z m$nޝ=C xѐq)Y9K:<[Rv:Qb.wn)3-`,(#!L!)Uؖa^W 6r Y*g! aM-/: F&̦v ,h, mv:bY8UbZdS|~\!#CË"\bY% $eYOMyf{\)!?$%"O5CAkaQqrIHK9Jj ;?׽j۵;7j[Eۣw^̃OGtL\~zycSI1Qo-D? yo,,6xi]'X{gA~K>  }0 v .hty$ ϣ(mBM)v1}=c&[ |qp crry DM%:ii.ЖqU#E Fmτc"Ͳz-݈cwהO_\OGOXLDQHE2Z^m׍os[#[[䭮??)-_?KNvwB?N|ϼʝUH|bpev:>IA pHYs   IDATx= \pSAB+xU[Vj@k+j=TkVA-Tj=*^ ` TP9EP#@f7Y$ Zo͛f̾}sIR̔ F 4"Ԅ+ ԉ@ކ---]aEEݼysҤI$ٳgVSS FX* F 0~HGկ8$5%_&*c 0ee4TI% hn2#κH5%Qcv{k=c{d4`g+)[ c SF*5bVJF i@DSw‡Ib4o@lY5Kՙr>g 0C6Y]ckLԀD(DO'ZO$ei@PoA,=#S>)/ZNG&gZ2_ɭJϭ?zqK4v͏I%SVo|K}l] @Ga 7&kkkS[X|~& %yX`աj% _wewnr~ajmo_F&  Y«|Tۇ+ᴱA*{g(_գj= "K ' oVgJ-M)k[kߝr|u Z6E--^9V:`RKؽۿ^~̮'R%P~xguTTï-}*&:_K&b=UZf cszjZTK8>Aw^~`Rӟp VJ#)L hK@d9$fQM4za" z=MCTZvEi°oGk"4Wu6W4/{%4go٧JA q.ITsaZnݸ6^l=`"WCFiJ.JXQ~FaP[w$Б VIG"۽hC W;sއuz* 3A0biµuG H%  ɲiX[ <-b]sc[%9xG>7Z-mBVDP^e_uh= !5Ay A2W7TԠ:q〸}Cɼ_v֜{DC$jѴD䕈- BZ:%m *~ZrpM!^pO"Y]^T;=hM'T*PIP$epA9<6e7sH^{p~V9{7W{}@ul?P°ZD-RI6DX݄~sN*hDQ;-=nθAj~K]-Rbû Ⱦo%a[$t{|$ t>a/L'dNgEl]Fj!t4"0&iLKm&D$RbR& < ]~oW-fY\s, :%P`{WB}zf&aI#b5<BF2uJ^aю}8ٿaUBu^1]*m`cgJJ]GJv}tl_uWMY԰?Ym,ifLT޽w/)T>{OH% EُXDH"ݻ/)4FpL9wITi3fx/<3_Kr7lfH oz]W޻ṱly77ARB۽vUnI' q}MtV%o8XՁy&F`st8ō37[emj|Uf1>A5_T}dU~LJ@YWX>>ÇOyp)YY*$Z9dISg;9O[rwW2-y݋Τ)hI`η ŎЌ(/BѳJ6P*x"i}DT2kR'^X ϠM[*$ QHdGQR 4 3xxrcX 'Bv(fF0U*nX5<˅rpR˰7tm('jrٵZ&7 }n;M,NRAr&R('H8K,Nnf6~;>3?\ ?÷rs[ɴDEqrWS`vω;8--a4ߡxHP_K?\~zkyֽ+VQJNkzԻ0 cs;$xZeVQfx ḿ7MYm;X= Uf(=)OP>̓"5I! Hݝ}q@nI.T,"-N•$jK>Є?O.P_x]C~Z='w(` ||a-&TtѺuaw!~ۉL Zܷ:Ps ge͙E`Oo/-?D~d4BQ:2GJDR hsԀqR`c*w8d#kIGdeJVDX iC)a1]MD9Y: Qa=~T΋&X"Ԕ\C,A^)a)1htJ59=.^%+cp`?n;wniZҶ\kֶx@ [KD+H N>sltUSe<l#4P$0FevУ:! u\j-c= M׸=K&$9(@vWl8Ϸd^Indžߦ]޳k%lȃ4ۘH'~KcHKrZjen@OOqG';wN 14U)pO.K?dO%QH e4hEhvD4Tg߉3|U7<yFv)&RZ-0M&H JM[' wa*; kd麟P<`R0\&?:"#$%gV6uy˜g [;)7;!\ !"Ff)fK0P1IWQmI{Nÿ݈ gs ũXӄE36nsV|n-;q*"㇥,mk`FEcu5͸Vo]sn@aZդ-AmCߌ,Gny~wNڊ` m"7FevC(q$ð|09]I>QnC}ko ^K%c*k%6À>uŕ8k;fZ"Ⴎ̄b7?*.i=-b1&}TZ5]K DX*˦P~A/ao?T7)$1QЀ'~<-Ѝ҈V \J%OJDB&* 0xAh72Rc&amajY0 &u X@I2s/gZr_R `Y=||nF޻*,}0YIؤݐ$_;T4<=k`?sW$I|vU`IJi[G/:@Fّ%!CȍX Hg.ÐYmo }Xȉ`{ѻGeq#? :}!|CT֟EC|w9;ޓ;x BTiͮ%&ٯxޱ /s腐{Bs~ zpx"baHs}nn*3N?!}+S AF&I^w0z*,)P4$ @=tnl}$Ȧ++~aWYo?s JHw480FFrs\D~66WmՁ5$=槏'OFl8̎^`h@o7r#i Jrʿha*2kQ9B;v4vxGDR* U2$2uȢ R22CWn4 -//733;/fEAZP-#=ahדciJ0l:%[^cA@rXl e$RU% p g#(A^(/`nGHњW ׊ 21 e0vM$%Ǯq |~Ny rivN_ ڰɤ_$GK /EIaaԆ>00VՏUV N%&&RpG9jjD*&!舮Epeu5 h9$@ٓJR08OK 4`PQ*\( 477=h] -ŶU@ t]n[XXPv 9:R&z?/i#dٙ =J"Wdv q-{fFx4'{gЖm f̙6uFt~8#r {/̶}Zj5/mn6eyEvb ]wsk22jA^:~ <%g>W8MTdA0JR 0xURȱtD˶'?BqaFBY~ټyW98' B]bIRI {[*?9n-x Vֆf-9GpQ8=Pc~jjNQxOC$YTA_T$E9q5ψ$8΋8wp5uYj^FO n61b(_'PC;5۪l+D߱t*~>t3&MyVAo0ܺVc3sTS.Q,Lil;Rh]Ҕb4С~{PUƣ|IK76_?/q!K- ']ҡ^Zi(<@WkIB&xP\" o[>Xp o؁kW3aUbJ{Z a `Ay"pURĜM\2x@2|:EN qʀj*Y4JNwCSeo2v\$E kWK{j eªU 7UY7MؙS$8 IDATr]L&Oc)Kɬx!W"@0TĄh d aaK^`1PśsZ[r xpЬN#\q8JսX$t (=ӯQBt&$&lva FCM*oPW7goL%OOقvxGe%3kfDxeX+ %Bf<P4cɌ\!ihj RΚތkҲ $*ʢP$A|>ӡ֦-@{z7#qUMM}3jה?Ͽ\]vlT:+g9?sJDZ2F WzAő <3` ׁYLHʳ·FWZtF8 6h?},*7=CrsssJ%|eLF!(eIuK4qRoeU 8+B GLF1l)G ,׷G9&S ОcTg5\s*dPN=²e/2 dؘ't`"r:JK%1upK6){ؔJjALKY/{MdfF$M:>~%6UW#cc*~Rh,j2tXX$?$$ku o²??ZIR& Fr kKm3#Me$%S['KNQtUS+<+d>CඓKh!v."BÂe_>i'5.--?!4mA!qk l5p#,-~3QSFERq 9V˔B Xjb6ۄoy+^x@<!W hoܻS>Mxsl=9]1̚ec;Cf^ YdwY]Rmil Z.#-" _@B~R+#h[ N&ʚ`Q @H%+D) dRx<==UxjF&*S1p:^1 >_M$ fW= $HL!4 =9)]#܎P*d}bwTjΐ'R2/Bd+}py~/B.Ó.jȑT{{{8CQSS[''*^{;3g,9ܙBEe8NAVBe6^A%&<P~[vO׶G4 rbLzQ/\}6\NLJO~pSe}M~YKs-콆 K]C_ZMf5+-Nz槁;$n[?~MU6E*#1ݷ-TZۻ|s  _8-q|Y2`4@j/I* YJ@ܠ!`zut#%K8iⲝ1;&{i^l=aI`kwف<ՓHrʦ_@T{kyPMyXoHٞ1m0Ks޹HOi^$Yaэվ}&!h"+q1j5\EDO\yvv!l9qAzEH ϐS9xeaNSW{\v^4Ĝ(Q#"CuGFC .:Q¢D-U֋@_F̒DQA.A)$[J^^#F1ƩDGyshwzZ}ݢ6`lȄj@I*Sa϶QpamojlX\_Z(,N ^k _Ā$aH[Z[ mnE,-,4miL][êK*|P*>toܿw&|ġ#AQ=Iꪣ<`G  (U3ѓ ;3C~#es0˳$LKS f(sa4$ @!H]I-Z̯F ?/[,r9%/tK0" cB܁#h;Gn΋zE"fXz",.>;qsv>Gj6܋V.5E,6:gKS7}i9פ^gv$wi:PkBcSWwAV!+>4jʋ^w8r?M%pF 9m2^^y<D܀4!%|fm @A;3DhL63Ccf_O w`3m@_ 0H@ y~# vه"!W ,Ą?K$uϠO؃1wuͰ[v,`Y^u?GYwlߦm7n}º45v]S53 TY,oӶR]Ey;,ԇt|՜_=ןeWprplS[PPVD0h)[ÿuR;tXJدMzd*_VxSSSS3/ٹIms;/{pS?{#)g֭Ypubo'R$y/z#}c!K`=ĹRWIk@Rz*hz* ZU8V;61U)Kv%- WhUn.-@WEH g =l^q;tp7ٿgAH`S8`g_3#z>n!0zҹM; ڸu%yU#/|޼ OSj(Z0 ƅuvqkJ/~\ښ&SX4GыBMwzo߶G,!.Bbo0 2EpN r}pz9z9vpwK`?IliU#jO@cCo )Ư\Pɧ3sPh#.wĝwYbiQB\[u Z&]FQW т+뇼?6+ k5`xpPSpEvqu%Ip8fh߉CXښ&SjN-mf $nxJv^ɰ%g[l=37\IOGG9eܦAqVʳ/r8xqc:t(!6kx`:]6fv4~JrB'ςJrX@*r.zrʺ|GK+ʲM4,<=^D8ïBa qߤߒJQ&aE_x%!|[_xA™_M?oj'N/Q{8DEppυˇÏc˕rkܢ{q!4dy%_+cāJ8D pg%h֬ĶĐ,h2b=-'% ҆$猥x 708v_l[P瀽q;mW}Ls+lm+njW#bk5?xC`7n~դb%Sql)hs` `}B[Ęcj;<BѰeUs>&tp.7Xشldh'Yf2'rapg6$ufb7?cIJPc!cnY8]kA9n`- ?`89.̎ A{q-&fn) 埘ϵ#+Lp?ގ6& @ &8l^Z1< X ^oַE3'Z%9:H "j ݇NlP!`Ni \ӐLJ0)'ٰ3^`Zv;Us#J#wPePVF"b)}}5<̼XbW Z,SMjD}+>zKWhZGwH90/&:@@Iu p[-eUF+(]7&W:$dAs@2H+NA(eA|O¶W %kszځˡn 3 ͫwM 2GL 9R@c_cSLGf!ɵhXq XhCZI./r`pԝ&n?ڹ\ȔNjmUJuw[.CeϿ&:>N'G/>iC|W8Nj}өt!,s̓4XMdI4˰ߟxKȘ% h/?1`4$pl*\t. [u'jjDƔxENTi݇4u8 yU!>kTsn*Xj,Z@0FvfaBSſ7,6֐6遴lyG4}o9r0;xGm[F]5d/kI 1I^dG<[>XGoը B:~/d6 նp,H=q4n)cA " 8ً{+rg_p= R'/K9`Uɢ(Bhٝy)>{ߩa|+hwK'~s‚Græ!Q= <sy̏A{R6f,ņ*bټz/4\8*OԔXUuIJ>Xp6*?b1ʻ_?=` ȠAY(r k7q:{zLeªU 7UY7MؙS8l8V.YkY! {M99#lhGq&ha4yQ)U7"ͩ;͐g֌#Pӌ>ѵ7v%{X=ɐ5 q䞏Ƌd^!ٍjj@YryFH4˃IcfDVO(3 ٽۀmI&<;@_#\ n]$%uQ8LA IDAT筫f c TSFVr~f7pÑę\S.ʐХ*&C-x3X0l]&zhf$Aͨ_SzҥY}eV_R; #LJyJ6<8垕ge,.e9'LYvoQ&k l5O m -R;0!?ۻ(FwX&&1W#wl<ߚP]3MgcEmTbB҃PI ,Y> `I<=Z(/؏U0.f p.ԟtRRZhx1'8t1>/*w]‹^y Xƽ!? , rہ^^ȡ8@^d2sX̹}Ia4Ѐq8I  5L]Igd( 0L^y,ԠT'WFJ|fɆ iV%: !9p&8q6"uG\:erhE6A>Q̹}(s:%Lă3;y2fx;5%/Qfxt`2(s&zo4rvM6]`{A [Rc> ~*6T꨼qzL+MCyp'j r8Oskm|N_Z26Z1Jx[ (->šGjp(BX|el aöm7}Cz^CڡT;rlr> L̹}9;>zqU׻aLP>#P#g2Kn(,|JOvg57%Z.ͬք]x.y{?  +Qnitʼ_m*}~G+~b"!aJ tY̹}]8&c8B9xLVN3S4ތ#>6̵*+1~IaFgΉ(JCC] CPRt~^p'ѕJP(a4[BAGCѣֹc""){ 425t xXfۻٷ;)Q%K3ݺ [:@VAXWƲf']5Z 5؀GqI sovz`p_9aW=-nVڨ¨)eeWFtO&oAtk oK[ŭ-͂ʇxޫbxї=|2sG `W}+C:wsV]R(]i)w~ee>rf/seYJ%dXN׳-AGDI Lx=4#!90t ?CAJksm彊"WGU"EIA`RFwZ. j>p.X<>';yi0w=ppq9GW<|0:}ֶl۶4"{B^ܾh|n}}ka0Nq$Ι@7J^>\(K¹}>"gvn_/kbzԹ}co.\- L㷭kɻ#)b9?4^3 e.+H9\gs}GŰbh;ޥ[O|PNŜL_!C5JKK LXC+ Uǹ `rur$g*J//jEHabw5}MvA&Q`(xM,k!jWQkx5dEU/ |'70Wg2 ?xnB>Ula|n°4Pv&:S>Ĺ}y~',¹}t <G$'Z]>$F̱VRW|a#lR2 Sl|ꥁUܿ]N9hР%Ox]:xEYozGcęQ,=n=6]XRDbxK? ih̹ BČ mkWjʊOyEyQMwhn-E~}[)OFHqi l7T`y?y(d%0.Â3ig *L&MCQhgDDw}{/ @Qݣn`FMjq璦 XkX%fq quȭ{*ɴڕ:7tJzps؍~~|3첺vI/okr*q"70_BaE̹}])c KY'1~7,+XLAֆHTtX0yոIMwW4&$e,l WZ DtZW"XY2]0\(}> Qo'i/nuN PKPH[kAWgnh%"8gS|cA [okVІo(O) H0s2Vma}RXBgB/:s(s_LuZ`:x O"WNt AAӊ< ㎓n-$ƠT!9Αiƺ 3w!v_-Z-h;YA#>>4e*NY~(pZs$1|Dpf8jNi'Y :d\,cC[9/SO6 5jJ!t=]D[x?n]vreҰ0LލݽJ]`S9r sjM5Kў"{X)s~ yW_"ֺOXW{&tkOA,NG?7Xd=?,::W)$q4W~ލᑭN}*ChlYntC[zҋ8X$:w[?V6?P.|J EV&?0릁$5u_>a#0u+_N̐lEocj W%%1  0`4\5PY oumF u^j pO@t_6#Ok#J Ƒnղ v+tbRs2W;ܭ=dĹK=uH>_ziKŽKł nWD\R}'c0J2=̙qGvz$ 4Uz{ZY)=mu? Mȹ^ܜ[gZ8PBU[Z[+J񪗫\mnPbhT,GĨ ͛q3;{3g.7!wz{?Ł^\1B_Q?Vy'(2?O~u%c#M'[gI~c'-nS 47mpWKHӂ]Yޮ)soJlX6- ETj9=os?gʤO ? j7m~? Q'Uq|+iM_,z'Cyqwm &!*rZmLi*jYɼR޾W8q"S>Vz4΋F@"8,cVzK]2k7hDPg]Q]QlM_@OZN=Z埱e넼Y]'k-,Uul\GzDn2l" *Yv6FBQ!+Ak`9p[z2hK!>9Yؓz,sD ?3BQxDOt9r6t&S`b痻[u]`ʨڐ=?EԴlQMy0c-2W^Oa-n%s^nynJh_:y,D7m8dT]異0zY~^u44mW*{n߹8?ԚMZ{v:}bҥ _:%FmzB<׎0J8<5kācΏC+X;%ռl`-{Ť@H4WFؠȝKjAAyQ@B~mv@s $ {N6h!c{␿~]]mWS[wm6|ðdR 26b7%r_[!]Pg(O $ 뷠n <9d &)~YpHt!>]'67ngm TM5RKOc=SwXXOqbeRui#@x^j>#~g5z529pbB6U,xR"*&\}oz*<۔)mn8.@rłYvd؍a㍷$F!s<)j[}EAMqg[ݩ[dt8X60w&s{c4Z~R/V ɗxN|\(ow6% ͞SC`jW'U:E4Z`u:7u{}pWYw5|>Rk^ժKmV춮+-=Z?Zrm#@x^j޾eIE(gK)>0ˤT7Xv 1|AbK|Ss=^PHr`5l(vIG{zGkC }A.jZЧ'jC NNQz,58zZIŀY;wʨ%Q CsWjY~ϑ"u/H7duE[otud)4țR-Rt*UR3ey#LȑEƧi4QJrIdU^>AJ!ֶ籪XȷL>>&‹խme V0á `7/ `%~^ogۇf/܂jKT ȤY4j׺ xqQorjD7T?tY~2ý9 3 \AIk"G^ \nxd}w)X1T#\wV4+TDPC>UVįJFB7U%|QF\斨U*ӠS- 2(ShH :{wc4Q1DʑۧJ9'R~) IDATx&b8r޾w3K/>+8! Dvo am/a>nΏîҜsifK38M uyS;*q^j_T f+x9ԕ:0;E%22;y*yJ>-T}"!HP}K!ۗ7 A (B&WdoxFzۙ褤0D#m}¼}*>l@ꐷ/5}y ey,?B7fe Oм}klNG[[x¼}^#{RhSTOoX={^doˀSouJw,NTm3 >OdDO;_ߴ0 KZ4k[Il"uC#j7BF>D=un7 Uק1Uyxswر#Ϸ6^ɂJib$9Xnְ'.A`ﱙyV1xP.WA^n]C|G*m|ٲ[gwxg|Qiu(k9_ f߷SU3Җ?|O jQ1^;PtܜG =)zAE+oQ,z3P=A&Ⱥy=86VnN@&ʍΥ3+2HpZ"tU깤0ah+@&^_ڪ>4׾%뒆b|ӗNLW(1&œ%U ( PGS+JZn鼤 ֖[Lvl)vLYO{0),iR%]ʙ4/w=E0p7BQ;lAU~@畜M(8C7"',q"GMX֡XEߺ0QiTGm%nF//i"?l֖0 3s'_KGaT!: =7gw$ EϨetgTҮ:lWH ^^^Ba8g}Q3qP3L쟴/uU2{}(J5-4wL)'+lq$B;T뛜8J !-ڦjSeP1m m@+h|BcRo:fh{s9f#+,+4AN3U?QDuH$4HdK /. eZk+zBbb/Eb^Hbavv1sWmհ2*YOf ㏒w_:8ڙ8=O{⊓BY梴UaGӚ <`XNTä Bg:ݖNJ R,׈qYL{^I5, :(ޯo4')UL?_t<(wܥ 4ZbjҤ :YVdYYOyH`jl$Z 'LT-hHdf\V+K*O;YS8&''81&}>2M¦ex)%I=8]tOӷ ُ,@'=R~paPAw JKȻ%XF-*H;Ce0byXy9ڵN҉_j{c e޻sԻ 9Ckv+2`5to>' eY=Ml1QU~n[~4U.;oџfRu*}iD#! Z'.CĽlp!(tb<|}ƪZde\L, #3ZN23S(yZeR)*N0e+W]׮mPbr-=k@'.Qn9ʙP `QCi¼\Z:Q~+$z#@_Sp5B_/2lvC@HVEe2'1o,Na-DD( ;/ri1 ! m!ԞV%X!(t׽"+w#jLJfmUα + Oą)FVOuBKv ?[ee)V:$jҲCOS{x)ڍ}ɲ,p %H$Hnl@rG$,UkQ)ʙ iIJzf0i% Qt%Ja[Ni=cNO] Y,c% @x2Ă%]]1ߛ튌0L Y{g%: 1pNdGC;y+;O*6z3ttH&<1w@OoFJJSV\UbTMD#ry5?v! 'B@;qJSP̵zX]B- QU65AL6BA qֽTjHj֎C[.d$&(CȂ7Y]p$Gc7"͜b~.z;+:{C zy'[LAWrRظOj;C?˘;Qc9Ek{rg[Vǡc@ X߲0p -!vO_ M?'l~zMxq 4 3kT7|X-͒?\\Č:~}85|&9 ՙI-\bwъ3ǠrA`[ :?*/]FAlK iY!TX-Ĵqq>-,2͏O6oZ7<^38H[-Tv[Wtt$FsW!0{QF >|ip?:. FT:OA @x|L+>3gQ\)|{KOS2G<6c^I˨֨.BeT$J#n9}@δ/sJ8iRL ^ ?.׳5g/Nf{쾬pT{q::3p.1U'<ݼsXtLDPhjD-LT!y-IKцzzy!I|Y';g5C/8k4=ݽ:RLcа0в b)HJ*S0lm+ژ±擓ץCHP%֓"s{z`a}eprgg :/̙>dlGOG16ztnӖ 6`9Lۢ&4Pqj^uLMMMw}NYWޘqq'^a3Gmrfn=X21Xbj-$;87!.#t^:8H/$5vi(2i_/^(6qAu@@&X^Yz3ĩ[FNv=M e wL`PY)jPFx2SAg9 ɀjA|WF .F >FYFFH/w;3$Uf0e޶c*1 Y~:e ~ S]&[nPedC F%q!+@Syo}~0Mp/07ԩюfRlTH)7 %GmV1yRY@SЄ̵0vj0Bf_̜#x$2[0{H"@'=0mIkmiv1]u>޾B)}:xPS,i\^ pbqA +AgG`NWVo_Zb\gT&[foo} *uR*) ~BAY0 V{ė#j>:ZAiΠQ'޳YՐ SOxUcQ@| :tȐ!` %`L]ZD^KL8a1ma1Y/h7D MP'A쒿ɗII 9 kum]#] AĽͿd}A qAkȪ#N?5V?d檳¬WBzF \}$_Hu%ö t^sK쒧A!^yZn XU~ ̩D=N([sA ϛqPg%Yř%z :e9[" D˜osTH29lPRW?]H z z0۠<ޔǤҡ;(87VqwO!nHd=$9/X-' єI|iʘaQVXݜLGn)]9LoVABrϊrioYQ& bNԮ}ߊ 39Oeė57?F4wV~w@E5  "f%]DHGIrd wΤ}R.9I\g,ZxBc^db,=5 +~uōfVʲ%mpa-ϴ7/'O j4u;L[ g~Ɛi?5qE5IxV24Pb<*A C@RnJya $ƜFTxt}k?+@-2CP/hJ8b+eom*YxT6=d m_RxzL@2#*";{c%-ǣ'adފ`%D>$* 4^[Rl~Vo;q6aєU펖;vO~F%o״@{ H?$OxU`+Jz]4Ȓ:}ԀnF!t^6fwջf&|P]`hL6BA 7cZZbqtx% E}bx~vl$քY\Ŗ@ LoFv" og,mیe(m@O+V$"^Sxn:+1,@n\(*N8z IAW(utVv"A 2#`Xc^6{,zYrk;G?JpϘf (?Z]k]dah7"JdTI`=08vT& dFeH|EAP Ln"7Ge?5 IDAT!zWz95uՈA& xLL B&޹+u2av{$_1x8{W=UaP8 %i+S"?.Ν0Ⅷ_[:J  N"B; 71\ӓ}m#j .#N=v`}D$M``eЎHB](ҿ_[&VQdCx]i+Qo] ٚEqs'Y3XQ=v_VF8*`8 wW[ãZ_ u\?8Z,|[zS`|bACo; nTU,% N5>[L$|!˰ {^ڬWx 4A$^m}`_&TÎwTnVv"'Fp-tBİ>QXj䵶ZBX2$(3-'CB|aXKJKK͛D]"WRj2>DI$?o_}uE߄rDu#3.a0ILӓAOïD&njcugCq >`*b@ *AQTY":+`4Kmte!?uSIn^FC/svvq}E+=G"A BHkP3X&2^`iʻ?۱= ni >9&SݚQ z,E)֔j * Q~8nMD|W`u@hW2.y_:͊!wC/Q^tWC!̤d!RLx "%zV Kv Sn*lo0s.cW~<]i:uLSceygܒܯ>ώWWԲUԱ#⻷kMzRFزR%#;t,cM:BI /655)=%t+m( 361{ISmטzZwU4p0SUPK)t5`$o6du<}N!,oR􋊬l4ƀSr%1?dM-\)5V/ _gW .>I:|x}44^_񡇙xQ|_B)zڷ\ˢT5rD{e+Ҿ&΁`?]; :ǧu{knuZ;ţԬ*=c<;kǎ9N#.omf-r܌t|U1Em-Yշ.O/۶Yqws 䩞d{?s No(G{b @x|깫 Dw ̋}CLx2sōF* BgP. YBhRrf$pnˠ0'|ŮX}N\t$u:+z۾)f{Q jHLxBѽI')H7k"=9D.W=⤜044 7WFnn3~J3`4OR1 p&bK'0+fFs:Yi{iw~5ﱴi])p:qj|Mf(P|]+n6b)0M/&4ᷤP GLkM~1l-\uNw̷ԩԓ\#%3miL_ҿ{)i&[90^+D)٥knz@z{+ZoӔݸ~ .ݶgm΁ݬ߹PƛٶuګِH7dfT>0),)i9,uׯѯ+g` {~)܇-;f<]Bm;G8΢5W}՗95\":w`ݪ늵 D@?ˋq7~?j,5\pc X`-IxAy8̣>i'<t6<0 Fn<j+X>cde<)xĤ07NL:) 6a^ե!4 ErJ.ox\Lxf ̂08s64UY$]C nIYc>cG[X&d^q0CV%8D6wFݐQt]D2B/bX_] vҰl @57P#x Ty hQ{BO>z_%͵Jd Q ȴJ[2kLXr=Dž\b1 1 :d{=lv/I`92V[i4dc^/B ʉ/yC6TQ\+ G{.J]\LoPdbaNEØkSoĚB5ɼ;P;pHt7J%TU W(B] c>$ObB l #bi@kކع 1Vd#=4e2s& 7Ugg Nm L&&in,i iku;3 6&|u*f`s@a|$}.2=yԊ(Nr"B jz.'LvcEDV{ެ+>C8?yGx ON!h1Sbg2#=lmB- =Cg<ʤTZ~0fI9Wi5E_da%T4B=F5g/er>A/IR Ɇ @xҹh*EW~p1=us)W1%BUf0e޶߳qQU xPP]5lɃq[}tqZX.lAhrF+ISpWzҮ2tf5@z N(d9YU:7L/0rjsV@=t<'_z^\qf{ ~o"7"5k#B׬#GNvʃ-e@)ҹ]^>xfs].Žt0H Fe-I8tFpRхRTY +zͻB-ܮ2/z@7,oPcuC/CnT+%;H[jkTĔ7555$Pu@;wk477766644W߹)oWWo߾u֍7K ?.|]7oQgH9AuCfƁK ÕUmm-\k7o޼z*mk+6;v/m4xZ'?AuS_ʫd/PM|á`Geq"d(u~O DbXO4η n 6㏝:[{,Vm.~p)(8b.hOXe8_D. q' *P|`j& R'lA :(ώOg1R@9FD.P=\b|N f![ rc_7Gy rԣ#s 3(Lpkuip7=T7C%ۜ}ncp6idDe#\pa )\peK]K+UgUUO:CsGw0;FujmaW=-4P[؅tϜ~Jx^_9ׇ @_Vp5B_/ph=>E0'7!M[P]1/60|B!efDi }L:aIfD91 diyE?P>¤~1YI3ׯ,Z1:t6!0m;ٔq.8DhpR R_[:׫-]D$F, v!fPAO$ k[7W;6/=ѶPf }; k,$FVKzj恵ABًyNIdܖlyۓw oR=uʬdԊHC@5-A @ K`uu"- 2-@_dUHI! AmU]L͸0+=fVo 9O$*>ZQu]'lg~7_^{A|tM"wF%8=}#ssS#iDąFF1u EIwCW#q8W=}1IhH-@Cj,&8$_5DE7zoК{lK;ssЬ}aMhTw01r @¸[S+7++ z NP۹*Hqca^F]WM֩RGGI&s`O'w7eDq(BE'HS׎咣a6$!UY8U3\,QM8v,Ȝ5Us3F 䁺1zD]{ԾkFA^#^ʇ@&ݐVW%OT!@Ԃ7n 1L~Л%_)#tJ-;.YpQ8WJfN H uo _|;"cKHF(`zm81y%m z(:5ֽ;y+;ocn;l.b޻}BhH`wTV-vnQV䃙'J`ʜ J;wtl:Vgʉ9kNV;Jٕ7#_$ SR* $R\,qhY 7 үoϷs7a8L.8[EBUۼ .?5$V{p8%h{k{7Q!l'xQ=ӝEo); |38|#4v1  sФpJQ0n ͦQ~3B>/3h @Vȯ ~\supй4yvCTKnMDSDTX%sQAVD'RPT0D <6-\!4ZrȴbP3фZ\wa#v֪N(@㵹mm%g"E7ЕUWZlsbXy ejoJjIs'xQ1ۑOrtkC'Kgu}mv#%a;vFK:z dY4Ғi3yJ?Q&.^ud`ݫ8alұ\i[InMoXrӢ W%R7k1r)<LXfWܼ00N 8G~.-MFXİ&IXZ/j`f IDAT.1$y 6mJDc2Kk۲@>tI**.@㇪Y%e"F8(y1*鈢p6j=ArH>hia_)Eg`+t3.Ei;]#KNv XBQ- ~B~FEh&d2t6͛6_AߡeET5@pt wyhwEAvU '<쒂̨y6Qu&\ʋ 싂OPD(uav[2z@-,aabE,PXL>hÛlX;++C% ǘOFD6< URf:S7Lst2Q&u Qh [z2p p{@Ot% Q&Z`NK?wY4w|'?|BYp>hiLV||{ז3@{4/laHޓ-bH[hjE@ 4sYCjuƠvm>h$w^]hoGGGk0'~r"o#"m`C4yɈnT1P ܗe~Wu[>䡔è7uJB7|z…ROB IxgQz@ ZA4e8|(n hD?5tt D1ڒ\D(]kވq"vPW' @xLܦ-l2[zْ |5韺v\wNj)`M{wuҹ{vcZy X(2SZ }TPxUqyr ]tB랢Cm¢$gͱl^wi[ Az~`HW^Dئ;9Vej 7m9^9i~e;uL HWлiÔGH@%U="tyo{uĠ(; WrwQPS$עCL31Ψ2KԝHYQFuS[D@9PTpvvG5ig1JA k0FphQH9A D_8A1B'Ą,uBW,lPN=bQe_lv;7^,-Ҩ.3r +dL~77?0}eO]qyP b+F߳qV\͛&'1=IJTqro XpMm[۷& _sTxXN ͍Z36:q7]O}5BY]vֿ/O=M`^f\;MfkB ,dq=dz]!2*PLABRa7SÏ}\4^!j? !|@: M!tgIY$"r;gPFP1{7P' R೦5IEL3BG.Q>HT!W*o*hLmOAqs"G4D}( QHE,X:=-_U.|&ښ:Ee 3ef٤8*1lmj=f:Jk&q0VT nC.=V&'jcId̏ʠJ%8kLOĞꂑ(Ok| wK3d2yvbhjW*ny-վk'EM 5>[L$%tu Qx_|w_$UBxQp}:_4ja8 {(85 b jQ gINK:603>6l\Fg dT0/zog}QZ (8D^cu<1MI}P~æZ)bhAwQQ jmxT߶ysXB->TAms" ؃C1y_!jQkzvE?[?2hYkVٱO\\sHmi5?HIBUtţUHlicEViwCA |0-|TwV6;2P3yɒja{ɾ_nl{_/wV^ k7mJ^,s~aA/UoIgA #%0|t_34`!|%J !/l>+eA @ /guuu"x_N WNKDdsssSSY 'm bȩA!iv - &J ?KVy~_L o[*y&f蕣A]1iKEp˼vgЛ-L+򑉆^GJJ )(^ z5f͚5kgufϙi4vwjKҧȻ)Nǫ鿶 B6`F`n u엜޽EL>6bF`@%z5hDxF0OIZ!<}K߰fن#X=Vn;hԱ_6~qԢNNSWngF6Cb쥻p㧽}kUwe:W-s y[0-OM͚J5h?ptxOb̀VMGcF`zEFj2+gF`[{c*+,8{P־r`F`F<\w?pF(ޕ~>' k\nQ!Pg~ ZUušf-+fF0e$Μ|"R_xY$;//$v˜ _3?稃~cuhq#F#PɵSNKT'/`l_ ?L޵krƪ8x9i =soS˟K۽vzX`6m)ӣo8N>sq_Z+\ٳw>}z-2TgP:[ڵ~\gʪŢ֢XU0ؽcW> o]^X4igϙf7w!p-T_Xw˅FXjܕS^p}͑oO3a_ש/Kdэ l5\>gGĬ6ޗm8}p}pzVy=%jSx!zE! ~mq\1%9f p Y||\%b*8r#4<^XH|3O PnO/]o8{dVy|Y;%v.wh?!zuC1!̯nۆD z 9f p Vfo[W_Gb@ ]i& G. 7wQ+B;1v Q9v joN-LM5 6/5l0t B`>\ݔs=O3](*TRuXӧ~ Aݴvd[CWl>^% ϟ?'"veb [示 D|BQm}݄t~Kʏ!Ow;w>@f>_hSA9|U*KN"VǙ#L;6'gƐj&iٳC/WW&Kg~tTY@v bB,3·qbQԒ M>oxɛ\wCAj ^h&O+r#0 ֌ׯɆ˦T6S{=1I-CСUL(,5 W*kqYqE2F*B>h=s8䟳hÿ5bjFV%aG-4u0`n__W-#V;輽'{cw3+𕂴=|}L7 w8 `+o>c d~^~a~0b6#4"g̫1J"|RŘan!)#0#/ ~`_Nh0Ewdm6M߶aWU]yu]QaNVjʦkg0ꐵeNfdո)#u,YS@"p-TVXXxE!lgZF=a~˦fc~=i\$ғj0ZH4{3hRQ݄{Iq")fʔvN陹6Cnk/~>BҒZʂ#pUa]0qNb~l} Mz/[La ǧ)L9Y*\[ywLz?n@wq~^qeGԶD›5aͼC%kUա֟`@Yȸ )k:ů=Y2G[O[ZXq2 X5Gh9g0Uӳc_H60qTg-;"q șYܸkr(SQOMoㆧ#i4}SQIYηSՃ;O]6mP`ȱ*FE,!]Ԕc%?CF̜#LW6>w*q`n,Kn1\#0@EkG.uevq<1XQRcuU\RppYK^ [oo7'XIlUTp1e9^p -+7^,=wwHT0e.Y9[OH~hEabFoʂUT.3GKw ^Bԝ yUUf6m]oUex6fUy+_|~ILh4oeiywoiF`e#/9:qBtL}3c6Vn@+C|[ 0]SjX2 1'uj'2?>]ٙ/>Y- } }Bld{ų/O*@0>_Ox*oz\r{ `!Z6o3eZ$ġ/lcH,sz,|qIsi_dnYܼϼ}O'Er_md5:907re#,|-{k&@-+4 =fC9,G÷5ܣ;i@Q"m7/WT_x4_p|m%>챿m**F y%W>gǻfGIoڜ9 /*DD;,51g&n<_r#P:Fq{Jy'xA#^J; rr8ӆ!:FϞwޯODo% 0`VanJBYyBF /-L7_x۶=ۨx#׏͈[2g˲yQyJ.=#PG4vwjKҧǩʾ͛s61!Bƕ)6L#I8ǎ4iZ- +0)//0"ʎDzsAGRWw#0=|λ]}gd!I8կ ?ɯ0V$+'"VrȎm.+3 %TXhG Br heGy<7-繗sF X5|N0׍@Jӟt:5jI ׭ 0# q 2~0ob%XcB9կF?iW\:wwm-pnlvǩrQG<4)AfKmTZ J2/j/dY/#8"ꈆ$[u2+]Ш+d1/x}I}!zF`Fz`zcyF`SaNzcLwR0e<,6OYgUn5hÌ-ɩ)ɻr 23ȭR/%JOr;FeLU2*U½~dڬ>cֈ {JQb9d#g1?c)8٘u?{ȝ9waAN-#}2>r&Lϱ/tkcIy53=ʌg~buK0`Y_}\yoʿd082FDHX=buU*F= _& L9ڍ9w; NY9"9f9-;l8_ۢWLEtbn]dO@NͮU*Gꔿ1վG]~޵?MsʛsZ84,/iX2Gr++Dplo ݅\q0s_/jРP}—3"Zu +,SbξE#BxYaI=?YR^ĥ}2EȟE}M C4ֈ3 fŬ  x:{#Z'z) h~7 rEqn4WoR_]Æ1@= Px$q^}ݯzK`;ӻƂ5  BLM5 6/5yS7?.c/(%xԗ4ʌusO/4Sօ̊2ѪaEcl>~ ލ>bȬ_:!ߔuuGZuߥhzxCGL}`HHIZ"ń"цrVE* KB/#PGdn],JO1푄SrxY+/bf -)?<ڣx}52'ħtFք"z@??};=O=={Pâm>Wf0iH}K\9V{(HDCvU"3V8LJZp1rZ3o:(GR ,A`q~XK3DܻsPy@M+HB<4Y0'F9*(1,;\l_GBEζ~zE,;ID'/TW]PMLɘC|> dܾ-155w6 9nʊ@>x-n #Xq5Mf97|&} A,L|***<8thbW0K~?v7Ȁx&ZU3U>qŋT`{27C[6IFuHf pm۶׏Ѩ[J/XRTRY-VYr9: ɳyL+ Jش*ƕY!d,-bq*/((U>Ng+bEu<{l{^^է2 0n<(_{6oFɗ? A0 ;'OܲeÍF=Q2ݤwܻ<[ٲhCC|ΰkׁ[ R[[t~8փ:[.J[/Vt 0ۦEW%>ZY([ r)W?ÙMr F]hkvaaN\S lݙbF^{8jgAֱ@C 33Nȑ#===Y_V^:cvYϥkh(Nw̟\\J>MX6m|/aŭ1=٬MqF0Yr`m98U4y$lWME-i_9.:wjޱq+z#m-) u)z!H"z)enC?yQF5nK?eʠ&㖯k6uKMƬĹcb"VHAypQOmov~IM8R({$Elc!?bdޠy}IuϦޱC# .^=KkI3;KipbG`#̚uP֏,uny߭{3◈ ]>ןIYtO"fOcijh3ya;[.$|p4/Ozc/^zka XҿUHUg*+(h`ϩm_/]HA^/jn2km>6Am\^0sn̤ߡm>-nе9U 3%I*_Ïշ:c{ӥ;>RPܝYWo1bg_ZuZ o~rtL p+˿^.5pՕnK\S̍ϴn}{=NҮ|m0k݉Hgu߷_ rAe LLLiuuxOJץu·4S2n8??~髯1bz QcK+J+[JO!^{QdohGu:a%O ϐCZ3gԨҊYy"틹s󔏗:Q1Ѧc̶ z'O邛8e*\ ®=CfCE@-gps.(NxנMX | ܋nV:qR APTUu]rwRޮ(- k.D~?]0*g!6jvCN5mv_S1ED r&%mN 浩\E»M9 >))]-JWˆ[Xcm_ ڦKkSp`c6mOSuV_eNCܯo֘P?lfƒw{W(Oh|*Gđ!wYz6!LO;3@x䄊2_Ks{O@tdN^ 1ǵnlV^RʢKށbq,$ǟ|YYcIXX}@?IHK eTZ>ӌm֑`M 8"x}̠`}os|1eF}𯙻uM|}˗)D /)q3t}\.:߮|# qAk)[fQPb⬐ٮ :fnMn,2]-I?kPaqsT^[p^ϝNt{xDkS)M05k#襒kPaK?6>#p]͢YYnJIN읐o[%;m̀f1~bV:GzyPl"4ֹOGk  i@b^͍|٨F.Ϗץ=_y|ݺ7Mg>˦QFؒ/IX gLۼ98Q:V"/j J)+n7Z{VSK;~?j%gn |$''S:%%N ֗}-zlT;fB .aM9&(۶ءCrJ) W꒨}=c8^"[ /I@_Δ˂$q Z%Z<)$&i2PRƿ\?prv[SL$.uh`2Ȣ~IeRQcRB/rsZгd%b ؉ H!ݾ}{w :u*88nXA6p @ Nsww %&Cחܴ}jㄘ[!,TD`,96hicFЎ2ƭ"3Tj\!!!4CF;HXR%+C6Ie%_&pΝ;G?<яD# #q=;kse.))!iӦ ӔI2-%) AaѺPXV` b2L$1$h$@S0Y! p&kƅMeAи@h4FJM) B*4xR݊%b$H$p=zMˡ2PExqMUK\~e)Ph M8_R@ǵ8|C$*B)#9DΦ,h >hd84H6F.6jfn"t}t%˘ns"MLr;@.rRIBQaCcG@@b), %hQr9d}b"T;Qfo%du-F OIt*%A`,! #R)iSYA@$iڀ Ar$i,P zC2@@q⨚%hՒ~4đȁ~ 3݊k:WJVIU&$&irG  Ad (#!IƑa*W]gQOIȺ#cTL%Me{+)b6 ш) dR#IeO18@Ē)G 'R/c욀RY$oB=)t%HC_"(ǺNh RMA BS,Lh|4pȰ_Erh$cQGqELV$&JPAe4 @֔IJᆈD#Ch@ bR1)$hI_BOJe2/!wD"P/1;PXԛ17'ߜUZ|Jgg94r1a)"mH\1d@͒4C! /lX%iڀkI\\Ĥ`RӈIEdLEZεhU!KZ%x MKzĥx%ژMbAӢk-wȭM @x"P P%8%$Lڶ_Ef m k&i"$$]d=eQq$A@riQ1q8 aDj'>K"l(EMR%H!c- tP_h 餖N.@QЈ!Z𡁃$M̅2K,Ho7DMY)H& j |d4 Ib\$@$є4 @6Z&$b\đ1Y4p@bbĤac$qFk6A^RjAAP-s;VR-]c?8!RQcqIENDB`testng-testng-6.9.5/pictures/classes.png0000755000175000017500000021553712551235562017672 0ustar eugeneeugenePNG  IHDRaHnYiCCPICC ProfilexXy8To,c'=AdߗlYc`%I)*VR)$f"ٲZDJ3[zy|sous,|@?H&j`mlԯ=8kp,o0, )- 7|sORF[QC3`@0G)e[Rp9 xQ Ƒ0$Yk8ƌ]vqzRtGb%y{+M$j}^w $+0 <ïe8f?rhÉ;zV?ܢYA=r;=mo/± - ~!YF.zk P ChBnOSQibisB7cY2e8Zxo^1_~`dTAN"C3򛊴J@Ն#jE4ifi~S[DAaѐɴٺ9!kf6^v'9 dqtvlE?L &'= ':<-uYsߍP{R}\WēSiW_Ξzpܭ쌆oe'u?=7ATWs#B"bز U55j=zjLAM^\imjni+j~ûٙ%۾ץsuPpHh+̯$5c{.v\m|y{l'ON>}7}_TggJ/~&BŋK=?WRW}7fˀH*FA ϣhj [= ]L 9l0k_}yf?B˂B5"bKQRyKq2+H**N+5)g>b*}ȸZ50u' =̓ZZS:zOIc7M>{hfcIr6;k`aaʼnri8(W;󘗁~?~"84F &4> />qTbd(Ѯc<..|=>+J_ISSWQ1^tcԭwbfޗΕyp0ODX#l!O1g {) SRXn)SwIH=3FƟ[R_85K4/ԷƶzyGWM^>ꁔA!ahdlUkbcOƫ'g~Ș̜X9? _gqs__-(~(Ի|qtM|i 11Aa2" ɉ|">QwT}ܳ* [6fC,W''_ 5Vb8zƒc)i.鎃gpr2E˫T(P$(q(T:,wJ5<hs Zz]:XS , 1Ff&,&Wl4/[Y Yg'(lٶ%8su<dW)yE|d~y_{z| Da}*&LBÁynbd/ەkW>:P>hb:6O+t|ԍ-Lfb^4X7g^Xo' QBDMCCyND,'#{ĥ#q $JHɽV(}f@vz=l܉gʋJs+k͟=e}T|5ݪCkw|v8a5qo?BϤ~M7?z/XX Y_w0oIn ;P+0DD oHud(9CYQ]p a*A &jn`~ElZd:vLz=1 3L6~6l~`Zqt2Vc'Ј-W +#@PJE|tĶ$Fj4O&V6SЄ_,R;O8\}ESBvNA+c!gX-r-|3/w8&D|uSr?%B F 4>%tz,Ǟ0 [|HԞKu6-7'3\nOfme߻ϖ{Cr#bB2+*UeˮW|Xz[KN>|`0qTUϛ1w:G&ݦN[}ʙ"8k4=ւ‡X][z/_++U"ɫk^k777\6766ǶTm-llP/Q a4v_ܓ Vbb <H6o-8Bv[G7ƺ a/MIưƇ``cF,~~;=.Er Y" `?2^붐B̭` Ph7"O;6gbp7Y?@ xw &}<^ ڑ#e?ZRc^莎/uϑ`[ہ++}mYxG^ofnt; ûѠx/M8y %Eɣ4ZRXHP((h+HV UP $ $2dkɚs2 q|Nz:g֚}Ξ[H8 p6,YY?ޙx“1j0q73hp-:X *k^5wyjF)k~4֏FޔuM4|Σ^LvsS ]jёg\dYZL8ekգG+RSS3oTVV~w7W^vy$yZ @$ *Lm̗̚yQiOؔܯ*Bn~3xhѢZl O p4qay`U\D.cM .Jb ϯ "qW$$$ 9vakFsz]v[/956+Ƈk=[#Gw ;o !|3[ y{:28! ɫp"Ocǎԩ: ۵sT.ApdH+&۹~E.>_Zz(|=oڇ$vrBӫ/K7A$8eNkj߫*$ +DzfكGu T$Djf2:nV׵ěOt$&-=Z$ǘG]iiMOPj;^re'gƯo-F$%>| N? v[{M^pѵ\߃Db58#ǣcN@'ID\3MdYF.j"&=&)HZұ j(ܿ߹6"-TٍL0z`>YX1?j/Y_3e/𣅟 WKlj3P* ػ`X $xv-UNH8pዌq/ @f 6MOZI D:%ZHH8^Z f5tOs ZW{KIDta>( 27)×턴VHNj$$J|uP] .n3SjpιYVXۦӹ§!ͅbM1^X{R_cP`kQ"%3[`7VK1ksh~;LLJDDkqb*%]Fr{j43Jo H:@B9_xgU|$~m&JiiVB35)JNQINP & (d[lLKyxW㻋+G}b Nj q3>zHI$v{:9ӁQtp)}qC~SXK p2/$\BwOVdbi܎$MX2&n&٬ϰ6H; ^(tµn)4]s ""DY`B >mтPBZD@0(<{77$9d^MS5'8NBl ~v:GN"BGZ--@$(Y\5NPߕGщt>mΌDoL\mx*d_%,wM=JtØ hY~aU(XRDTX!݂| = tQ0- {x]Y4lY4|KBd:'ytXXO\&0%d$sc6qk C.8 `g;yFv6_m$Dhde[FfL ))H-NtPX߭ 8ͦxNHxVEfE,:~ek"#)hM(-}3@OCKU!}rʷM/f|TS-Jd=n3j٥8e IJD@ķ8ibSB?(iO?q)m;ҡC IlsCÒyWzϻ}>~w?.RZ$#EdrrB2N!,?w;3Ͽ˫&zƙgF|ArI5aH3;8٦'d_oz @س/iv<;!عh-v :N2%q?&=yf݋?G ݵ OWI}Lzpb*P\$IK%1ɥ(|0\uL%d$Ƙ[,!HVyӜ-]l뿎=( r)\&D3!'QNmC)wn,ݣbkZ?Pe%%%HvC|$㜈XeY\{-X3ٶ =No2;ۏݥ%ܯM/-55E%f'|Ԋ*oI" 7sMiG|$B:їrsqV;ƴK(FE3~Gecs_{ߪka7#YWi끦y@*ks૓i @-<+cJLVkf 5礢x.t@zK>C)еS&>3ґt(v$Kmɓ'Bzg=sbb\jYf.sEp&,4#[F%$0̇$ቼI‘s-0<-魴hG?~{V3[m if 䗈#IH~$.|;uSUH;۶[FDd GITu*ڷKt5)1Ekmy 1n&Ld钖[$& GZE&c tXH>R8j^`Xo=Јn[I_]|pR#EF,#kgYsѰ swf$"ń:גtm¬4>zωtZ(C/tmωMg;~ X^2ZɆgF,l=`=`=`=4p?1$s5I%tDiQ&# AalW9]<}.c--X1kr0n&dCk=f`4Dn, ჋fyܯ)/0a9Xy@V<{XjfIMi1$ҿxV$拎:x-joK, qi[x1Ւ Qt禞6z܆晰هŭb[F7ctX.1Zi\q3a EAAjBÄ&rLDV 5b=`=`=`=<H5knU 8/q]%D"(тX' .h9iMY\tqd়\KE~7 XNh?!<[[XXX4ouխ ] 0ЛT뎢m@ ֵ$ } tB4v-zzzz 6pl5㬉KfYb5ΰn46;2s-6\tDM K،hS_pZp94dJTeȴMRd].8^b=`=`=`=|xY3.Ky ]i@=ft F:Òp73e %?̑wrz춈&VQwbc9_frzaԝ/'qUEq(3ўXպ&-(5f N艁N] w.٠?Gm~zYzz3feuǭzhQ=%lK˰6Vd5ͭYsPn2 h!<;5X=ܻ2a_v;;P*ޅG8~X<Ӟ}7d,uwwccl/a7Ct\$u ~N}2Ƽ; jo?4!H{ Sށӷư߿K|r칔l5bCf wgv_ L_O߅~xFG8=c]]KAps-I!fZ?x} OӚjCC@/X}x[1۝;Z^yd7yb ?rZo9xp$@0},$-->- ۵'j&iv0 oa/Snd5WۡQ:;m}ړx`MV=.H[ڦ9܇uǧnmHkz/ iռ3{h{. |xH#?b=`=`0\DkWӓ FkxI- .5ָFY!:oXN \7q>֭{|oouz:Կ5dl NzsapW`0#]N5Rmo\w~z5޼?X)x\A#Y#JM] 8Tв YD-EBgV3֛pqtx+IfҊ@%2l+lD(v89~34^C1|mH cs`p P?୷|*1LGaǡ4|ͼ]`b=`=po5]jS_E;qzPDNpMo}!}mCT=X@ko9!an}# ?~?hF^?BRKA7LZb,`ƭwuv[gUsa}1-`ྖý,=G)"X#vʹ 7<0tJ9l="<7/~OƜ6p4A.^7 ӑw̽`1+aܵ ,m|ψeZX|< Vl 76oLΕ4 knHNd<` 3MqHz@QQωs VUXOҜ0D&`f VH *]^4z2KU%VoUٛPb~ gC< 0$8|ӽ?w?8MgheOȨt>CәgŰY#Hq J&.tugk=EFkNmp+s(iBI[ ap~իdm`9m ú/. w=-߰5K8#= 4N:,&n5γxm)d\n< [XXXuӣJ<.2rPg,FskҬ_l&~Gӓ_LFґ JpmƸ"/2zzzz&1ٌlMWǚװBqiVj$5y:&kXd4ͭ-/cMF^Fxubҽ]#%g1WܲȘr&_p/}k2Fګ/:G3?}[XXX4:25]4x%#m& @pڍ8=+N w57yufФfX_bMx8=%& fw@x hsѢE96!1tc q@(}Ayy9x!(4>XVdmd;Ѓicik4O_2HIIqc؄K<K"bN<{/q5㱎&Mߔ㙌̎Lix׮]1`6YJs8%3&uA˖-6yyҭ>KĒ8Z1n[hRDZ{]]vequmzzzL@ǎi$"naɇy&U@=0r馜ٗŭ3J:F ͭwm@w2QDNpM:fkD19W~SisG( 3ϔ7qzzzz c-7,`03qm6\`7q'ZWkPYBYUTJ͵-K8=p䤨! ]O74vƛ q ᢣkSGWA&-g8ImNm1-`Ē"[\7f♌p?MhсSض$Vf"OgYY@ t?V9)HIQCF; >|7Wݕ)6NxBc\`}k5W\tizTXU*_會v[(4;jD[͘lg&]Bo5 Hweaψ6ψڷMïzz̿i|/~27"h^VYO;~G]! T4jLp;%JLӉ\-vr3rwk_IEf-Mf}*,OU=cgĦէ :_r12-@z6P4Vќt<2nRtUaT,S9Tn`' ٴBB1X p6T5ڧIh&l^I'~YJf*z]݁`hL3}8 X2k'Q _^|ETWW#++  99٩NLLĩS>9q(_7Q1Y"4DԫumЫҰy̋QFJrhUaDojm]4%8\vAR,{rgB.{"۟ _ ,aUjN\4֗g`Amr⑿/-/~lDF;`ȋŌQ5ʱjy[%lC0qpy+Ksin6.q 7:R|" {ϊ/_*U|v-t񭛖MvO^Z|OdLf,ƞy΃eC<$t9Pm"r|n8l9Ϩ=fcs958\]tЩmktJBOrt1>Wxp[q"6Ӱv=&#ekuXF}bذa1rH 2=z@.]еkWt9w9._t0,2bԦKߔID:tފtg#TD9ttCG:q21+Cyolp;%\# ^M+'4Ph\O ZO|cJ?}>+g86dOYTOycZmt b²Z[|;eys] ufh'9,?B:*KCiḀYm|MTyWB~ѣt*CUUUN1oΝO?4TXX*)) UTT8<?~qyO,+q1O9>sxݏ߽xq;=}8p^y G8p^LQxfbZލQ۝Dd/-.G]p_k ]4/vSh2ߣ/o/L9F VˈARr{WeGVGC~82IK>-\v3.GNw=sDFNx.Kܩ#zsǮη6$u%ºŋ 7s8=`1$9]\2d1Vs|+nPd5xp6qdOT ?h3f2߇tOz]Hc0yb۟mP<1O]Jqlۃ|u=e&\ܓn Kg.鏽§_GPMS,tYсf a5YmeϝQ=) \Qc}kQiaSf|͹Ds>Y/oP읏wW,{Uaay!ZJ (*9~liEn^:ҧ6#5iT Ƿޜ r'j-Tso7F- 1IJ4dթBb}n4Tyxu%~!gF_=o$-x%4=O0o|#!+]0ߜ.`Jo9Kp8ӱ6 `q0/|"$giqU#Z!'\cBWT)NLAZKZw!d^}5rSܦOy+gㇾ`ONYˆ6$sֵځՍq-mym_tp}xwy~cQeV菇d#U΁oZCR8@u[KO-$3d_O')^fLL:\{RL"0e/*R\|y.H`t?ys-ϻ2aot-O!/oҧPY?J>'اDrσ@3E3xs,19dan4EZFsEE;㹸i7qA6oŃx_9=>)> γʮ PX>z0ys:o6*#xy C(Yu0bx_m9c/Jg#Ѯ0*3u|zaC.2=_Da7TO.vF[p K>Rl^A'wK%șqB}=_,/A_W݃C1tP}-Nz=<ˣP\UyFu~{ &݇|La;=۷#uh}Q<7u2_{;rVLCxjFd˷pf `AwO%݄AǰvD+=3:z)F `D)G" |A1T ܎ DfF FEl/e_b3u%^mJ\+zurCَ0Gh ]ۋV]賕wAhxNÁ"_r*:& ͫXdڈЛ"   ]DG"i1?n:]<JKQv>.tp}b\ y)j_r-W`ѫ_UhK+bւI=c۲Y9;˙,[}ROL/ ~-gc+Mzx;&d(78ܶ 7 7c<'52ڬ(oI ôY-} ٙ0{O@=}܇ia o/憽u|ogGӧ+ :L{(ބY`XWZTA&faooq} 8?a@ G7{}YP%dl7 NuOdd._\{~y~2zƷ[|BB2:Nxٹ+ӑ1O* “.> ?׾9X1s3Rp*糲u scNie}GF$Χ6Ƭdj; 7¶9F=]Zpjb.1[Ӿu^㟶n0Qyns*U-Z #ۙ IDAT;# 6W_s=Gc}y@ϓDtkx3mв&/*ܭ ]`$4MXR1C(9ᵖ0u2ϩ,[“cr9~zpO{?œW%ugJ3 ̈<;'AWV#5rqL ?;rti]*=a7xENHn DBU9Ai9nc1f1㟈L k?//=*D[xkIJZr ɭ'O܅^Ν;رcXvWc9-1KSM~Bmt/sce8''3Min#tw~D5'#)l.~<2BkV g4LW@ D#Wo O EN E⭎nK֏E^{M9]fg qkngk/xijU?¶ʮHjSHKF5-)jeGn|fK{v15Iff4]l så$#8Fhyzͪyמ@IE)G*2Ꭻ U;v|4dd[P%:B1 f9M7qݨ$#Ƶ"#d\nѼYV}{DnIJLY<_,<πr #}2[ь+֔Loih{u1{R:暰ĥCx`glʹ;&ъwaapldGR l&OD6:N6!Z+l=`= p2ODK-7bD'jC!TBTJB[L0o_N9P\Y݄d[ьԯ_x&#H%6NxBc\`U9]=#ϻ9>WbǫQ]s/m4Q=xH|'.{7~gTBHشn?LXI|Kc5*aY~Gko~ o#{Ģfec'=%>#S-QZ;\yNti;z_bK4Ռf|Nhb/Fkai,vD_4FzqߥTIDkYC_hϣ:h {ߌ]3Ѩoֆ&RQmj#kWh;&j"H[,HoȢ_v,,9a\xˀ}a͵ocKU8hd, NsZ.г*z/b@]mԳ;=ҐJφh%7RSЂbT(^EhID E⯛阬a4hʏufeW'&K8"^rC%zP%$3oّ/cp}ds'ismy1 /c̼1ls^-6 "koyn@qٶ,pM.5YiPMMxD(-#C.1a8Z'k5╌L2Ek7G KDkZt䰣32]btws;ir;Ij Liܶ.ߍǦbEcv7m *?@zcƠ;iۀgBWz15;Aq酌3@\wJ=*d\2e)h/zxlmL/l(D+ŵw א^5ɗ oWP}GWWŠpwx{ ߚ]DoF/f"%XZPFb,h~2^i5n _O:79sPD&1,˱bt5?4t{<Om&{Xug/Lk5|Ngp[ (^?G7/żv~Hpv6†oNo-Gtl(].hD>׀6ô]iw_zAGĉnuc;)>an9]8}#2n7N Wځ6CY Lclko-Km@ʒ_ 2盠 9ziz|g/Rqɵ@"b n%rIHInAx2(n̨%%"]n|WZsWn Mj65.FфSm7׫ny\c:ӱ; YszVt<5'DR2h QF+zG}Lmicdan46JZXsEEw\QU&k,}lgn@qζ hHgoILB9:E OLuZg,^mDMFІ ]ikӴ`^}wbd\k:\FIl@9HK)|&C! QU y8@"~ĵ^ Xwbɋ g22;4 O7Qvs=Lo ~wd\k:cݹ(U2V8gtu͌NMBe` gJ MwOByk ~] .aҍ7y"ӬZw 1M5{i\05@X?#Ln Vo/E3ϫ /[}p%PMS So8AQV:~-,A{1vXl*idC=yLyLs9A ]`"G ;~< wV$ Oi~jv޼L6?t׆m9z^Ftsm=2o#^5Vj$%PlYR~Z}~XҏC7z)y^Vh.t"x'#1ZaXڤzzl@a|}[`$OE:m*<De ՅyҷK6-\:m8)0҈%;%X9 7=/[#:.~6%&]B}RsNnk1sEEE:5ss=w7AbӯsZ8zСcogӵC&tˠKj:,ZfDRpX{Z#ze3ڃѓH%l(‘#'l`[;1w94+}c b.=ڍ܅ "eҞ;#9ߘ*Tl So&Ek4 FrNH,\ƛ'Ә;gȘNVL!1c&c}HOg7}r Cz9-pHœk@R<ᣝUJ)KF_xNY$"X@.@ ?vSЎ6\vO%~iQz;?_ph(bt*uZӜxc&"_Gq4q 3M_lm=`=`=x }QVFJxzҶ똭arnsݔddgm"oZO`_4a6M*l@:,&n5vUҦ q ᢣkSG,l=`=`=`=H1 OF+MMDP1\a(8T%wmמ@IE)G*2ᎫnNb=`=`=yE=hw4ϙt$\'<1.ȋq\7hhR u;ztq)gXXX&1ٌ7->D^̈3-/4 3.^'^UrwFVZ{$HB&OD6xx%rխmzzzL_74Od vkˋk2҆:1^- ̷~t-]~WJx5kNMc5޲3 \N߅rxdS3"kt07)2f=ecMFҨY{Eg}OT~J\okG8޷W]C $!%@%(*- jo[[ת"*> X RG A; o3'=9 97s6.s:|lٴmԻ/Rc7y7Z{g"`s+ՉD .ش |*GD" ?ᬩs?kG&6qGμIs^Ӯ1|sm"ԓ<Yg\.9,.!SOL"lɖh|>u9S߇ ;gHN{ttuߍ?oi: d8m 8:ŁZֲ ߅ǿF0]9R'}-;;ܔ ?UX'~;q^*.E~﷿VPkg_"vI9ފ0T;!c(SHG':`׺bܹCuH(w=6  ҍq-5V=Z`ɜoxU t]:Z*œCІt-%h!v6][ή'}MgHc\2Я] <|!7_n<%֮(kЮk \P/?݃+O1?zN(qn{rįiTO4g7~}E?MC}0qO3qeXknL#׷ C,r= ^ہ|) \9w5<:Ԡ_Z$-%i>OoJk5(XiBdeWMN; p,5pέ.,\sCB\^zc1\riۀ\mhawŸx.ߐ+{M&.s8"c>{rVSLlvT6B>>[1j J>?t]{n뎟+' [ߞ;[~8n, opvD/ =S꯴j^.c_{p۱N XLEįڅ[#c鏠j!|^R%xGAx-1x`gb!޽Lc/x^[;ǯ/9䲳pOjp>M=IJ>yqz#Z˹0w+\vv gδnSہ/~jwź2ڶ+]d/ұa{fZ8 ss}2o?#|bvD*h%#XP2#f,;J5{;c [O^%8WLGaȉdxW*Dtnnkg;p៷k+[%[iDr{n'(S-F~a-vOD|hK'ǰΣҪȷu[tXR?EuL+h|9;g̼xsGY'WhRݺ4W}TdvZE5dtV518';/JBZԞwfB!XCr~]I+|EqC -hTtԷKq2/{pSouN-Oi> 􊻾p'OD,f$>}(_'ͽd]%85bZ\ NCZ=K4S,vUįrp"?|0BDuX[{u[֚X_lYӚuaMᵰRq a5(X{uw3W]Rwf5+ ʨԒx'~IR#ogq$Ɵ'wlp5m@/ܫv(}JU1 7?1"L,-mrI-O}^QWdaYt\ڡoA'#S8ll(+_cXz&nݺ퀷&w:՛$dkIzNlXtr<*jBJVSˏ# *Yad?&gbbn5nh'c&YhnMC N48J4V %eG!tIDRDUc(pϛ`#"] |۷OOKGυеPHRmV8B=˿"NG#p}:nplˁD=Y/čZbVxgxVNVCja0tpЧR?S|ӆ JXW,2~:\SK2Nn׵(c2ZMSV~cMk[1U]zvA ) ֔g% ڑ8qpk99ڶCUCRQF'/kک?g[ :0Ux~jQsSv~g0U݇}~QW'hzmSl[D`X͋u&.\i팼cA4xu  D+7Il [|Pմ"ٴsr/LI0$_u1oኽ|y,*+ yHgZ sIE{qD7;%d"Q%]g#뽝 97{uik?Og|;$^ϳ1Ak}Bwc{6Ėe6,+܌ԘN]]qN5ji; q@W!ÍT}`Hǟ܌nwiɱGw3Go:kn'cJ/ZëO!o S*.ݨH,j]=!H_'GSqx/htF*]/~Yx%ֿc;:*ï8 7SOWv9芹K/Wȧ X4 xM1FR+E%oGwgޓ!cA`{kقc_ɾڭ#:ܩSxqIQp>moE1A1*3~8[ӆVç-ӹ}i|*$OS^:P9(.ƒcV+'BGIJm9+1)GV99/3,X = %"55Q9i~9Eo<^1GW@Wwp1`cxp ܻ)T'.s&8{[.y`)7,8akW|SQ!`8-5Nxt.t 㶂vdzj6 z[' rƀ[ ό8ǡs]~dOU?6L+1t;=ڎMţ7 @smU~9- kQpf \2Ԧs Fя?FcVё 9hm)Cm*;7Ĥl__:X|/M؈[JPS RWLYOކgߋ-e܇P"?zzehz~4yhB 5f9DMkօUdV^ +uXPhL|Deܿ%]gLνY;daWѪ V-BDtNQ0}h56,*Q=i@qgp"8or$OrH76svLLU0V> ??(x ?>42;!ɼM[)Ihսߨ.ɰ}rft:ctmxB \9N_#Q^58IhLuߣ_KAe#-p$0NIG \{%<&z1ʬ}o\A'@\;Ir"N߻ĂF^L'iUD>x!Le_s|EX^ZA~NA=&1M-wP c4ЃB):ft ttʀs٩N~Qd>W^;/"0(C ?0'g+Ȩ~T(pBNdCrd}NUtpF%x(GT1T.igcm%oA'WWAHN\.~`fEe:! uye(Xt6<2'կ7߶YHpm}znoFiЎn|UNWGb̔U(X?ڱLݎ&ݓut,_Ѹ1rxZU[zu9uuӸwb#|znu=nu}7NO7Cz O5 h{˰.QC)8M4ޤ"ʿ;Nм ۷N>/Mk?^$uoz ɟkikk׮ŢE`cXO &1u]R6ηWLP' 1:^NԠcU_w<5l!i?}xߊR5z|`\<:nl  o]N{1=Ξ3@ M-~ؠ֍nLIr@c-x:y2)\6ː96y ǚ_Z4!S+eLבO_A\afntG|KMWY Y9&3cʐQHVszsj@쭶nhdk3/ι! Ό8יulZ9.HYPS+^$+"֣wPeUHM@d=m˄R.+8Fiiⓒ}:y9}!͕6;橊Y(O?MGG?x頼qtPO7k l tr~\ 9evyͫ\gRe1^`984:@VG%H,xug Y| ymMj12U#C*>VW]19Lpb5:oBǛᚰo)<%CÄlHɺVJ)={~uD!vzU5G-xms`xlvYyB#䲆£sGYjjoc~ZV /sF+)[<]5 [\fQ4J`, p2xۨTtMVBpќk1T 5N2(iW 'uB/4RՀՀՀ@5m5miY 7HNB[/teBDڙAh  mE&6YB8…it^x/~ݖM~]lE.Kl5`5pi :ms5S3&Y/eIf%=RWdA\/~lՀՀՀ_2e5>]؊32;ԂJ$AKY8wJS IDATa\/lU'cp={#?jFUcsq>|oFYlӧӂwSww5N,醓r\eE4iBoƒ#! I9aц7`aJD!=lSH7ue`n8JMXs g d hG㫲G((]) cRM$I[mHPä8|?x@"̻M ?jj,82HE +#݁5N +x Ez6lp=ߊvGo/Tċ \^.} PE'J ;AOj?K.)<<-|<*@g0]>/utM֚X_T5*GkaN7*z׋Vp~S1 3މ`Ks-!%`ᰵc^x}(1FS7$ցS0Q2՞>XۛgLJyh2lEqI' -BqCe_SjOmcF˘f4)oNgJPu2 M#sK{fp>Y1Kz?9LI\#\Z'^gW*\F9Np9*z 'zA8^+,z/G RrW7$ 7 Np=8H uAۺg~:H|NpC:;SpV[#ﱗ=׉/, 7-AQ ='뵓z׏/J/^׌Tw_p> \/+sp=^zǿ-(^˔`k3(ἒ>dcGp!3L'bF!-s ƛ<22zb]bZ٪JVEV E[ytcmt-p&-;u@(Ny h{˰.GEM1vF")uϼfY ;#}u+H%ȻPV6ŕE t?zP9$ \:(eTaoĞPw؀a0iAϨ~ötjijj^xuvF"JұIYro.)bƷfk6Z=ɩ\oOj[0 =T䆎OHAPxO?w)8nQ/^0;nL! wQ7:&ŝ{m7DZgd g#-Τ7LԔz~9 /}lp=}Rt뽩蕙|:mJ} uazy:$ 뉷IVڴxj? 7L鼭#zIÆyܶwPxdt_bKEq$,-׀xm5CtnFb6svb܄989xYy˂7v;}_KzΪqOqڼjW\chVyƸotm;HkOyw\ɗ+nQP q-hPPqj3m pd5X/kQ2۲SJb6aiG62 ,Q^ zoqrBeiNI s%JyKjjBpw8=#$s|t:qY`)lǝَO: 9ȓnVpliM̢dH&N$)^hiث hMְh[[^8w9KNLp4zaY X eN\ FԎIgK=i#uFҨ{ g~OTYà װ,Հims.lFjANpˠ,tt}D ,Հm4]qMuF^ *8Y e 'u6^D:)Oz'PVM@(l{,<p m^mk:p6 k4DTÍu@v}|lj& kP~7DFԕQ!`8-5Nxt.tl-zM/^xq~8ĕ|ܬ;pזw1FR3P|ycTiƂ'@lkM{Ygo҄,7ueqSxiٖoևUlp,h{ OGH؎_:R(y硯4>e`.x0W!~k,GvR ZjhcM+u,YǸ&tFU'48lpr'#ZRC 9hm)Cm*;N"ލ󷠶 ό8NIKRk٘]+T˶j5-úl:]5LEPSxM4yͲvn\/rvaTLTںw1եKV$掹#j R x[mC'Pmg$Bk4, %7fYmpHuu뼃1Mv;ޒ '!qcXO12 GPD!B N'j4 Vl 7ԯ7DZgd g#-Τ7LԔz ayh1bQ>_~藝dR}gMxfӄX]`Jj՞}8X'd5p\4eo5^l έA4™e-\`7˚O`rӺ@w[m2}Su{pI0zO ? y }ZDsh@ٶuNͲ#b6svb\`.yz7s(gWދ=@9yvz<*Q6)!~ry\Eڠ_$^9m'*@}qOFڣj$ ǛOq=ߊz8ioo֙Zjz,^Ϩe\B?MQkHͫD-6Ҿ,@pPy>B9A Ne^hlsk jd>n8.>^[iPBx~ӰWo5`5`5`54 ukEia8pZ3«*!M~/:PW0,4f/&Y/e/~>ZL:s  0 [UjjԀ {iER'8eR:p>b׋XejjԀ^vZnn:#N,醓s\/bYSliͲhWMuFiuc!StnualpQ5V>G.Ϫ]̖jjրM4DF FͱhVҤɍw:[?o9XY꩒FV㝫o|K\bQV h"BrꦮDhm`gaaOzΈˑ?< / +}|:`3_܎j8$QN ]KFm9XBlo3l_QX4WF`20ƛ‡v4"Odp-fx>|R,~n%N0x?o+8c-/cN]ޘ}O&XWd%3ѕ|*O1&> R]ބvs`c6\ss\hVMՀxm5}k:rkIpfYXͲXhq.JʎbgC蒖I[s(,ǶQVQ{0%Ōg@1/X< {!}WH3Ī(UKSJC4 i22+V!{~(~p\Z#O LDuIU. Gz&:Mw)H[Ǫ2g-)9 > Lŵ` n흂@]R@pً&BɄAP$jʮՉ˥s30,KQJ@>u9gܦX X D&uNͲnƬ v+ M]6ܔz~9 /}vLAPp/^Hϭ1L\۟$^^Y)Gcґ#6>pk9o}s V5pM*n9?J=?snG3gI X2!(G&Lܩ$6if +|]Jd2&f;}0yz\(|( ʟч%MG;(i@ǰ4 [zM'86ݟ&ZʫO`KVVj@o(z&ypҦ/sw+B3 ݂Ah5Ij7ƓB [JP߮h@쯛Nd vk 'Rgzubu[6u]Ñl50QW2^(tk894J9ά2{h$/!ܧPJP̂VVVVQЀ {i<"$HY8wF6^fN/ heVk3MPI1.n8kTn5Jmjj@(l{,bU'4AySvnXk []8\/lUYBSn6Yp^N!Z6:@C9 ^t[ #mpUfjkkctx:G`lkM{Ygvo҄,GNLqf&YVT.osbCL ?d\} ,Y"h4,Ήc8I7,aJf1)+#SP‡v4"Oz~"_S8|?x@(|FD ae'/u#j[ X q,󩩩 İ .J |5Yhc5xQ=Ճ뭇/^2 QF[:<.8QC؋{VW eBv([&05 +q2{)80̴«mr/~7 \WF"J"IYro.t'P'QX j>j\ͻ%_".ٳEYlhN Ӊ 8.a\Zh\x5C{m#^cVFfgf;A0Mz4QKOp=Ѫmٷv!LѺg69 n;v@7"!L8Z@t5[saG$pӎ\~j ߍqFZPևY:XͲXhq~zRK`/wU3e ֏vV7%w'Sp=~[td>NڦgRܾL Ϸ0W-Y D]xsȑ6'!Q\\8m6FP5N/h" ^`3g'8MX1auLO$?H&'t\?RZ?ȟlpnP{Mֆmjj@kw;"gUԪU+n*IVCU6ߡU}Fzwnmԩ=[O?z:(OÂc~v:3\6aƹ3$6$nK$I3?'Ӱolp;;&R0?/Jmh~ IKKC˖-;[p*WF:tZjDƪMְ0N`p!y"uFZ0ݡW'&ދ_a_Yjjj[dzr?_%%%S;^)ӧ묈R#S(+uj{ά2{FꌤQ3 BC+2 Z X X |4 [uYYYhӦWJCeNk|(E5͑Ҿ$AKY8wz [ X X |5_ɗscǎtq^vZnbi~zW\SWF^ *8Y e 'umpF2Z X 4q[v)))DCwL͜Bds,H; p,5pέ." ,ՀqҀv6%;$v>'NHW3f՝v: z7"ͱhVXܨk,Հ@3k 9t| H 7XlkM{Ygo҄,G» L7*zaY X ` #b16l؀?A**"{̰QQmP5&c)|:iB.Y땯 H$9ca?DCĂZR1ӟ'5{ʉn&o#2˦E{ed -=k:]kǧM]&t݈;eX6_YBWwFZK.uVF۲e VXaÆ9$zy{[mCu'Pmg$Bk4, %7fY9^ *pxv͛O|q:&G*"2>C %VVw@/OW^y_|wGͬ/fk?z5 IDATqY!벆ލ_7wpռQ%LV*E Z Ыc߾}F{a꫸[Y04fki5[Yڋ8o323Z-Bo5B#sqG vߊRٮ3&ގY0悫hTuB":un]ķ9]#n2X X tcԨQN؈={8guBD-5n0iY6 " v+ M]ܬHަuW NDŽ!/`GXY"FbEƬePntfYf7[[a3 t{v4 Sil84ʶcJ>BGIG2()kNp\XFM9$Ɔ-^cشsr/BC2$Q>0y-ՀՀq@8մɦ}fqp2 _ :#"5 B4 { )nGd|Fz:8%Ë7/FhuMְ0N`p!y"uFZ0ݡW'&ދ_a_E z iN pq_q*\AСCpCsa&B_6WܥИݛtfߓ6Rg$^xJ5_Yjjjۧ!#u/̯8,"mk˰PtaͯtZP Nrs7ՀՀՀ@h@_/;-x7 4[+ȫS7A'9 ,BVVVVͣHlr$AiM`n8JMXsgE2`5`5pzh@lɂ ^ tz8-5Nxt.t(k,Հ=׬3o҄,G» L7.zaZ X Hh>$^sJp>X.hM5:bv߂ܫFX0SPu2M#s\/bYqDenn.-[{뾔OhM52moe7m ̎cM4ޤ3 l녥&Kd5`5p4 rK׭ZE뜿-NK補W6Zpnm.+#Z a@,7Bvn녭*Kh5`5p5? %KYYY4hP95C{mn0GB_Ƭ2w 2a.fi8׻v[{?ǧlo7[ WR?HC\]eq&?̾/?$޴16 ?^Ee10k^_ʋ{7B/(̈s|}XA0mKjKVTjjۭѣ~_sv@zz5ab&m,toqgՉ\hz,<:F\/.\OVo 9ޏ{5Npgtj!\+"D.^| 3*^uqrĴT>r'_7a6-sp?CzN /IB:'#Plxd:OB}w(F*zq9rxZU[zUJojjjv2T/'$x ) G0DnZ%hNp\XFMODp8EFd( }ބg2+0;)*=.eT g`ŝwLMe85 *9#vF±M6#fM"uF,X8ҽhziXE y+^*|uQGgcqɁixWxpg@^%_-Kg"kP&w򥙫J0]a3SRTdSYY >|GunY1O#_7]:m5,4ح-/\HHLwՉmiu;]˪2$'Cԧ Nt=CO=UIHNSלҲ*'%CUE4NKl5`5z+߿eeeN<#v@.e˖NX ;"mD eN\ swBcvmҙRf~O:k(˽s/B)B+:p޼yΒ/Z||SOTO ? Y1nGuXjjjO6¼Ű*nmnymN% ,x90#J.9;Ç׹g)͐s>u ߙ3.ק -gdv&$AKY0ڵ3!dO wƚojc<>/jq8RN& J[{o+ctñM\J1%έIqR(΃svl2o}3@ZZZmIpbzqF\8sK|,g<'$M5LZ7 \SWn NruYtI]Ȝ'Ynݜ':f_`CI{$NG6Hnk&KOzz'#.&ΗӬBm OLD,54y o,1[}ĖWn"+ǚ}ڔQ .eGE[mжM<Q Ē&ahSE+~ZZc ;:.8{ʪaTK兩#UGb){D3עmrs?}]y[-TH>oq}֭_II ۋC.]8ގ5j@Ga m>L,)ʬ?Aeb]:a1ꨚ53xd8Fp I$??~A7$$ mKrF-ÅL5ZtN7wB-Q|KzϳqKwOtޫbdqt,j*Q59xmm;b8RgĎ&#/=F$߰a?9lqfx m>Ϙc'9I[Mtt#;*ڧ&jogC7ZS!GD~UU,/C\Q8U(6|uC}V8ɖ΁| ?ugϞ ;37<;PIbĉΡ|֜'﵅$M+bi-8܋ߍ6mg$Bk4,%7fY<*?J Юν3G=|Y WJ "##gƖ-[<+&31^;ͬ,pY\>)[m5ܐh }θ,uY\/|Me_#c7H#j*)Uתu+HR+ 5䤨?ri;}CxiI|9;8n[us8_Uqv4h;GIȊ)wg$N##iH = 8#ny8}{~;XJ`ũT1Ca9B+c(s,0 H4^l 3s+K{qFpfY XͲXh`='F buODKwL;ڽ>GEK /Z%1=->ڝsx_ Y~?;Eh[WMMHWSYqH>t;|X3p5g>qHxKO>m:· / ?p[]z饸k$r˶ rFbYE: ^\74,6#㌼: v+ M] 33O /_~%AvzIfn!ѽޡMBބvKbBr:1$R=YEU^)Ul8*rF|WӇB| ;y{8^@^8^|O߾} ZxNm۶ 83s[VUBr/$jMg$ج3<87\؃%䩈'q%j"?)BPh) twTWviI@ ? 7K[&ҹԻ2jIvf9?)m ~#n>BGIG2()kNp\XF<sI|{Lbf8u>}2$I|6Y X ? .ڹ];tYY}藅vTfc/t8}̉yKcG_JgϞʈx2rkÍ$R'7fcܘFd Hn83`3b!X 4NÚ/,8,ǨJ*[8Gl2xKvF|6OTNWSNjj4|;$SbC8q* ^}qF̟Fۍ]eck`IӍiXh'[[^<:#-ЫůҰɯ8&@E1xem-RDz6!gWEZ X X p@ۄqz[mC5'Pmg$Bk4, %7fY\;9õ"N! G{4bopC1$k6ٙYdP&e,3MVVVV׀b㌴*է(Лe'H9D=ۘՀՀI6 :7˂86\тjͲ<M ys Z?;g$bߜKCƈl@͑Xt+0t\xFp8Sgv$Vak@췶&,4a7 a4J`,nHJH%:5GM1Z]?I=\颁\gʥ$D}0ܽx舰ΨɗHnpYz4:|1>nZ.Z(P}o6]R%tZ8zrTcjӾggiB'SqJ4N51s1wǭdpn8r p3X]LMxy5d[ ﵀\5.zϽVb3fPW.t7r'sۡKvเNq?S#~Y&staJj~8U'$ufX2~fPG˗8ca6,گ`?Fo~>y'+.Ѭ}Df#'p G6x ҭK>y NJ+q_7O4ˀ5X<ĺs'Ĺ_χ@?;3=pø:nOsls&TP?͞^_Q:Xq!4ޭ-/Gꌼ{ GHߋA|5[s;xW ,ͻpL^J{=O#ƩW᳕sQv(J_lG$vøg{V࿇u6QX3|kSdUَ+V1ۛJ# EX ,{a8l g}᳋x!g;ny;]y<}C] k?)Dckw≜QXgo-BX*˰/W_w@J4 IDk ː"HX4CPaQT( :12(0.㠂(,LNBIwS}u\>|{9^Uw^Rf_\:oHi̙@F9s/|8;4=r祟+^59$0.$`-_>"<_ NBLU29r˼ϗET'~\}3NYo*W8O1c̝}M|;Sڗp5$ pCcq֝.2}NysGw' .;Q:di;/W"/@v}\> ]ͤy|Z?dytFxN[ḽdɒYW1Sdc9GR SseusD 2C1vY/j;gܜp?' ._:8;*lt?/}jd1g㬟vc IDAT*?Qjŋ@^>ķeo^XE#O]wܺ u! b)#o njͷe7^z#+`b(C S"ߘ}L?DdhFVێnFLsrݓτ)Pa0^[) dGKv ӭ3\#SCqzE13[]x+ϱʔ9V﷏2y.7ʓ˟DzC1ǛUJʏBcSs s;C qߛ?Gm4^#b/32tN,](^dy(Id3Nl 9ٛp2\)O/Lsny-t3GJe@K.`cs&|#]xV1%[P.j|CqIwȶrW:dII)[Sb恋y]Ƅ}-Ƈc|m|9d$Yq )Z$gN=N^=<9w sB]}d^l9 3${Af?ֆ>V-T:WN{g¨PWoL GI>B{uYa׮SdXgY1\Ȗ/ÎG}Mz\v\uYywˡېJS$DŽMk,;"|2@6MSwv0ma)cdu2s[d :0sV&39}&5tfy[+Go&(Y8WY)*3G"c{i8W0W.w)LVk"G~m\vrܓN Wp F=s`86WW;#Rw6;c@T&^/?bަMk_l(|msF_SrmϺ~_V #/k»0 yd(8qLmtrOrN9_&G0W+]q"Keѳݲ;+;J&tFQOnOXWKoex_?C&o!vO.)Ĝ"G6^gs!;{GM.}%z?ʹB=ʈm߮ت K=n{xI`,6S5#(=ҥ2tAr?*ϑ$[z:޶p1tSҹs8y0nsՅsL01q $f 8]2; ItyYx饲s|Գ톥υB ͷZl|p#!|p.lZMz[hDs^E!K$Ü买p>K?6zyruK9Z,vy#Fj2bcj3ҋ6ðy:?vPº+S/+p1\ٶ={|iF*.:SƗ&O^#/,aΝ/g^tdvmiK'˧÷^{>9wrInP@N=8wʸdngQ>vW]jHYd8z2/ˎ}Ȧn1ϗʌ  ]m'}229d2 6؎r'Sed ٗ@<=Zs,?L>rGsIVq{=aĸEe8"9ϕiaS?{es9^ vn0c\r3ŌgI8dق#bSrƌJ@Ϝ- xK Igzg_}L}9ne~#+ozxdaϑkBɿ]ygyL 'S|xO׆;C#~l#ps 2;\d9~UqWXkuM&"U\OFqV:N#tFݗ-[nP-Jm;}ǬOVI/0,[j*]=|h Mtf-?\ /mhӮW,.4׳JVu kU2oͺ 3F+|-l&*۴U>g99p_I ]gGBxՅ~nSpIGN\:O{>w\_'Ztqc蝿Sfz5\fH$ "\)mZ[Gw_>;|հ"778M[8gMzd=rק+*txU{YBz>_=O 7R/0-z.Dr75:k4>b" qVګ!lTO0b,(o[vE5/g`ca \}K '\ + \J'vuW=jHhP{C~ }:N4Xk3鍨}2c$ V>F?62F36&S~X͈֛:78ڔ6rҤII;gx0Qz6oʹ 8@j\lXt\nxyMnz>qꌷΣ.gpg@\ܘ8[xòfZDo1zZѲHwpgqXuM^ fčb[bs9 8΀3PZ~Y)o2A֛lg m΀3 83Pښl3vø"k0F6ڌ6Q32是14WgpJd76隬uh,6W c~h3Jm"Swgg ҧk13c*6i3͈ZZ$#= 8΀3BOi뜦W/ G@q1L]wgtMi?ڌR6JBFKgpaHVn0lΏmq1c΀3 80Zk2 Ħ6DA#1}`5-1םgpec]Ϯc]f3 ҧz3 8@9 &Cg>ƴ$m>1\:΀3 πеm47j7Oȵ6s 8΀3P.zktފfMMi 36ŭ8΀3 82zkzqQ3nXHoJxk#Ƈ3 8@ u:vbv;nY[oFo:㭭3Kgp`3573&ްlgި6s,]wgho]sSz(qzq]踘iFvs֛xk<ꌡpgyX u͍c7,iFE7u-xםgpg[ܔ2lF8*Y91,6c΀3 8ȫEw/q!m9xv 8΀3:Ejɶ>c1+ckd(o5+CoӺJspgDXcSjZgbs0G6&RX<\m~*qgp|/}j33Ʈb㬟v*?7ڌ8ER8@^݃΀3 81k.Tָiz݀(}(yôugpa@T&ہΏX(hl(!katgɍmX æf9 8΀3P&KHlj*j3N1F\cђqspg\Pkm=: e6#ݼ,}on;΀3 j21thNlcLKr Q|< C̥3 8@ z ]۶h_i;)Msv:N4\ks>΀3 82F筘˩nFܴޔֹ0hSZڌs 8΀3P.fkj̯7ӌ欍6b|8΀3 @j\lc7:.f7fݜfƩ3::chtgh_;q]sc:om fQjqj~k3G"1:ugp`577>{27΃-o}FN 3 8@qjk]d5rlF\E[o>b31]:΀3 @jkE h3DЛcƴ\ug(ؔڧk\)Q("OG7@spg KŽ8망6#Njej"o3 8@k =U5s^fd77J1JmA0wpg``7Uvc(j3J-(1Jl&c}.gpFjr#n[mFi6ð):?Y|9΀3 kR+4ڌEosd\wg(Z[u>Bv.h77K[΀3 80z 5Ӓf<Hs 8΀3P>B׶m>WNnFvܨݼ>#ڜϥ3 8@ ꭮y+rVMMi06ŭ͸pg 뭮ZO&:H||4#l'׶3%9qĖ=p8p5kb6kX6snzzomG1]:΀3 4믝1q̷6e3(8cFe3 8@ ~뚛@F͈AŖ>k#'rpg8yH.Re6#.ă7G1.gpZgHm5g"qwE`llmfbe1_cZWi:΀3 olJ5YXlfDj O9 8΀3@^O\cfUlNgF'2H G~˷{ppg5tͅ9M^V3%6 c 8΀300 c;1km%6|ms1>΀3 8@#5_w6#4baq,b>ǜgpaVdbMQ[mFՉ7F\ck9Z2Nc;΀3 jǺZ]]Z_!fdכOcmgpr@Mf=m}iId3|ctg(]ok6+m'e7#inn^iƑkmpg\RVSy9U_͈֛:fmJ[q.gpeVl[fݜޔFgpH[뚭uFwL3ތ8u[[Qg m΀3 83kg knLgMaL3J-7QomhY$Fǻ 8΀38ߺg/Qf3yPȉasg(@^m-RFn~͈ hG 6u3Kgp(R[mMa]5[#mFyXzsטU΀3 8%2RtM:c4+1?o6ZhSq;΀3 3W5W똙1vgSfIL-‘_vgh]suNӫՌF#F8;΀3 4t~ZmFEc%F !_d ϥ3 80HMnm{݈4baΏĸ%?ܿyvnL!nl n:.7] l TWΞpG|z|bA,22[oAט,q1GKi%}ahB^qr;'N9F營nGN[0|ro+<,[L^{ gN "l?^ɘ1c4[EZU+7yѲNwxrt&qrO /W?>}rXv׿Ef9]wU6trxβrJy[nnA<@9cd1K~r\t"2d [J}oJ]-2٪W%ʂEw>.'.g15Kưa2"Z+FRnZyvnIQV L2E~?Clrz>3tZN6iD6}Z^Ե /k:bs(""7 (Q IDAT"hHÇCw.9;ɸq[V|K5[@~#55ҲAprmkX>J,^*m%vV c=ereaSwͷ㖪s/$+_]-#7d1ӽek֬뮻NgzU횬p :$TV>%'MϦԬߊQӌB#_fuBö{_/Ї%_+C+m'_Z+ÇZٗ~SK5!?O+oKū=#|9^k2=B@,QrOs|X  ʚʠ-7P{ K::Z-$h\l55iFvsxk<ꌡݰrp~sNE+ /Rǟ~>[xwMC|š|瞓#<2{ό{ehxw?8|ޱIV=]f}k%[H{efdaGdMJ] 𶻫+{8nn͛7/x 7v\2z]enU妃eLx agOF|I>1eŢ/|L2N^ 7օ[b7~^.r/N pU|G[V_-]S2j-{I_N= u͍ӸffZLo1<@Zh_!M3^! Nw{,}R.^Xw.\η۠"7 _*}2ЌM0vs<|/;rb+VwmPxb%3J{d7O'3/=dLyq#VeKnO.r?'_|5<fO7Tg_bxD(y!Ǜm k3 ;(qy>k cX.Zj,k?Vi]NUw'cDJW^q rD!sbJ?9d̓V9@\XCɉ߿S~VrEȌ14/˿$׭rry{ɿ}X>яW&8Z^z~t/~ǷSG>iwg"m ڤ-;;hU ;8nq542|Æсo9.;Ȱ&#nk$ʱu6e78Vƍ Q4G\z.F3'eٷ˄q:R%5M=dHbш6ZZJ^m-R,Fn~䥖_Ƀb}`SgfM9 AhL:sxG g?L^ 0W;B{n3:ύC/fvЈ#ī#68^.\u h+c?!R~tWd伛zd~q4\ ȤmdtЃ%b<(44=|ưJ\t=Y[9o>$ kgΔs9ooÕQ%7eBFƃ/`4yN4܎ C Qx ̍/[m @W{Nmշ^xlaX|l.__)e9Se'gF\-37`+G\!u+4Y7 ܢYc}&k1Ja96#1`j\ZWHߚ['egm8fpEZ:\*y~KnRtЀ;n%3NیXl[רD'd{|`5;oKKEN\>򧋿ޞ+#t=lVۦÄ3)W|`(y2j!]OrQmЌz[>58(>l*ϜƏ풕kֆ/b!-ttxS5%ʈU]&2˷֛2rz^2ry F\2j~Wχw|MW5W`1gmqR+SLOnJM~w>(SlчOC^,n6z`E _k]bE< ǢRCf~I g:=,G|fL>i//;.??›j֝A=oɵ:U+Y>C]# ] N[:wݕ\T6"H~6oYq] WGdʯD6X[t-="C9@3 C|q؄>XC=Mg(@ٳWSЌ~)9\u7 k_ |}UڞJK/ɧ%: 3 qV0HWnVt)`go{%l@ q93|wOu?;CBӅAmr/O|pz |f`ժUrwgf;lX DY~Eyq V0:mWWGHlYZw /fykX/|xp"TSxUs>\uUP04 O>ꐰSgſbLQ‡|m3>װ׷z˧^w?HWr|t֡5xW{_'c鍨kJhv{Ln+hFge˾T]}hhDV{X>ў"N> 8ÕnρK7;pk]?*7/U=Zb*/R_ԍntVfr2όV+nwڙq ȫamT|'[=:}~aqos*.+h!ѡe ^o|ovkoie׺_xey_ɤ-_N͸7^L,šn:bSsTX3FiuޒN~#ne)^&2_^CʪUk;p8(׆?|7"Hzꩧdm}W1ܶB"I•ҥK;o=3u/g>lvK,{OmwAokbsmlQ۽˖>"ѯ^s۳>v3V(px[Fnӡ1ݪá L7 `h.tׄWg֔o]'Ov|xoݸ^ˎo)t|l@ {?PTQhGB~ޖ;s e\yK`xi ~$nHt_Q/w/zDnQ_Gx6Jx=!Cldo |< m~p|F4P~)zhB# |AM NtFc:͈ R7!`x H-7#26JCiom=G:mB&OA^zDwiVo"^x⅋ϒpUby3\AoXXQ\|gܽA#UouZ*?/+qzSZŒMiqk35%J򍚄 |QYן7Szkl6AY6b|8΀3 @j 4#QPemM>@ꌷΣ.gpg@\ܘ8[xòfZDo1zZѲHwpgqXuM^ fčb[bs9 8΀3PGyyH3 8@/kW^y|c#'tյV7X}_p<m:n.hMiaç6> 8΀3ÀnD&BuR7,#6vJ2?oIEB9 ,6qp,^όpZ  6%:hŸH>R~tuH΀3 8) ؈gFAjt 9Qό$Ey:%|hz#Ƈ3 8@Ј9餓FژL*j)uf*0y%e+#(mAbz1_젙X{ϒ>΀3 8 Ul8zWo|am5h3I5O ~nVBO=0pg0 ,^B2)Qu,}V2ڍ4FXc΀3 l Vu]Wxl#;XS)Càv$ KIx#IE&#N$%t΀3 8 "7WK]^Y~';JC;W#ӁQRVb*mٲe gp?Dz8fÂ:|ٔhW=~X[1Q3 &&g#iS:F\??}l N[x n\♂sCf>d3n sQ<* $<`3:}1krz| :m[̡ĚQ٤Eua80\`0D,1c8g.mHն |Rlaϯ0is^?8F1A81lPC壟T01?uak ڏX<>Wp~`hL[ʁu(Q21u,}elhCb Z/<mFX^un6a8:l8A0 3VKa;:XbV<1?1~ȝ唱Ο: {7GL?XzI R?2nX?3̍oqc蓚hLggG&)3z`C |A}Z"p^ut 6|,ҹUfY1#Fl*D W2A?F'đXHt[ Q'08R1gI*vR6ҌD8}EƒE8DPCc |x܌Dsj[c'CF^Ly y7?b`.\  skt TObZ1i:q>󆶟?qU[CdYqn=k ]?K?t6VyiW N?pbKf~nR?c} 7\4&Y[58tFfhbc㭌0G;oe,6<ڱx+c1ю0[a6v,61Xl yc1Vbcͣa2lXl cfh3u:mhS1h}Z ycpHROs`G3 s!b47qK C>h#9z1~1ysx}U7n8M~Joxu-zZUzJfS/$(t*!16 fA5C?uX┘1!9o̧k K_yk1y?Ql`xFu~{ʈs1FO2LUbU#6#&`RX.@14NGlhh38cChuN\ k@%F~,6<֟cl^L+ qs?0w}`Pj56A=&˱sֱ”յsh?0؅Gf u,\8}lAYt>F98A:F;~4򊩍ݘ_?8v}uJbA.6㙋ssgq1L'hb,ɍ8eQq^CA~L@?t 0v 8d5klJhqu`9 }u"WFvlC/ <7%cou͆Dg‡A88@F 0>9ՕȃG91q\`1>`kT6y6uJ⹲h3¤,m 0HL7"CGl6-f>·bd,60Ϗ3*ųc׏1bͣa2lXl cfhX18c #6=׉I`z (ڌDXo ?m~Xc͆kCaSj|=ވ0x EԼ_xJΟױs^|1a|06b1bQxOIk =60GCf8ɠ} pRG0ts=À:q|́Oݎ<cb|_a -mؼ4 bԭD>b8n}2/&9b|_a DCOn“*mwb?|Y;?zqx[p̧OK#668u,tOVj~Rjưqڮ:6uk;X.b1Z1yz^<]h=/GtuLs}:G:&O9Z>uhѺurOh]:Gy9ڧsct9Z1yz,~;I1:6c9ѯeJ.8F M: 4.0.0 org.testng testng-test TestNG 1.0-SNAPSHOT TestNG test. http://testng.org Apache License, Version 2.0 http://apache.org/licenses/LICENSE-2.0 scm:svn:http://testng.googlecode.com/svn/trunk/ scm:svn:http://testng.googlecode.com/svn/trunk/ http://testng.googlecode.com/svn/trunk org.sonatype.oss oss-parent 3 6.8.22-SNAPSHOT org.apache.ant ant 1.7.0 true junit junit 4.10 org.beanshell bsh 2.0b4 provided com.google.inject guice 2.0 provided com.beust jcommander 1.48 org.yaml snakeyaml 1.12 org.testng testng ${testng.version} test org.assertj assertj-core 2.0.0 test org.apache.maven.plugins maven-compiler-plugin 3.1 1.7 1.7 true org.apache.maven.plugins maven-surefire-plugin 2.14.1 src/test/resources/testng.xml listener test.invokedmethodlistener.MyListener env.TESTNG_VERSION ${env.TESTNG_VERSION} testng-testng-6.9.5/maven/bundle-pom.xml0000644000175000017500000000412712551235562017547 0ustar eugeneeugene 4.0.0 org.testng testng TestNG 5.12.1 TestNG is a testing framework inspired from JUnit and NUnit but introducing some new functionalities that make it more powerful and easier to use. http://testng.org Apache License, Version 2.0 http://apache.org/licenses/LICENSE-2.0 scm:svn:http://testng.googlecode.com/svn/trunk/ scm:svn:http://testng.googlecode.com/svn/trunk/ http://testng.googlecode.com/svn/trunk org.apache.ant ant 1.7.0 true junit junit 4.10 org.beanshell bsh 2.0b4 provided com.google.inject guice 2.0 provided testng-testng-6.9.5/maven/build-with-maven0000644000175000017500000000164712551235562020066 0ustar eugeneeugene# Two different POMs are needed to build TestNG with Maven because it's not # allowed to have circular dependencies. # - pom.xml defines the project version "n-SNAPSHOT", builds, jars and deploys (but doesn't # run the tests). # - pom-test.xml declares a test dependency on "n-SNAPSHOT", which it will find # in the local repository (~/.m2/repository). All it does then is run the tests. mvn clean install -Dgpg.skip=true #or if you want to sign the jar, uncomment this: #mvn clean install mvn -f pom-test.xml test echo echo "To run the tests: mvn -f pom-test.xml test" echo "To deploy to the snapshot repository: mvn deploy" echo "To deploy to the release directory: mvn release:clean release:prepare release:perform" echo "Nexus UI: https://oss.sonatype.org/index.html" echo "Wiki: https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide" # deploy without tagging: mvn deploy -DperformRelease testng-testng-6.9.5/gradlew.bat0000644000175000017500000000441212551235562015767 0ustar eugeneeugene@if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS= set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :init @rem Get command-line arguments, handling Windowz variants if not "%OS%" == "Windows_NT" goto win9xME_args if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* goto execute :4NT_args @rem Get arguments from the 4NT Shell from JP Software set CMD_LINE_ARGS=%$ :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega testng-testng-6.9.5/gradlew0000755000175000017500000001173012551235562015226 0ustar eugeneeugene#!/usr/bin/env bash ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS="" APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn ( ) { echo "$*" } die ( ) { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; esac # For Cygwin, ensure paths are in UNIX format before anything is touched. if $cygwin ; then [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` fi # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >&- APP_HOME="`pwd -P`" cd "$SAVED" >&- CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules function splitJvmOpts() { JVM_OPTS=("$@") } eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" testng-testng-6.9.5/gradle/0000755000175000017500000000000012551235562015107 5ustar eugeneeugenetestng-testng-6.9.5/gradle/wrapper/0000755000175000017500000000000012564576474016605 5ustar eugeneeugenetestng-testng-6.9.5/gradle/wrapper/gradle-wrapper.properties0000644000175000017500000000034612551235562023624 0ustar eugeneeugene#Sun May 10 15:22:08 PDT 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-2.3-bin.zip testng-testng-6.9.5/gradle/uploadSnapshot.sh0000755000175000017500000000034412551235562020453 0ustar eugeneeugene#!/bin/sh echo "TRAVIS_HDK_HOME" $TRAVIS_JDK_HOME if [ $TRAVIS_JDK_HOME == 'oraclejdk7' ] then echo "Uploading snapshot" ./gradlew uploadArchives else echo "Current JDK is ${TRAVIS_JDK_HOME}, not uploading snapshot" fi testng-testng-6.9.5/gradle/publishing.gradle0000644000175000017500000000261212551235562020434 0ustar eugeneeugeneimport java.text.SimpleDateFormat apply plugin: 'signing' Date buildTimeAndDate = new Date() ext { buildTime = new SimpleDateFormat('yyyy-MM-dd').format(buildTimeAndDate) buildDate = new SimpleDateFormat('HH:mm:ss.SSSZ').format(buildTimeAndDate) } jar { manifest { attributes( 'Built-By': System.properties['user.name'], 'Created-By': System.properties['java.version'] + " (" + System.properties['java.vendor'] + " " + System.getProperty("java.vm.version") + ")", 'Build-Date': project.buildTime, 'Build-Time': project.buildDate, 'Specification-Title': project.name, 'Specification-Version': project.version, ) } } javadoc { failOnError false } task javadocJar(type: Jar, dependsOn: javadoc) { classifier = 'javadoc' from 'build/docs/javadoc' } task sourcesJar(type: Jar) { from sourceSets.main.allSource classifier = 'sources' } artifacts { archives jar archives javadocJar archives sourcesJar } buildscript { repositories { jcenter() } dependencies { //Check for the latest version here: http://plugins.gradle.org/plugin/com.jfrog.artifactory classpath "org.jfrog.buildinfo:build-info-extractor-gradle:3.0.3" } } apply from: 'gradle/publishing-maven.gradle' apply from: 'gradle/publishing-jcenter.gradle' testng-testng-6.9.5/gradle/publishing-maven.gradle0000644000175000017500000000305612551235562021543 0ustar eugeneeugene// // Publish to Maven Central // // ./gradlew publish (to publish to Maven Central) apply plugin: 'maven-publish' apply plugin: 'maven' javadoc { failOnError false } signing { required { gradle.taskGraph.hasTask("uploadArchives") } sign configurations.archives } publishing { publications { mavenCustom(MavenPublication) { from components.java artifact sourcesJar groupId 'org.testng' artifactId 'testng' version project.version } } } // ./gradlew uploadArchives (upload snapshot to Maven Central's snapshot repo) uploadArchives { repositories { mavenDeployer { beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2") { authentication(userName: System.getenv('SONATYPE_USER'), password: System.getenv('SONATYPE_PASSWORD')) } snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots") { authentication(userName: System.getenv('SONATYPE_USER'), password: System.getenv('SONATYPE_PASSWORD')) } pom.version = project.version pom.artifactId = 'testng' pom.groupId = 'org.testng' } } } uploadArchives.doLast { if (! version.contains("SNAPSHOT")) { println("Now go to https://oss.sonatype.org/index.html#stagingRepositories to close" + " and publish the distribution") } }testng-testng-6.9.5/gradle/publishing-jcenter.gradle0000644000175000017500000000364512551235562022073 0ustar eugeneeugene// // Artifactory // ./gradlew artifactoryPublish (upload snapshot to jfrog) // ./gradlew bintrayUpload (upload release to JCenter) // apply plugin: 'com.jfrog.bintray' apply plugin: 'com.jfrog.artifactory' Properties properties = new Properties() try { properties.load(project.rootProject.file('local.properties').newDataInputStream()) } catch (FileNotFoundException ignore) {} group = 'org.testng' bintray { user = properties.getProperty("bintray.user") key = properties.getProperty("bintray.apikey") publications = ['mavenCustom'] // Without this, javadocs don't get uploaded configurations = ['archives'] pkg { repo = 'maven' name = 'testng' desc = 'Testing framework for Java' licenses = ['Apache-2.0'] labels = ['testng'] version { name = project.version //Bintray logical version name gpg { // Without this, .asc files don't get generated sign = true } } } } artifactory { def a_user = hasProperty('artifactory_user') ? artifactory_user : System.getenv('artifactory_user') def a_password = hasProperty('artifactory_password') ? artifactory_password : System.getenv('artifactory_password') def a_contextUrl = hasProperty('artifactory_contextUrl') ? artifactory_password : System.getenv('artifactory_contextUrl') contextUrl = "${a_contextUrl}" //The base Artifactory URL if not overridden by the publisher/resolver publish { repository { repoKey = 'oss-snapshot-local' username = "${a_user}" password = "${a_password}" maven = true } defaults { publications('mavenJava') } } resolve { repository { repoKey = 'libs-snapshot' username = "${a_user}" password = "${a_password}" maven = true } } } testng-testng-6.9.5/gradle/buildWithTravis.sh0000644000175000017500000000002112551235562020560 0ustar eugeneeugene../gradlew check testng-testng-6.9.5/eclipse-projects/0000755000175000017500000000000012551235562017124 5ustar eugeneeugenetestng-testng-6.9.5/eclipse-projects/org.testng.eclipse/0000755000175000017500000000000012551235562022641 5ustar eugeneeugenetestng-testng-6.9.5/eclipse-projects/org.testng.eclipse/feature.xml0000644000175000017500000002760412551235562025027 0ustar eugeneeugene This is the Eclise plug-in for TestNG (http://testng.org). [Enter Copyright Description here.] Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. testng-testng-6.9.5/eclipse-projects/org.testng.eclipse/build.properties0000644000175000017500000000003312551235562026052 0ustar eugeneeugenebin.includes = feature.xml testng-testng-6.9.5/eclipse-projects/org.testng.eclipse/.project0000644000175000017500000000056512551235562024316 0ustar eugeneeugene org.testng.feature org.eclipse.pde.FeatureBuilder org.eclipse.pde.FeatureNature testng-testng-6.9.5/eclipse-projects/beust.com/0000755000175000017500000000000012551235562021023 5ustar eugeneeugenetestng-testng-6.9.5/eclipse-projects/beust.com/web/0000755000175000017500000000000012551235562021600 5ustar eugeneeugenetestng-testng-6.9.5/eclipse-projects/beust.com/web/site.xsl0000644000175000017500000001571512551235562023305 0ustar eugeneeugene beust.com

beust.com

" + label + "" + label + "
dark-row light-row dark-row light-row dark-row light-row

( - )
-

Operating Systems:
Windows Systems:
Languages:
Architecture:


Uncategorized

( - )
-


Operating Systems:
Windows Systems:
Languages:
Architecture:

( - )
-


Operating Systems:
Windows Systems:
Languages:
Architecture:
testng-testng-6.9.5/eclipse-projects/beust.com/web/site.css0000644000175000017500000000131712551235562023260 0ustar eugeneeugene testng-testng-6.9.5/eclipse-projects/beust.com/site.xml0000644000175000017500000000037112551235562022512 0ustar eugeneeugene testng-testng-6.9.5/eclipse-projects/beust.com/index.html0000644000175000017500000000372112551235562023023 0ustar eugeneeugene beust.com
testng-testng-6.9.5/eclipse-projects/beust.com/.project0000644000175000017500000000056212551235562022475 0ustar eugeneeugene beust.com org.eclipse.pde.UpdateSiteBuilder org.eclipse.pde.UpdateSiteNature testng-testng-6.9.5/doc/0000755000175000017500000000000012551235562014416 5ustar eugeneeugenetestng-testng-6.9.5/doc/testng.css0000644000175000017500000000502412551235562016435 0ustar eugeneeugenebody, td, th { font-family: Lucida Grande, Tahoma, Verdana, Arial, sans-serif; font-size: 9pt; } table,th,tr,td { border: none; } th { background: #aaa; } td { background: #efefef; } td { padding-top: 3px; padding-right: 4px; padding-left: 4px; padding-bottom: 3px; } h2 { text-align: center; } h3 { background: #efefef; letter-spacing: 0.12em; border-bottom: 1px dotted #aaa; padding-top: 8px; padding-left: 4px; width: 70%; } hr { height: 5px; border: 0; color: #aaa; background-color: #aaa; } .doctype { color: red } .xml-comment { color: green; } .attribute { color: blue; } .tag { color: #7f0055; font-weight: bold; } .float-right { float: right; } .code { margin-left: 20px; margin-top: 10px; background-color: #ffffdd; border: 1pt solid silver; border-color: #ccc #999 #999 #CCC; color: #000000; padding: 5px 5px 5px 7px; font-size: 11px; padding: .3em .6em; font-family: Courier New } .box { border: 1pt solid silver; border-color: #ccc #999 #999 #CCC; background-color: #ffffdd; } #menu { font-size: small; line-height: 0.9em; clear: both; margin-top: 10px; } #menu li { margin-bottom: 7px; } #menu li li { margin-top: 2px; margin-bottom: 2px; } #menu li.submenuitems { margin-bottom: 2px; } #menu a { text-decoration: none; } .e{margin-left:1em;text-indent:-1em;margin-right:1em} .m{color:blue} .t{color:#990000} A:link { text-decoration: none; } A:hover.summary { text-decoration: none; color: #ff9900; } A:visited { text-decoration: none; } /*********************************************/ /* The following rules apply to the top menu */ /*********************************************/ #topmenu a { text-decoration: none; } #topmenu a:link { color: #0066bb; } #topmenu a:visited { color: #006699; } #topmenu a:active { color: red; } #topmenu a:hover { color: red; } #topmenu table { background-color: #ffcc66; text-align: center; } #topmenu td { font-size: small; font-weight: bold; } #topmenu td.current { background: #ffff00; } /* The next rule is a patch because other rules are not scoped correctly */ #topmenu td { background-color: #ffcc66; } testng-testng-6.9.5/doc/selenium.html0000644000175000017500000002763112551235562017136 0ustar eugeneeugene TestNG

Selenium and TestNG

This documentation was written by Felipe Knorr Kuhn and is adapted from
a series of articles posted on his blog.

Content

  1. How to use TestNG configuration methods with parameters
  2. How to configure your test
  3. Creating the XML file for TestNG
  4. Lauching your tests with Eclipse
  5. How to make the test design a little better for the future

Modeling your test case

Before writing a test case, you need to know how and what will be validated. Let's use the WordPress "Create New Post" test case.

  1. Go to http://demo.opensourcecms.com/wordpress/wp-login.php
  2. Enter "admin" in the "Username" field
  3. Enter "demo123" in the "Password" field
  4. Click on the "Log In" button
  5. Verify that the text "Howdy, admin" is present
  6. Click on the "Posts" link
  7. Click on the "Add New" button
  8. Type "Selenium Demo Post" in the title field
  9. Click on the "Publish" button
  10. Verify that the text "Post published" is present

Considering this scenario, the first thing that comes to mind is creating a long test case that goes through all the steps. This might be a good approach if you are writing a manual test case. However, since we are writing an automated test, we want to write our script as modular as possible to be able to reuse parts of it in future scenarios.

This is how I would break down the test:

  1. Launch the WordPress site
  2. Open the Admin Login page
  3. Enter valid login data
  4. Navigate to the Write Post page
  5. Write the post
  6. Publish the post
  7. Verify that it was actually post

Keep in mind that this is just an example. You are free to model your tests in any way you want, as long as they have business value and will validate your business logic.

Let's see how to do that with actual Java code:

@Test(description="Launches the WordPress site")
public void launchSite(){
  selenium.open("");
  selenium.waitForPageToLoad("30000");
  assertEquals(selenium.getTitle(), "Demo | Just another WordPress site");
}
 
@Test(description="Navigates to the admin page")
  public void openAdminPage() {
  selenium.open("wp-admin");
  selenium.waitForPageToLoad("30000");
  assertEquals(selenium.getTitle(), "Demo › Log In");
}
 
@Test(description="Enters valid login data")
  public void loginAsAdmin() {
  selenium.type("user_login", "admin");
  selenium.type("user_pass", "demo123");
  selenium.click("wp-submit");
  selenium.waitForPageToLoad("30000");
  assertTrue(selenium.isTextPresent("Howdy, admin"));
}
 
@Test(description="Navigates to the New Post screen")
public void navigateNewPost() {
  selenium.click("//a[contains(text(),'Posts')]/following::a[contains(text(),'Add New')][1]");
  selenium.waitForPageToLoad("30000");
  assertTrue(selenium.isTextPresent("Add New Post"));
}
 
@Test(description="Writes the new post")
public void writeBlogPost() {
  selenium.type("title", "New Blog Post");
  selenium.click("edButtonHTML");
  selenium.type("content", "This is a new post");
  //TODO:Assert
}
 
@Test(description="Publishes the post")
public void publishBlogPost() {
  selenium.click("submitdiv");
  selenium.click("publish");
  selenium.waitForPageToLoad("30000");
  assertTrue(selenium.isTextPresent("Post published."));
}
 
@Test(description="Verifies the post")
public void verifyBlogPost() {
  selenium.click("//a[contains(text(),'Posts') and contains(@class,'wp-first-item')]");
  selenium.waitForPageToLoad("30000");
  assertTrue(selenium.isElementPresent("//a[text()='New Blog Post']"));
}
 
@Test(description="Logs out")
public void logout() {
  selenium.click("//a[text()='Log Out']");
  //TODO:Assert
}

These are the test methods (or steps) we are going to use.

Configuration methods

If you are familiar with unit testing frameworks, you probably know about the setup and teardown methods. TestNG goes beyond that idea and allows you to define methods that will be run after or before your test suites, test groups or test methods. This is very useful for our Selenium tests because you can create a Selenium server and browser instance before you start running your test suite.)

To achieve this, we will use two TestNG annotations: @BeforeSuite and @AfterSuite:

 
@BeforeSuite(alwaysRun = true)
public void setupBeforeSuite(ITestContext context) {
  String seleniumHost = context.getCurrentXmlTest().getParameter("selenium.host");
  String seleniumPort = context.getCurrentXmlTest().getParameter("selenium.port");
  String seleniumBrowser = context.getCurrentXmlTest().getParameter("selenium.browser");
  String seleniumUrl = context.getCurrentXmlTest().getParameter("selenium.url");
 
  RemoteControlConfiguration rcc = new RemoteControlConfiguration();
  rcc.setSingleWindow(true);
  rcc.setPort(Integer.parseInt(seleniumPort));
 
  try {
    server = new SeleniumServer(false, rcc);
    server.boot();
  } catch (Exception e) {
    throw new IllegalStateException("Can't start selenium server", e);
  }
 
  proc = new HttpCommandProcessor(seleniumHost, Integer.parseInt(seleniumPort),
      seleniumBrowser, seleniumUrl);
  selenium = new DefaultSelenium(proc);
  selenium.start();
}
 
@AfterSuite(alwaysRun = true)
public void setupAfterSuite() {
  selenium.stop();
  server.stop();
}

PS: Did you notice those weird parameters? They are stored in the XML file (we are going to see in the next section) and accessed by a ITestContext object, which was injected.

By adding these annotations, the TestNG engine will invoke the configuration methods automatically before/after your test suite (make sure the test methods are annotated with @Test), launching the Selenium server and instantiating the Selenium client object only once, reusing the same browser session across the tests.

Creating the XML file

To define the order of the tests, we will have to create an XML file listing the test methods we would like to run. Make sure that the test methods are annotated with @Test, or else the TestNG engine will not invoke them.

Before TestNG 5.13.1, you had to use Method Interceptors if you wanted to run the tests in the order defined in the XML file. I have posted my implementation of a Method Interceptor on my Github account. From TestNG 5.13.1+, you can just add the preserve-order parameter to your test tag and include the methods you would like to run, reducing unecessary code in your test suite.

Here is the XML file:




  <parameter name="selenium.host" value="localhost" />
  <parameter name="selenium.port" value="3737" />
  <parameter name="selenium.browser" value="*firefox" />
  <parameter name="selenium.url" value="http://demo.opensourcecms.com/wordpress/" />

  
    
      
        
          <include name="launchSite" />
          <include name="openAdminPage" />
          <include name="loginAsAdmin" />
          <include name="navigateNewPost" />
          <include name="writeBlogPost" />
          <include name="publishBlogPost" />
          <include name="verifyBlogPost" />
        
      
    
  

Launching your tests in Eclipse

We finished writing our tests, now how can we run them?

You can launch TestNG from the command line, using a Eclipse plugin or even programatically. We are going to use the Eclipse plugin. Follow the steps described on the official TestNG documentation over here

If you installed TestNG correctly, you will see this menu when you right click on the XML file:

Click on “Run as TestNG Suite” and your test will start running. You will then see this nice results tree:

Thinking about the future

If you really want to think about the future of your test suite, I would recommend you to read Adam Goucher’s article published on PragPub. He talks about Selenium 2 and the Page Objects Model (a very nice way to model your tests, especially if you use Selenium 2).

Since there are lots of people still using Selenium 1, I'll stick to that for a while, but Selenium 2 will eventually be covered here.

As the number of tests in your test suite grows, you will find that grouping them in different test classes is a good idea. If you do that, you can take advantage of object oriented programming and create a new class named BaseTest (for example), and leave your configuration logic there. That way, every test class must extend the BaseTest class and use static attributes.

public class WordPressAdmin extends BaseTest {
@Test
public void test1(){
  selenium.open("");
  //...
}

@Test
public void test2(){
  selenium.open("");
  //...
}
}

This is better than leaving your configuration methods in the test class.

testng-testng-6.9.5/doc/samplereport/0000755000175000017500000000000012551235562017133 5ustar eugeneeugenetestng-testng-6.9.5/doc/samplereport/index.html0000644000175000017500000002703312551235562021135 0ustar eugeneeugene

Summary

TestsErrors FailuresSuccess RateTime
70185.714%190.072

Note: failures are anticipated and checked for with assertions while errors are unanticipated.

Package List

PackageTestsErrors FailuresSuccess RateTime
TestNG Suite70185.714%190.072

Note: package statistics are not computed recursively, they only sum up all of its testsuites numbers.

TestNG Suite

ClassTestsErrors FailuresSuccess RateTime
TestNG Suite70185.714%190.072

Test Cases

TestNG Suite

net.sf.tacos.ajax.components.DialogTest#testClickDialog 189.174
Connection timed out
net.sf.tacos.services.SiteMapTest#testInitialize0.006
net.sf.tacos.services.SiteMapTest#testCategory0.569
net.sf.tacos.services.SiteMapTest#testContains0.138
net.sf.tacos.services.SiteMapTest#testSitemapXml10.05
net.sf.tacos.services.SiteMapTest#testCategoryLists0.117
net.sf.tacos.services.SiteMapTest#testUnsetResource0

testng-testng-6.9.5/doc/samplereport/images/0000755000175000017500000000000012551235562020400 5ustar eugeneeugenetestng-testng-6.9.5/doc/samplereport/images/update.gif0000644000175000017500000000030012551235562022342 0ustar eugeneeugeneGIF89a ٕ\Ҫ?!y~LWA(xdGϾV.6+Vqg! ,mPI8!Hhy7E"[\Ӭ' OHvhz߉u  "y.F#J*` < c` Af{ ;testng-testng-6.9.5/doc/samplereport/images/sw_min.gif0000644000175000017500000000005512551235562022363 0ustar eugeneeugeneGIF89a!,DP;testng-testng-6.9.5/doc/samplereport/images/sw_med_rond.gif0000644000175000017500000000005612551235562023370 0ustar eugeneeugeneGIF89a!,DnP;testng-testng-6.9.5/doc/samplereport/images/sw_maj_rond.gif0000644000175000017500000000006312551235562023370 0ustar eugeneeugeneGIF89a!, D~Κ;testng-testng-6.9.5/doc/samplereport/images/strich.gif0000644000175000017500000000005312551235562022361 0ustar eugeneeugeneGIF89a!, ;testng-testng-6.9.5/doc/samplereport/images/se_maj_rond.gif0000644000175000017500000000006212551235562023345 0ustar eugeneeugeneGIF89a!, y;testng-testng-6.9.5/doc/samplereport/images/remove.gif0000644000175000017500000000034312551235562022364 0ustar eugeneeugeneGIF89a!ᕔHJG=9121۽NJgduqMusVQLH!,IûeY(jh ,Bǫ.x D]/Y0`h @N0-PpV2GA\ތ@`PC‚h &<)<] X% ng~ v? \  c 8 W TM;testng-testng-6.9.5/doc/samplereport/images/product_logo.gif0000644000175000017500000000125012551235562023565 0ustar eugeneeugeneGIF89a3f5]u! ,I8ͻ`(dih,Am}/υ0Hlv$1cS*'Jt {2DSOK MBcuTwM}%O k2 {B10b/g[n1{f V&^PrfbOCh BŚxCJ&J1̼P [gz F AfY#O$cC`L=D<ŒI Q T,Y8S&O`{ӂ]FM0cLn%)҃G;0mR-zÂY&])tG !pY!miE8gP e*{4i6YCG]o 9"_QNr,Wn쵲O,KS$s+f?ZOX-\T 0Mdh(iL./UeV5sn@bUд1vht СklO%DUmM M'AwuLE쀍I:C a}2G(@ecGJ^O[bhaeqmw~zxr5' ,942&(ITBYWL\O^]HHMTWa[jLa_t`MdYarfpffinayrz~xwvKOMSKPKQPKPJ^ZCgrqvxsyzws}̉oσưЀӇ݁܊ډވًݐӜݙٞڗۧߧܮνئޡؽ珍툎鎝钘䟤䪞릟梡楫䮢꯱ೠⳡ簩꽸ôƶ!,  8cA*rE 5A.^`ɓw&`s)yBh˴5]LJ0 cU*a Ac!;=iQ R7*SAb([m4@slQ1Opę#D%  ;testng-testng-6.9.5/doc/samplereport/images/nw_min_hi.gif0000644000175000017500000000005612551235562023037 0ustar eugeneeugeneGIF89a!,sP;testng-testng-6.9.5/doc/samplereport/images/nw_min_036.gif0000644000175000017500000000005512551235562022746 0ustar eugeneeugeneGIF89a3f!,Q;testng-testng-6.9.5/doc/samplereport/images/nw_min.gif0000644000175000017500000000006312551235562022355 0ustar eugeneeugeneGIF89a!,-!R;testng-testng-6.9.5/doc/samplereport/images/nw_med_rond.gif0000644000175000017500000000005612551235562023363 0ustar eugeneeugeneGIF89a!,\;testng-testng-6.9.5/doc/samplereport/images/nw_med_hi.gif0000644000175000017500000000005712551235562023022 0ustar eugeneeugeneGIF89a!,a ;testng-testng-6.9.5/doc/samplereport/images/nw_med.gif0000644000175000017500000000006012551235562022334 0ustar eugeneeugeneGIF89a!,a ;testng-testng-6.9.5/doc/samplereport/images/nw_maj_rond.gif0000644000175000017500000000006312551235562023363 0ustar eugeneeugeneGIF89a!,  ;testng-testng-6.9.5/doc/samplereport/images/nw_maj_hi.gif0000644000175000017500000000006312551235562023021 0ustar eugeneeugeneGIF89a!,  ;testng-testng-6.9.5/doc/samplereport/images/nw_maj.gif0000644000175000017500000000006112551235562022337 0ustar eugeneeugeneGIF89a!, B;testng-testng-6.9.5/doc/samplereport/images/none.png0000644000175000017500000000166212551235562022052 0ustar eugeneeugenePNG  IHDRgAMA|Q cHRMz%u0`:o_FPLTEe tRNS0J pHYs  IDATc`i2ag~IENDB`testng-testng-6.9.5/doc/samplereport/images/newwindow.png0000644000175000017500000000033412551235562023127 0ustar eugeneeugenePNG  IHDR Ӻ&gAMA7tEXtSoftwareAdobe ImageReadyqe< PLTEuuu8tRNS@*FIDATxb`ffffb@  8@! @`6L& ^IENDB`testng-testng-6.9.5/doc/samplereport/images/newwindow-classic.png0000644000175000017500000000166712551235562024560 0ustar eugeneeugenePNG  IHDR Ӻ&tIME 8e1 pHYsiTSgAMA aPLTE0`etRNS A+IDATxc`bbb& L2022"x0s`dZIENDB`testng-testng-6.9.5/doc/samplereport/images/logos/0000755000175000017500000000000012551235562021523 5ustar eugeneeugenetestng-testng-6.9.5/doc/samplereport/images/logos/maven-feather.png0000644000175000017500000000553312551235562024761 0ustar eugeneeugenePNG  IHDRZa xgAMA atIME:bKGD pHYs."."ݒ IDAThZPTYM48怎\T#IADPa芨:cvR$Ӏ`fY1U[;;cUoλI~ٳgVDEEٳg8x ܹ#t͛7_o9s::: .|A틇1cEsO@ӳW\իWŋFD<}x}}~||y$ۇ>}`ɒ%HKK謬,,_ׯǍ7Ľ#;;}ff&\aMp[ w.B Gaݺuҥ pС׀0`<==}vZJ`;"N:b8__ݺu//@ u/_^;+c\Jb"Ty+.A2ܾP;~9r$N:] AkEPQE!I9zp,C>نC{!wt QO)S^32/--JJJz.u//4Pq eeeĉ$=6l2_QUgVi%yȖ!U3U]os 倶®]Ē|VX!  k,ͼyдiSAٳG[q%\vM)|>.qU'[e'DJCR!9!9A(WOd4S㈈رcѹsgfΜ)P =z3g7qDᕳg6F*sEqqk?)1bv*ƪ-Zȶm3V:ű ~2z¹3j m}t5 o ?L?[",Fa?K;@o}H mnٓKmIyl܁ [v z~NVS4F ;|z5GKwL2 A;[ew+#^̒#3rd j:"2|ܰy8s䟸VRϞ@scsvv4L B졎HA;’a }{|i եۻ:tj}0l%W/^!O y"SKoh56a66ףfr8?58# OJ0Veל*hGo 5ݤL1^3 -#"keI ZoW .6F|Fn[6.ͳ{qRQ0%犐Cap dM></x@úXo>kL.`W]oؙ٢ɗh"{}#]C4E7u1L `>\=N\S51JAұ`ݎ'~@SA2+- C+qry E֮ȫ&(gi<'c{LSjX#{T3_62%9Y}uOk G=FX~<׸%Y.=ŋq(rmG̓&ðv kVn FE!H[ ppi#qGD٫yrg8d'!=}D@WrzDzexdށuG%H" HdpCpEr7Od ~H5IK2$ !f>HG!א*ʄ;0z>S{V%ٸ 8qAAH_.uɓrXaNOؽ{"yd "ܿ𱱱ŽU>{EEE…rߥg(EQh4%IBƍQNgZ]hڵk+k/^5kmz)]ߺur!7jHx%##۷/7X*$XF ժm۶m+wheYرjdC}f̈́AbQX m;)LLL@Zj077/wh } Q8ԵjJ ^@RYw'Աd.3@޽{С7o\p%''D޺uKˮʉ # ,hz>Aiӄ3?z*KII:a3ddǎv\u,p>}auu{瀦I_ zVZ8w\q 24e˖-[l)6zB3OWt,ײrH YJ=ͦ>|BGt \\J=W o 4ٯ_~_WWr@3-'GaN͛7܌y SjJSh^//ܽ{WphɓT.8)Ms ,l,rcVfh4088XDEyKWࡃZƍ'}4Eԓ>VBwOɿ6"UQIENDB`testng-testng-6.9.5/doc/samplereport/images/icon_waste_sml.gif0000644000175000017500000000106212551235562024074 0ustar eugeneeugeneGIF89a4W냗Ӱ`}\xPhEYxbUn`{hjlkyƗŝɧΩЭҫб԰ӲԳյֶּڿcǟʮҹ!I,I'!!;< I 3/6I)BA+ 817*?C77D6*5C%9 11,(:)72#"͒8C-:'G, Ӎ >6& 1@:.A=I0EA^?&;testng-testng-6.9.5/doc/samplereport/images/icon_waste_lrg.gif0000644000175000017500000000141412551235562024066 0ustar eugeneeugeneGIF89a PqRiy~[vYsWqTmRjOfNe_{]x\wWpSkPgMccb~UmQhOeNdgjkppqtu|ÙǗŘŝɜȡ˨ϩϭҬѰӳշ׸ؼھ\uÓßʤ͹؃ɝظѫ!T, TEGD C A F'2CC:?>F:QQ:BXKtx0H%$+jbB_ʐ]1ä# ˜ EaKRZ"1!l̚4a=0?]AJa45tHN)jS$Ԫ 5LWi<vdSTu"%a,6rJ|Qibgrq|Ҍlyv{䞇ǛТxw!,  HdNeI@ǏHaF`@ .G8q<^f YIT nD#sJN`8T8A`ÊB4 pCbo߿)GO<8UDyܵsɀ˘/qSc|8X7^9wAFylM[8 LK{\`ϝ:ٮM{\̗kc8GiϜ rʤcWNО)u;lqGܸo]%#7d/$@aւ9`5ijQ<*CA@Q f`cM5Șa ܂J#F1 'tr+œ@\A\> xhnj( J*B2"B ()@9hS<фY%r( " )+,@2TAE7X|!v{G CL:NE @Ѕ[݀I+#0C 6АI!p $P |p (,̤;testng-testng-6.9.5/doc/samplereport/images/icon_usergroups_sml.gif0000644000175000017500000000200212551235562025162 0ustar eugeneeugeneGIF89aJS SAb.iVm[DCY^#T"[5bFIK /a PR@;%P<} f|T:{:u!=|VNɌwt}{z~̴иkc͵j˳iսoӼnηphǵx՜'D\b«igfWTYrw|ILM}LP`huHrFtHrJya|jZAzTl_KoHwS(QF9]OVK?U*wvsrpvzys_yz"$`8*r4x>zell iwv|'P%Zad}m_WRO]IJKM% FD C<0=%;7 3 2!,m HAjD@14N`)kBD< 3><9ŋ+ɱF7L 19PĐc ,M!/eHL%t'G0=jtI`\8PgP F2B$A`PgQ"@ QDg &P?&u 2l ǐ%NBJu >(QVrʖ!HCJRZ%+ ;testng-testng-6.9.5/doc/samplereport/images/icon_usergroups_lrg.gif0000644000175000017500000000276012551235562025166 0ustar eugeneeugeneGIF89a 燦  k @C_e&,2&6ഺ4J]h>XN&Mg]|tfbdb`arIjzgJ2M5= 'SG]~\wRipƣ̱Ծ.?S,0FkDؕ߬ȓvtN s?wDairBVq;ZXcn8P;{k3\;hg.Mh2x[opnFhd):PnX|}y}~mڎݮ鷈}njB@0*&ƸxٞMD%r|ueۀxƱh߃иkȰgpԼnѹl˴iӼni{'Db`^[ƮfĬeªdRQNLV|IOsCm@^T?{_wb>;/{_(o-],\rtz9LޓPn@xJvګ͸aiemlx%ۀ2܇=ۋHZ<#ؓYenM1fM~wp\> OaXdr)w6ӈOە_ǐekwme۷SXG'h&l4{D~L W"k:D ĀZ9W"@_?/1S(z!:??fff!,  H*\ȐL2Y4BO3`@M4 .^(dA~ 8̙p-tiӢJ菡Ho)5!' AeN%>D RQu3L 1/y@zh^XBxѠm^7JYAvv< ޾lR (L|2Y'š:j4SBs'~EYZN)6$F~ PѨzh>9j!Q*-r*>:Uԩ4ʔ-ӢPODeޔTL?].,P?X6D2B -1?2 O6E?E',ޢ?V!t:C b0-4٤.hDA# I,F^x13 1R1XsiC<St,BK,RK09L8Tch5D8 DD+yRK 0L)5Ԅ#8H? :J //@#7k2HCC$qıP/é14 7l 9ؒLADDN S1Lͻ#:3NJ;O8G/F;mی9鸣0<ܳHB,o: <ē?WhqOTDLDQ ŔM7o!S AW'gc';ﰓM$TOtH;testng-testng-6.9.5/doc/samplereport/images/icon_success_sml.gif0000644000175000017500000000173612551235562024431 0ustar eugeneeugeneGIF89aΧμc~w˗éSq*/%(#8='*!37,/(CH'AF&>B/2*,)FI"!PrkjtŲFcO7G;ȝȣ֩۴߲2B.ᥳ⦷㫸䬸䭺导屏€㩲ࢲࣜΈޘܙٗۗ]B΅ԋۑ̈́՗]>Ԅሻfrmjb7Jw*U0W2im;Ag$r?o=e8f8b7Z2Y1S.Jt)Qy1WYuQeFcE{{hGv@u?k:h7`3Jr(E^3Q|,S~-Dh%}DEi&QŢIm&Qx+Ot)Mo(Ll&Ig%Gc$!, HA!,XE aCF5pAƏ *01#"NT0A=Y& NRI1bJ':o8b3-e˓у>|¥ (qŋ4hԱ(ЋmT"J;*d("4lp ,P( ;testng-testng-6.9.5/doc/samplereport/images/icon_success_lrg.gif0000644000175000017500000000272412551235562024420 0ustar eugeneeugeneGIF89a ]yXsTnLcG\|CWu[vWqRjPhNeKaI_H]}DXvb5D[hgpt{Öřǝɡ˨Ϭѱ԰ӳշ׶ָؽۿܾ*7Iʤͺٹ`{gNd|VuvQo}tkRwndq@]G;Q@KuSGkM]bqpËۣ~|àʩ~zQKc[zHpADi=Bd;ۙЇّ㟩⚫>\5:U2╧▩l^5X1S/Q-J}*~MvHW}R|_r{hɞӲƬ|Cv@q=oJJX7yR+Q+O~*N{)Jt)!,  H_$@ǎ衃F q@ǏA`FE@e.#8qt2LCfXItVDc8mJCE|8T)QŠKK!@Ppʥ%K0[\†ϟ<[H%r=%³a3c.1‹=!re1cS4hKӄA-%P`zc;ZCT-NL 31%9i#jrz2,&EDIѶڦ26N#<'O-cRuEyUDR(`=s:`PsgK\^#L8A,\a@J<E_t",pQ=#.Q tB4Q7 1Ũ@EHqhPC~ D6p 3Jͼ+ϱO?Q =(BgnuaG}"~4#e,A9P 1B D ) &'eP ?"'=,,K 4@X`h0<;testng-testng-6.9.5/doc/samplereport/images/icon_sortup.gif0000644000175000017500000000016512551235562023435 0ustar eugeneeugeneGIF89aj?S-Z}ZJt)!,"I8ͩql!AXIZVGmn<;testng-testng-6.9.5/doc/samplereport/images/icon_sortright.gif0000644000175000017500000000017212551235562024124 0ustar eugeneeugeneGIF89aj?S-Z}ZJt)!,'IW`+Φ}@fE[ =d[;testng-testng-6.9.5/doc/samplereport/images/icon_sortleft.gif0000644000175000017500000000017112551235562023740 0ustar eugeneeugeneGIF89aj?S-Z}ZJt)!,&IXLqAXIJu  =0;testng-testng-6.9.5/doc/samplereport/images/icon_sortdown.gif0000644000175000017500000000016512551235562023760 0ustar eugeneeugeneGIF89aj?S-Z}ZJt)!,"I8뽅QAE1qk檬\|E;testng-testng-6.9.5/doc/samplereport/images/icon_members_sml.gif0000644000175000017500000000177712551235562024420 0ustar eugeneeugeneGIF89a4D[Rj4CY!*8tds^hwgp~ѱԲԽۿܾ7H`=PjŚǺ[jzYjnY[ZTlXC\A>l*6]#`Gfs`TxAd&c&T+r>r?R.Ew(hF= c&a&a&f-i/h0c.j3j4l6i4s;,JxEa"`&_(r?6XTY ](S[(PLq(-OJvN|!1Knjoc#Ed?P 9=wtz~иkc͵jսoηp'D\b«igf  TXrMP`hrFmEnGrJ!,3 HA JG p 6n!BcN<2mp@ :4 72?yG 2` =RqMI(z4+Zh"%L<^RB "Bx̘ N uƒA12X@@E pǑ(Wl#&2!HI,^1&MALc҅5;testng-testng-6.9.5/doc/samplereport/images/icon_members_lrg.gif0000644000175000017500000000304212551235562024374 0ustar eugeneeugeneGIF89a! 燱ԋDXv]]b&2CXsSlRk^zWqH]}EYxdhz˧βԷ׶ֽ۲߹Ўtɣ̺ٞvyz⢦iT^sNq/-//.37<>CEKn9PVT\\e|TczKeՊgxUy}*{),~+|*8EITb8_mr}w%{(y'x&z(}-}.2:MR[`etxLUAu$t#r"u$t#s#v%w'z,j(~5FYjpr!p o q!q"t'>Rbmnu*Ekiw/Wq(ghy4eg"ca|_w_yvX^t]q[len;UcFK~HMW\*GJxylHKEFFF?>lhNutsۀ}{yxx܁иkʳhȰgԼnѹl͵jrӼnb^[ªdaŭfWKyGOMqAzf?k?lAoX4eM-e\P!,!  Hq@Wd`Ae5q"x>yEV`rxAMa$9JHD ;4QTX! sB!\r &t7RHFmQp bI!„ V:RYk1~H Tʥp =Yq!zAy(҈$P (b BYh!~q"8ˆ&|b* C :@ Ђ\B#tI) + +.B0{jvI)+B .@j $0I#k.hpmd "! JH" 1L/4P38 ]!P?PvIX0 sDwwA;testng-testng-6.9.5/doc/samplereport/images/icon_infosml.gif0000644000175000017500000000011512551235562023543 0ustar eugeneeugeneGIF89a !,  wlzO=wiXMbL[;testng-testng-6.9.5/doc/samplereport/images/icon_info_sml.gif0000644000175000017500000000113612551235562023706 0ustar eugeneeugeneGIF89ar 'SG]}]yVpOgLcJ`EYxCWtI^~FZyehgjlmpXltvdyw|~wunzw…ǘƂ˦ΩЭҬџ԰ӵָؼݲ@TpAUqy}ŞɧŹ!r,r`fg`l\d LG^qqopnQmbj.MObhNgr\oP6 [ig%dmE4k_^eL PRah YcHBjfV F`\- 5Z=97D`] I' 130@KICA@,"c $XA ?tr兊!8h2† @Pab ;testng-testng-6.9.5/doc/samplereport/images/icon_info_lrg.gif0000644000175000017500000000254712551235562023706 0ustar eugeneeugeneGIF89a Um 'S(Bi+Fm6OsG_H^H^_|]yYtVpSlRkLcJ``}XrRjQiOfNeMdH]}bLbI^~egjlmoWlpqtuzg|{~luxzt~wz’Å|ǘƗŗÝɜȐ˕ΨϧΩМѫС±԰ӲԳյֶ֧Ÿؽۼڬȯʭȿ߸\xco}Ŕǃʤ̢ͣˮҤúٹدɮȳ!, k H*\ȰBqsGΜ:qAL10*Rʚ5`'B8NJ)`%K)j(%|ҩrOvJUL:eO4h0!PTӍtx%KBŊ*WDƑ5w'էW88'PZ9hH-T72kKSChS8h ̪`bMLRAd0S-:mA|e;rZ4x`8t]6jS0nV2qY4iR0X@&!,5JF7pرBF6.H( :F` $Xx@aB AftltA &@DH 7s4!" $?h#"2f*W¡  F݈Ds ,;testng-testng-6.9.5/doc/samplereport/images/icon_help_lrg.gif0000644000175000017500000000261212551235562023674 0ustar eugeneeugeneGIF89a mb6a䅳_܅ߍ! 1*KB!_T,^S,ZP*OF%SJ'dY0nb5l`4h]3yCi]4|EK~GzDwk|e;x`8t]6r[5{c:w_8nV2qY4!,  Hv"IQ$C}zp % 8РA %?|!`Hu#8H+~ٳ̙5zqB *jHO=CE*L0Ubz+>idh(2D#UںMFMR*r## `n5[^ltaR$rs Cm_OIi6nhA X"'acd1}p-t eF+s,H7\ulljd%u#IT)zlEϟJHt' #rP"1 ejDY TQUb1yofGDvd1 %<0 Fd\R%*s)5noQQ$&ɈF*ׅd4r"'0s-k`w!QI($s+G|L""@ tAE|NBdL r 2Hr*b'R-('E.fgh2/t!*,$#MGK/K.(sk'.3 1Ō,`0~kn3ܢVC,j32 4$DQ@;testng-testng-6.9.5/doc/samplereport/images/icon_folder_sml.gif0000644000175000017500000000117212551235562024226 0ustar eugeneeugeneGIF89aـ{~r}|wvuts~}|zyxxwtиkζj̴iʲhȰgcq־oԼnӻmѹl͵j˳irսoӼnb\[aa``__^]]\[ƮfŭeĬeëdyOPWVUTTSRRPNYXwEJ}IMK|IO}\oAtDpBoAm@yGi=j>zb9ya9lY:nV2mU2kT1jZBdM.bM1bM2!|,׀eJHHIO|#!:N|_ UH`@F78b7 * 4i_Sf$A"%4?_KWD&]|g#XF;* f|W#B   4.Z|[#-7#)371?\|U'E+(!602GSH|40p N&UX!xxB$H,TADeNeL9=ad/WAȑ9GhGJ͚o֐sQ/z;testng-testng-6.9.5/doc/samplereport/images/icon_folder_lrg.gif0000644000175000017500000000301412551235562024214 0ustar eugeneeugeneGIF89a ߭׈ܑܓٓߪڴچ֍ԌˉǽwyLjʜ䈾puzۂr}|{wvuttssۀۀ~}|{zzyyxxwvڀиkζj̴iʲhʳhɱgȰgǯfcqp־oԼnӻmҺmѹlϷk͵j˳irq׿pսoӼnYb[Zbaa`__^^]]\[ƮfŭeĬeëdªdOWVUUTSSRQY|zGwEJxFM~JLKxuDsCqBoAn@xFvEpBoAm@yGʁɀg<}f;{d:k>i=~f<|e;l?j>rZ4s\5r[5{c:ya9kT1fN.٪vԠt節|ަ{ۢyߢ|ߞ}~桂ܛ|!,  Hʳg>n"=m ظCHadHԨM N\iQJ$yѣPtLh@B.6>hybTyL5p]ŠCB N,\ɲE#JLQo [e 2fȑ!+@ "Af ԂGl1wzI+8:Ј+Y1FB@r@l152Elxaod \@ƒXQ/P FFH$#w.Q5Ҙ w}ыA%*huRK~2CeqVWlGqCH2cPF&!grԑA&fT1EoaP'Ё .(AaWg\Bs`r-E&,)UaFXlȚn!bGek|h&4.-hjDxP pڱH'(3`_ZH!Hp  2X 0\la hH.Ǥb@ x BA%|2L2\<*RC~!%b ,*J,o G#K0A\"tRL2} Xr""-ŞhM@;testng-testng-6.9.5/doc/samplereport/images/icon_error_sml.gif0000644000175000017500000000176212551235562024111 0ustar eugeneeugeneGIF89a  q x v m;@GJf46_     i [        ~ } s q p n X V L     v l ~ "",9?6;{6:df島$')OWͱ-/*"4"3s}%8&:(=*@+A*?5H=MM\+B.F/G0I2M3O2N%9J.FprN3Ovx{@-EL6RO8V08G3O1:bGm3=4>7 C5AgOx?2ME7TmW|d}gu^V!,; H AJgN޴Yc* FrM/]HIh $5iΌ %BT 0P8$2,ㅋ,Z(DL@;Gk$<Hd >`'!\2?vhp  u@ .X = q0 )f$Tp"FQGr̉C;testng-testng-6.9.5/doc/samplereport/images/icon_error_lrg.gif0000644000175000017500000000277312551235562024105 0ustar eugeneeugeneGIF89a   i c _FGBCfg w t [         ~ | z r p n f        y w j  t s g !{lZ$&FHilfhjmdf٨#"!)!,U[".$1&2,;)6W`)1BJL-;v!*ۯ6H".8KP:Nh']"-9䱷8KAW>RCYBXD=LS]G^@UJbF!H"M%ܶOiT*PjQlPjIaH%Zh]#09L= UqToOi[jXvYxZyJ*Xv`^~e-Jʆ ;T`Ê,][Ī ɾpGW3ok1v4_*5jO1% \(L,ARd(7m=

]y[wYtXsUoJ`\xRjDXvtzŧΩЬѰӳյֶֽۿܾßʣ̢!<,@/Z,&N($lrh[@W'CH`Fhp(i4咉8dVTmo%'d:5 $M2%Nd-4*#N vM.;63 ($ 1N9n%/M)"0/BBA;testng-testng-6.9.5/doc/samplereport/images/icon_doc_lrg.gif0000644000175000017500000000246712551235562023521 0ustar eugeneeugeneGIF89a ]y[wYtXsUoSlOgLcJ`G\|CWua~ZuWqRjQiPhNeMdKaI_H]}DXv?Rm5E\bUnLbI^~6F]3BXhgmprtwz{~’ØƗŝɜȡ˦ΨϧΩЭҬѫб԰ӲԳյַ׶ָؽۼڿܾ^{*7IcÕŔĚǟʞɤ̢ͣˮҺٹ!, + H+A9`0#B #% v 1 AE\ R %`D c8qDdELuP.aI"DPJ =|fdlJ σ`zH Pxl5[ #Rp3ċڄ\ ˷/'y\A.S)I$PLLre2쀜8|:Rƍg Hq4Hx?nA8q;vAPA& {"5zA:iի[>M ȟnӘ"@ *pV/\90]U$#҇!,dхYwlWL@FGH"h^lGSD#Cˑd$" Ca||X!O,GGD)jajGdCi WPEL$t1@t  !8$t1@0cN,jE!Dp !dd `@HЁ|@(P (k%;testng-testng-6.9.5/doc/samplereport/images/icon_confirmsml.gif0000644000175000017500000000013612551235562024250 0ustar eugeneeugeneGIF89a!,/+(7`נꙆ+BBZ";testng-testng-6.9.5/doc/samplereport/images/icon_arrowwaste2_sml.gif0000644000175000017500000000114112551235562025227 0ustar eugeneeugeneGIF89a4W냗Ӱ`}\xPhEYxbUn`{hjlkyƗŝɧΩЭҫб԰ӲԳյֶּڿcǟʮҹVUUlll!O,O'!!;< F 3/6)BA+ 817*+?C77D6KJ*5C%9JIILLMMN 11,(:J؆)72#"م8C-:JM Xw `6LxP+҂ˀ!.9ЃGC`)"'QF9P ;testng-testng-6.9.5/doc/samplereport/images/icon_arrowwaste1_sml.gif0000644000175000017500000000113612551235562025232 0ustar eugeneeugeneGIF89a4W냗Ӱ`}\xPhEYxbUn`{hjlkyƗŝɧΩЭҫб԰ӲԳյֶּڿcǟʮҹVUUlll!O,O'!!;< F 3/6)BAKO+ 817*J+?C77D6I*5C%9LLƆ* 11,(:LMӄ)72#"M8C-:N'G,@3I>I aƒU%- =n}BbY=0Fg("E է0c ;testng-testng-6.9.5/doc/samplereport/images/icon_arrowusergroups2_sml.gif0000644000175000017500000000206412551235562026327 0ustar eugeneeugeneGIF89aJS SAb.iVm[DCY^#T"[5bFIK /a PR@;%P<} f|T:{:u!=|VNɌwt}{z~̴иkc͵j˳iսoӼnηphǵx՜'D\b«igfWTYrw|ILM}LP`huHrFtHrJya|jZAzTl_KoHwS(QF9]OVK?U*wvsrpvzys_yz"$`8*r4x>zell iwv|'P%Zad}m_WRO]IJKM% FD C<0=%;7 3 2VUUӫlll!,k H",c"a)zell iwv|'P%Zad}m_WRO]IJKM% FD C<0=%;7 3 2VUUӫlll!,k H",c" #"U$d̓Zcظq`B.JhB@X8s|EP *hHsĈ1 |ʕ,YfI͒ / a zu5_hӃ3a18V*UY@KSL!Dw]@H`?|-$hP(@v #HoP*Ѐ r ʣ#L \B  %NHBaC>atiSQNRV  F N%PPb* ;testng-testng-6.9.5/doc/samplereport/images/icon_arrowmembers2_sml.gif0000644000175000017500000000206012551235562025537 0ustar eugeneeugeneGIF89a4D[Rj4CY!*8tds^hwgp~ѱԲԽۿܾ7H`=PjŚǺ[jzYjnY[ZTlXC\A>l*6]#`Gfs`TxAd&c&T+r>r?R.Ew(hF= c&a&a&f-i/h0c.j3j4l6i4s;,JxEa"`&_(r?6XTY ](S[(PLq(-OJvN|!1Knjoc#Ed?P 9=wtz~иkc͵jսoηp'D\b«igf  TXrMP`hrFmEnGrJVUU̫lll!,? H*HP>3)Q: C1%d !s B3]ypC\СQ=u!'K\j鏟l*6]#`Gfs`TxAd&c&T+r>r?R.Ew(hF= c&a&a&f-i/h0c.j3j4l6i4s;,JxEa"`&_(r?6XTY ](S[(PLq(-OJvN|!1Knjoc#Ed?P 9=wtz~иkc͵jսoηp'D\b«igf  TXrMP`hrFmEnGrJVUU̫lll!,? H*HP> (P aΡ? @H|iH8 ! i` H-'A1]ĉSN0R X02HO^ZRk"MzD)Xt+ VDJ &w;%(a&( "nj)IpĀ^$G!E R2X@@EIO :@00" G\0E@ ANd4i~4K*]ȜQhQ@;testng-testng-6.9.5/doc/samplereport/images/icon_arrowfolderopen2_sml.gif0000644000175000017500000000123012551235562026240 0ustar eugeneeugeneGIF89a!י}~ً|vutqվo}x{tكӂ{̴ipѹlϷkɱhsӼnDznlijzż`]ZŭecOWT}IwFLoBh=u^7jR0VUUmmm!C,!C.-,,"!0C0 )*,30%/1 52 !/6,-44C?>1 "$56-#-'>=88Bׄ2014<+ h.^( Q*X>@Gh zb9ya9lY:nV2mU2kT1jZBdM.bM1bM2VUU׫lll!, H`%H$y2pDN J   b&x‚T( @iL13R" "r˒+D p0ѥ3#6`1à 蠁fX!xe!  @4\hgϞ? -nذa3ne rJrȊ~QCƑ)H[ p48F(FT c @ ~H"/ R% :~$ƖHeNeL9=NTæ%_FH7r0'5߬!cz^D1;testng-testng-6.9.5/doc/samplereport/images/icon_arrowfolder1_sml.gif0000644000175000017500000000207212551235562025362 0ustar eugeneeugeneGIF89aـ{~r}|wvuts~}|zyxxwtиkζj̴iʲhȰgcq־oԼnӻmѹl͵j˳irսoӼnb\[aa``__^]]\[ƮfŭeĬeëdyOPWVUTTSRRPNYXwEJ}IMK|IO}\oAtDpBoAm@yGi=j>zb9ya9lY:nV2mU2kT1jZBdM.bM1bM2VUU׫lll!, H`%H$y2pDN J   b&8ƅ(P@ 4|b`>$"g ?,B]lÏ X:h9ϟ?L%^A$p Zl~-nذa3nE.?t%V9Qd(B؀!$H N&UX H3I"AdBǏM9  `3G9ad/WACrD7r0'YCΝy}@;testng-testng-6.9.5/doc/samplereport/images/icon_alertsml.gif0000644000175000017500000000023212551235562023717 0ustar eugeneeugeneGIF89aӯz{{aaj__! ,GLFU6*J|޼He" q a, r0b)ϖ;testng-testng-6.9.5/doc/samplereport/images/icon_alert.gif0000644000175000017500000000214012551235562023203 0ustar eugeneeugeneGIF89ajg((;;QQ__~~!,jg` dihlp,tmx|pH,#A0h pZV \tZ tiv2 ݂dH^wtGlrHmHewFw@ _ 6  W 1 m+ ¿f  %Т_۬# w  f ͭ[`Pz n IA@kP\[ nD7'hP$[dڥls-Mo,tĈHY2WT1NhItJ6a\$7 A)0j&֩# i6n]ݦhVHegOr4bvJ^}_4WVfG \c2Cv-CI7.j( 6.~:{[os 9.>Y +@{կڏr|(ٿX'v3lO=47< V@`#) 0B_pVy<$a ‰4Ő\ :TX":Ds;d c7CBP =z4†`)K swS$fRa`=f%Hsb &0s͛)i3e .Rw8l^(y yX_#ʐb@ #|z] Em * z&\a(G) ɑa kښ6M`H`[,(*M4$;[~xQ l:V"]N2,tZӎdG!VQ!(/+ [׊"yQJ|e;x`8t]6r[5{c:w_8nV2qY4ȼ}}}pppcccWWWJJJ>>>!,4 H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JtKa6TɑK IBHHEwZ `( 44TVbHH@B xEA=|AFۚ_^(` mɣgӤLH(؀"ɕ-cFO5<ˬ@ 0BDА#VXVfa0-Y!j&K$lB'PON ~bswy{GrŐMkзysˤm\7_.I 1XtJpӍ~qxI E uKx N\A EGmaِe#7l 9`c,)r 1!r<1vdFA9q39shĊ >drI!%qG_R#ŒyAPZ73Jp׭!tTd0uT(zФe*pR()qtXlXH$Tc*qj4d^ zUA77Iݔ{.BvHκ6߈#7ꍾ{)rqpa$tH'ɀ;ݔ3M $l<8$I豙tq9 1cIct<2"I(<3"Nja8+8b9$$8#'6**8]3q8p㦬FvmcmDr 3G#=!;6!=6\M!fMP[N6rp]|H%1У'Ҍ NNڬi7d.D@aLw]xaz%PM"z.貌Qh9/NȎ.zA`s$2Q.L!Sq+P QE,dROlԧM.x $x?mDȳ2NbUT'L@ɂˆBP%65YQ͑aP~d"n%.@DokgQ fT!4f~-8|xC ~kc,1 ^43q dLp 9FǕ##Q|? h?+2鍐 f$FhB )Hh^a cpd$5Aqs&Ւ(k!I8)#HB͓XpLڸbXDLYO\f?ρՉڙІ: ;testng-testng-6.9.5/doc/samplereport/images/folder-open.gif0000644000175000017500000000034512551235562023303 0ustar eugeneeugeneGIF89a fffvvv! ,pIx ! 0d@ @:m.4R @ @ЂJ CPD%l "(`@@ {Ԑ괶uNo lO)L&s# !PxYE<'M4%w LB|;testng-testng-6.9.5/doc/samplereport/images/folder-closed.gif0000644000175000017500000000033412551235562023611 0ustar eugeneeugeneGIF89a zzzfff! ,pIxN)KqA0Hr@*)'RAp`A:8B`xbUU( ]Ja (N mwqG `Sc+&t#5CE5ZuA7)f!)+ qz;testng-testng-6.9.5/doc/samplereport/images/fix.gif0000644000175000017500000000026512551235562021660 0ustar eugeneeugeneGIF89a-H/Ʊ8)&#騦rT:$TRTxwv!,b9 ^+_'nYE1REAeWܮQ!{pKe0`!5 VJ`Q7  );testng-testng-6.9.5/doc/samplereport/images/file.gif0000644000175000017500000000023012551235562022001 0ustar eugeneeugeneGIF89a  鯯333! , EHr#iDp$(16H` Hnr lIraL.";testng-testng-6.9.5/doc/samplereport/images/external.png0000644000175000017500000000034612551235562022733 0ustar eugeneeugenePNG  IHDR Ӻ&gAMA7tEXtSoftwareAdobe ImageReadyqe< PLTEuuuPtRNS@*PIDATxb`&& @ P6#@ `XĆ2 d@A3 ( *tIENDB`testng-testng-6.9.5/doc/samplereport/images/external-classic.png0000644000175000017500000000167412551235562024357 0ustar eugeneeugenePNG  IHDR Ӻ&tIME 89 pHYsiTSgAMA aPLTE0`etRNS A0IDATx=A0`+q0u ȄGzZy6S߱^ȱIENDB`testng-testng-6.9.5/doc/samplereport/images/expanded.gif0000644000175000017500000000006412551235562022657 0ustar eugeneeugeneGIF89a! , j ;testng-testng-6.9.5/doc/samplereport/images/collapsed.gif0000644000175000017500000000006512551235562023036 0ustar eugeneeugeneGIF89a! , D`c5 ;testng-testng-6.9.5/doc/samplereport/images/add.gif0000644000175000017500000000031712551235562021620 0ustar eugeneeugeneGIF89a*|~Η0XpN>tA9CGOs+ج!,|I8kl_@4DJ,l Ѡ*e|q8HH ET8(`"B`A`iM0[!KǸ|NianVXp\ KXDNNRmKcEXcJn#;testng-testng-6.9.5/doc/samplereport/css/0000755000175000017500000000000012551235562017723 5ustar eugeneeugenetestng-testng-6.9.5/doc/samplereport/css/print.css0000644000175000017500000000033612551235562021573 0ustar eugeneeugene#banner, #footer, #leftcol, #breadcrumbs, .docs #toc, .docs .courtesylinks, #leftColumn, #navColumn { display: none !important; } #bodyColumn, body.docs div.docs { margin: 0 !important; border: none !important } testng-testng-6.9.5/doc/samplereport/css/maven-theme.css0000644000175000017500000000463212551235562022650 0ustar eugeneeugenebody { padding: 0px 0px 10px 0px; } body, td, select, input, li{ font-family: Verdana, Helvetica, Arial, sans-serif; font-size: 13px; } code{ font-family: Courier, monospace; font-size: 13px; } a { text-decoration: none; } a:link { color:#36a; } a:visited { color:#47a; } a:active, a:hover { color:#69c; } #legend li.externalLink { background: url(../images/external.png) left top no-repeat; padding-left: 18px; } a.externalLink, a.externalLink:link, a.externalLink:visited, a.externalLink:active, a.externalLink:hover { background: url(../images/external.png) right center no-repeat; padding-right: 18px; } #legend li.newWindow { background: url(../images/newwindow.png) left top no-repeat; padding-left: 18px; } a.newWindow, a.newWindow:link, a.newWindow:visited, a.newWindow:active, a.newWindow:hover { background: url(../images/newwindow.png) right center no-repeat; padding-right: 18px; } h2 { padding: 4px 4px 4px 6px; border: 1px solid #999; color: #900; background-color: #ddd; font-weight:900; font-size: x-large; } h3 { padding: 4px 4px 4px 6px; border: 1px solid #aaa; color: #900; background-color: #eee; font-weight: normal; font-size: large; } h4 { padding: 4px 4px 4px 6px; border: 1px solid #bbb; color: #900; background-color: #fff; font-weight: normal; font-size: large; } h5 { padding: 4px 4px 4px 6px; color: #900; font-size: normal; } p { line-height: 1.3em; font-size: small; } #breadcrumbs { border-top: 1px solid #aaa; border-bottom: 1px solid #aaa; background-color: #ccc; } #leftColumn { margin: 10px 0 0 5px; border: 1px solid #999; background-color: #eee; } #navcolumn h5 { font-size: smaller; border-bottom: 1px solid #aaaaaa; padding-top: 2px; color: #000; } table.bodyTable th { color: white; background-color: #bbb; text-align: left; font-weight: bold; } table.bodyTable th, table.bodyTable td { font-size: 1em; } table.bodyTable tr.a { background-color: #ddd; } table.bodyTable tr.b { background-color: #eee; } .source { border: 1px solid #999; } dl { padding: 4px 4px 4px 6px; border: 1px solid #aaa; background-color: #ffc; } dt { color: #900; } #organizationLogo img, #projectLogo img, #projectLogo span{ margin: 8px; } #banner { border-bottom: 1px solid #fff; } testng-testng-6.9.5/doc/samplereport/css/maven-classic.css0000644000175000017500000003546512551235562023177 0ustar eugeneeugenebody { background: #fff; color: #000; padding: 0px 0px 10px 0px; } .contentBox h2 { color: #fff; background-color: #036; } .contentBox h3 { color: #fff; background-color: #888; } .a td { background: #ddd; color: #000; } .b td { background: #efefef; color: #000; } .contentBox th { background-color: #bbb; color: #fff; } div#banner { border-top: 1px solid #369; border-bottom: 1px solid #003; } #banner, #banner td { background: #036; color: #fff; } #banner { border-bottom: 1px solid #fff; } #leftColumn { background: #eee; color: #000; border-right: 1px solid #aaa; border-bottom: 1px solid #aaa; border-top: 1px solid #fff; } #navcolumn { /* bad for IE background: #eee; */ color: #000; border-right: none; border-bottom: none; border-top: none; } #breadcrumbs { background-color: #ddd; color: #000; border-top: 1px solid #fff; border-bottom: 1px solid #aaa; } .source { background-color: #fff; color: #000; border-right: 1px solid #888; border-left: 1px solid #888; border-top: 1px solid #888; border-bottom: 1px solid #888; margin-right: 7px; margin-left: 7px; margin-top: 1em; } .source pre { margin-right: 7px; margin-left: 7px; } a[name]:hover, #leftColumn a[name]:hover { color: inherit !important; } a:link, #breadcrumbs a:visited, #navcolumn a:visited, .contentBox a:visited, .tasknav a:visited { color: blue; } a:active, a:hover, #leftColumn a:active, #leftColumn a:hover { color: #f30 !important; } a:link.selfref, a:visited.selfref { color: #555 !important; } #legend li.externalLink { background: url(../images/external-classic.png) left top no-repeat; padding-left: 18px; } a.externalLink, a.externalLink:link, a.externalLink:visited, a.externalLink:active, a.externalLink:hover { background: url(../images/external-classic.png) right center no-repeat; padding-right: 18px; } #legend li.newWindow { background: url(../images/newwindow-classic.png) left top no-repeat; padding-left: 18px; } a.newWindow, a.newWindow:link, a.newWindow:visited, a.newWindow:active, a.newWindow:hover { background: url(../images/newwindow-classic.png) right center no-repeat; padding-right: 18px; } h2, h3 { margin-top: 1em; margin-bottom: 0; } img.handle { border: 0; padding-right: 2px; } #navcolumn div div { background-image: none; background-repeat: no-repeat; } #navcolumn div div { padding-left: 10px; } /* $Id$ This file defines basic default formatting for HTML conforming to Tigris application style. To extend or override these rules for your instance, edit inst.css instead of this file. */ /* colors, backgrounds, borders, link indication */ .contentBox h2, .contentBox h3, .tabs td, .tabs th, .functnbar { background-image: url(../images/nw_maj_rond.gif); background-repeat: no-repeat; } .functnbar, .functnbar2 { background-color: #aaa; } .functnbar2, .functnbar3 { background-color: #aaa; background-image: url(../images/sw_maj_rond.gif); background-repeat: no-repeat; background-position: bottom left; } .functnbar3 { background-color: #ddd; background-image: url(../images/sw_med_rond.gif); } .functnbar, .functnbar2, .functnbar3 { color: #000; } .functnbar a, .functnbar2 a, .functnbar3 a { color: #000; text-decoration: underline; } #navcolumn .body div, body.docs #toc li li { background-image: url(../images/strich.gif); background-repeat: no-repeat; background-position: .5em .5em; } #searchbox .body div, #navcolumn .body .heading { background-image: none; } a:link.selfref, a:visited.selfref { text-decoration: none; } #leftColumn a, #breadcrumbs a { text-decoration: none; } /* Unsure of this. TODO */ .contentBox h2 a:link, .contentBox h2 a:visited, .contentBox h3 a:link, .contentBox h3 a:visited { color: #fff !important; text-decoration: underline; } table, th, td { border: none; } div.colbar { background: #eee; border-color: #999 #EEE #EEE #999; border-width: 1px; border-style: solid; } .toolgroup { background: #efefef; } .toolgroup .label { border-bottom: 1px solid #666; border-right: 1px solid #666; background: #ddd; color: #555; } .toolgroup .body { border-right: 1px solid #aaa; border-bottom: 1px solid #aaa; } #main { border-top: 1px solid #999; } #rightcol div.www, #rightcol div.help { border: 1px solid #ddd; } body.docs div.docs { background-color: #fff; border-left: 1px solid #ddd; border-top: 1px solid #ddd; } #helptext .label { background-image: url(../images/icon_help_sml.gif); background-repeat: no-repeat; background-position: 97%; } body.docs { background: #eee url(../images/help_logo.gif) top right no-repeat !important; } .docs h2, .docs h3 { border-top: solid 1px #000; } #apphead h2 em { color: #777; } .tabs th { border-right: 1px solid #333; background-color: #ddd; color: #fff; border-left: 1px solid #fff; } .tabs td { background-color: #999; border-bottom: 1px solid #fff; border-right: 1px solid #fff; border-left: 1px solid #fff; } .tabs { border-bottom: 6px #ddd solid; } .tabs th, .tabs th a:link, .tabs th a:visited { color: #555; } .tabs td, .tabs td a:link, .tabs td a:visited { color: #fff; } .tabs a { text-decoration: none; } .axial th { background-color: #ddd; color: black; } .alert { background-color: #ff9; } .expandedwaste { background: url(../images/icon_arrowwaste2_sml.gif) no-repeat; } .collapsedwaste { background: url(../images/icon_arrowwaste1_sml.gif) no-repeat; } .filebrowse .expanded, .filebrowse-alt .expanded { background-image: url(../images/icon_arrowfolderopen2_sml.gif); background-repeat: no-repeat; } .filebrowse .collapsed, .filebrowse-alt .collapsed { background-image: url(../images/icon_arrowfolderclosed1_sml.gif); background-repeat: no-repeat; } .filebrowse .leafnode, .filebrowse-alt .leafnode { background-image: url(../images/icon_folder_sml.gif); background-repeat: no-repeat; } .filebrowse .leaf, .filebrowse-alt .leaf { background-image: url(../images/icon_doc_sml.gif); background-repeat: no-repeat; } .sortup { background: url(../images/icon_sortup.gif) no-repeat; } .sortdown { background: url(../images/icon_sortdown.gif) no-repeat; } .collapsedwaste { background: url(../images/icon_arrowwaste1_sml.gif) no-repeat; } body .grid td { border-top: 1px solid #ccc; border-left: 1px solid #ccc; background-color: transparent; } .confirm { color: #090; } .info { color: #069; } .errormessage, .warningmessage, .donemessage, .infomessage { border-top: 5px solid #900; border-left: 1px solid #900; background-image: url(../images/icon_error_lrg.gif); background-repeat: no-repeat; background-position: 5px 1.33em; } .warningmessage { background-image: url(../images/icon_warning_lrg.gif); border-color: #c60; } .donemessage { background-image: url(../images/icon_success_lrg.gif); border-color: #090; } .infomessage { background-image: url(../images/icon_info_lrg.gif); border-color: #069; } .docinfo { background: url(../images/icon_doc_lrg.gif) no-repeat; } .dirinfo { background: url(../images/icon_folder_lrg.gif) no-repeat; } .memberinfo { background: url(../images/icon_members_lrg.gif) no-repeat; } .usergroupinfo { background: url(../images/icon_usergroups_lrg.gif) no-repeat; } .errormark, .warningmark, .donemark, .infomark { background: url(../images/icon_error_sml.gif) no-repeat; } .warningmark { background-image: url(../images/icon_warning_sml.gif); } .donemark { background-image: url(../images/icon_success_sml.gif); } .infomark { background-image: url(../images/icon_info_sml.gif); } .cvsdiff, .cvsblame { background-color: #ccc; } .cvsdiffadd { background-color: #afa; } .cvsdiffremove { background-color: #faa; } .cvsdiffchanges1 { background-color: #ff7; } .cvsdiffchanges2 { background-color: #ff7; } li.selection ul a { background: #fff; } .band1 { color: #fff; background-color: #663; } .band2 { color: #fff; background-color: #66C; } .band3 { background-color: #C99; } .band4 { background-color: #CFF; } .band5 { color: #fff; background-color: #336; } .band6 { color: #fff; background-color: #966; } .band7 { background-color: #9CC; } .band8 { background-color: #FFC; } .band9 { color: #fff; background-color: #633; } .band10 { color: #fff; background-color: #699; } .band11 { background-color: #CC9; } .band12 { background-color: #CCF; } .band13 { color: #fff; background-color: #366; } .band14 { color: #fff; background-color: #996; } .band15 { background-color: #99C; } .band16 { background-color: #FCC; } .contentBox .helplink, #helptext .helplink { cursor: help; } .legend th, .bars th { background-color: #fff; } /* font and text properties, exclusive of link indication, alignment, text-indent */ body, th, td, input, select { font-family: Verdana, Helvetica, Arial, sans-serif; } code, pre { font-family: 'Andale Mono', Courier, monospace; } body, .contentBox h2, .contentBox h3, #rightcol h2, pre, code, #apphead h2 small, h3, th, td { font-size: x-small; voice-family: "\"}\""; voice-family: inherit; font-size: small; } small, div#footer, div#login, div.tabs th, div.tabs td, input, select, .paginate, .functnbar, .functnbar2, .functnbar3, #breadcrumbs, .courtesylinks, #rightcol div.help, .colbar, .tasknav, body.docs div#toc, #leftColumn, .legend, .bars { font-size: xx-small; voice-family: "\"}\""; voice-family: inherit; font-size: x-small; } .tabs td, .tabs th, dt, .tasknav .selfref, #login .username, .selection { font-weight: bold; } li.selection ul { font-weight: normal; } #apphead h2 em { font-style: normal; } #banner h1 { font-size: 1.25em; } /* box properties (exclusive of borders), positioning, alignments, list types, text-indent */ #bodyColumn h2 { margin-top: .3em; margin-bottom: .5em; } p, ul, ol, dl, .bars table { margin-top: .67em; margin-bottom: .67em; } form { margin: 0; } #bodyColumn { padding-left: 12px; padding-right: 12px; width: 100%; voice-family: "\"}\""; voice-family: inherit; width: auto; } html>body #bodyColumn { width: auto; } .docs { line-height: 1.4; } ol ol { list-style-type: lower-alpha; } ol ol ol { list-style-type: lower-roman; } .contentBox h2, .contentBox h3 { padding: 5px; margin-right: 2px; } .contentBox td, .contentBox th { padding: 2px 3px; } .h2 p, .h3 p, .h2 dt, .h3 dt { margin-right: 7px; margin-left: 7px; } .tasknav { margin-bottom: 1.33em; } div.colbar { padding: 3px; margin: 2px 2px 0; } .tabs { margin-top: .67em; margin-right: 2px; margin-left: 2px; padding-left: 8px; } .tabs td, .tabs th { padding: 3px 9px; } #rightcol div.www, #rightcol div.help { padding: 0 .5em; } body.docs #toc { position: absolute; top: 15px; left: 0px; width: 120px; padding: 0 20px 0 0; } body.docs #toc ul, #toc ol { margin-left: 0; padding-left: 0; } body.docs #toc li { margin-top: 7px; padding-left: 10px; list-style-type: none; } body.docs div.docs { margin: 61px 0 0 150px; padding: 1em 2em 1em 1em !important; } .docs p+p { text-indent: 5%; margin-top: -.67em; } .docs h2, .docs h3 { margin-bottom: .1em; padding-top: .3em; } .functnbar, .functnbar2, .functnbar3 { padding: 5px; margin: .67em 2px; } .functnbar3 { margin-top: 0; } body { padding: 1em; } body.composite, body.docs { margin: 0; padding: 0; } th, td { text-align: left; vertical-align: top; } .right { text-align: right !important; } .center { text-align: center !important; } .axial th, .axial th .strut { text-align: right; } .contentBox .axial td th { text-align: left; } body .stb { margin-top: 1em; text-indent: 0; } body .mtb { margin-top: 2em; text-indent: 0; } .courtesylinks { margin-top: 1em; padding-top: 1em; } dd { margin-bottom: .67em; } .toolgroup { margin-bottom: 6px; } .toolgroup .body { padding: 4px 4px 4px 0; } .toolgroup .label { padding: 4px; } .toolgroup .body div { padding-bottom: .3em; padding-left: 1em; } .toolgroup .body div div { margin-top: .3em; padding-bottom: 0; } .tier1 { margin-left: 0; } .tier2 { margin-left: 1.5em; } .tier3 { margin-left: 3em; } .tier4 { margin-left: 4.5em; } .tier5 { margin-left: 6em; } .tier6 { margin-left: 7.5em; } .tier7 { margin-left: 9em; } .tier8 { margin-left: 10.5em; } .tier9 { margin-left: 12em; } .tier10 { margin-left: 13.5em; } .filebrowse .expanded, .filebrowse .collapsed { padding-left: 34px; } .filebrowse .leafnode, .filebrowse .leaf { padding-left: 20px; } .messagechild { padding-left: 34px; } .filebrowse-alt .expanded, .filebrowse-alt .collapsed, .filebrowse-alt .leaf, .filebrowse-alt .leafnode, .expandedwaste, .collapsedwaste, .sortup, .sortdown { /* hide from macie5\*/ float: left; /* resume */ display: inline-block; height: 15px; width: 34px; padding-left: 0 !important; } .filebrowse-alt .leaf, .filebrowse-alt .leafnode, .sortup, .sortdown { width: 20px; } .filebrowse ul, .filebrowse-alt ul { list-style-type: none; padding-left: 0; margin-left: 0; } .filebrowse ul ul, .filebrowse-alt ul ul { margin-left: 1.5em; margin-top: 0; padding-top: .67em; } .filebrowse li, .filebrowse-alt li { margin-bottom: .67em; } td.filebrowse h2 { margin-top: 0; } .errormessage, .warningmessage, .donemessage, .infomessage, .docinfo, .dirinfo, .memberinfo, .usergroupinfo { margin: .67em 0; padding: .33em 0 .67em 42px; min-height: 32px; } .errormark, .warningmark, .donemark, .infomark { padding-left: 20px; min-height: 15px; } .alt { display: none; } #banner h1 { margin: 0; } .axial th, .axial th .strut, #leftColumn .strut { width: 12em; } #breadcrumbs { padding: 2px 8px; } /* Bad for IE .contentBox h2, .contentBox h3, .bars { clear: both; } */ .legend { float: right; } .legend th, .bars th { text-align: right; padding-left: 1em; } .bars table { table-layout: fixed; } .bars th { width: 12em; } #projectdocumentlist td.filebrowse-alt { padding-right: .75em; } #organizationLogo img, #projectLogo img, #projectLogo span{ margin: 8px; } testng-testng-6.9.5/doc/samplereport/css/maven-base.css0000644000175000017500000000453212551235562022457 0ustar eugeneeugenebody { margin: 0px; padding: 0px; } img { border:none; } table { padding:0px; width: 100%; margin-left: -2px; margin-right: -2px; } acronym { cursor: help; border-bottom: 1px dotted #feb; } table.bodyTable th, table.bodyTable td { padding: 2px 4px 2px 4px; vertical-align: top; } div.clear{ clear:both; visibility: hidden; } div.clear hr{ display: none; } #bannerLeft, #bannerRight { font-size: xx-large; font-weight: bold; } #bannerLeft img, #bannerRight img { margin: 0px; } .xleft, #bannerLeft img { float:left; text-shadow: #7CFC00; } .xright, #bannerRight img { float:right; text-shadow: #7CFC00; } #banner { padding: 0px; } #banner img { border: none; } #breadcrumbs { padding: 3px 10px 3px 10px; } #leftColumn { width: 150px; float:left; } #bodyColumn { margin-right: 1.5em; margin-left: 177px; } #legend { padding: 8px 0 8px 0; } #navcolumn { padding: 8px 4px 0 8px; } #navcolumn h5 { margin: 0; padding: 0; font-size: small; } #navcolumn ul { margin: 0; padding: 0; font-size: small; } #navcolumn li { list-style-type: none; background-image: none; background-repeat: no-repeat; background-position: 0 0.4em; padding-left: 16px; list-style-position: ouside; line-height: 1.2em; font-size: smaller; } #navcolumn li.expanded { background-image: url(../images/expanded.gif); } #navcolumn li.collapsed { background-image: url(../images/collapsed.gif); } #poweredBy { text-align: center; } #navcolumn img { margin-top: 10px; margin-bottom: 3px; } #poweredBy img { display:block; margin: 20px 0 20px 17px; border: 1px solid black; width: 90px; height: 30px; } #search img { margin: 0px; display: block; } #search #q, #search #btnG { border: 1px solid #999; margin-bottom:10px; } #search form { margin: 0px; } #lastPublished { font-size: x-small; } .navSection { margin-bottom: 2px; padding: 8px; } .navSectionHead { font-weight: bold; font-size: x-small; } .section { padding: 4px; } #footer { padding: 3px 10px 3px 10px; font-size: x-small; } #breadcrumbs { font-size: x-small; margin: 0pt; } .source { padding: 12px; margin: 1em 7px 1em 7px; } .source pre { margin: 0px; padding: 0px; } testng-testng-6.9.5/doc/prettify.js0000644000175000017500000012171712551235562016633 0ustar eugeneeugene// Copyright 2005 Google Inc. // All Rights Reserved. // // msamuel@google.com // Usage: // 1) include this source file in an html page via // // 2) define style rules. See the example page for examples. // 3) mark the

 and  tags in your source with class=prettyprint.
//    You can also use the (html deprecated)  tag, but the pretty printer
//    needs to do more substantial DOM manipulations to support that, so some
//    css styles may not be preserved.

// Change log:
// cbeust, 2006/08/22
//   Java annotations (start with "@") are now captured as literals ("lit")
// 

var PR_keywords = new Object();
/** initialize the keyword list for our target languages. */
(function () {
  var CPP_KEYWORDS = (
    "bool break case catch char class const const_cast continue default " +
    "delete deprecated dllexport dllimport do double dynamic_cast else enum " +
    "explicit extern false float for friend goto if inline int long mutable " +
    "naked namespace new noinline noreturn nothrow novtable operator private " +
    "property protected public register reinterpret_cast return selectany " +
    "short signed sizeof static static_cast struct switch template this " +
    "thread throw true try typedef typeid typename union unsigned using " +
    "declaration, using directive uuid virtual void volatile while typeof");
  var JAVA_KEYWORDS = (
    "abstract default goto package synchronized boolean do if private this " +
    "break double implements protected throw byte else import public throws " +
    "case enum instanceof return transient catch extends int short try char " +
    "final interface static void class finally long strictfp volatile const " +
    "float native super while continue for new switch");
  var PYTHON_KEYWORDS = (
    "and assert break class continue def del elif else except exec finally " +
    "for from global if import in is lambda not or pass print raise return " +
    "try while yield");
  var JSCRIPT_KEYWORDS = (
    "abstract boolean break byte case catch char class const continue " +
    "debugger default delete do double else enum export extends false final " +
    "finally float for function goto if implements import in instanceof int " +
    "interface long native new null package private protected public return " +
    "short static super switch synchronized this throw throws transient " +
    "true try typeof var void volatile while with NaN Infinity");
  var PERL_KEYWORDS = (
    "foreach require sub unless until use elsif BEGIN END");
  var SH_KEYWORDS = (
    "if then do else fi end");
  var KEYWORDS = [CPP_KEYWORDS, JAVA_KEYWORDS, PYTHON_KEYWORDS,
                  JSCRIPT_KEYWORDS, PERL_KEYWORDS, SH_KEYWORDS];
  for (var k = 0; k < KEYWORDS.length; k++) {
    var kw = KEYWORDS[k].split(' ');
    for (var i = 0; i < kw.length; i++) {
      if (kw[i]) { PR_keywords[kw[i]] = true; }
    }
  }
}).call(this);

// token style names.  correspond to css classes
/** token style for a string literal */
var PR_STRING = 'str';
/** token style for a keyword */
var PR_KEYWORD = 'kwd';
/** token style for a comment */
var PR_COMMENT = 'com';
/** token style for a type */
var PR_TYPE = 'typ';
/** token style for a literal value.  e.g. 1, null, true. */
var PR_LITERAL = 'lit';
/** token style for a punctuation string. */
var PR_PUNCTUATION = 'pun';
/** token style for a punctuation string. */
var PR_PLAIN = 'pln';

/** token style for an sgml tag. */
var PR_TAG = 'tag';
/** token style for a markup declaration such as a DOCTYPE. */
var PR_DECLARATION = 'dec';
/** token style for embedded source. */
var PR_SOURCE = 'src';
/** token style for an sgml attribute name. */
var PR_ATTRIB_NAME = 'atn';
/** token style for an sgml attribute value. */
var PR_ATTRIB_VALUE = 'atv';

/** the position of the end of a token during.  A division of a string into
  * n tokens can be represented as a series n - 1 token ends, as long as
  * runs of whitespace warrant their own token.
  * @private
  */
function PR_TokenEnd(end, style) {
  if (undefined === style) { throw new Error('BAD'); }
  if ('number' != typeof(end)) { throw new Error('BAD'); }
  this.end = end;
  this.style = style;
}
PR_TokenEnd.prototype.toString = function () {
  return '[PR_TokenEnd ' + this.end +
    (this.style ? ':' + this.style : '') + ']';
};


/** a chunk of text with a style.  These are used to represent both the output
  * from the lexing functions as well as intermediate results.
  * @constructor
  * @param token the token text
  * @param style one of the token styles defined in designdoc-template, or null
  *   for a styleless token, such as an embedded html tag.
  * @private
  */
function PR_Token(token, style) {
  if (undefined === style) { throw new Error('BAD'); }
  this.token = token;
  this.style = style;
}

PR_Token.prototype.toString = function () {
  return '[PR_Token ' + this.token + (this.style ? ':' + this.style : '') + ']';
};


/** a helper class that decodes common html entities used to escape source and
  * markup punctuation characters in html.
  * @constructor
  * @private
  */
function PR_DecodeHelper() {
  this.next = 0;
  this.ch = '\0';
}

PR_DecodeHelper.prototype.decode = function (s, i) {
  var next = i + 1;
  var ch = s.charAt(i);
  if ('&' == ch) {
    var semi = s.indexOf(';', next);
    if (semi >= 0 && semi < next + 4) {
      var entityName = s.substring(next, semi).toLowerCase();
      next = semi + 1;
      if ('lt' == entityName) {
        ch = '<';
      } else if ('gt' == entityName) {
        ch = '>';
      } else if ('quot' == entityName) {
        ch = '"';
      } else if ('apos' == entityName) {
        ch = '\'';
      } else if ('amp' == entityName) {
        ch = '&';
      } else {
        next = i + 1;
      }
    }
  }
  this.next = next;
  this.ch = ch;
  return this.ch;
}


// some string utilities
function PR_isWordChar(ch) {
  return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
}

function PR_isIdentifierStart(ch) {
  return PR_isWordChar(ch) || ch == '_' || ch == '$' || ch == '@';
}

function PR_isIdentifierPart(ch) {
  return PR_isIdentifierStart(ch) || PR_isDigitChar(ch);
}

function PR_isSpaceChar(ch) {
  return "\t \r\n".indexOf(ch) >= 0;
}

function PR_isDigitChar(ch) {
  return ch >= '0' && ch <= '9';
}

function PR_trim(s) {
  var i = 0, j = s.length - 1;
  while (i <= j && PR_isSpaceChar(s.charAt(i))) { ++i; }
  while (j > i && PR_isSpaceChar(s.charAt(j))) { --j; }
  return s.substring(i, j + 1);
}

function PR_startsWith(s, prefix) {
  return s.length >= prefix.length && prefix == s.substring(0, prefix.length);
}

function PR_endsWith(s, suffix) {
  return s.length >= suffix.length &&
         suffix == s.substring(s.length - suffix.length, s.length);
}

/** true iff prefix matches the first prefix characters in chars[0:len].
  * @private
  */
function PR_prefixMatch(chars, len, prefix) {
  if (len < prefix.length) { return false; }
  for (var i = 0, n = prefix.length; i < n; ++i) {
    if (prefix.charAt(i) != chars[i]) { return false; }
  }
  return true;
}

/** used to convert html special characters embedded in XMP tags into html. */
function PR_textToHtml(str) {
  return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}


/** split markup into chunks of html tags (style null) and
  * plain text (style {@link #PR_PLAIN}).
  *
  * @param s a String of html.
  * @return an Array of PR_Tokens of style PR_PLAIN and null.
  * @private
  */
function PR_chunkify(s) {
  var chunks = new Array();
  var state = 0;
  var start = 0;
  var pos = -1;
  for (var i = 0, n = s.length; i < n; ++i) {
    var ch = s.charAt(i);
    switch (state) {
      case 0:
        if ('<' == ch) { state = 1; }
        break;
      case 1:
        pos = i - 1;
        if ('/' == ch) { state = 2; }
        else if (PR_isWordChar(ch)) { state = 3; }
        else if ('<' == ch) { state = 1; }
        else { state = 0; }
        break;
      case 2:
        if (PR_isWordChar(ch)) { state = 3; }
        else if ('<' == ch) { state = 1; }
        else { state = 0; }
        break;
      case 3:
        if ('>' == ch) {
          if (pos > start) {
            chunks.push(new PR_Token(s.substring(start, pos), PR_PLAIN));
          }
          chunks.push(new PR_Token(s.substring(pos, i + 1), null));
          start = i + 1;
          pos = -1;
          state = 0;
        }
        break;
    }
  }
  if (s.length > start) {
    chunks.push(new PR_Token(s.substring(start, s.length), PR_PLAIN));
  }
  return chunks;
}

/** splits chunks around entities.
  * @private
  */
function PR_splitEntities(chunks) {
  var chunksOut = new Array();
  var state = 0;
  for (var ci = 0, nc = chunks.length; ci < nc; ++ci) {
    var chunk = chunks[ci];
    if (PR_PLAIN != chunk.style) {
      chunksOut.push(chunk);
      continue;
    }
    var s = chunk.token;
    var pos = 0;
    var start;
    for (var i = 0; i < s.length; ++i) {
      var ch = s.charAt(i);
      switch (state) {
        case 0:
          if ('&' == ch) { state = 1; }
          break;
        case 1:
          if ('#' == ch || PR_isWordChar(ch)) {
            start = i - 1;
            state = 2;
          } else {
            state = 0;
          }
          break;
        case 2:
          if (';' == ch) {
            if (start > pos) {
              chunksOut.push(
                  new PR_Token(s.substring(pos, start), chunk.style));
            }
            chunksOut.push(new PR_Token(s.substring(start, i + 1), null));
            pos = i + 1;
            state = 0;
          }
          break;
      }
    }
    if (s.length > pos) {
      chunksOut.push(pos ?
                     new PR_Token(s.substring(pos, s.length), chunk.style) :
                     chunk);
    }
  }
  return chunksOut;
}

/** walk the tokenEnds list and the chunk list in parallel to generate a list
  * of split tokens.
  * @private
  */
function PR_splitChunks(chunks, tokenEnds) {
  var tokens = new Array();  // the output

  var ci = 0;  // index into chunks
  // position of beginning of amount written so far in absolute space.
  var posAbs = 0;
  // position of amount written so far in chunk space
  var posChunk = 0;

  // current chunk
  var chunk = new PR_Token('', null);

  for (var ei = 0, ne = tokenEnds.length; ei < ne; ++ei) {
    var tokenEnd = tokenEnds[ei];
    var end = tokenEnd.end;

    var tokLen = end - posAbs;
    var remainingInChunk = chunk.token.length - posChunk;
    while (remainingInChunk <= tokLen) {
      if (remainingInChunk > 0) {
        tokens.push(
            new PR_Token(chunk.token.substring(posChunk, chunk.token.length),
                         null == chunk.style ? null : tokenEnd.style));
      }
      posAbs += remainingInChunk;
      posChunk = 0;
      if (ci < chunks.length) { chunk = chunks[ci++]; }

      tokLen = end - posAbs;
      remainingInChunk = chunk.token.length - posChunk;
    }

    if (tokLen) {
      tokens.push(
          new PR_Token(chunk.token.substring(posChunk, posChunk + tokLen),
                       tokenEnd.style));
      posAbs += tokLen;
      posChunk += tokLen;
    }
  }

  return tokens;
}

/** splits markup tokens into declarations, tags, and source chunks.
  * @private
  */
function PR_splitMarkup(chunks) {
  // A state machine to split out declarations, tags, etc.
  // This state machine deals with absolute space in the text, indexed by k,
  // and position in the current chunk, indexed by pos and tokenStart to
  // generate a list of the ends of tokens.
  // Absolute space is calculated by considering the chunks as appended into
  // one big string, as they were before being split.

  // Known failure cases
  // Server side scripting sections such as <?...?> in attributes.
  // i.e. <span class="<? foo ?>">
  // Handling this would require a stack, and we don't use PHP.

  // The output: a list of pairs of PR_TokenEnd instances
  var tokenEnds = new Array();

  var state = 0;  // FSM state variable
  var k = 0;  // position in absolute space of the start of the current chunk
  var tokenStart = -1;  // the start of the current token

  // Try to find a closing tag for any open <style> or <script> tags
  // We can't do this at a later stage because then the following case
  // would fail:
  // <script>document.writeln('<!--');</script>

  // We use tokenChars[:tokenCharsI] to accumulate the tag name so that we
  // can check whether to enter into a no scripting section when the tag ends.
  var tokenChars = new Array(12);
  var tokenCharsI = 0;
  // if non null, the tag prefix that we need to see to break out.
  var endScriptTag = null;
  var decodeHelper = new PR_DecodeHelper();

  for (var ci = 0, nc = chunks.length; ci < nc; ++ci) {
    var chunk = chunks[ci];
    if (PR_PLAIN != chunk.style) {
      k += chunk.token.length;
      continue;
    }

    var s = chunk.token;
    var pos = 0;  // the position past the last character processed so far in s

    for (var i = 0, n = s.length; i < n; /* i = next at bottom */) {
      decodeHelper.decode(s, i);
      var ch = decodeHelper.ch;
      var next = decodeHelper.next;

      var tokenStyle = null;
      switch (state) {
        case 0:
          if ('<' == ch) { state = 1; }
          break;
        case 1:
          tokenCharsI = 0;
          if ('/' == ch) {  // only consider close tags if we're in script/style
            state = 7;
          } else if (null == endScriptTag) {
            if ('!' == ch) {
              state = 2;
            } else if (PR_isWordChar(ch)) {
              state = 8;
            } else if ('?' == ch) {
              state = 9;
            } else if ('%' == ch) {
              state = 11;
            } else if ('<' != ch) {
              state = 0;
            }
          } else if ('<' != ch) {
            state = 0;
          }
          break;
        case 2:
          if ('-' == ch) {
            state = 4;
          } else if (PR_isWordChar(ch)) {
            state = 3;
          } else if ('<' == ch) {
            state = 1;
          } else {
            state = 0;
          }
          break;
        case 3:
          if ('>' == ch) {
            state = 0;
            tokenStyle = PR_DECLARATION;
          }
          break;
        case 4:
          if ('-' == ch) { state = 5; }
          break;
        case 5:
          if ('-' == ch) { state = 6; }
          break;
        case 6:
          if ('>' == ch) {
            state = 0;
            tokenStyle = PR_COMMENT;
          } else if ('-' == ch) {
            state = 6;
          } else {
            state = 4;
          }
          break;
        case 7:
          if (PR_isWordChar(ch)) {
            state = 8;
          } else if ('<' == ch) {
            state = 1;
          } else {
            state = 0;
          }
          break;
        case 8:
          if ('>' == ch) {
            state = 0;
            tokenStyle = PR_TAG;
          }
          break;
        case 9:
          if ('?' == ch) { state = 10; }
          break;
        case 10:
          if ('>' == ch) {
            state = 0;
            tokenStyle = PR_SOURCE;
          } else if ('?' != ch) {
            state = 9;
          }
          break;
        case 11:
          if ('%' == ch) { state = 12; }
          break;
        case 12:
          if ('>' == ch) {
            state = 0;
            tokenStyle = PR_SOURCE;
          } else if ('%' != ch) {
            state = 11;
          }
          break;
      }

      if (tokenCharsI < tokenChars.length) {
        tokenChars[tokenCharsI++] = ch.toLowerCase();
      }
      if (1 == state) { tokenStart = k + i; }
      i = next;
      if (tokenStyle != null) {
        if (null != tokenStyle) {
          if (endScriptTag) {
            if (PR_prefixMatch(tokenChars, tokenCharsI, endScriptTag)) {
              endScriptTag = null;
            }
          } else {
            if (PR_prefixMatch(tokenChars, tokenCharsI, 'script')) {
              endScriptTag = '/script';
            } else if (PR_prefixMatch(tokenChars, tokenCharsI, 'style')) {
              endScriptTag = '/style';
            } else if (PR_prefixMatch(tokenChars, tokenCharsI, 'xmp')) {
              endScriptTag = '/xmp';
            }
          }
          // disallow the tag if endScriptTag is set and this was not an open
          // tag.
          if (endScriptTag && tokenCharsI && '/' == tokenChars[0]) {
            tokenStyle = null;
          }
        }
        if (null != tokenStyle) {
          tokenEnds.push(new PR_TokenEnd(tokenStart, PR_PLAIN));
          tokenEnds.push(new PR_TokenEnd(k + next, tokenStyle));
        }
      }
    }
    k += chunk.token.length;
  }
  tokenEnds.push(new PR_TokenEnd(k, PR_PLAIN));

  return tokenEnds;
}

/** splits the given string into comment, string, and "other" tokens.
  * @return an array of PR_Tokens with style in
  *   (PR_STRING, PR_COMMENT, PR_PLAIN, null)
  *   The result array may contain spurious zero length tokens.  Ignore them.
  *
  * @private
  */
function PR_splitStringAndCommentTokens(chunks) {
  // a state machine to split out comments, strings, and other stuff
  var tokenEnds = new Array();  // positions of ends of tokens in absolute space
  var state = 0;  // FSM state variable
  var delim = -1;  // string delimiter
  var k = 0;  // absolute position of beginning of current chunk
  for (var ci = 0, nc = chunks.length; ci < nc; ++ci) {
    var chunk = chunks[ci];
    var s = chunk.token;
    if (PR_PLAIN == chunk.style) {
      for (var i = 0, n = s.length; i < n; ++i) {
        var ch = s.charAt(i);
        if (0 == state) {
          if (ch == '"' || ch == '\'' || ch == '`') {
            tokenEnds.push(new PR_TokenEnd(k + i, PR_PLAIN));
            state = 1;
            delim = ch;
          } else if (ch == '/') {
            state = 3;
          } else if (ch == '#') {
            tokenEnds.push(new PR_TokenEnd(k + i, PR_PLAIN));
            state = 4;
          }
        } else if (1 == state) {
          if (ch == delim) {
            state = 0;
            tokenEnds.push(new PR_TokenEnd(k + i + 1, PR_STRING));
          } else if (ch == '\\') {
            state = 2;
          }
        } else if (2 == state) {
          state = 1;
        } else if (3 == state) {
          if (ch == '/') {
            state = 4;
            tokenEnds.push(new PR_TokenEnd(k + i - 1, PR_PLAIN));
          } else if (ch == '*') {
            state = 5;
            tokenEnds.push(new PR_TokenEnd(k + i - 1, PR_PLAIN));
          } else {
            state = 0;
            // next loop will reenter state 0 without same value of i, so
            // ch will be reconsidered as start of new token.
            --i;
          }
        } else if (4 == state) {
          if (ch == '\r' || ch == '\n') {
            state = 0;
            tokenEnds.push(new PR_TokenEnd(k + i, PR_COMMENT));
          }
        } else if (5 == state) {
          if (ch == '*') {
            state = 6;
          }
        } else if (6 == state) {
          if (ch == '/') {
            state = 0;
            tokenEnds.push(new PR_TokenEnd(k + i + 1, PR_COMMENT));
          } else if (ch != '*') {
            state = 5;
          }
        }
      }
    }
    k += s.length;
  }
  tokenEnds.push(new PR_TokenEnd(k, PR_PLAIN));  // a token ends at the end

  return PR_splitChunks(chunks, tokenEnds);
}

/** used by lexSource to split a non string, non comment token.
  * @private
  */
function PR_splitNonStringNonCommentToken(s, outlist) {
  var pos = 0;
  var state = 0;
  for (var i = 0; i <= s.length; i++) {
    var ch = s.charAt(i);
    // the next state.
    // if set to -1 then it will cause a reentry to state 0 without consuming
    // another character.
    var nstate = state;

    if (i == s.length) {
      // nstate will not be equal to state, so it will append the token
      nstate = -2;
    } else {
      switch (state) {
      case 0:  // whitespace state
        if (PR_isIdentifierStart(ch)) {
          nstate = 1;
        } else if (PR_isDigitChar(ch)) {
          nstate = 2;
        } else if (!PR_isSpaceChar(ch)) {
          nstate = 3;
        }
        if (nstate && pos < i) {
          var t = s.substring(pos, i);
          outlist.push(new PR_Token(t, PR_PLAIN));
          pos = i;
        }
        break;
      case 1:  // identifier state
        if (!PR_isIdentifierPart(ch)) {
          nstate = -1;
        }
        break;
      case 2:  // number literal state
        // handle numeric literals like
        // 0x7f 300UL 100_000

        // this does not treat floating point values as a single literal
        //   0.1 and 3e-6
        // are each split into multiple tokens
        if (!(PR_isDigitChar(ch) || PR_isWordChar(ch) || ch == '_')) {
          nstate = -1;
        }
        break;
      case 3:  // punctuation state
        if (PR_isIdentifierStart(ch) || PR_isDigitChar(ch) ||
            PR_isSpaceChar(ch)) {
          nstate = -1;
        }
        break;
      }
    }

    if (nstate != state) {
      if (nstate < 0) {
        if (i > pos) {
          var t = s.substring(pos, i);
          var ch0 = t.charAt(0);
          var style;
          if (PR_isIdentifierStart(ch0)) {
            if (PR_keywords[t]) {
              style = PR_KEYWORD;
            }
            else if (ch0 == '@') {
              style = PR_LITERAL;
            } else {
              // Treat any word that starts with an uppercase character and
              // contains at least one lowercase character as a type, or
              // ends with _t.
              // This works perfectly for Java, pretty well for C++, and
              // passably for Python.  The _t catches C structs.
              var isType = false;
              if (ch0 >= 'A' && ch0 <= 'Z') {
                for (var j = 1; j < t.length; j++) {
                  var ch1 = t.charAt(j);
                  if (ch1 >= 'a' && ch1 <= 'z') {
                    isType = true;
                    break;
                  }
                }
                if (!isType && t.length >= 2 &&
                    t.substring(t.length - 2) == '_t') {
                  isType = true;
                }
              }
              style = isType ? PR_TYPE : PR_PLAIN;
            }
          } else if (PR_isDigitChar(ch0)) {
            style = PR_LITERAL;
          } else if (!PR_isSpaceChar(ch0)) {
            style = PR_PUNCTUATION;
          } else {
            style = PR_PLAIN;
          }
          pos = i;
          outlist.push(new PR_Token(t, style));
        }

        state = 0;
        if (nstate == -1) {
          // don't increment.  This allows us to use state 0 to redispatch based
          // on the current character.
          i--;
          continue;
        }
      }
      state = nstate;
    }
  }
}

/** split a group of chunks of markup.
  * @private
  */
function PR_tokenizeMarkup(chunks) {
  if (!(chunks && chunks.length)) { return chunks; }

  var tokenEnds = PR_splitMarkup(chunks);
  return PR_splitChunks(chunks, tokenEnds);
}

/** split tags attributes and their values out from the tag name, and
  * recursively lex source chunks.
  * @private
  */
function PR_splitTagAttributes(tokens) {
  var tokensOut = new Array();
  var state = 0;
  var stateStyle = PR_TAG;
  var delim = null;  // attribute delimiter for quoted value state.
  var decodeHelper = new PR_DecodeHelper();
  for (var ci = 0; ci < tokens.length; ++ci) {
    var tok = tokens[ci];
    if (PR_TAG == tok.style) {
      var s = tok.token;
      var start = 0;
      for (var i = 0; i < s.length; /* i = next at bottom */) {
        decodeHelper.decode(s, i);
        var ch = decodeHelper.ch;
        var next = decodeHelper.next;

        var emitEnd = null;  // null or position of end of chunk to emit.
        var nextStyle = null;  // null or next value of stateStyle
        if (ch == '>') {
          if (PR_TAG != stateStyle) {
            emitEnd = i;
            nextStyle = PR_TAG;
          }
        } else {
          switch (state) {
            case 0:
              if ('<' == ch) { state = 1; }
              break;
            case 1:
              if (PR_isSpaceChar(ch)) { state = 2; }
              break;
            case 2:
              if (!PR_isSpaceChar(ch)) {
                nextStyle = PR_ATTRIB_NAME;
                emitEnd = i;
                state = 3;
              }
              break;
            case 3:
              if ('=' == ch) {
                emitEnd = i;
                nextStyle = PR_TAG;
                state = 5;
              } else if (PR_isSpaceChar(ch)) {
                emitEnd = i;
                nextStyle = PR_TAG;
                state = 4;
              }
              break;
            case 4:
              if ('=' == ch) {
                state = 5;
              } else if (!PR_isSpaceChar(ch)) {
                emitEnd = i;
                nextStyle = PR_ATTRIB_NAME;
                state = 3;
              }
              break;
            case 5:
              if ('"' == ch || '\'' == ch) {
                emitEnd = i;
                nextStyle = PR_ATTRIB_VALUE;
                state = 6;
                delim = ch;
              } else if (!PR_isSpaceChar(ch)) {
                emitEnd = i;
                nextStyle = PR_ATTRIB_VALUE;
                state = 7;
              }
              break;
            case 6:
              if (ch == delim) {
                emitEnd = next;
                nextStyle = PR_TAG;
                state = 2;
              }
              break;
            case 7:
              if (PR_isSpaceChar(ch)) {
                emitEnd = i;
                nextStyle = PR_TAG;
                state = 2;
              }
              break;
          }
        }
        if (emitEnd) {
          if (emitEnd > start) {
            tokensOut.push(
                new PR_Token(s.substring(start, emitEnd), stateStyle));
            start = emitEnd;
          }
          stateStyle = nextStyle;
        }
        i = next;
      }
      if (s.length > start) {
        tokensOut.push(new PR_Token(s.substring(start, s.length), stateStyle));
      }
    } else {
      if (tok.style) {
        state = 0;
        stateStyle = PR_TAG;
      }
      tokensOut.push(tok);
    }
  }
  return tokensOut;
}

/** identify regions of markup that are really source code, and recursivley
  * lex them.
  * @private
  */
function PR_splitSourceNodes(tokens) {
  var tokensOut = new Array();
  // when we see a <script> tag, store '/' here so that we know to end the
  // source processing
  var endScriptTag = null;
  var decodeHelper = new PR_DecodeHelper();

  var sourceChunks = null;

  for (var ci = 0, nc = tokens.length; ci < nc; ++ci) {
    var tok = tokens[ci];
    if (null == tok.style) {
      tokens.push(tok);
      continue;
    }

    var s = tok.token;

    if (null == endScriptTag) {
      if (PR_SOURCE == tok.style) {
        // split off any starting and trailing <?, <%
        if ('<' == decodeHelper.decode(s, 0)) {
          decodeHelper.decode(s, decodeHelper.next);
          if ('%' == decodeHelper.ch || '?' == decodeHelper.ch) {
            endScriptTag = decodeHelper.ch;
            tokensOut.push(new PR_Token(s.substring(0, decodeHelper.next),
                                        PR_TAG));
            s = s.substring(decodeHelper.next, s.length);
          }
        }
      } else if (PR_TAG == tok.style) {
        if ('<' == decodeHelper.decode(s, 0) &&
            '/' != s.charAt(decodeHelper.next)) {
          var tagContent = s.substring(decodeHelper.next).toLowerCase();
          // FIXME(msamuel): this does not mirror exactly the code in
          // in PR_splitMarkup that defers splitting tags inside script and
          // style blocks.
          if (PR_startsWith(tagContent, 'script') ||
              PR_startsWith(tagContent, 'style') ||
              PR_startsWith(tagContent, 'xmp')) {
            endScriptTag = '/';
          }
        }
      }
    }

    if (null != endScriptTag) {
      var endTok = null;
      if (PR_SOURCE == tok.style) {
        if (endScriptTag == '%' || endScriptTag == '?') {
          var pos = s.lastIndexOf(endScriptTag);
          if (pos >= 0 && '>' == decodeHelper.decode(s, pos + 1) &&
              s.length == decodeHelper.next) {
            endTok = new PR_Token(s.substring(pos, s.length), PR_TAG);
            s = s.substring(0, pos);
          }
        }
        if (null == sourceChunks) { sourceChunks = new Array(); }
        sourceChunks.push(new PR_Token(s, PR_PLAIN));
      } else if (PR_PLAIN == tok.style) {
        if (null == sourceChunks) { sourceChunks = new Array(); }
        sourceChunks.push(tok);
      } else if (PR_TAG == tok.style) {
        // if it starts with </ then it must be the end tag.
        if ('<' == decodeHelper.decode(tok.token, 0) &&
            tok.token.length > decodeHelper.next &&
            '/' == decodeHelper.decode(tok.token, decodeHelper.next)) {
          endTok = tok;
        } else {
          tokensOut.push(tok);
        }
      } else {
        if (sourceChunks) {
          sourceChunks.push(tok);
        } else {
          // push remaining tag and attribute tokens from the opening tag
          tokensOut.push(tok);
        }
      }
      if (endTok) {
        if (sourceChunks) {
          var sourceTokens = PR_lexSource(sourceChunks);
          tokensOut.push(new PR_Token('<span class=embsrc>', null));
          for (var si = 0, ns = sourceTokens.length; si < ns; ++si) {
            tokensOut.push(sourceTokens[si]);
          }
          tokensOut.push(new PR_Token('</span>', null));
          sourceChunks = null;
        }
        tokensOut.push(endTok);
        endScriptTag = null;
      }
    } else {
      tokensOut.push(tok);
    }
  }
  return tokensOut;
}

/** splits the quotes from an attribute value.
  * ['"foo"'] -> ['"', 'foo', '"']
  * @private
  */
function PR_splitAttributeQuotes(tokens) {
  var firstPlain = null, lastPlain = null;
  for (var i = 0; i < tokens.length; ++i) {
    if (PR_PLAIN = tokens[i].style) {
      firstPlain = i;
      break;
    }
  }
  for (var i = tokens.length; --i >= 0;) {
    if (PR_PLAIN = tokens[i].style) {
      lastPlain = i;
      break;
    }
  }
  if (null == firstPlain) { return tokens; }

  var decodeHelper = new PR_DecodeHelper();
  var fs = tokens[firstPlain].token;
  var fc = decodeHelper.decode(fs, 0);
  if ('"' != fc && '\'' != fc) {
    return tokens;
  }
  var fpos = decodeHelper.next;

  var ls = tokens[lastPlain].token;
  var lpos = ls.lastIndexOf('&');
  if (lpos < 0) { lpos = ls.length - 1; }
  var lc = decodeHelper.decode(ls, lpos);
  if (lc != fc || decodeHelper.next != ls.length) {
    lc = null;
    lpos = ls.length;
  }

  var tokensOut = new Array();
  for (var i = 0; i < firstPlain; ++i) {
    tokensOut.push(tokens[i]);
  }
  tokensOut.push(new PR_Token(fs.substring(0, fpos), PR_ATTRIB_VALUE));
  if (lastPlain == firstPlain) {
    tokensOut.push(new PR_Token(fs.substring(fpos, lpos), PR_PLAIN));
  } else {
    tokensOut.push(new PR_Token(fs.substring(fpos, fs.length), PR_PLAIN));
    for (var i = firstPlain + 1; i < lastPlain; ++i) {
      tokensOut.push(tokens[i]);
    }
    if (lc) {
      tokens.push(new PR_Token(ls.substring(0, lpos), PR_PLAIN));
    } else {
      tokens.push(tokens[lastPlain]);
    }
  }
  if (lc) {
    tokensOut.push(new PR_Token(ls.substring(lpos, ls.length), PR_PLAIN));
  }
  for (var i = lastPlain + 1; i < tokens.length; ++i) {
    tokensOut.push(tokens[i]);
  }
  return tokensOut;
}

/** identify attribute values that really contain source code and recursively
  * lex them.
  * @private
  */
function PR_splitSourceAttributes(tokens) {
  var tokensOut = new Array();

  var sourceChunks = null;
  var inSource = false;
  var name = '';

  for (var ci = 0, nc = tokens.length; ci < nc; ++ci) {
    var tok = tokens[ci];
    var outList = tokensOut;
    if (PR_TAG == tok.style) {
      if (inSource) {
        inSource = false;
        name = '';
        if (sourceChunks) {
          tokensOut.push(new PR_Token('<span class=embsrc>', null));
          var sourceTokens =
            PR_lexSource(PR_splitAttributeQuotes(sourceChunks));
          for (var si = 0, ns = sourceTokens.length; si < ns; ++si) {
            tokensOut.push(sourceTokens[si]);
          }
          tokensOut.push(new PR_Token('</span>', null));
          sourceChunks = null;
        }
      } else if (name && tok.token.indexOf('=') >= 0) {
        var nameLower = name.toLowerCase();
        if (PR_startsWith(nameLower, 'on') || 'style' == nameLower) {
          inSource = true;
        }
      } else {
        name = '';
      }
    } else if (PR_ATTRIB_NAME == tok.style) {
      name += tok.token;
    } else if (PR_ATTRIB_VALUE == tok.style) {
      if (inSource) {
        if (null == sourceChunks) { sourceChunks = new Array(); }
        outList = sourceChunks;
        tok = new PR_Token(tok.token, PR_PLAIN);
      }
    } else {
      if (sourceChunks) {
        outList = sourceChunks;
      }
    }
    outList.push(tok);
  }
  return tokensOut;
}

/** returns a list of PR_Token objects given chunks of source code.
  *
  * This code assumes that < tokens are html escaped, but " are not.
  * It will do a resonable job with <, but will not recognize an &quot;
  * as starting a string.
  *
  * This code treats ", ', and ` as string delimiters, and \ as a string escape.
  * It does not recognize double delimiter escapes, or perl's qq() style
  * strings.
  *
  * It recognizes C, C++, and shell style comments.
  *
  * @param chunks PR_Tokens with style in (null, PR_PLAIN)
  */
function PR_lexSource(chunks) {
  // positions of ends of tokens in order
  var tokensIn = PR_splitStringAndCommentTokens(chunks);

  // split entities out of so that we know to treat them as single units.
  tokensIn = PR_splitEntities(tokensIn);

  // split non comment|string tokens on whitespace and word boundaries
  var tokensOut = new Array();
  for (var i = 0; i < tokensIn.length; ++i) {
    var tok = tokensIn[i];
    var t = tok.token;
    var s = tok.style;

    if (PR_PLAIN == s) {
      PR_splitNonStringNonCommentToken(t, tokensOut);
      continue;
    }
    tokensOut.push(tok);
  }

  return tokensOut;
}

/** returns a list of PR_Token objects given a string of markup.
  *
  * This code assumes that < tokens are html escaped, but " are not.
  * It will do a resonable job with <, but will not recognize an &quot;
  * as starting a string.
  *
  * This code recognizes a number of constructs.
  * <!-- ... --> comment
  * <!\w ... >   declaration
  * <\w ... >    tag
  * </\w ... >   tag
  * <?...?>      embedded source
  * &[#\w]...;   entity
  *
  * It does not recognizes %foo; entities.
  *
  * It will recurse into any <style>, <script>, and on* attributes using
  * PR_lexSource.
  */
function PR_lexMarkup(chunks) {
  // This function works as follows:
  // 1) Start by splitting the markup into text and tag chunks
  //    Input:  String s
  //    Output: List<PR_Token> where style in (PR_PLAIN, null)
  // 2) Then split the text chunks further into comments, declarations,
  //    tags, etc.
  //    After each split, consider whether the token is the start of an
  //    embedded source section, i.e. is an open <script> tag.  If it is,
  //    find the corresponding close token, and don't bother to lex in between.
  //    Input:  List<String>
  //    Output: List<PR_Token> with style in (PR_TAG, PR_PLAIN, PR_SOURCE, null)
  // 3) Finally go over each tag token and split out attribute names and values.
  //    Input:  List<PR_Token>
  //    Output: List<PR_Token> where style in
  //            (PR_TAG, PR_PLAIN, PR_SOURCE, NAME, VALUE, null)
  var tokensOut = PR_tokenizeMarkup(chunks);
  tokensOut = PR_splitTagAttributes(tokensOut);
  tokensOut = PR_splitSourceNodes(tokensOut);
  tokensOut = PR_splitSourceAttributes(tokensOut);
  return tokensOut;
}

/** classify the string as either source or markup and lex appropriately. */
function PR_lexOne(s) {
  var chunks = PR_chunkify(s);
  // treat it as markup if the first non whitespace character is a < and the
  // last non-whitespace character is a >
  var isMarkup = false;
  for (var i = 0; i < chunks.length; ++i) {
    if (PR_PLAIN == chunks[i].style) {
      if (PR_startsWith(PR_trim(chunks[i].token), '&lt;')) {
        for (var j = chunks.length; --j >= 0;) {
          if (PR_PLAIN == chunks[j].style) {
            isMarkup = PR_endsWith(PR_trim(chunks[j].token), '&gt;');
            break;
          }
        }
      }
      break;
    }
  }
  return isMarkup ? PR_lexMarkup(chunks) : PR_lexSource(chunks);
}

/** pretty print a chunk of code.
  *
  * @param s code as html
  * @return code as html, but prettier
  */
function prettyPrintOne(s) {
  try {
    var tokens = PR_lexOne(s);
    var out = '';
    var lastStyle = null;
    for (var i = 0; i < tokens.length; i++) {
      var t = tokens[i];
      if (t.style != lastStyle) {
        if (lastStyle != null) {
          out += '</span>';
        }
        if (t.style != null) {
          out += '<span class=' + t.style + '>';
        }
        lastStyle = t.style;
      }
      var html = t.token;
      if (null != t.style) {
        // This interacts badly with the wiki which introduces paragraph tags
        // int pre blocks for some strange reason.
        // It's necessary for IE though which seems to lose the preformattedness
        // of <pre> tags when their innerHTML is assigned.
        html = html.replace(/(?:\r\n?)|\n/g, '<br>').replace(/  /g, '&nbsp; ');
      }
      out += html;
    }
    if (lastStyle != null) {
      out += '</span>';
    }
    return out;
  } catch (e) {
    //alert(e.stack);  // DISABLE in production
    return s;
  }
}

/** find all the < pre > and < code > tags in the DOM with class=prettyprint and
  * prettify them.
  */
function prettyPrint() {
  // fetch a list of nodes to rewrite
  var codeSegments = [
      document.getElementsByTagName('pre'),
      document.getElementsByTagName('code'),
      document.getElementsByTagName('xmp') ];
  var elements = [];
  for (var i = 0; i < codeSegments.length; ++i) {
    for (var j = 0; j < codeSegments[i].length; ++j) {
      elements.push(codeSegments[i][j]);
    }
  }
  codeSegments = null;

  // the loop is broken into a series of continuations to make sure that we
  // don't make the browser unresponsive when rewriting a large page.
  var k = 0;

  function doWork() {
    var endTime = new Date().getTime() + 250;
    for (; k < elements.length && new Date().getTime() < endTime; k++) {
      var cs = elements[k];
      if (cs.className && cs.className.indexOf('prettyprint') >= 0) {

        // make sure this is not nested in an already prettified element
        var nested = false;
        for (var p = cs.parentNode; p != null; p = p.parentNode) {
          if ((p.tagName == 'pre' || p.tagName == 'code' ||
               p.tagName == 'xmp') &&
              p.className && p.className.indexOf('prettyprint') >= 0) {
            nested = true;
            break;
          }
        }
        if (!nested) {
          // XMP tags contain unescaped entities so require special handling.
          var isRawContent = 'XMP' == cs.tagName;

          // fetch the content as a snippet of properly escaped HTML
          var content = cs.innerHTML;
          if (isRawContent) {
            content = PR_textToHtml(content);
          }

          // do the pretty printing
          var newContent = prettyPrintOne(content);

          // push the prettified html back into the tag.
          if (!isRawContent) {
            // just replace the old html with the new
            cs.innerHTML = newContent;
          } else {
            // we need to change the tag to a <pre> since <xmp>s do not allow
            // embedded tags such as the span tags used to attach styles to
            // sections of source code.
            var pre = document.createElement('PRE');
            for (var i = 0; i < cs.attributes.length; ++i) {
              var a = cs.attributes[i];
              if (a.specified) {
                pre.setAttribute(a.name, a.value);
              }
            }
            pre.innerHTML = newContent;
            // remove the old
            cs.parentNode.replaceChild(pre, cs);
          }
        }
      }
    }
    if (k < elements.length) {
      // finish up in a continuation
      setTimeout(doWork, 250);
    }
  }

  doWork();
}
�������������������������������������������������testng-testng-6.9.5/doc/prettify.css����������������������������������������������������������������0000644�0001750�0001750�00000001206�12551235562�016775� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.prettyprint .kwd, .tag {
  font-weight: bold;
  color: #7f0055;
}

.prettyprint .str,.atv {
  color: #0000cc;
}

.prettyprint .com {
  color: #008800;
}

.prettyprint .lit {
  color: #cc2222;
  font-weight: bold;
}


pre.prettyprint { padding: 2px; border: 1px solid #888; }

@media print {
  .str { color: #060; }
  .kwd { color: #006; font-weight: bold; }
  .com { color: #600; font-style: italic; }
  .typ { color: #404; font-weight: bold; }
  .lit { color: #044; }
  .pun { color: #440; }
  .pln { color: #000; }
  .tag { color: #006; font-weight: bold; }
  .atn { color: #404; }
  .atv { color: #060; }
}

������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/pics/�����������������������������������������������������������������������0000755�0001750�0001750�00000000000�12551235562�015354� 5����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/pics/show-output2.png�������������������������������������������������������0000644�0001750�0001750�00000006431�12551235562�020466� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG

���
IHDR�����p���dy��IDATxMrdz_++|"fk7\Bu^9..Qۉx9g!K Dp8(T*A~y}}%?~^2"9�)ϵ�!��<@H��!CUU.�7K|%FAw�&&Aw��<@H��!C~H":/FYAN6D=Q1Yo&D-	ڒr|M5Dja@E%^vC$Uar
5Qi"IB=rBRVMod@3]3j\^ڻIY#$'4	sQm]TbvL]wcڿ]k(vD;fH}f7NYVq־E~[zj܋k-)Q֓1YV!wײ<Sq'5vmgnk8B4rz6$QKnGXT&zXje]ҕۼu&W�Xg^%Uco<ײd%EJ=X!trjRNSɪ>W'ީq''-kzգU;!1{+1уuß~Njs'5>C:z:҉3T
oԖJOurl:aG[GW'nXMnqMTb4DnG36"5Dz -Γ8&zr[qws_((P)CD0n~z9{4'.znHE-\MB`zbFBiS3%?t.SUk-aE>\SR(j5>oL\
ϻ<Aϻ6!Ř;Y�~:TUV ŞK!U<UIH&ci%'ቧ!LI7^5Brδc+vD
HKt/<d._Q\jzoABi/29u8lnR9[B1gC7ڠ	� $�x�B!`{"6ϳҏ'ʴ1_X=*WZIW.Vz'7o>`Q<^S[fU	lEL!sh6m6zgl$S-1LJ|;hYDh\aL;rSwKlj;T2	^1dk9͛fcYl9>t%:յt>I'":jkK^x�gcGw3IZN
|bF|Sʺ161LaXu7
v>n[k|oxp)Tܰ;%=a>NXDTEǍ^HC[YHj!ԅ/0,(WKBMnurw6IU[9UoYrj0*9ĤP^pcl7:|3¹~U�:uq713hy|ߦn!_3f>Vo	O^NQ`avފ~x{wt0^dqno6lhvSIzp
�X	� $�xX!$�A󴯟NA8ABE|9w9ns hNA8AkLԥhߧIv<R"JNP^JI
Mԥ8MY6eC""%!YxAIMM<ԉ@DDؗ:ՉMѝ؄k!fJ#V}kt_I
 N.~/le'Jew3DauǷ~p(Ds%kiEY'D$s,I	p]&u'!+|?He
4	ft+nڱIewfYOr'lʲ(^d1u쨓:bTE2./˜DEHM)(+DC�$aߔJQ$u]F&[]jae}wxS8á8}D4tLU.y$DV$RT`&6$ʤGRY6CL\ZQt::/D_$,kH>b*##8"l`FL$U9CBVD2$3~Q&:k{R"	MlV͸)(	Vɐl4,YFúZŇ8\s0ɜ9Jj؄2 藜byP=eHg#鱍;_siGmQ'CdΪ!+2Hu#|^;"{YRU۝U#>ϝpB5KZ.~	3%.9{܁q>)	� $�xX=wXF3<FAn'+)qI˜(k;Όx'_TK$~sNvLBH2x8X\NYvTaFuW+AgFaR/4ƁWbew+e>q؏a*glԥOulOδ.&	,{Hx\F*O\	nB<ǵW
um~򔟭r=MR?}-9sIX2ڄeGV#Ճ�bzdT2׵,"-?wDH2oy{lz!QUvƩԶB'%88:<ѸYs\3:(vaF!`|anLV?3u0e](IQFlY:
NFG{Oz$ f?c%V3`D"%j\]h\T!<e8u2Qh('*z^H!ԉ=4Qٵ.93K
F4mpڼ,�eAJЖBk>v=}9͵w^k]&f]4$uy0x3n&j'mښ:'C\OYBUnwȥT^9K`\,8B	� $�x�!hUwK|oln�t�I<yr�pθ�nB	� $�x�B	� $�x�B	� $�x�BvY\����IENDB`���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/pics/show-output1.png�������������������������������������������������������0000644�0001750�0001750�00000005757�12551235562�020477� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG

���
IHDR�����o���ns��IDATx?oƟKHi"5ꮸZ.'H\`Q;mqRԻU`K!<JO#>K>?~L&�;#4trrPPPPPP PW
g0x-�B\\+b`
,K`
Ov̞J6ƒ㧊^<4Q%*=Mox0*Xɒc\{nRQЛC(Ն!yNh&0fq+n� ..LnBk_]I�bljI=f&U@hFWR_OH-h^#I%dFySjye¹2J`9q2HdUJV
U�J	SϼNS	a3:c#V?a,L60U:MuRVE)>:jmT=w21Z�TAXQ˫Ѽd2)+d2WL1/H~UB,:GvɒUŏ 5BѾ*!c'p6<hAbCUbCUbCUb3cgߌIσH/ġ0m%>{C{8xbjI
"1Ō]aywx<!~(Ozn"_k_mj\[QS}POvLKmы\F^ԧSKv]*(̤Y'f-KBQ}5P{&xBu3}$<{!	wI5ʹ[d7y�V"3q~nhOQ:ɢqB0rRfj0[1jL4>WPRX6卫Fn7BB5NmK]cT[=y&M)#3]QM")̸[j1B9μrBn}OWꐩ,Ly*Q!^RꝚi(~bhqQ<Pr~�O?�T]V^�Cz񞐃|:U0Y($JӐLp=}*MZ4nk#]\JO's:R](nEz;?M!aOgo)k<3=7J*kP<Gэ_2(OŧhH4IE?8kY㙞N&P/̸G;/ӊ]ҏ޾pQOӥ>uv�2Ue>+{~2,IePFQ-
R+86L/ܩf@G1c߅2X�ym/7=mg64�.}
i2[!
Yא?W#&|2n1gR_gZF15BhV^l}cQ8)HB$͋|jܗ,{	ũlŬ9NsPR=h|Ufz-(B-(Bl
Bl
Bl
Bl
Bl<ffOiLD>+mZuQD/ Cx
:R}ŧfsq+ !-((gb>J
gm׋$rиBIN=Ӎd:O^Q7,Ū>eE{Ӗ\ř8_
02¨m+YE3>\fYKk=vUzRovbV.mǛTJL"+`yȬ}mz%U>`%O
)AE,0uwSftlɘٕP9Y2޻aD6M<7,PTu'~0ʹ?QM4"zpLQLiFN	#Q
;9rHL3lGϳZci
-œK
Yrn-U3
6Bu @ ߶}oPVn�n(7֬c͡i1Mv#.sSN 3᱿BΐvαaV-x|u~9(uڹQ")!9ۜ`U)pp!6\H
UA
UA
UA
UA
UA
UA
UA:�t䡮c�QH̫<CRETCZTwylDl0>Tt`�KWy7I^*"yk"*t:	}pD[ؤyA
*R=]|].iʗʞ
.(WE}ۛXW!H8blys]b7U%H2늦 Q9s֗/_{��W:Ftl&UVmO{$U?$]t۟6h~ۦ݇vm?|b(}#xWoqU-_^ݯo
QEڟweU51۞)HNٰ^sDe~W?nW$i7K$i�tČ>:n&2J\1ϮHPá#2UI
׫:DP%PAw/o�@o6ZI4I"nH"88"`FhJ,¯paazTQ	xJ8[eiA>M�ucsVADbjsA&a]'DD4Ѿ.@ftRDB7$՛:wa暌TzJ5`bU!J7݄vNWx&
u`&.]&"Wo{7YE(p:A13AG=HYBU!6T!6T!6T!6T!6T!6T!6T!6T!6T!6T!6T!6LGэ6A����IENDB`�����������������testng-testng-6.9.5/doc/pics/parameters.png���������������������������������������������������������0000644�0001750�0001750�00000012044�12551235562�020226� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG

���
IHDR�����e���}x��IDATxϑ^ڪlrV VVs\7%1
"@kjkʫH@
"Cc~!"E���|?l���<|v���$kPo{$�����8#ٹ���p,~�o	<?��pF`���3T 
iхB=vr-ѳ`>+"HK+׏ܬrQRm޾;=&冒>~}8װRԎNt'j]K.DsJt'
{oDwƢ-#Dy*~߉+WjoK;=t˃CWW~"nD%-(t\PzєaP$d{o]p%$M0UD55QEm*,:e+d閙ݰvo4;\f<VxG٦j\fgf*϶UL&dxf?UD.^/S\Ն~^-$u5db<Z+{-FTˣeci$$w]IpEpKv6RJ
DэFu^,kz]%gvQ;m@Ʌu'a<ߔԦ*0KІ8{Q-u޼	[Vta3)1RJI7T#6#[}
koшm
-<ҙ?:6XkD5A
G:\Qs;ԅ?Z[O Trm-{XMBu.Çx-ҤT?-PrCT=H^t.&>&-k/Su\"n)
J*s4Bu]HWFNRhLB3,,xO3/Xs_pl_Y5\2_E[cOj5PSj+1ԇ~AI\VF=
@u[).dgB^]D03vKN7͚Bҕfq;[\csiYkq篈A!$\Iz'l#*?bQvR_0q)ִ5%ԻX6<3VaW=Ur	KR>쎔(,4ŋ*T㖲գO;:țuHQo:n	")\ǫwuR�KdNy&j)5d0<؛!.eJ.{Rʵ:)pV]5wnB]^_WsqKtK'LYfkv>zIb.6Mt	wo$zr?r.Z%,m+:wtnxcJ.|Ivr	SvjF"-QRhW֕gHur[JWQTw*}ѫPWzKͭ/UaS좲}&?Y7UWh5H?UHr]^)ԏ˲+@hi[Xnuz~fh)>ZJvuֽgWOGr;K>{wK4|wѕfIŹFA4&Ėp5?e5ѽ<ւKE=pfLo7dч<֔frއ~^"dY�
N$ZSeW}5\s֚7eFqJRk[P;i}OR<B=?�����X��8#��pF`��)Xi7կTkWĎ̍vST~Bt[D�VX:t_rCĪJC"Y(z4�`=?rևM?m.+Oo3Ed|*cL?� "0[νۊpSmK9OI5_	{�/lL9LR4JXu2xfh9=ŚNW
zSe9<:8t>%|S��C0w8K#ec=pl+G9D¼*ӯt^8hN=@䅦W5ljH ǣ
/G
l-&R��f_숬fTkq**CAiu<E̪(MPR]n跑+\l'Y
+G3pjʜH­H2s�9!|
0+FFkllڒ-Ob1SŻa?0iPVO8�xyIkIIUhsǩsyٗ3dB�{}KgnXuV6 >(A^;zZՔ+΄ɃBt]T~ƣ��`LzEd5-+QHLur͏Џ(bߢ#K@yS5"
["v\k0"o�87��v�$^���إ�ؗ-3��0�3��gds�?�7��8#ٹ���p,S+>��#���3��g��ScR\Vq^Ŝٜ	qԚ\~stEDuQiiU$]zdAPwU2d1ϳñV}qHڭ%čv%s|:YR*|y=*@t`c졫+?g۸M[Aors7뗈aP$dFWQؼ*>e8:ck@)tW^YN&-3
aHW%w2V!<>cs_0l2X3MdW
ے̚Lٶ߃6Z[~`SZE2)8?Luj#umH["{h:o9 M^kIEw,9 %Q|]Q]6T{�b~jp1:޺@{nGəƹ]o"s[-Pra݉h7.)Ja$La!A.^vKݠ7iBy#]ELJdcRM)7Hğ
VDD[4m$e[C^9zǯM c׍QKTs9@pEePr j;Zl>Y +Sʵmmcq[7	ڻp5*hHNR@
QUV yj妺܇pJ�HNs4(uӐ2vsuy#]iܺO:QJ1	u6v;'*?|Jbe}	eHnr],Wo?%@eJLt\ǸRw%FsY֮zKzۗ7\%=RlwΟyuϤ:-:4k
KW<n)sΥk~dŝ"ʇ|Ds%MσjL
\>Eȣ_?JE|yWYX֔Pb;KXeJ^YTN%,IƊ;RR[./<Si;[V"uǟPyN}"Sx M2AT4xN
`|)$[ִ5%ԻF6f{3ĥL%uXTV'ΪKC2-0Yj.nn)䂑)̹.0'RO:SEކR	~.8YM3D/CBN%S뼄me[".Ӟ1o�<WɅu7)r.W.aaN(Sd2J
MʺNnK)~SOtϟ"_|³|>U(JtK*CIа)evQيZԟlᛪ+jm4`KUsK$U}eu$.NWGe i^7H{V
=?34-|c%:tލ3˂+WwHEn'#RuĥQ=˻mBkh
Jw3$\#IF{MbK2sYk%OƞKKlz3&yЁOJWkJg39NyC?~/ynf
,ZvR^~ur])+.@9kM웲_Jz8%I-Uʾjq){!Ξ���K��?��X��8#��pF`�Xu�CǗv+2`ý9K�^u	:ߒ`~Oڀ9Yڊ?oCԠ~Sn`x{~䈫. bt'Ec=kLdIr<2&,S2ܻ8lyc}�ÓF̚:p-;-�>ϔc$.M#fV/ZNf/f-qoe6nRf'4RzPeH,-@	#BIR)UpB�?u|h~#ղ8U|[>6yU_'輢qМ8NɿG0ە!}:r'U:2Hps7|$.$on�މ9_Oʺ|]JYX	ܐ PBO#R2<˟q%�C64A's~$l�oϏjswmYi4X5Zhז$hyZZ^P}.EKiiW[1c$)<(%>�%3
:+@JMrýDߒ+,EǮ$I!Q}�x7[<s K+BJ{OQ0z*U$%{oGtQ|}�x7
o4MՑ97	rgF!1m 5?6_YqT%LРQ6>,y_YxU>rJ"Edc̾=�_^0r�`pQpp&`Q1p�m
?��X��8#ߋW��x]!��x~��d��L^_����g��4.W:����IENDB`��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/pics/chronological-methods.png����������������������������������������������0000644�0001750�0001750�00000040267�12551235562�022357� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG

���
IHDR��`��^���l�� �IDATx]PTg}uVQ[M@tӐΎ?vȆRFN4VgHINNdG-LLr1ѲiS	;b^ 6kHsV~]-4tӿx<okА����nu����/$��� A��	"���4H��A���
D���h ��@544~���AD),,8���'b��FDEmmTAAҗ9$	n8

$\("GP!6$
G\A"b10���
D���h ��@���$���Ј"AtM!>W]cVx8!��`|z|hhh5w㛣&/Z[6%Il��Ľ ɠ:WDT:44Ze!^Dr��Q$'*Uϩ&��$[♠LsMY9~<i}Tv:`ǕND|
qU;ܥ0��̈%JDZUmqT;&P.ǎ[Ea;dJh[9Ǖ+%)tX\{{CLUJ2inU�@R67*)WX}=pj\I5qݓfjf4Nk��IdAt)i2@k?FM'
ĺv��d.A,;h5xɔ@u%ڵ�2ORQX5)qXQ]Mbv/S{i%޵�duh[]tgVSP؉8kV9Wyx6TO,bSխcVrGu^847ěJ$ڵ13|VDq˽}„1xޟa{}Ȕ�!
c"aEz[˿Q'[/w^SJ/:~e>/	-Xս}M܇[[[=ע!x2a}LV)4=wjsk'gXK<g$YN\OfB[:
!vhHt#̸k0C@wS7zg%ykS?X}|3o4LVU~klmSI'*t?-j1$[
s=PcNjޔ1iw[(?.>-F-3<	"3*ZAz"XPCyAτgl
Ķj*Iͼ6wOxMJZٳj4hG�5=&+>*)DDDߖ&L.YЇ~4CFxŞ={ώ$I
Lo
(+SLխqjRWЃ|*RygE}wʚU{>#ǭ^[5:1O
xuu^



VW{}Sxxڟ;|{M7n<X

AA2ͣ<Sc`Aĸ3a)ӣcUADLUʌ})&JOŎ6D}zS9/5vFs]&SuUz#ğļ6ƑE$W2'ZaftBFha7
3?Q>S;`$ʴ}퀷ȴjs]##zÄ×YjjjB-O棒F'E|
}|/}ƴ "ny>(<{L0aB\}<mgGЃ~oiRǞ>V_U6Ś7
Rs90J|8t0hz@5D/mՄreq_n&]S	zPJ	pԬqՏ6c8#[r".Vemх^"YHƟ|?j/2+"A~<єSꁽ4] >F^:_wm:*/~M&tQ;G5kz{[}Zپ{}o,ک.J=DYKS'P;yhq bh(uw>y;'sn~R41'-
_Uh[{K|~9}
_ay4`|lHAƒjrq\
/K
2tàb<y!fGMyz|x親֑)(g[M'ah@xQS^P}`V580URYpSBQBF	2ғI<ă+VkL^QF�MH'~Ҽ{>8%qxVިC	ٱX{#D3YC[%߫P"W:6=LJ[5�V{Oh2y<2سg*jWw~:l݆qZ�� zQ'ʐkިv;yL���dtA'
���DuF?*nw���}Pv'-(���`Fq>N!\q*v<Q :BDbb<$GkUVmU}Tǃl+ZF^LUCUz^("w[ZO騮U-6*ߘ|k0U���Q{E*cզ>Q0x���puj+QD��0N=T:6C^��7: �� aDAlhh8"H7qBE0pL��c���ᆘQ#תOC$IBDbb<01ɜщ#$IpWhH,X$:��A���
D���h ��@���zcgOȬ/eDcocxC_q~['.y]-CޱƗ>K�@"ї ~ӿZA,j|P&5
N;{W?xv謍l0o<;E~9}6��F!恖]6*RY7N_%aËn-oh+1vN6EzYej5o͟Y?Pw��#:ľ)3Hu/\qCƕCG_:t`S_M1ʍ0_w��:{~_M65N{E
Ȭl/}70)J,w򒲿7
9x<fHߕo\|iG*7Hj~Y_\V3%sqbz2Y9yY��IzėϮY]9ҡ_9_S}WrO
TZ8/TXqξqe{H1twSڰ(7j|J]3#W~9}iA߯tdi=Xxy'��/os70&0_\*;TߕDdrY"ї}/"Ƃg׼5ȬJ2鰫38
k6fȍZt50��=3R'K/}c>SLj*erY_N/yKξѯ?*y[j�
"aYaLNZN=,KD˜ƱO_Qǩ;���Ďјat]fD*3u2/`|у5Z,_]ˍ+RHȀ|㍲,w:LIsS��g95̳M<۸}nj6N^SwE]K߀,
f=_dxGy7^Mf|J?aj*"AYepz��}T<[wKWdL0)9xH[욲Tٟ_L"Y욍"Y+{U.oW,j'^9g"Ϯ)Ɨ5zU%+cg=-dM_kyk��`]<|Mո/ZAHj[#ј\V^+日H@"~YgOk+0<��Q*f���k$r+���Nbn=Y�� ��@#B⿙WNO$IBDb"M;PXX8&���`1���pCњQ#zLH7qBxaщ#$IpWhH,X$:��A���
D���h ��@���zSEǚ^ˈFwuxZ4a"þXO=Ӳ>6_{.dm><C�H_2_\ִwNq'=:S4%|nG{58Uz?~|xoeM{5(;~uփV��0$c;YcK6
ǷsӐ&iQɅon˴I"cM{\MYzROh맇{)݇*Rp��0H^no'>2nwcT?O[TtvP9}|ݎo=&_}k,-��9~I2Mr;)stߺ'2)\y"r{;dm>=|aNH_z],~&iY(;y?}gުoƝݎoev>g[VHsYK}wf%.(Ѿ(>_OU *u|gf��JUSw]ִQyy^Чn<ڴwYӋS}WOMh)25;fG{5]Q?ޱ?|]˚9uxN^zwPP
 t���}8b6i݋Y"uuG<cj|\.|s[sw}ezެ|?sKN]?sӝD*23iݶeM{[*"~gJE�� t1O|dtwLgJQVLh2QWSt[&I׈O2)=vWsYKEN~¹fJ��[:IKt3?M*z|,& g4ǚ>?IS3	~M.Fw0`ܮ6k;T$ц�� 1g>¹n-[+37sJi&L]_<‡_칽xb?uvCY(VA2qT0F�� =Iemw_}TuQI^̪y([z>uԝ{QV1Oݹ=|‡"*3ފz閩;>)71u2QdSîvɴKI~>IϹW1�� >joZG{bI~˚|ݻ=\"f>)"^6;};��Jmn���3$��� A��	"���4",R)OFdI# XhHt544I4���s1��@#ow/8%I# XhO"AoQ	#$IpWhH,X$:��A���
D���h ��@���z>}4Nal91".V6ljxo�x/A<w}WH$Ts)ѲDe\],-+Wǝr/ȥQ��0V$}EDWKN4-sӐfܴ(zNfD$]ѕ'Z<mHUruO��;:Ζ놴lنΖ*}+Ν>-Nsu{X=ie˥ρٹEz
��xDxH_i6LWpb$|9wiK~aNEP鲢~%m˲;\"ҿD2u^o{ɖK-|m=l1mNxzjK)D��b+1W1/u}宽g҅>ղ]ŮՃ>͕}Ձ}+w]WÖeu}Y|[9u6agNS:@\HyzAΏPW{]3��@,Asu[djB8Z=H>0ߢٗZI_w'=:]Sɹ?Uj6my^VTA,1(azkز]?ͽ|05��Č1ې&c>SLj*%m˲]&SVrhec
S=*ڜ.tj?_e;)E6���å#A?3c1QD<Vڧb joh+-۠.FY\,pVg@=-2%1악6d���ghgkg>gQֲ?eG]\[sfv~ٞܥw4--Yܿ%JxfUOOm	6b���1obwgvKncS(:(OPr-vmvO+tQKuI]m۟wxѮ}E.<U3-'D3xѮOE-Obiw~>I+NOW;->]?޽9X���wJe64
|+W|¢ӕEኄ:h(l`/Ί��@%67���D���h ��@���m8"H7qBE044wpL��c���ᆘ?]9jqnkeF<D$+4H$Z,Ɠsynt(~"Ip$-!f���h ��@���$��� A��+<tRxb`H^a-#rzp}Q��GyW3_C*8_ڢ)aԤzL]=UYz]z(���+zĞ_XvXED>VpҦᰅMCJ]F&_SjX6Xs~0>~,SDzj>I��;:āF@FS2r
2E?Z:ly3p1biH][`OX[���	=m6uIz~ePY?aCh:2ÜgÖR3xВw+@2u(?ly谒jyO+3GDD{wv/ﴩ�� ss*oᔭ~,_o?S'R+5@~R{j>yŖJɑ$qz;ę;ڔ=~_yǼ�� OGlvR!EM`Z)kџR/vX"GjsM1HU2DD$jrR#;I2)3l=k[=-"0]j^/b���1_2%#Wh2ϔ1Jɝ3"h,Tߵ-Cyq@O婳LJkGzjT{ZD\[+5WJ��[:zS[SۺhK}ښH)3,'_ooɰf*cOe1/es@nPh�� 1gTlmE-Voy2OF)i\[**rғCk|V"]=bK]!,e \lH%l��b@dhx%_DZ>!k=lS/-J;=
N$sG<"Voe_to,R~r~Q_D-ފz2Dz$sJaKFe2}�� �IDAT+3wڮU|:Wzl_k_j-6yj��	CCC~
Eӕ<7Qi¿̈H7qB8��� fH��A���
D���hDZoQ	C$IpWhH,X$p��b��F!غxj0!$
G\A"b1DxQD$+4H$Z,C��� A��	"���4H��A���HORq8z#"R}ݻ	~awZ|̈P_mI��/z/<sdʻ[*D1uMy[{n]ep'\ߓܺw٣tV��`\ғ .پDD$c
9d]ݩ6P!T/B>(9REdCO&J��$t$=}'u,RszφЊJߟQ]O%ό)2��#H2%3.cJ4+.J3/HƼ}zBATX1=="n
'()rg6\پTv]8+[Z󚜵+>_*fCnOmSY-%1:p3$sKߜמJu|
ux+��T⥽Dzy5	u*L"%>sh]3v}SۓSg=|^ݕy[D:vu{nݻ"">mz3L2Hkjmf_,%?aŻ=j{qI\}|/п=Ƨ@톓l<+͊Qx��0zO{~YnO#{uyO=yl*Ô9H7{z2=*N.ߦe
?}~HuY[ƔσҼ=GO>S2Sr$rۼ3OnЉ��Dt%RswLgJQV]{??!h!""]pvj}kXjH؛O95KK"qg)>aOK"%Dl���"+AҌI_vwddDX}]v>D{JK͙%sGO:sfMQ5,=*߱
��CzI\ڦ{ϑ5ctv3Kϭ
ض&̩?Z=߼z4`CO>	|M/WE?QO!gwmwlƼo��ƥ	CCC~
E?.^S<G98&ORa4Eg=ׇ̮VTf&c燦qs>]z,Rv^6߯j֔:Hw{wQ_[$ep` XhO&c_Q
G\A"b1{���	"���4H��A��� NytQD$+4H$Z,]U���HB1��@#oW֎ZAƫO<>1"Ip$-I9O[5:qD?$	n8

D3���4H��A���
D���h ��@Co;fqc1'v���IG_غq}NΛo<(N��gzĎ>'"RR?cVPs0DJw,ϋx���zڟ6-'c,2ļ7M-3c?>nc��ęOR藜&Ӕ\*-\[}3ODZ7qFIܼiO=cY|QV_t_$Kg㙭RR`G��NG39SرU$Oۡnf?~K^lI{kV��H
os=^FbP^#rOoL)Q[]LHZA���xALIӌ)LI#ʪ7wD8C1f���LOyi\lZi*u8o7W?���AyLy0&a3Y)���DE"[ơSc{kE?lqqQ֏n=V{U�� ]Ŝͥ1$FJwv+>A^3�� E���	"���4H��A���Tщ#$IpWhH,X$	CCC~
$���9��n?I# XhO"A̝j8"H7qBEc���$��� A��	"���4H��?AݗN	vNm��؈͍SJ71ԩˋޞ;��`LA\ˏ8~Tkim&;�G֞u &5Zkpy‘�{P	CA]_~dkO,\N?"��"ީY-kw_^zÏr{?E0f 5o?Y._^zTР�Y|Q{N>dy~yi6Q.~jO>yǿ0Ӄ("/Z1WDdS,llC4k��|l+6z%Yl-Ù+�L}z\��O&xy_EޥKmLG<"_ϕ?x[#31>8��${A6#J~/#D ޹۫=p#3c_䝴O �'m≗Oy6ѿ^wK%)Lۼ<M
S0ʢ([NWy񢷕D̷]{=�ą<d{IS6~{'EOrO~hqJLۼ-s>1t&O6��0Nxjё|N\rъE13��0 ��@���$���ЈHdSQD$+4H$Z,݄!C


c
���C���7?}rx$IpWhH,X' N5NO$IBDb"1���
D���h ��@���$���ЈG^o//Zp;ݯcEdx�+Z֞dyXG�DgxTk"21ԩˋ&5(mZ֞䝴 @9ļpyёp6o߿rԧ"27r?V@"?ĵd#
�m'()ս;".C2P�H@I//?2D`T~y{27ȶ|]ܓED$m˓N*iY󢖵?bj%"#o9C|ɇ7/1�$a$uMEGK^?U/3ʌ?:{'Oث.C߿Gޖ|G;S֩~yi6Q9_;-QR�cbYxъ""3zdac7e1 }򚈤x*`\S2qE+ۏ8G{rimȤ /1GگJ�0\g-S2QVSN
~m.w)ҟE�gez\^Ay[ёmr~nec#/g;{gcDExnŏ̸֢;Aw�`M\rёmE~^6AN99Bb˧.T_ֿ%�`\rl9^ŋV3^~w"aw�X(ԟϩ_oQᴅF;-kwmޖ'ltb~jgy;-kO�ICg#F0�a3Zt)﷛_}9(�[Ø�����$��� A��FE*%
F''$
G\A"b&

jhh(,,h���0b��F!?-7jqʛ;8"Ip$-I9H8"H7qBEc���$��� A��	"���4H��7A71Θlgv6#��Ikή~V:lW\euvoĦ+A7a-r\*b��I)R0EaɎPU_`Q8Mvw﫴]<z`t$:lcmj[٦؄�@Go_ĒnW{_%ΎEoUZ˜HIdMYc4AO8Ő-}vOcu6g,��HhQw߉h94=xEx`KxZtlT��$4nk٦%sSDbCeN
@SyWN)sD;W-)פ8QAo)193ZmotdfAу>";%Ei[��u`b.uaKRe8.V:E\4:q["nʧC2;<HUf1:FqvԹR38M^^zbo:S隣V#Dcn9equt,al��ΎA99il
Xa;:\
C_#bWż ")2.eU:S*s:gNΙݛh1vׅ$oِsښ#"8r,"vGg9J{b
��hpED$E&[ϰoٹ9GG_[] S+w
`K:]">MD\NI2EDUg[̜Kn>��`l655W:!2%sEA++ې"gwX|u)ْz'ϔ9Rj�Jz&C_gigsY۠:kjӥ9nl4Zޤna7̩HwOy:#Atu;EMK~�C
KAY͟^0떽=q0@uI6(cCNEz}Q|>7Q[bhojT,,J[ *fZL6ݳv{oe	#؄!C


"~13
eI# XhO1�� ) ��@���$���ЈyGDI# XhHtV1�� 	1���pCZ8o7wzH7qBxabl?$	n8

D3���4H��A���
D���h ��@#*f{әJHif#%'{D� )
/pX̥K;.9EDst|Uښ%X=:YjپJ[]BFDWL8kAbY۠|_eS_,� )TXJfgԡ/;?Xf}[kZzڔboz: t$:lcm[٦>E��`]|{"t*qv0-z2Z<^zS֕Ra-P4;7"]AO8Ő-}vOcu6g,��HhQPEfl2w"on2MeHf]9qF.HWyszY:F6*��{`IϴBl~TB1ZHJx+'[vuԹ{w|Pkꨠ\FE[:ʚd82	JGbthrڛnY4��sC\갖:,sq)x{V_@7SءteV*{SKf8;\JKRu&i/39J`~+Q:.흮׈Xk[fo/{dD\]3*b��コkPgx j/k0sì51V:쎎:WHXUe1/0HJKkmIR*s:gNΙݛh1vz>%;w#Wk˱jB!5GDpXDvos2[;�"~4)-Rfo6ٚ}}ͱ88*f2YXVP;]ID\NI	?0;`͋ ozATt59	=~즑}�5%)8MM͕NcmȴLD,s.haeRDON!%[RB/<H2HLTg)d��D%=g=OemPI/M.`
Ӎ2iv8hBvmvÜtG{):ל
5=2{{Hi��an1p/ItښsnٛOXwlOMI>6TgwslʽU:.֙Nk˒
_RkRikVeTN]oAb044wPDpo2i7jYq<D$+4H$Z,C���H
$��� A��	"���4"b~QD$+4H$Z,]U���HB1��@#8z͝=6$
G\A"b1D?[}O$IBDb"1���
D���h ��@���$���Јt)"mZr:7H9m��HJu\""simζeA}f	VOd2{{ZlQa<Ճho:S)kZX6=W��HJ)R("vGG7Eb.udow`Z갖6x0^H]uNc(""ZMM}��$:{YKQ\u~8;Uk-sp|/)%Ms6~LO8Ő-}vOcu6g,��Hha߉h94=VzNMJ!K1蜃8	*oN5KgF�@Bs61Z`VJ(ZtI04wd+®:qA~jݒyMzC7u].ÿM[:zӧ[d@`(tb}��GصKjv,Ra#NWk7ݳ)u<ٗewXyMb.us).g.qXK%̮~ۛT(_e9,R k-wevϑ,kfAEc�`\pvp
נD\eMfcvn&
SQ2V)ʵ,%IɖAw)c-IJy^̩5t9S6{-9v>y	o
99"#"bwp{Y�@AI9m2{3Dvn|W1V)']B2NנSä,.`SR*BO1lh9}md2sb.ux_,idD��s
vJ*/fSSs:R;\b16$haeRDON!%[RB/<q6&":W'ϔ9Rj�Jz&C_{8ա_^P.]0deӐo/hB{Ebg[0"=lDgqd;c1/=2{{Hi#*�� a~$RikVg8)eorOL/P>aER
>5}&eؐSniߵMgA*VlXg6ڛ;-K*,K~';HmJY==SfHKaӧGڋ	LG蝀RvG�Ra)Yijgx+a1
<DUwv!b��@R A��	"���4H��aʴG''$
G\A"b&

jhh(,,h��Y���fIDAT�0b��F!yG-_SC$IBDbb<08wQD$+4H$Z,C��� A��	"���4H���,d|����IENDB`�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/misc.html�������������������������������������������������������������������0000644�0001750�0001750�00000026372�12551235562�016251� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html>
    <head>
        <title>TestNG - Miscellaneous</title>
        <script type="text/javascript" src="banner.js"></script>
        <link rel="stylesheet" href="testng.css" type="text/css" />
      </head>
<body>

<script type="text/javascript">
    displayMenu("misc.html")
</script>



<h2 align="center">MORE <a name="news">TESTNG READING</a></h2><p>Here are
several articles and presentations about TestNG (<a href="#english">English</a>,
<a href="#french">French</a>, <a href="#german">German</a>).</p>
<h3><a name="english">English</a></h3><ul>


<!--
       <li><a href=""></a></li>
-->

       <li><a href="http://blogs.atlassian.com/2013/02/testng-plus-junit-bamboo/">
        How I Learned to Stop Worrying and Love TestNG (March 2013)</a></li>
       <li><a href="http://zeroturnaround.com/labs/using-spock-to-test-groovy-and-java-applications/">Using Spock to test Groovy AND Java applications (March 2013)</a></li>
       <li><a href="http://www.asjava.com/testng/testng-tutorials/">TestNG tutorials (Jammy Chen)</a></li>
       <li><a
       href="http://kaczanowscy.pl/tomek/2012-04/why-testng-and-not-junit">Why TestNG and not JUnit? (Tomek Kaczanowski)</a></li>
       <li><a href="http://www.randomsync.net/2012/02/excel-testng-driving-testng-tests.html">TestNG and Excel</a></li>
       <li><a href="https://github.com/rackspace/python-proboscis">TestNG in Python</a></li>
       <li><a href="http://www.opengamma.com/blog/2011/04/04/converting-opengamma-junit-testng">Converting a large codebase from JUnit 4 to TestNG</a></li>
       <li><a href="http://seleniumexamples.com/blog/guide/using-soft-assertions-in-testng/">Using soft assertions with TestNG</a></li>
       <li><a href="http://kaczanowscy.pl/tomek/2011-02/visualization-dependent-test-methods">Visualizing live dependencies (Tomek Kaczanowski)</a></li>
       <li><a href="http://www.lysergicjava.com/?p=165">Passing parameters to @DataProviders.</a></li>
       <li><a href="http://barisergun.blogspot.com/2010/09/integrated-mockito-testng-and-emma-on.html">TestNG, Emma and Mockito </a></li>
       <li><a href="http://www.dotneter.org/2010/09/data-driven-testing-using-selenium-testng-part-1-of-4.html">Data-driven testing using Selenium and TestNG (video)</a></li>
       <li><a href="http://blog.meesqa.com/2010/09/11/combine-multiple-testng-resultsxml-files-into-a-single-xml-file/">Combining multiple testng-results.xml file into a single file</a></li>
       <li><a href="http://techo-ecco.com/blog/testng-with-cobertura/">TestNG + Cobertura</a></li>
       <li><a href="http://blog.jayway.com/2009/12/14/powermock-testng-true/">TestNG + PowerMock + Mockito</a></li>
       <li><a href="http://maxheapsize.com/2009/09/23/test-jboss-rules-5-with-testng/">TestNG and Drools </a></li>
       <li><a href="http://functionaltestautomation.blogspot.com/2009/10/dataprovider-data-driven-testing-with.html">Data Driven Testing with Selenium and TestNG</a></li>
       <li><a href="http://margelatu.org/2009/06/25/java-code-coverage-reports-in-eclipse/">Code coverage with Emma and TestNG</a></li>
       <li><a href="http://www.mkyong.com/unittest/junit-4-vs-testng-comparison/">Comparison between JUnit 4 and TestNG</a></li>
       <li><a href="http://www.michaelminella.com/testing/unit-testing-with-testng-and-jmockit.html">Unit testing with TestNG and JMockit (part 1)</a></li>

       <li>
	<a href="http://www.michaelminella.com/testing/unit-testing-with-testng-and-jmockit-part-2.html">Unit testing with TestNG and JMockit (part 2)</a></li>

       <li>
	<a href="http://www.techbookreport.com/tbr0332.html">Review of the book</a></li>

	<li>
	<a href="http://thediscoblog.com/2006/10/05/testng-is-so-groovy/">TestNG and
	Groovy (Andrew Glover, October 2006)</a></li>
		<li>
	<a href="http://www-128.ibm.com/developerworks/java/library/j-cq08296/">In
	pursuit of code quality (Andrew Glover, August 2006)</a></li>
		<li>
	<a href="http://membres.lycos.fr/testng/">TestNG Tutorial (Claude Quezel,
	March 2006)</a></li>
		<li>
	<a href="http://stripes.mc4j.org/confluence/display/stripes/Unit+Testing">
	TestNG and Stripes (Tim Fennel, April 2006)</a></li>
		<li>
	<a href="http://testearly.com/2006/04/03/rerunning-of-failed-tests/">
	Rerunning failed tests (Andrew Glover, April 2006)</a></li>
		<li>
	<a href="http://howardlewisship.com/tapestry-javaforge/tapestry-testng/">
	Tapestry and TestNG (Howard Lewis-Ship, April 2006)</a></li>
		<li>
	<a href="http://thediscoblog.com/2006/03/27/using-junit-extensions-in-testng/">
	Using JUnit extensions in TestNG (Andrew Glover, March 2006)</a></li>
		<li>
	<a href="http://www-128.ibm.com/developerworks/forums/dw_thread.jsp?forum=812&thread=110765&cat=10">
	Code coverage of TestNG tests with Cobertura (Andrew Glover, March 2006)</a></li>
		<li>
	<a href="http://beust.com/weblog/archives/000369.html">Statistical Testing (C&eacute;dric
	Beust, February 2006)</a></li>
		<li>
	<a href="http://bill.dudney.net/roller/page/bill?entry=testng_is_a_leap_beyond">
	TestNG and JUnit (Bill Dudney, February 2006)</a></li>
		<li>
	<a href="http://beust.com/weblog/archives/000362.html">Distributed TestNG (C&eacute;dric
	Beust, January 2006)</a></li>
		<li>
	<a href="http://erik.thauvin.net/blog/news.jsp?date=2006-01-29#418">Testing
	private methods (Erik Thauvin, January 2006)</a></li>
		<li>
	<a href="http://blog.hibernate.org/cgi-bin/blosxom.cgi/2005/11/24#ejb3withtestng">
	Testing EJB3 with TestNG (Christian Bauer, November 2005)</a></li>
		<li>
	<a href="http://www.vanwardtechnologies.com/cedricb01.php">Vanward
	Technologies interview (October 2005)</a></li>
	<li>
	<a href="http://jroller.com/page/tfenne?entry=i_m_starting_to_really">TestNG
	reaction (Tim Fennell, October 2005)</a></li>
	<li>
	<a href="http://www.realsolve.co.uk/site/tech/blog.php?name=philzoio&mydate=20050826">
	Using JUnit libraries with TestNG (Phil Zoio, August 2005)</a></li>
	<li><a href="http://jyperion.org/articles/testng/testng.htm">Introducing
	TestNG (Thierry Janaudy, August 2005)</a></li>
	<li><a href="http://www.theserverside.com/news/thread.tss?thread_id=35737">
	Migrating to TestNG (TheServerSide, August 2005)</a></li>
	<li><a href="http://forum.springframework.org/viewtopic.php?t=7903">TestNG
	and Spring (August 2005)</a></li>
	<li>
	<a href="http://groups-beta.google.com/group/comp.lang.ruby/browse_thread/thread/3a0952199bb1bc1d/8a4a6d7931c039ce?lnk=st&q=testng+ruby&rnum=1&hl=en">
	TestNG and Ruby (August 2005)</a></li>
	<li><a href="http://www.thechanfam.net/wordpress/?p=36">TestNG and Maven
	(April 2005)</a></li><li><a href="http://kevin.oneill.id.au/2005/04/06/testng">
		TestNG review (April 2005)</a></li><li>
	<a href="http://www.javaworld.com/javaworld/jw-04-2005/jw-0404-testng_p.html">
	JavaWorld (April 2005)</a></li><li><a href="http://pcal.net/blog/archives/2005/03/a_great_new_ide.html">
		Solving the JUnit dependency problem (March 2005)</a></li><li><a href="http://beust.com/weblog/archives/000259.html">
		Are dependent test methods really evil?&nbsp; (March 2005)</a></li><li><a href="http://beust.com/weblog/archives/000252.html">
		The &quot;call super&quot; anti-pattern (March 2005)</a></li><li>TestNG:&nbsp; A
		different look at testing (Presentation at TheServerSide Symposium,
		March 2005)</li><li><a href="http://beust.com/weblog/archives/000236.html">
		Testing asynchronous code with TestNG (February 2005)</a></li><li><a href="http://www-106.ibm.com/developerworks/java/library/j-testng/">
		Making Testing a Breeze with TestNG (DeveloperWorks, January 2005)</a>
		(also
	<a href="http://www.51testing.com/tech/20050122_1.htm">in Chinese</a>)</li><li><a href="http://www.theserverside.com/news/thread.tss?thread_id=31214">
		TestNG:&nbsp; Catch the Testing Fever (TheServerSide, January 2005)</a></li><li><a href="http://www.beust.com/weblog/archives/000230.html">
		Why use XML to configure tests?&nbsp; (January 2005)</a></li><li>
	<a href="http://www.javapolis.com/confluence/display/JP04/Beyond+JUnit+,+introducing+TestNG,+the+next+generation+in+testing">
	TestNG:&nbsp; Beyond JUnit (Presentation at JavaPolis, Belgium, December
	2004)</a></li><li><a href="http://www.theserverside.com/news/thread.tss?thread_id=30394">
		Announcing TestNG 2.0 (TheServerSide, December 2004)</a></li><li><a href="http://www.javalobby.org/articles/testng/">
		TestNG:&nbsp; Catching the TestNG fever (JavaLobby, December 2004)</a></li><li><a href="http://www.beust.com/weblog/archives/000170.html">
		Using inheritance of annotations for flexible testing (August 2004)</a></li><li><a href="http://www.beust.com/weblog/archives/000175.html">
		Multiple instantations of tests (August 2004)</a></li><li><a href="http://theserverside.com/blogs/showblog.tss?id=Unitized">
		Don't get unitized (July 2004)</a></li><li>
	<a href="http://www.google.com/url?sa=X&start=3&q=http://www.theserverside.com/news/thread.tss?thread_id=25568">
	TestNG:&nbsp; Testing, the Next Generation (TheServerSide, April 2004)</a></li></ul>
<h3><a name="french">French</a></h3>
<ul>
	<li><a href="http://www.spalud.info/testng/">Le framework TestNG</a> (S&eacute;bastien
	Palud, April 2006)<br>
&nbsp;</li>
</ul>

<h3><a name="german">German</a></h3>
<ul>
	<li><a href="http://www.qaware.de/downloads/to1-adersberger.pdf">Comparison TestNG / JUnit 4</a> (Josef Adersberger,
	May 2006, PDF)<br>
&nbsp;</li>
</ul>

<h2 align="center">
<a name="contributors">CONTRIBUTORS</a></h2><p align="left">TestNG has received a lot of help from various people throughout
its existence.</p><p align="left">With code:</p><ul>
	<li>
	<p align="left"><a href="mailto:the_mindstorm@evolva.ro">Alexandru Popescu</a>,
	who ported TestNG to JDK 1.4 and has been tirelessly contributing ever
	since.</li>
	<li>
	<p align="left">Hani Suleiman and Mark Derricutt (IDEA plug-in).</li>
	<li>
	<p align="left">Andrew Glover and <a href="http://tacos.sourceforge.net">Jesse Kuhnert</a>/<a href="http://blogs.codehaus.org/people/brett//archives/maven.html">Brett Porter</a> (Maven 1 and Maven 2
	plug-ins respectively).</li><li>
	<p align="left">Jolly Chen (JUnitReport plug-in).</li><li>
	<p align="left">Thierry Janaudy (PDF report plug-in).</li></ul><p align="left">And also with ideas, articles and bug reports:</p><ul>
	<li>
	<p align="left">Filippo Diotalevi, Matthew Schmidt Robert McIntosh, JR
	Boyens, Robert Watkins, Aleksi Kallio, Doug Lea, Eron Wright, Guillaume
	Laforge, Owen Griffiths, Jean-Louis Berliet,
	Morten Christensen and many others... </li>
</ul>

<h2 align="center">&nbsp;</h2>

<h2 align="center">
SPECIAL THANKS
</h2>
To <a href="http://yourkit.com">YourKit</a> for helping us profiling TestNG.<p>&nbsp;</p>


<h2 align="center"><a name="testimonies">TESTIMONIES</a></h2><p align="left">A great product is nothing without testimonies, so here is what
people have to say about TestNG:</p><p align="left">&quot;It's a lot of fun.&nbsp; Not as fun as Seinfeld, but more fun than
Chris Rock on a bad day&quot;<br>
&nbsp;&nbsp;&nbsp; - <i>A buddy</i>&nbsp;<br>
<br>
&quot;Are you going to eat your dessert?&quot;<br>
&nbsp;&nbsp;&nbsp; - <i>Someone I met at the cafeteria</i><br>
&nbsp;<br>
&quot;Rock on, dude&quot;<br>
&nbsp;&nbsp;&nbsp; - <i>A skateboarder<br>
</i>&nbsp;<br>
&quot;Okay, I'll try it.&nbsp; Can I have my laptop back now&quot;?<br>
&nbsp;&nbsp;&nbsp; - <i>A scared contractor<br>
</i>&nbsp;<br>
&quot;Cedric, stop talking to him, he's sleeping&quot;<br>
&nbsp;&nbsp;&nbsp; - <i>Some random person who should mind their own business</i></p>

</body>

</html>
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/migrating.html��������������������������������������������������������������0000644�0001750�0001750�00000011227�12551235562�017270� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html>
    <head>
        <title>TestNG - Migrating from JUnit</title>

        <link rel="stylesheet" href="testng.css" type="text/css" />
        <link type="text/css" rel="stylesheet" href="http://beust.com/beust.css"  />
        <script type="text/javascript" src="http://beust.com/prettify.js"></script>
        <script type="text/javascript" src="banner.js"></script>

        <script type="text/javascript" src="http://beust.com/scripts/shCore.js"></script>
        <script type="text/javascript" src="http://beust.com/scripts/shBrushJava.js"></script>
        <script type="text/javascript" src="http://beust.com/scripts/shBrushXml.js"></script>
        <script type="text/javascript" src="http://beust.com/scripts/shBrushBash.js"></script>
        <script type="text/javascript" src="http://beust.com/scripts/shBrushPlain.js"></script>
        <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shCore.css"/>
        <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shThemeCedric.css"/>
        <script type="text/javascript">
          SyntaxHighlighter.config.clipboardSwf = 'scripts/clipboard.swf';
          SyntaxHighlighter.defaults['gutter'] = false;
          SyntaxHighlighter.all();
        </script>

      </head>
<body onLoad="prettyPrint()">

<script type="text/javascript">
    displayMenu("migrating.html")
</script>


<h2 align="center">Migrating from JUnit</h2>

<h3>Using Eclipse</h3>

The easiest way to convert your JUnit tests to TestNG is to use the Eclipse TestNG plug-in refactoring support. You will find a full description of its features in the <a href="eclipse.html#eclipse-quickfix">Eclipse section</a>.

<h3>Asserts</h3>
Note that the class <tt>org.testng.Assert</tt> uses a different argument ordering than the ones used by JUnit. If you are porting code that uses JUnit's asserts, you might want to us a static import of that class:

<pre class="brush: java">
import static org.testng.AssertJUnit.*;
</pre>

<h3>Running JUnit Tests</h3>

<p>TestNG can automatically recognize and run JUnit tests, so you can use TestNG as a runner for all your existing tests and write new tests using TestNG.</p>

<p>All you have to do is to put JUnit library on the TestNG classpath, so it can find and use JUnit classes,
change your test runner from JUnit to TestNG in Ant and then run TestNG in <tt>"mixed"</tt> mode.
This way you can have all your tests in the same project, even in the same package, and start using TestNG.
This approach also allows you to convert your existing JUnit tests to TestNG incrementally.</p>

<h4>Example - replacing JUnit Ant task with TestNG one</h4>

JUnit version:
<pre class="brush: xml">
&lt;junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true"&gt;
    &lt;batchtest todir="${build.test.results.dir}"&gt;
        &lt;fileset dir="${test.src.dir}"&gt;
            &lt;include name="**/*Test.*"/&gt;
    &lt;/batchtest&gt;
    &lt;classpath&gt;
        &lt;path path="${run.test.classpath}"/&gt;
    &lt;/classpath&gt;
    &lt;syspropertyset&gt;
        &lt;propertyref prefix="test-sys-prop."/&gt;
        &lt;mapper from="test-sys-prop.*" to="*" type="glob"/&gt;
    &lt;/syspropertyset&gt;
    &lt;formatter type="xml"/&gt;
    &lt;jvmarg value="-ea"/&gt;
    &lt;jvmarg line="${run.jvmargs}"/&gt;
&lt;/junit&gt;
</pre>

TestNG version:
<pre class="brush: xml">
&lt;taskdef name="testng" classname="org.testng.TestNGAntTask" classpath="${run.test.classpath}"/&gt;

&lt;fileset id="mixed.tests" dir="${test.src.dir}"&gt;
    &lt;include name="**/*Test.*"/&gt;
&lt;/fileset&gt;

&lt;testng mode="mixed" classfilesetref="mixed.tests" workingDir="${work.dir}" failureProperty="tests.failed" outputdir="${build.test.results.dir}"&gt;
    &lt;classpath&gt;
        &lt;pathelement path="${build.test.classes.dir}"/&gt;
        &lt;pathelement path="${run.test.classpath}"/&gt;
        &lt;pathelement path="${junit.lib}"/&gt;
    &lt;/classpath&gt;
    &lt;propertyset&gt;
        &lt;propertyref prefix="test-sys-prop."/&gt;
        &lt;mapper from="test-sys-prop.*" to="*" type="glob"/&gt;
    &lt;/propertyset&gt;
    &lt;jvmarg line="${run.jvmargs}"/&gt;
&lt;/testng&gt;
</pre>


<h3>Related reading</h3>

<ul>
    <li><a href="http://www.opengamma.com/blog/2011/04/04/converting-opengamma-junit-testng">Here is the detailed report of a company that successfully converted a large codebase of JUnit 4 tests over to TestNG</a>.</li>
    <li><a href="http://wiki.netbeans.org/TestNG_MixedMode">Mixed mode in TestNG</a>.</li>
</ul>

<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-238215-2";
urchinTracker();
</script>


</body>
	�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/maven.html������������������������������������������������������������������0000644�0001750�0001750�00000016433�12551235562�016421� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html>
    <head>
        <title>TestNG - Maven</title>

        <link rel="stylesheet" href="testng.css" type="text/css" />
        <link type="text/css" rel="stylesheet" href="http://beust.com/beust.css"  />
        <script type="text/javascript" src="http://beust.com/prettify.js"></script>
        <script type="text/javascript" src="banner.js"></script>

        <script type="text/javascript" src="http://beust.com/scripts/shCore.js"></script>
        <script type="text/javascript" src="http://beust.com/scripts/shBrushJava.js"></script>
        <script type="text/javascript" src="http://beust.com/scripts/shBrushXml.js"></script>
        <script type="text/javascript" src="http://beust.com/scripts/shBrushBash.js"></script>
        <script type="text/javascript" src="http://beust.com/scripts/shBrushPlain.js"></script>
        <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shCore.css"/>
        <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shThemeCedric.css"/>
        <script type="text/javascript">
          SyntaxHighlighter.config.clipboardSwf = 'scripts/clipboard.swf';
          SyntaxHighlighter.defaults['gutter'] = false;
          SyntaxHighlighter.all();
        </script>

</head>

<body onLoad="prettyPrint()">

<script type="text/javascript">
    displayMenu("maven.html")
</script>


<style type="text/css">
    *.P1 { font-family:Sans; font-size:10pt; margin-left:0in; margin-right:0in; text-align:left ! important; text-indent:0inch; color:#a52a2a; }
    *.P2 { font-family:Sans; font-size:10pt; margin-left:0in; margin-right:0in; text-align:left ! important; text-indent:0inch; }
    *.P3 { font-family:'Nimbus Roman No9 L'; font-size:12pt; margin-left:0in; margin-right:0in; text-align:left ! important; text-indent:0inch; }
    *.Standard { font-family:'Nimbus Roman No9 L'; font-size:12pt; }
    *.Textbody { font-family:'Nimbus Roman No9 L'; font-size:12pt; margin-top:0in; margin-bottom:0.0835in; }
    *.T1 { font-weight:bold; }
    *.T2 { color:#353535; }
    *.T3 { color:#a52a2a; font-weight:bold; }
    *.T4 { color:#a52a2a; }
    *.T5 { color:#353535; font-family:Sans; font-size:10pt; }
    *.T6 { color:#a52a2a; font-family:Sans; font-size:10pt; font-weight:bold; }
    *.T7 { color:#a52a2a; font-family:Sans; font-size:10pt; }
  p,pre { width: 80%; }

  ul.toc {
    list-style: none;
    margin:0 0.7em 0;
    padding:0;
    font-family: verdana, arial, sans-serif;
  }
  ul.toc li {
    padding:0;
    margin: 0.2em 0 0;
  }
  ul ul {
    margin:0 2em 0;
    padding: 0;
    list-style-type: none;
  }
  li a {
    display: block;
    text-decoration: none;
    padding: 2px 10px;
    width: 140px;
  }
  ul.sub li a {
    display: block;
    border-top: none;
    padding: 2px 10px;
    background-color: transparent;
  }
</style>

<h2>TestNG Maven plug-ins</h2>

<h4>Table of Contents</h4>
<ul class="toc">
  <li class="first">
    <a class="summary" href="#maven2">Maven2 Plugin</a>

    <ul class="sub">
      <li><a href="#archetype">Archetype</a></li>
    </ul>
  </li>
  
  <li class="last"><a class="summary" href="#maven1">Maven 1 Plugin</a></li>
</ul>

<!--  begin maven2  -->
<h3 id="maven2">Maven 2</h3>

<p>Maven 2 supports TestNG out of the box without the need to download any additional plugins <em>(other than TestNG itself)</em>. It is recommended that you use version 2.4 or above of the Surefire plugin (this is the case in all recent versions of Maven).</p>

<p>
You can find the full instructions on the <a href="http://maven.apache.org/plugins/maven-surefire-plugin/">Maven Surefire Plugin web site</a>. There are also <a href="http://maven.apache.org/plugins/maven-surefire-plugin/examples/testng.html">TestNG-specific instructions</a>.
</p>

<h4>Specifying your pom.xml</h4>

The dependency in your project should look like the following:

<pre class="brush: xml">
 &lt;dependency&gt;
   &lt;groupId&gt;org.testng&lt;/groupId&gt;
   &lt;artifactId&gt;testng&lt;/artifactId&gt;
   &lt;version&gt;6.8&lt;/version&gt;
   &lt;scope&gt;test&lt;/scope&gt;
 &lt;/dependency&gt;
</pre>

<h4>Sample Report</h4>
<p>
A sample surefire report with TestNG can be found <a href="samplereport/index.html">here</a>.
</p>
<br/>
<!--  end maven2  -->

<!-- maven2 archetype -->
<h3 id="archetype">Maven TestNG Archetype <em>(Martin Gilday)</em></h3>
<p>
  Martin Gilday has added a new archetype for Maven2: to create a project using the archetype you simply have to specify my repository and the archetype ID.
</p>
  <pre class="brush: text">
  mvn archetype:create -DgroupId=org.martingilday -DartifactId=test1 -DarchetypeGroupId=org.martingilday -DarchetypeArtifactId=testng-archetype
    -DarchetypeVersion=1.0-SNAPSHOT -DremoteRepositories=http://www.martingilday.org/repository/</pre>

<p>Of course substitute in your own groupId and artifactId.</p>
<p>Don't forget to keep checking back at <a href="http://www.martingilday.org/updates/Maven+TestNG+Archetype">Martin's blog</a> for more updates. </p>
<!-- end maven2 archetype -->

<br/><br/>
<h3 id="maven1">Maven 1 (by Andrew Glover)</h3>

<p>The TestNG Maven plug-in is quite simple and consists of
two goals and a series of optional properties.</p>

<p>Currently the 1.1 version of the plug-in is bundled with
official releases of TestNG. To utilize the plug-in, copy the
<tt>maven-testng-plugin-<version>.jar</tt> to the <tt>$MAVEN_HOME/plugins</tt>
directory.</p>

<p>For the latest version of the plug-in (1.2 as of 12/12/05),
update your <tt>maven.repo.remote</tt> to include <tt>http://www.vanwardtechnologies.com/repository/</tt>
and then issue the following command: <tt>maven plugin:download</tt>. Maven will issue a series of questions,
answer them as follows: <BR>
<BR>
<TABLE border="1" id="table1">
    <TR>
        <TD><tt>artifactId:</tt></TD>
        <TD><tt>maven-testng-plugin</tt></TD>
    </TR>
    <TR>
        <TD>groupId:</TD>
        <TD><tt>testng</tt></TD>
    </TR>
    <TR>
        <TD>version:</TD>
        <TD><tt>1.2</tt></TD>
    </TR>
</TABLE>
</p>


<h4>Goals</h4>
<table border="1" id="table2">
    <tr>
        <th>Goal</th>
        <th>Description</th>
    </tr>
    <tr>
        <td><tt>testng</tt></td>
        <td>Runs TestNG</td>
    </tr>
    <tr>
        <td><tt>testng:junit-report</tt></td>
        <td>Creates a JUnit style report</td>
    </tr>
</table>
<h4>Properties</h4>
<table border="1" id="table3">
    <tr>
        <th>Property</th>
        <th>Optional?</th>
        <th>Description</th>
    </tr>
    <tr>
        <td><tt>maven.testng.suitexml.name</tt></td>
        <td>Yes</td>
        <td>XML file name- defaults to <tt>testng.xml</tt></td>
    </tr>
    <tr>
        <td><tt>maven.testng.suitexml.dir</tt></td>
        <td>Yes</td>
        <td>Directory where XML file lives. Defaults to <tt>${basedir}/test/conf</tt></td>
    </tr>
    <tr>
        <td><tt>maven.testng.output.dir</tt></td>
        <td>Yes</td>
        <td>Default report directory. Defaults to <tt>${maven.build.dir}/testng-output</tt></td>
    </tr>
    <tr>
        <td><tt>maven.testng.report.dir</tt></td>
        <td>Yes</td>
        <td>Directory for JUnit reports. Defaults to <tt>${maven.build.dir}/testngJunitReport</tt></td>
    </tr>
</table>

<!-- end maven stuff -->

<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
<script type="text/javascript">
_uacct = "UA-238215-2";
urchinTracker();
</script>
	
</body>
�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/index.html������������������������������������������������������������������0000644�0001750�0001750�00000021301�12551235562�016410� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html>
  <head>
    <title>TestNG - Welcome</title>
      <link rel="stylesheet" href="testng.css" type="text/css" />
      <link type="text/css" rel="stylesheet" href="http://beust.com/beust.css"  />
      <script type="text/javascript" src="http://beust.com/prettify.js"></script>
      <script type="text/javascript" src="banner.js"></script>

      <script type="text/javascript" src="http://beust.com/scripts/shCore.js"></script>
      <script type="text/javascript" src="http://beust.com/scripts/shBrushJava.js"></script>
      <script type="text/javascript" src="http://beust.com/scripts/shBrushXml.js"></script>
      <script type="text/javascript" src="http://beust.com/scripts/shBrushBash.js"></script>
      <script type="text/javascript" src="http://beust.com/scripts/shBrushPlain.js"></script>
      <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shCore.css"/>
      <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shThemeCedric.css"/>
      <script type="text/javascript">
        SyntaxHighlighter.config.clipboardSwf = 'scripts/clipboard.swf';
        SyntaxHighlighter.defaults['gutter'] = false;
        SyntaxHighlighter.all();
      </script>

    </head>

<body onload="prettyPrint()">

<script type="text/javascript">
   displayMenu("index.html");
</script>


<h2 >TestNG</h2>
<h2>Now available</h2>
<p align="center">
<a href="book.html">
<img border="0" src="http://beust.com/pics/book-cover.jpg" />
</a>
</p>
<p align="center">
<a href="book.html">Click for more details.</a>
</p>



<p align="right"><font size="-2"><em>C&eacute;dric Beust (cedric at beust.com)<br>
Current version: 6.9.4<br>
Created:&nbsp;April 27th, 2004<br>
Last Modified:&nbsp; May 9th, 2015</em></font></p>


<p>TestNG is a testing framework inspired from JUnit and NUnit but introducing
some new functionalities that make it more powerful and easier to use, such as:</p>
<ul>
       <li>Annotations.
       </li>
       <li>Run your tests in arbitrarily big thread pools with various policies available
       (all methods in their own thread, one thread per test class, etc...).
       </li>
       <li>Test that your code is multithread safe.
       </li>
       <li>Flexible test configuration.
       </li>
       <li>Support for data-driven testing (with <tt>@DataProvider</tt>).
       </li>
       <li>Support for parameters.
       </li>
       <li>Powerful execution model (no more <tt>TestSuite</tt>).
       </li>
       <li>Supported by a variety of tools and plug-ins (Eclipse, IDEA, Maven,
       etc...).
       </li>
       <li>Embeds BeanShell for further flexibility.
       </li>
       <li>Default JDK functions for runtime and logging (no dependencies).
       </li>
       <li>Dependent methods for application server testing.</li>
</ul>
<p>TestNG is designed to cover all categories of tests:&nbsp; unit, functional,
end-to-end, integration, etc...</p>
<p>I started TestNG out of frustration for some JUnit deficiencies which I have
documented on my weblog <a href="http://beust.com/weblog/2004/08/25/testsetup-and-evil-static-methods/">here</a> and <a href="http://beust.com/weblog/2004/02/08/junit-pain/">here</a>
Reading these entries might give you a better idea of the goal I am trying to
achieve with TestNG.&nbsp; You can also check out a quick
<a href="http://www.beust.com/weblog/archives/000176.html">overview of the main
features</a> and an <a href="http://beust.com/weblog/2004/08/18/using-annotation-inheritance-for-testing/">
article</a> describing a very concrete example where the combined use of several
TestNG's features provides for a very intuitive and maintainable testing design.</p>
<p>Here is a very simple test:</p>

<h3 class="sourcetitle">SimpleTest.java</h3>
<pre class="brush: java" >
package example1;

import org.testng.annotations.*;

public class SimpleTest {

 @BeforeClass
 public void setUp() {
   // code that will be invoked when this test is instantiated
 }

 @Test(groups = { "fast" })
 public void aFastTest() {
   System.out.println("Fast test");
 }

 @Test(groups = { "slow" })
 public void aSlowTest() {
    System.out.println("Slow test");
 }

}
</pre>

The method <tt>setUp()</tt> will be invoked after the test class has been built and before
any test method is run.&nbsp; In this example, we will be running the group
fast, so <tt>aFastTest()</tt> will be invoked while <tt>aSlowTest()</tt> will be
skipped.<p>
<!-------------------------------------

 WRITING A TEST

 ------------------------------------>

Things to note:</p><ul>
       <li>No need to extend a class or implement an interface.</li><li>Even though the example above uses the JUnit conventions, our methods
       can be called any name you like, it's the annotations that tell TestNG what
       they are.</li><li>A test method can belong to one or several groups.</li></ul>

       <p>

Once you have compiled your test class into the <tt>build</tt> directory, you
can invoke your test with the command line, an ant task (shown below) or an XML
file:

<h3 class="sourcetitle">build.xml</h3>
<pre class="brush:java">
&lt;project default="test"&gt;

 &lt;path id="cp"&gt;
   &lt;pathelement location="lib/testng-testng-5.13.1.jar"/&gt;
   &lt;pathelement location="build"/&gt;
 &lt;/path&gt;

 &lt;taskdef name="testng" classpathref="cp"
          classname="org.testng.TestNGAntTask" /&gt;

 &lt;target name="test"&gt;
   &lt;testng classpathref="cp" groups="fast"&gt;
     &lt;classfileset dir="build" includes="example1/*.class"/&gt;
   &lt;/testng&gt;
 &lt;/target&gt;

&lt;/project&gt;
</pre>

Use ant to invoke it:

<pre class="brush: text">
c:&gt; ant
Buildfile: build.xml

test:
[testng] Fast test
[testng] ===============================================
[testng] Suite for Command line test
[testng] Total tests run: 1, Failures: 0, Skips: 0
[testng] ===============================================


BUILD SUCCESSFUL
Total time: 4 seconds
</pre>

Then you can browse the result of your tests:

<pre class="brush: text">
start test-output\index.html (on Windows)
</pre>

<h3><a name="requirements">Requirements</a></h3>
<p>TestNG requires JDK 7 or higher.</p>

<h3><a name="mailing-lists">Mailing-lists</a></h3>

<ul>
<li>The users mailing-list can be found on <a href="http://groups.google.com/group/testng-users">Google Groups</a>.
<li>If you are interested in working on TestNG itself, join the <a href="http://groups.google.com/group/testng-users">developer mailing-list</a>.
<li>If you are only interested in hearing about new versions of TestNG, you can join the low volume <a href="http://groups.google.com/group/testng-announcements">TestNG announcement mailing-list</a>.
</ul>


<h3><a name="locations-projects">Locations of the projects</a></h3>
<p>If you are interested in contributing to TestNG or one of the IDE plug-ins,
you will find them in the following locations:</p>
<ul>
       <li><a href="http://github.com/cbeust/testng/">TestNG</a></li>
       <li><a href="http://github.com/cbeust/testng-eclipse/">Eclipse plug-in</a></li>
<!--
       <li><a href="http://code.google.com/p/testng/">TestNG</a></li>
       <li><a href="http://code.google.com/p/testng-eclipse">Eclipse plug-in</a></li>
-->
      <li><a href="https://github.com/JetBrains/intellij-community/tree/master/plugins/testng">IDEA IntelliJ plug-in</a></li>
       <li><a href="http://wiki.netbeans.org/TestNG">NetBeans plug-in</a></li>
</ul>
<h3><a id="bug-reports" name="bug-reports">Bug reports</a></h3>

If you think you found a bug, here is how to report it:

<ul>
<li>Create a small project that will allow us to reproduce this bug. In most cases, one or two Java source files and a <tt>testng.xml</tt> file should be sufficient. Then you can either zip it and email it to the <a href="http://groups.google.com/group/testng-dev">testng-dev mailing-list</a> or make it available on an open source hosting site, such as <a href="http://github.com">github</a> or <a href="http://code.google.com/hosting/">Google code</a> and email <tt>testng-dev</tt> so we know about it. Please make sure that this project is self contained so that we can build it right away (remove the dependencies on external or proprietary frameworks, etc...).

<li>If the bug you observed is on the Eclipse plug-in, make sure your sample project contains the <tt>.project</tt> and <tt>.classpath</tt> files.

<li><a href="https://github.com/cbeust/testng/issues">File a bug</a>.

</ul>

</p>

<p>For more information, you can either <a href="download.html">download TestNG</a>, read the <a href="documentation-main.html">manual</a> or browse the links at the<a href="#top">top</a>.</p>

<h3>License</h3>

<a href="http://testng.org/license">Apache 2.0</a>

<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-238215-2";
urchinTracker();
</script>


</body>

</html>

�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/idea.html�������������������������������������������������������������������0000644�0001750�0001750�00000005301�12551235562�016205� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html>
    <head>
        <title>TestNG - IDEA Plugin</title>
        <script type="text/javascript" src="banner.js"></script>
        <link rel="stylesheet" href="testng.css" type="text/css" />
      </head>
<body>

<script type="text/javascript">
    displayMenu("idea.html")
</script>

<h2 align="center">TestNG IDEA Plug-in</h2>



<p align="center">
<img src="http://testng.org/pictures/idea-output.png" />
</p>

<h3>IDEA 7</h3>

TestNG is bundled in IDEA 7 onwards, no extra plugins need to be installed.  The full documentation can be found <a href="http://www.jetbrains.com/idea/features/junit_testng.html#TestNG">here</a>.

<h3>IDEA 6 and older </h3>


TestNG has an IDEA plug-in that mirrors much of the behavior of the built-in JUnit support. You should be able to run tests within IDEA without defining any files externally, as well as quickly and easily migrate JUnit code. The plug-in also provides the same output test view as JUnit tests.

Installation

<ul>
	<li>From IDEA, go to Preferences -> Plugins.</li>
	<li>Click over to the Available Plugins tab.</li>
</ul>
<p>The latest version of the TestNG plugin will be listed there, ready to download and install.&nbsp;
Also, you can go to the <a href="http://svn.jetbrains.org/idea/Trunk/bundled/testng">
TestNG IDEA plug-in project page</a> and download its source from there.</p>
<p>Please note that this plug-in only works on IDEA 5.0 and 6.0.</p>

<p><b>Creating a TestNG Run/Debug configuration</b></p>
<p>Once you have installed the plug-in and restarted IDEA, and have some TestNG classes you would like to run, simply
open the Run/Debug window. You will see a TestNG tab, where you can add a configuration.

</p>
<p>There are a number of methods for determining the set of tests that will be run. These are:</p>
<ul>
	<li>Package: Specify a package to run. All tests in this package and below will be included.</li>
	<li>Group: Specify a TestNG group to run.</li>
	<li>Suite: Specify an external testng.xml file to run.</li>
	<li>Class: Run all tests in a single class.</li>
	<li>Method: Run a single test method.

</li>
</ul>
<p>Once you create the run configuration, you can run it. Upon running, the plug-in will launch an external process to run your tests. The test results will be display in a tree view, with passed and failed tests highlighted. You can narrow down on the console output for a specify test by clicking on it, while double clicking a test will navigate to its source code.
</p>

<p align="center">
<img src="http://testng.org/pictures/idea-rundialog.png" />
</p>


<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-238215-2";
urchinTracker();
</script>

</body>

</html>
�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/faq�������������������������������������������������������������������������0000644�0001750�0001750�00000000246�12551235562�015112� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������- I'm running groups and now, my @Before methods are no longer running.
- How to return various numbers of parameters in a data provider based on the group
being run
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/eclipse.html����������������������������������������������������������������0000644�0001750�0001750�00000027503�12551235562�016737� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html>
    <head>
        <title>TestNG - Eclipse</title>
        <script type="text/javascript" src="banner.js"></script>
        <link rel="stylesheet" href="testng.css" type="text/css" />
      </head>
<body>

<script type="text/javascript">
    displayMenu("eclipse.html")
</script>


<h2 align="center">TestNG Eclipse plug-in</h2>
<p>The TestNG Eclipse plug-in allows you to run your TestNG tests from Eclipse 
and easily monitor their execution and their output. It has its own <a href="http://github.com/cbeust/testng-eclipse">project repository called <tt>testng-eclipse</tt></a>.</p>


<h3>Table of Contents</h3>

&nbsp;&nbsp;<a class="summary" href="#eclipse-installation">1 - Installation</a>
<br>
&nbsp;&nbsp;<a class="summary" href="#eclipse-creating">2 - Creating a TestNG class</a>
<br>
&nbsp;&nbsp;<a class="summary" href="#eclipse-create-launch">3 - Launch configurations</a>
<br>
&nbsp;&nbsp;<a class="summary" href="#eclipse-create-class">3.1 - From a class file</a>
<br>
&nbsp;&nbsp;<a class="summary" href="#eclipse-create-groups">3.2 - From groups</a>
<br>
&nbsp;&nbsp;<a class="summary" href="#eclipse-create-xml">3.3 - From an XML file</a>
<br>
&nbsp;&nbsp;<a class="summary" href="#eclipse-create-method">3.4 - From a method</a>
<br>
&nbsp;&nbsp;<a class="summary" href="#eclipse-listeners">3.5 - Specifying listeners and other settings</a>
<br>
&nbsp;&nbsp;<a class="summary" href="#eclipse-viewing">4 - Viewing the results</a>
<br>
&nbsp;&nbsp;<a class="summary" href="#eclipse-search">5 - Search</a>
<br>
&nbsp;&nbsp;<a class="summary" href="#eclipse-summary">6 - The Summary tab</a>
<br>
&nbsp;&nbsp;<a class="summary" href="#eclipse-quickfix">7 - Converting JUnit tests</a>
<br>
&nbsp;&nbsp;<a class="summary" href="#eclipse-quickfixes">8 - Quick fixes</a>
<br>
&nbsp;&nbsp;<a class="summary" href="#testng-xml"></a>

<!--
  Installation
-->
<h3><a name="eclipse-installation">1 - Installation</a></h3><p>
Once you have <a href="http://testng.org/doc/download.html">installed the plug-in</a>, restart Eclipse and select the menu <tt>Window / Show View 
/ Other...</tt>&nbsp; and you should see the TestNG view listed in the Java category.</p><p align="center">
<img border="0" src="http://testng.org/pictures/view.png" />
</p>

<!--
  Creating
-->
<h3><a name="eclipse-creating">2 -Creating a TestNG class</a></h3><p>

To create a new TestNG class, select the menu File / New / TestNG:

<p align="center">
<img border="0" src="http://testng.org/pictures/new-1.png" />
</p>

If you currently have a Java file open in the editor or if you have a Java file selected in the Navigator, the first page of the wizard will show you a list of all the public methods of that class and it will give you the option to select the ones you want to test. Each method you select on this page will be included in the new TestNG class with a default implementation that throws an exception, so you remember to implement it.

<p align="center">
<img border="0" src="http://testng.org/pictures/new-2.png" />
</p>

The next page lets you specify where that file will be created, whether it should contain default implementation for some configuration methods, if you'd like a data provider and finally, if a <tt>testng.xml</tt> file should be generated.

<p align="center">
<img border="0" src="http://testng.org/pictures/new-3.png" />
</p>

The plug-in will make a guess about the best location where this file should be created (for example, if you are using Maven, the default location will be under <tt>src/test/java</tt>).

<h3><a name="eclipse-create-launch">3 - Launch configuration</a></h3><p>Once you have created classes that contain TestNG annotations and/or one or 
more <tt>testng.xml</tt> files, you can create a TestNG Launch Configuration.&nbsp; 
Select the <tt>Run / Run...</tt> (or <tt>Run / Debug...</tt>) menu and create a new TestNG 
configuration:</p><p align="center">
<img border="0" src="http://testng.org/pictures/launch.png" />
</p>
<p>You should change the name of this configuration and pick a project, which 
can be selected by clicking on the <tt>Browse...</tt> button at the top of the window.</p><p>Then you choose to launch your TestNG tests in the following ways:</p><h4><a name="eclipse-launch-class">4.2.1 - From a class file</a></h4><p>Make sure the box near <tt>Class</tt> is checked and then pick a class from your 
project.&nbsp; You can click on the <tt>Browse...</tt> button and pick it directly from a 
list.&nbsp; This list only contains classes that contain TestNG annotations:</p><p align="center">
<img border="0" src="http://testng.org/pictures/classes.png" />
</p>

<h4><a name="eclipse-create-groups">3.2 - From groups</a></h4>
<p>If you only want to launch one or several groups, you can type them in the 
text field or pick them from a list by clicking on the <tt>Browse...</tt> button&nbsp;

<p align="center">
<img border="0" src="http://testng.org/pictures/groups.png" />
</p>


<h4><a name="eclipse-create-xml">3.3 - From a definition file</a></h4>
Finally, you can select a suite definition from your project.  It doesn't have to be named
<tt>testng.xml</tt>, the plug-in will automatically identify all the applicable TestNG XML files 
in your project:
<p align="center">
<img border="0" src="http://testng.org/pictures/suites.png" />
</p>


<h4>
<a name="eclipse-create-method">3.4 - From a method </a>
</h4>
<p>This launch isn't accomplished from the Launch dialog but 
directly from your Outline view:</p><p align="center">
<img border="0" src="http://testng.org/pictures/outline.png" />
</p>
You can right-click on any test methods and select <tt>Run as... / TestNG test</tt> and only the selected
method will be run (not shown on the above screenshot because I couldn't find a way to capture
a contextual menu).<p>Method launching is also available from the Package 
Explorer view and from the Java Browser perspective.</p><p>Once you have selected one of these launches, you can also choose the logging of level. Then you can launch the tests by pressing the <tt>Debug</tt> (or <tt>Run</tt>) button, which will switch you to the Debug perspective and will open the main TestNG view.</p>

<h4>
<a name="eclipse-listeners">3.5 -Specifying listeners and other settings </a>
</h4>

As you saw above, the plug-in will let you start tests in many different ways:  from an XML file, from a method, a class, etc...  When you are running an XML file, you can specify all the settings you want for this run in the XML file, but what if you want to run a package in parallel mode with specific listeners?  How can you configure the settings for all the launches that are not done from an XML file?

<p>

In order to give you access to the most flexibility, TestNG lets you specify an XML suite file for all these launches, which you can find in the Preferences menu:

<p align="center">
<img border="0" src="http://testng.org/pictures/template.png"/>
</p>

If you specify a valid suite file as "XML template file", TestNG will reuse all the settings found in this XML file, such as parallel, name, listeners, thread pool size, etc...  Only the <tt>&lt;test&gt;</tt> tags in this file will be ignored since the plug-in will replace these by a generated <tt>&lt;test&gt;</tt> tag that represents the launch you chose.

<!--
  Viewing
-->
<h3>
<a name="eclipse-viewing">4 - Viewing the test results </a>
</h3>

<p align="center">
<img border="0" src="http://testng.org/pictures/success.png" />
</p>

<p>The above view shows a successful run of the tests:&nbsp; the bar is green 
and no failed tests are reported.&nbsp; The <tt>All tests</tt> tab shows you a list of 
all the classes and methods that were run.</p><p>If your test run contains failures, the view will look like this:</p><p align="center">
<img border="0" src="http://testng.org/pictures/failure.png" />
</p>

<p>You can use the <tt>Failed tests</tt> tab to display only these tests that failed, and 
when you select such a test, the stack trace will be shown on the right-hand 
pane.&nbsp; You can double click on the offending line to be taken directly to 
the failure in your code.</p>

<h3>
<a name="eclipse-search">5 - Search </a>
</h3>


<p align="center">
<img border="0" src="http://testng.org/pictures/search.png" />
</p>

<p>When you have hundreds of tests running, finding a specific one is not always easy, so you can type a few letters of the test method or its parameters in the Search box and the content of the tree will automatically narrow down to methods matching your search. Note in the screen shot above that the search also works on parameters provided by <tt>@DataProvider</tt>.</p>

<h3>
<a name="eclipse-summary">6 - Summary </a>
</h3>


<p align="center"> 
<img border="0" src="http://testng.org/pictures/summary1.png" />
</p> 
<p>The Summary tab gives you statistics on your test run, such as the timings, the test names, the number of methods and classes, etc&#8230; Since the results are shown in a table, you can also sort on any criterion you like for easier parsing. This is especially handy when you are trying to determine what tests take the longest time.</p>

<p>The search box works in this view as well, and note that in the screen shot below, the Time column is sorted in decreasing order:</p> 
<p align="center"> 
<img border="0" src="http://testng.org/pictures/summary2.png" />



<h3><a name="eclipse-quickfix">7 - Converting JUnit tests</a></h3>

You can easily convert JUnit 3 and JUnit 4 tests to TestNG.

<p>

Your first option is to use the Quick Fix function:

<p>

<p align="center"> 
<img border="0" src="http://testng.org/pictures/convert1.png" />
<br>
<b>Convert from JUnit 3</b>
</p>

<p align="center"> 
<img border="0" src="http://testng.org/pictures/convert2.png" />
<br>
<b>Convert from JUnit 4</b>
</p>

You can also convert packages or entire source folders with the conversion refactoring:

<p align="center"> 
<img border="0" src="http://testng.org/pictures/refactoring1.png" />
</p>

The refactoring wizard contains several pages:

<p align="center"> 
<img border="0" src="http://beust.com/pics/menu-convert2.png " />
</p>
 
This page lets you generate a testng.xml automatically. You can configure whether to include your test classes individually or by package, the suite and test name and also whether these tests should run in parallel.

<p align="center"> 
<img border="0" src="http://testng.org/pictures/refactoring2.png" />
</p>

This page gives you an overview of the changes that are about to be performed. You can also decide to exclude certain files from the refactoring.

<p>

When you are done, press the "Finish" button. Like all Eclipse refactorings, you can undo all these changes in one click:

<p align="center"> 
<img border="0" src="http://beust.com/pics/menu-convert4.png" />
</p>

<h3><a name="eclipse-quickfixes">8 - Quick fixes</a></h3>

The TestNG Eclipse plug-in offers several quick fixes while you are editing a TestNG class (accessible with <tt>Ctrl-1</tt> on Windows/Linux and <tt>&#8984;-1</tt> on Mac OS):

<h4>Convert to JUnit</h4>

This was covered in the <a href="#eclipse-quickfix"> previous section</a>.

<h4>Pushing and pulling <tt>@Test</tt> annotations</h4>

If you have several test methods annotated with <tt>@Test</tt> and you'd like to replace them all with a single <tt>@Test</tt> annotation at the class level, choose the "Pull annotation" quick fix:

<p align="center">
<img border="0" src="http://testng.org/pictures/refactoring-pull-annotation.png" />
</p>

Reciprocally, you can move a class level <tt>@Test</tt> annotation onto all your public methods:

<p align="center">
<img border="0" src="http://testng.org/pictures/refactoring-push-annotation.png" />
</p>

<h4>Automatically importing <tt>asserts</tt></h4>

Apply a quick fix on an assert method to automatically import it:

<p align="center">
<img border="0" src="http://testng.org/pictures/quickfix-import.png" />
</p>



<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-238215-2";
urchinTracker();
</script>

</body>���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/download.html���������������������������������������������������������������0000644�0001750�0001750�00000010030�12551235562�017105� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html>
    <head>
        <title>TestNG - Download Current Release and Beta Versions</title>

        <link rel="stylesheet" href="testng.css" type="text/css" />
        <link type="text/css" rel="stylesheet" href="http://beust.com/beust.css"  />
        <script type="text/javascript" src="banner.js"></script>

      <script type="text/javascript" src="http://beust.com/scripts/shCore.js"></script>
      <script type="text/javascript" src="http://beust.com/scripts/shBrushJava.js"></script>
      <script type="text/javascript" src="http://beust.com/scripts/shBrushXml.js"></script>
      <script type="text/javascript" src="http://beust.com/scripts/shBrushBash.js"></script>
      <script type="text/javascript" src="http://beust.com/scripts/shBrushPlain.js"></script>
      <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shCore.css"/>
      <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shThemeCedric.css"/>
      <script type="text/javascript">
        SyntaxHighlighter.config.clipboardSwf = 'scripts/clipboard.swf';
        SyntaxHighlighter.defaults['gutter'] = false;
        SyntaxHighlighter.all();
      </script>
      <script type="text/javascript" src="http://beust.com/toc.js"></script>

        <style type="text/css">
            /* Set the command-line table option column width. */
            #command-line colgroup.option {
                 width: 7em;
            }
        </style
      </head>
<body onload="prettyPrint()">

<script type="text/javascript">
    displayMenu("download.html")
</script>


<h2 align="center">Downloading TestNG</h2>

<h3>Current Release Version</h3>

<h4>Maven</h4>

<pre class="brush: xml">
    &lt;repositories&gt;
      &lt;repository&gt;
        &lt;id&gt;central&lt;/id&gt;
        &lt;name&gt;bintray&lt;/name&gt;
        &lt;url&gt;http://jcenter.bintray.com&lt;/url&gt;
      &lt;/repository&gt;
    &lt;/repositories&gt;

    &lt;dependency&gt;
      &lt;groupId&gt;org.testng&lt;/groupId&gt;
      &lt;artifactId&gt;testng&lt;/artifactId&gt;
      &lt;version&gt;6.9.4&lt;/version&gt;
      &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;
</pre>

<h4>Gradle</h4>

<pre class="brush: java">
repositories {
    jcenter()
}

dependencies {
    testCompile 'org.testng:testng:6.9.4'
}
</pre>

<h3>Snapshots</h3>

TestNG <a href="https://oss.sonatype.org/content/repositories/snapshots/org/testng/testng/">automatically uploads snapshots to Sonatype</a> which you can access by adding the following repository:

<pre class="brush: java">
repositories {
    maven {
        url 'https://oss.sonatype.org/content/repositories/snapshots'
    }
}
</pre>

<h3>Eclipse plug-in</h3>
<p>You can use either the Eclipse Market Place or the update site:</p>
<ul>
	<li>Select<i> Help / Install new software.</i> 
	</li>
	<li><i>Search for new features to install.</i> 
	</li>
	<li><i>New remote site.</i> 
	</li>
	<li>For Eclipse 3.4 and above, enter <a href="http://beust.com/eclipse">http://beust.com/eclipse</a>.
	<li>For Eclipse 3.3 and below, enter <a href="http://beust.com/eclipse1">http://beust.com/eclipse1</a>.
	</li>
	<li>Make sure the check box next to URL is checked and click <i>Next</i>. 
	</li>
	<li>Eclipse will then guide you through the process. </li>
</ul>

<p>You can also install older versions of the plug-ins <a href="http://beust.com/eclipse-old">here</a>. Note that the URL's on this page are update sites as well, not direct download links.

<p>TestNG is also <a href="http://github.com/cbeust/testng">hosted on GitHub</a>, where you can download the source and build the distribution yourself:

<pre class="brush: plain">
$ git clone git://github.com/cbeust/testng.git
$ cd testng
$ mvn package
</pre>

<p>You will then find the jar file in the <tt>target</tt> directory</p>

<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-238215-2";
urchinTracker();
</script>


</body>

</html>
��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/documentation-main.html�����������������������������������������������������0000644�0001750�0001750�00000300652�12551235562�021105� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html>
    <head>
        <title>TestNG</title>

        <link rel="stylesheet" href="testng.css" type="text/css" />
        <link type="text/css" rel="stylesheet" href="http://beust.com/beust.css"  />
        <script type="text/javascript" src="banner.js"></script>

      <script type="text/javascript" src="http://beust.com/scripts/shCore.js"></script>
      <script type="text/javascript" src="http://beust.com/scripts/shBrushJava.js"></script>
      <script type="text/javascript" src="http://beust.com/scripts/shBrushXml.js"></script>
      <script type="text/javascript" src="http://beust.com/scripts/shBrushBash.js"></script>
      <script type="text/javascript" src="http://beust.com/scripts/shBrushPlain.js"></script>
      <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shCore.css"/>
      <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shThemeCedric.css"/>
      <script type="text/javascript">
        SyntaxHighlighter.config.clipboardSwf = 'scripts/clipboard.swf';
        SyntaxHighlighter.defaults['gutter'] = false;
        SyntaxHighlighter.all();
      </script>
      <script type="text/javascript" src="http://beust.com/toc.js"></script>

        <style type="text/css">
            /* Set the command-line table option column width. */
            #command-line colgroup.option {
                 width: 7em;
            }
        </style>
    </head>
<body onLoad="generateToc();">

<script type="text/javascript">
    displayMenu("documentation-main.html")
</script>

<h2 align="center">TestNG</h2>

<!-- --------------------------

<table class="float-right">
  <tr>
    <td>
<script type="text/javascript"><!--
google_ad_client = "pub-1467757024002850";
google_ad_width = 120;
google_ad_height = 600;
google_ad_format = "120x600_as";
google_ad_channel ="5560744946";
//-->
<!-- 

</script>

<script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>      
    </td>
  </tr>
</table>

------------------------------- -->

<!-------------------------------------
  TOC
  ------------------------------------>

<h3>Table of Contents</h3>

<div id="table-of-contents">
</div>


<!-------------------------------------
  INTRODUCTION
  ------------------------------------>
<h3><a class="section" name="introduction">Introduction</a></h3>

TestNG is a testing framework designed to simplify a broad range of testing needs, from unit testing (testing a class in isolation of the others) to integration testing (testing entire systems made of several classes, several packages and even several external frameworks, such as application servers).

<p>

Writing a test is typically a three-step process:

<ul>
<li>Write the business logic of your test and insert <a href="#annotations">TestNG annotations</a> in your code.
</li>
<li>Add the information about your test (e.g. the class name, the groups you wish to run, etc...) in a <tt><a href="#testng-xml">testng.xml</a></tt> file or in build.xml.
</li>
<li><a href="ant.html">Run TestNG</a>.
</li>
</ul>
You can find a quick example on the <a href="index.html">Welcome page</a>.
<p>
The concepts used in this documentation are as follows:

<ul>
<li>
A suite is represented by one XML file.  It can contain one or more tests and is defined by the <tt>&lt;suite&gt;</tt> tag.
</li>
<li>
A test is represented by <tt>&lt;test&gt;</tt> and can contain one or more TestNG classes.
</li>
<li>
A TestNG class is a Java class that contains at least one TestNG annotation.  It is represented by the <tt>&lt;class&gt;</tt> tag and can contain one or more test methods.
</li>
<li>
A test method is a Java method annotated by <tt>@Test</tt> in your source.
</li></ul>A TestNG test can be configured by <tt>@BeforeXXX and @AfterXXX </tt>annotations which allows to perform some Java logic before and after a certain point, these points being either of the items listed above.<p>
The rest of this manual will explain the following:
<p>
<ul>
<li>A list of all the annotations with a brief explanation.  This will give you an idea of the various functionalities offered by TestNG but you will probably want to consult the section dedicated to each of these annotations to learn the details.
</li>
<li>A description of the testng.xml file, its syntax and what you can specify in it.
</li>
<li>A detailed list of the various features and how to use them with a combination of annotations and testng.xml.
</li>
</ul>


<!-------------------------------------
  ANNOTATIONS
  ------------------------------------>

<h3><a class="section" name="annotations">Annotations</a></h3>

Here is a quick overview of the annotations available in TestNG along with their attributes.

<p>

<table>

<tr>
<td colspan="2"><b><tt>@BeforeSuite<br>@AfterSuite<br>@BeforeTest<br>@AfterTest<br>@BeforeGroups<br>@AfterGroups<br>@BeforeClass<br>@AfterClass<br>@BeforeMethod<br>@AfterMethod</tt></b></td><td><b>Configuration information for a TestNG class:</b>

<br>

<br><b>@BeforeSuite: </b>The annotated method will be run before all tests in this suite have run.

<br><b>@AfterSuite: </b> The annotated method will be run after all tests in this suite have run. 

<br><b>@BeforeTest</b>: The annotated method will be run before any test method belonging to the classes inside the &lt;test&gt; tag is run.

<br><b>@AfterTest</b>: The annotated method will be run after all the test methods belonging to the classes inside the &lt;test&gt; tag have run.

<br><b>@BeforeGroups</b>:   The list of groups that this configuration method will run before. This method is guaranteed to run shortly before the first test method that belongs to any of these groups is invoked.

<br><b>@AfterGroups</b>:   The list of groups that this configuration method will run after.  This method is guaranteed to run shortly after the last test method that belongs to any of these groups is invoked.

<br><b>@BeforeClass</b>: The annotated method will be run before the first test method in the current class is invoked.

<br><b>@AfterClass</b>: The annotated method will be run after all the test methods in the current class have been run. 

<br><b>@BeforeMethod</b>: The annotated method will be run before each test method.

<br><b>@AfterMethod</b>: The annotated method will be run after each test method.

</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>alwaysRun</tt>
</td>
<td>
   For before methods (beforeSuite, beforeTest, beforeTestClass and
   beforeTestMethod, but not beforeGroups):
   If set to true, this configuration method will be run
   regardless of what groups it belongs to. 
   <br>
   For after methods (afterSuite, afterClass, ...): 
   If set to true, this configuration method will be run
   even if one or more methods invoked previously failed or
   was skipped.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>dependsOnGroups</tt>
</td>
<td>
          The list of groups this method depends on.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>dependsOnMethods</tt>
</td>
<td>
          The list of methods this method depends on.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>enabled</tt>
</td>
<td>
          Whether methods on this class/method are enabled.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>groups</tt>
</td>
<td>
          The list of groups this class/method belongs to.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>inheritGroups</tt>
</td>
<td>
          If true, this method will belong to groups specified in the @Test annotation at the class level.
</td>
</tr>

<tr class="separator">
<td colspan="3">&nbsp;</td>
</tr>

<tr>
<td colspan="2"><tt><b>@DataProvider</b></tt></td><td><b>Marks a method as supplying data for a test method. The annotated method must return an Object[][] where each Object[] can be assigned the parameter list of the test method. The @Test method that wants to receive data from this DataProvider needs to use a dataProvider name equals to the name of this annotation.</b></td></tr><tr>
<td>
</td>
<td>
<tt>name</tt>
</td>
<td>
The name of this data provider. If it's not supplied, the name of this data provider will automatically be set to the name of the method.
</td>
</tr>
<tr>
<td>
</td>
<td>
<tt>parallel</tt>
</td>
<td>
If set to true, tests generated using this data provider are run in parallel. Default value is false.
</td>
</tr>
<tr>
<td colspan="3">&nbsp;</td>
</tr>

<tr>
<td colspan="2"><b><tt>@Factory</tt></b></td><td><b> Marks a method as a factory that returns objects that will be used by TestNG as Test classes.  The method must return Object[].</b></td></tr><tr>
<td colspan="3">&nbsp;</td>
</tr>

<tr>
<td colspan="2"><b><tt>@Listeners</tt></b></td><td><b>Defines listeners on a test class.</b></td></tr>
<tr>
  <td></td>
  <td>
    <tt>value</tt>
  </td>
  <td>
    An array of classes that extend <tt>org.testng.ITestNGListener</tt>.
  </td>
</tr>

<tr>
<td colspan="3">&nbsp;</td>
</tr>

<td colspan="2"><b><tt>@Parameters</tt></b></td><td><b>Describes how to pass parameters to a @Test method.</b></td></tr><tr>
<td>
</td>
<td>
<tt>value</tt>
</td>
<td>
The list of variables used to fill the parameters of this method.
</td>
</tr>

<tr>
<td colspan="3">&nbsp;</td>
</tr>

<tr>
<td colspan="2"><b>@Test</b></td><td><b>Marks a class or a method as part of the test.</b></td></tr><tr>
<td>
</td>
<td>
<tt>alwaysRun</tt>
</td>
<td>
          If set to true, this test method will always be run even if it depends on a method that failed.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>dataProvider</tt>
</td>
<td>
The name of the data provider for this test method.
</td>
</tr>


<tr>
<td>
</td>
<td>
<tt>dataProviderClass</tt>
</td>
<td>
The class where to look for the data provider.  If not specified, the data provider will be looked on the class of the current test method or one of its base classes. If this attribute is specified, the data provider method needs to be static on the specified class.  
</td>
</tr>






<tr>
<td>
</td>
<td>
<tt>dependsOnGroups</tt>
</td>
<td>
          The list of groups this method depends on.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>dependsOnMethods</tt>
</td>
<td>
          The list of methods this method depends on.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>description</tt>
</td>
<td>
          The description for this method.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>enabled</tt>
</td>
<td>
          Whether methods on this class/method are enabled.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>expectedExceptions</tt>
</td>
<td>
           The list of exceptions that a test method is expected to throw.  If no exception or a different than one on this list is thrown, this test will be marked a failure.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>groups</tt>
</td>
<td>
          The list of groups this class/method belongs to.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>invocationCount</tt>
</td>
<td>
          The number of times this method should be invoked.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>invocationTimeOut</tt>
</td>
<td>
          The maximum number of milliseconds this test should take for the cumulated time of all the invocationcounts.  This attribute will be ignored if invocationCount is not specified.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>priority</tt>
</td>
<td>
          The priority for this test method. Lower priorities will be scheduled first.
</td>
</tr>

<tr>
<td>
</td>
<td>

<tt>successPercentage</tt>
</td>
<td>
          The percentage of success expected from this method
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>singleThreaded</tt>
</td>
<td>
             If set to true, all the methods on this test class are guaranteed to run in the same thread, even if the tests are currently being run with parallel="methods". This attribute can only be used at the class level and it will be ignored if used at the method level. Note: this attribute used to be called <tt>sequential</tt> (now deprecated).

</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>timeOut</tt>
</td>
<td>
          The maximum number of milliseconds this test should take.
</td>
</tr>

<tr>
<td>
</td>
<td>
<tt>threadPoolSize</tt>
</td>
<td>
             The size of the thread pool for this method.  
The method will be invoked from multiple threads as specified by 
invocationCount. <br>Note:  this attribute is ignored if invocationCount is not specified

</td>
</tr>

</table>




</pre>
<!-------------------------------------
  TESTNG.XML
  ------------------------------------>
<h3><a class="section" name="testng-xml">testng.xml</a></h3>

<p>You can invoke TestNG in several different ways:</p><ul>
	<li>With a <tt>testng.xml</tt> file</li><li><a href="http://testng.org/doc/ant.html">With ant</a></li><li>From the command line</li></ul><p>This section describes the format of <tt>testng.xml</tt> (you will find documentation 
on ant and the command line below).</p><p>The current DTD for <tt>testng.xml</tt> can be found on the main Web site:&nbsp;
<a href="http://testng.org/testng-1.0.dtd">http://testng.org/testng-1.0.dtd</a> 
(for your convenience, you might prefer to browse the
<a href="http://testng.org/dtd">HTML version</a>).</p>

Here is an example <tt>testng.xml</tt> file:

<p>
<h3 class="sourcetitle">testng.xml</h3>
<pre class="brush: xml">
&lt;!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" &gt;
 
&lt;suite name="Suite1" verbose="1" &gt;
  &lt;test name="Nopackage" &gt;
    &lt;classes&gt;
       &lt;class name="NoPackageTest" /&gt;
    &lt;/classes&gt;
  &lt;/test&gt;

  &lt;test name="Regression1"&gt;
    &lt;classes&gt;
      &lt;class name="test.sample.ParameterSample"/&gt;
      &lt;class name="test.sample.ParameterTest"/&gt;
    &lt;/classes&gt;
  &lt;/test&gt;
&lt;/suite&gt;
</pre>

You can specify package names instead of class names:

<h3 class="sourcetitle">testng.xml</h3>
<pre class="brush: xml; highlight: [5,6,7]">
&lt;!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" &gt;

&lt;suite name="Suite1" verbose="1" &gt;
  &lt;test name="Regression1"   &gt;
    &lt;packages&gt;
      &lt;package name="test.sample" /&gt;
   &lt;/packages&gt;
 &lt;/test&gt;
&lt;/suite&gt;
</pre>


<p>In this example, TestNG will look at all the classes in the package 
	<tt>test.sample</tt> and will retain only classes that have TestNG annotations.</p>

You can also specify groups and methods to be included and excluded:

<h3 class="sourcetitle">testng.xml</h3>
<pre class="brush: xml">
&lt;test name="Regression1"&gt;
  &lt;groups&gt;
    &lt;run&gt;
      &lt;exclude name="brokenTests"  /&gt;
      &lt;include name="checkinTests"  /&gt;
    &lt;/run&gt;
  &lt;/groups&gt;
 
  &lt;classes&gt;
    &lt;class name="test.IndividualMethodsTest"&gt;
      &lt;methods&gt;
        &lt;include name="testMethod" /&gt;
      &lt;/methods&gt;
    &lt;/class&gt;
  &lt;/classes&gt;
&lt;/test&gt;
</pre>

<p>You can also define new groups inside <tt>testng.xml</tt> and specify additional details in attributes, such as whether to run the tests in parallel, how many threads to use, whether you are running JUnit tests, etc...&nbsp;
<p>

By default, TestNG will run your tests in the order they are found in the XML
file. If you want the classes and methods listed in this file to be
run in an unpredictible order, set the <tt>preserve-order</tt>
attribute to <tt>false</tt>

<h3 class="sourcetitle">testng.xml</h3>
<pre class="brush: xml">
&lt;test name="Regression1" preserve-order="false"&gt;
  &lt;classes&gt;

    &lt;class name="test.Test1"&gt;
      &lt;methods&gt;
        &lt;include name="m1" /&gt;
        &lt;include name="m2" /&gt;
      &lt;/methods&gt;
    &lt;/class&gt;

    &lt;class name="test.Test2" /&gt;

  &lt;/classes&gt;
&lt;/test&gt;
</pre>

<p>

Please see the DTD for a complete list of the features, or read on.</p>

<!-------------------------------------
  RUNNING TESTNG
  ------------------------------------>

<h3><a class="section" name="running-testng">Running TestNG</a></h3>

TestNG can be invoked in different ways:

<ul>
<li>Command line
</li>
<li><a href="ant.html">ant</a>
</li>
<li><a href="eclipse.html">Eclipse</a>
</li>
<li><a href="idea.html">IntelliJ's IDEA</a>
</li>
</ul>

This section only explains how to invoke TestNG from the command line.  Please click on one of the links above if you are interested in one of the other ways.
<p>
Assuming that you have TestNG in your class path, the simplest way to invoke TestNG is as follows:

<pre class="brush: text">
java org.testng.TestNG testng1.xml [testng2.xml testng3.xml ...]
</pre>

You need to specify at least one XML file describing the TestNG suite you are trying to run.  Additionally, the following command-line switches are available:

</p>

<table id="command-line">
    <caption>Command Line Parameters</caption><colgroup class="option"/>
    <colgroup class="argument"/>
    <colgroup class="documentation"/>
    <thead>

        <tr>
            <th>Option</th>
    	<th>Argument</th>
    	<th>Documentation</th>
        </tr>
    </thead>

    <tbody>
        <tr>
            <td>-configfailurepolicy</td>
	    <td><tt>skip</tt>|<tt>continue</tt></td>
	    <td>Whether TestNG should <tt>continue</tt> to execute the remaining tests in the suite or <tt>skip</tt> them if
            an @Before* method fails.  Default behavior is <tt>skip</tt>.</td>
        </tr>

        <tr>
            <td>-d</td>
	    <td>A directory</td>
	    <td>The directory where the reports will be generated (defaults to <tt>test-output</tt>).</td>
        </tr>

        <tr>
            <td>-dataproviderthreadcount</td>
	    <td>The default number of threads to use for data
            providers when running tests in parallel.</td>
	    <td>This sets the default maximum number of threads to use
            for data providers when running tests in parallel. It will only take effect if the parallel mode has been selected (for example, with the -parallel option). This can be overridden in the suite definition.</td>
        </tr>

	<tr>
            <td>-excludegroups</td>
	    <td>A comma-separated list of groups.</td><td>The list of groups you want to be excluded from this run.</td>
        </tr>
	  
        <tr>
            <td>-groups</td>
	    <td>A comma-separated list of groups.</td>
	    <td>The list of groups you want to run (e.g. <tt>"windows,linux,regression"</tt>).</td>
	</tr>

        <tr>
            <td>-listener</td>
	    <td>A comma-separated list of Java classes that can be found on your classpath.</td>
	    <td>Lets you specify your own test listeners.  The classes need to implement <a href="../javadocs/org/testng/ITestListener.html"> <tt>org.testng.ITestListener</tt></a></td>
        </tr>

	<tr>
            <td>-methods</td>
	    <td>A comma separated list of fully qualified class name and method. For example <tt>com.example.Foo.f1,com.example.Bar.f2</tt>.</td>
	    <td>Lets you specify individual methods to run.</tt></a></td>
        </tr>

        <tr>
            <td>-methodselectors</td>
	    <td>A comma-separated list of Java classes and method
            priorities that define method selectors.</td>
	    <td>Lets you specify method selectors on the command
            line. For example: <tt>com.example.Selector1:3,com.example.Selector2:2</tt></td>
        </tr>

	<tr>
            <td>-parallel</td>
	    <td>methods|tests|classes</td>
	    <td>If specified, sets the default mechanism used to determine how to use parallel threads when running tests. If not set, default mechanism is not to use parallel threads at all. This can be overridden in the suite definition.</td>
        </tr>

        <tr>
            <td>-reporter</td>
	    <td>The extended configuration for a custom report listener.</td>
	    <td>Similar to the <tt>-listener</tt> option, except that it allows the configuration of JavaBeans-style properties on the reporter instance.
	      <br>
            Example: <tt>-reporter com.test.MyReporter:methodFilter=*insert*,enableFiltering=true</tt>
	      <br>
            You can have as many occurences of this option, one for each reporter that needs to be added.</td>
        </tr>

        <tr>
            <td>-sourcedir</td>
    	    <td>A semi-colon separated list of directories.</td>
            <td>The directories where your javadoc annotated test sources are. This option is only necessary if you are using javadoc type annotations. (e.g. <tt>"src/test"</tt> or <tt>"src/test/org/testng/eclipse-plugin;src/test/org/testng/testng"</tt>).</td>
        </tr>

       <tr>
           <td>-suitename</td>
	   <td>The default name to use for a test suite.</td>
	   <td>This specifies the suite name for a test suite defined on the command line. This option is ignored if the suite.xml file or the source code specifies a different suite name.  It is possible to create a suite name with spaces in it if you surround it with double-quotes "like this".</td>
        </tr>
        
        <tr>
            <td>-testclass</td>
	    <td>A comma-separated list of classes that can be found in your classpath.</td><td>A list of class files separated by commas (e.g. <tt>"org.foo.Test1,org.foo.test2"</tt>).</td>
	</tr>

         <tr>
            <td>-testjar</td>
	    <td>A jar file.</td>
	    <td>Specifies a jar file that contains test classes.  If a <tt>testng.xml</tt> file is found at the root of that jar file, it will be used, otherwise, all the test classes found in this jar file will be considered test classes.</td>
        </tr>

        <tr>
            <td>-testname</td>
	    <td>The default name to use for a test.</td>
	    <td>This specifies the name for a test defined on the command line. This option is ignored if the suite.xml file or the source code specifies a different test name. It is possible to create a test name with spaces in it if you surround it with double-quotes "like this".</td>
        </tr>

        <tr>
            <td>-testnames</td>
	    <td>A comma separated list of test names.</td>
	    <td>Only tests defined in a &lt;test&gt; tag matching one of these names will be run.</td>
        </tr>

        <tr>
            <td>-testrunfactory</td>
	    <td>A Java classes that can be found on your classpath.</td>
	    <td>Lets you specify your own test runners.  The class needs to implement <a href="../javadocs/org/testng/ITestRunnerFactory.html"> <tt>org.testng.ITestRunnerFactory</tt></a>.</td>
        </tr>

        <tr>
            <td>-threadcount</td>
	    <td>The default number of threads to use when running tests in parallel.</td>
	    <td>This sets the default maximum number of threads to use for running tests in parallel. It will only take effect if the parallel mode has been selected (for example, with the -parallel option). This can be overridden in the suite definition.</td>
        </tr>

	<tr>
            <td>-xmlpathinjar</td>
	    <td>The path of the XML file inside the jar file.</td>
	    <td>This attribute should contain the path to a valid XML file inside the test jar (e.g. <tt>"resources/testng.xml"</tt>). The default is <tt>"testng.xml"</tt>, which means a file called "<tt>testng.xml</tt>" at the root of the jar file. This option will be ignored unless <tt>-testjar</tt> is specified.</td>
        </tr>

      </tbody>
</table>

<p>

This documentation can be obtained by invoking TestNG without any arguments.

<p>

You can also put the command line switches in a text file, say <tt>c:\command.txt</tt>, and tell TestNG to use that file to retrieve its parameters:

<pre class="brush: text">
  C:> more c:\command.txt
  -d test-output testng.xml
  C:> java org.testng.TestNG @c:\command.txt
</pre>

<p>

Additionally, TestNG can be passed properties on the command line of the Java Virtual Machine, for example

<pre class="brush: text">
java -Dtestng.test.classpath="c:/build;c:/java/classes;" org.testng.TestNG testng.xml
</pre>

Here are the properties that TestNG understands:

<table id="system=properties">
    <caption>System properties</caption>
    <colgroup class="option"/>
    <colgroup class="type"/>
    <colgroup class="documentation"/>
    <thead>
      <tr><th>Property</th>
      <th>Type</th>
      <th>Documentation</th></tr>
    </thead>

    <tr>
    <td>testng.test.classpath</td>
    <td>A semi-colon separated series of directories that contain your test classes.</td>
    <td>If this property is set, TestNG will use it to look for your test classes instead of the class path.  This is convenient if you are using the <tt>package</tt> tag in your XML file and you have a lot of classes in your classpath, most of them not being test classes.
    </tr>
</table>

<br>

<b>Example:</b>

<pre class="brush: text">
java org.testng.TestNG -groups windows,linux -testclass org.test.MyTest
</pre>

The <a href="ant.html">ant task</a> and <a href="#testng-xml">testng.xml</a> allow you to launch TestNG with more parameters (methods to include, specifying parameters, etc...), so you should consider using the command line only when you are trying to learn about TestNG and you want to get up and running quickly.

<p>

<em>Important</em>: The command line flags that specify what tests should be run will be ignored if you also specify a <tt>testng.xml</tt> file, with the exception of <tt>-includedgroups</tt> and <tt>-excludedgroups</tt>, which will override all the group inclusions/exclusions found in <tt>testng.xml</tt>.

<!-------------------------------------
  METHODS
  ------------------------------------>

<h3><a class="section" name="methods">Test methods, Test classes and Test groups</a></h3>

<h4><a class="section" indent=".." name="test-methods">Test methods</a></h4>

Test methods are annotated with <tt>@Test</tt>. Methods annotated with <tt>@Test</tt> that happen to return a value will be ignored, unless you set <tt>allow-return-values</tt> to <tt>true</tt> in your <tt>testng.xml</tt>:

<pre class="brush: xml">
&lt;suite allow-return-values="true"&gt;

or

&lt;test allow-return-values="true"&gt;
</pre>


<h4><a class="section" indent=".." name="test-groups">Test groups</a></h4>

<p>

TestNG allows you to perform sophisticated groupings of test methods. Not 
only can you declare that methods belong to groups, but you can also specify 
groups that contain other groups. Then TestNG can be invoked and asked to 
include a certain set of groups (or regular expressions) while excluding another 
set.&nbsp; This gives you maximum flexibility in how you partition your tests 
and doesn't require you to recompile anything if you want to run two different 
sets of tests back to back.</p>

<p>
Groups are specified in your <tt>testng.xml</tt> file and can be found either under the <tt>&lt;test&gt;</tt> or <tt>&lt;suite&gt;</tt> tag. Groups specified in the <tt>&lt;suite&gt;</tt> tag apply to all the <tt>&lt;test&gt;</tt> tags underneath. Note that groups are accumulative in these tags: if you specify group "a" in <tt>&lt;suite&gt;</tt> and "b" in <tt>&lt;test&gt;</tt>, then both "a" and "b" will be included.

<p>

<p>For example, it is quite common to have at least two categories of tests</p><ul>
  <li>Check-in tests.&nbsp; These tests should be run before you submit new 
	code.&nbsp; They should typically be fast and just make sure no basic 
	functionality was broken.<br>
&nbsp;</li>
  <li>Functional tests.&nbsp; These tests should cover all the functionalities 
	of your software and be run at least once a day, although ideally you would 
	want to run them continuously.</li></ul>


	Typically, check-in tests are a subset of functional tests.&nbsp; TestNG 
allows you to specify this in a very intuitive way with test groups.&nbsp; For 
example, you could structure your test by saying that your entire test class 
belongs to the &quot;functest&quot; group, and additionally that a couple of methods 
belong to the group &quot;checkintest&quot;:

<h3 class="sourcetitle">Test1.java</h3>
<pre class="brush: java">
public class Test1 {
  @Test(groups = { "functest", "checkintest" })
  public void testMethod1() {
  }

  @Test(groups = {"functest", "checkintest"} )
  public void testMethod2() {
  }

  @Test(groups = { "functest" })
  public void testMethod3() {
  }
}
</pre>

Invoking TestNG with
	<br>

<h3 class="sourcetitle">testng.xml</h3>
<pre class="brush: xml">
&lt;test name="Test1"&gt;
  &lt;groups&gt;
    &lt;run&gt;
      &lt;include name="functest"/&gt;
    &lt;/run&gt;
  &lt;/groups&gt;
  &lt;classes&gt;
    &lt;class name="example1.Test1"/&gt;
  &lt;/classes&gt;
&lt;/test&gt;
</pre>

<p>will run all the test methods in that classes, while invoking it with <tt>checkintest</tt> will only run 
<tt>testMethod1()</tt> and <tt>testMethod2()</tt>.</p>


Here is another example, using regular expressions this time.&nbsp; Assume 
that some of your test methods should not be run on Linux, your test would look 
like:

<h3 class="sourcetitle">Test1.java</h3>
<pre class="brush: java">
@Test
public class Test1 {
  @Test(groups = { "windows.checkintest" }) 
  public void testWindowsOnly() {
  }

  @Test(groups = {"linux.checkintest"} )
  public void testLinuxOnly() {
  }

  @Test(groups = { "windows.functest" )
  public void testWindowsToo() {
  }
}
</pre>


You could use the following testng.xml to launch only the Windows methods:

<h3 class="sourcetitle">testng.xml</h3>
<pre class="brush: xml; highlight: [4,9]">
&lt;test name="Test1"&gt;
  &lt;groups&gt;
    &lt;run&gt;
      &lt;include name="windows.*"/&gt;
    &lt;/run&gt;
  &lt;/groups&gt;

  &lt;classes&gt;
    &lt;class name="example1.Test1"/&gt;
  &lt;/classes&gt;
&lt;/test&gt;
</pre>

<blockquote>
<em>Note:  TestNG uses <a href="http://en.wikipedia.org/wiki/Regular_expression">regular expressions</a>, and not <a href="http://en.wikipedia.org/wiki/Wildmat">wildmats</a>.  Be aware of the difference (for example, "anything" is matched by ".*" -- dot star -- and not "*").</em>
</blockquote>

<h4><a name="method-groups">Method groups</a></h4>

You can also exclude or include individual methods:

<h3 class="sourcetitle">testng.xml</h3>
<pre class="brush: xml">
&lt;test name="Test1"&gt;
  &lt;classes&gt;
    &lt;class name="example1.Test1"&gt;
      &lt;methods&gt;
        &lt;include name=".*enabledTestMethod.*"/&gt;
        &lt;exclude name=".*brokenTestMethod.*"/&gt;
      &lt;/methods&gt;
     &lt;/class&gt;
  &lt;/classes&gt;
&lt;/test&gt;
</pre>

This can come in handy to deactivate a single method without having to recompile 
anything, but I don't recommend using this technique too much since it makes 
your testing framework likely to break if you start refactoring your Java code 
(the regular expressions used in the tags might not match your methods any 
more).


<h4><a class="section" indent=".." name="groups-of-groups">Groups of groups</a></h4>

Groups can also include other groups.&nbsp;These groups are called &quot;MetaGroups&quot;.&nbsp; 
For example, you might want to define a group &quot;all&quot; that includes &quot;checkintest&quot; 
and &quot;functest&quot;.&nbsp; &quot;functest&quot; itself will contain the groups &quot;windows&quot; and 
&quot;linux&quot; while &quot;checkintest will only contain &quot;windows&quot;.&nbsp; Here is how you 
would define this in your property file:


<h3 class="sourcetitle">testng.xml</h3>
<pre class="brush: xml">
&lt;test name="Regression1"&gt;
  &lt;groups&gt;
    &lt;define name="functest"&gt;
      &lt;include name="windows"/&gt;
      &lt;include name="linux"/&gt;
    &lt;/define&gt;
 
    &lt;define name="all"&gt;
      &lt;include name="functest"/&gt;
      &lt;include name="checkintest"/&gt;
    &lt;/define&gt;
 
    &lt;run&gt;
      &lt;include name="all"/&gt;
    &lt;/run&gt;
  &lt;/groups&gt;
 
  &lt;classes&gt;
    &lt;class name="test.sample.Test1"/&gt;
  &lt;/classes&gt;
&lt;/test&gt;
</pre>

</p><!-------------------------------------
  EXCLUSION
  ------------------------------------>

<h4><a class="section" indent=".." name="exclusions">Exclusion groups</a></h4>

<p>TestNG allows you to include groups as well as exclude them.</p>


For example, it is quite usual to have tests that temporarily break because 
of a recent change, and you don't have time to fix the breakage yet.&nbsp; 4
However, you do want to have clean runs of your functional tests, so you need to 
deactivate these tests but keep in mind they will need to be reactivated.</p><p>A simple way to solve this problem is to create a group called &quot;broken&quot; and 
make these test methods belong to it.&nbsp; For example, in the above example, I 
know that testMethod2() is now broken so I want to disable it:


<h3 class="sourcetitle">Java</h3>
<pre class="brush: java">
@Test(groups = {"checkintest", "broken"} )
public void testMethod2() {
}
</pre>

All I need to do now is to exclude this group from the run:

<h3 class="sourcetitle">testng.xml</h3>
<pre class="brush: xml; highlight: 5">
&lt;test name="Simple example"&gt;
  &lt;groups&gt;
    &lt;run&gt;
      &lt;include name="checkintest"/&gt;
      &lt;exclude name="broken"/&gt;
    &lt;/run&gt;
  &lt;/groups&gt;
 
  &lt;classes&gt;
    &lt;class name="example1.Test1"/&gt;
  &lt;/classes&gt;
&lt;/test&gt;
</pre>

<p>This way, I will get a clean test run while keeping track of what tests are 
broken and need to be fixed later.</p>

<blockquote>
	<p><i>Note:&nbsp; you can also disable tests on an individual basis by using the 
&quot;enabled&quot; property available on both @Test and @Before/After
	annotations.</i></p>
</blockquote>


<!-------------------------------------
  PARTIAL GROUPS
  ------------------------------------>

<h4><a class="section" indent=".." name="partial-groups">Partial groups</a></h4>

You can define  groups at the class level and then add groups at the method level:

<h3 class="sourcetitle">All.java</h3>
<pre class="brush: java">
@Test(groups = { "checkin-test" })
public class All {

  @Test(groups = { "func-test" )
  public void method1() { ... }

  public void method2() { ... }
}
</pre>

In this class, method2() is part of the group &quot;checkin-test&quot;, which is defined 
at the class level, while method1() belongs to both &quot;checkin-test&quot; and 
&quot;func-test&quot;.

<!-------------------------------------
  PARAMETERS
  ------------------------------------>

<h4><a class="section" indent=".." name="parameters">Parameters</a></h4>

<p>


Test methods don't have to be parameterless.&nbsp; You can use an arbitrary 
number of parameters on each of your test method, and you instruct TestNG to 
pass you the correct parameters with the <tt>@Parameters</tt> annotation.</p><p>


There are two ways to set these parameters:&nbsp; with <tt>testng.xml</tt> or 
programmatically.</p>


<h5><a class="section" indent="..." name="parameters-testng-xml">Parameters from <tt>testng.xml</tt></a></h5>


If you are using simple values for your parameters, you can specify them in your 
<tt>testng.xml</tt>:


<h3 class="sourcetitle">Java</h3>
<pre class="brush: java">
@Parameters({ "first-name" })
@Test
public void testSingleString(String firstName) { 
  System.out.println("Invoked testString " + firstName);
  assert "Cedric".equals(firstName);
}
</pre>

In this code, we specify that the parameter <tt>firstName</tt> of your Java method 
should receive the value of the XML parameter called <tt>first-name</tt><i>.</i>&nbsp; 
This XML parameter is defined in <tt>testng.xml</tt>:<p>

<h3 class="sourcetitle">testng.xml</h3>
<pre class="brush: xml">
&lt;suite name="My suite"&gt;
  &lt;parameter name="first-name"  value="Cedric"/&gt;
  &lt;test name="Simple example"&gt;
  &lt;-- ... --&gt;
</pre>

<h4><span style="font-weight: 400">The same technique can be used for <tt>@Before/After </tt>and <tt>@Factory</tt> annotations:</span></h4>

<pre class="brush: java">
@Parameters({ "datasource", "jdbcDriver" })
@BeforeMethod
public void beforeTest(String ds, String driver) {
  m_dataSource = ...;                              // look up the value of datasource
  m_jdbcDriver = driver;
}
</pre>

This time, the two Java parameter <i>ds</i> 
and <i>driver</i> will receive the value given to the properties <tt>datasource</tt> 
and <tt>jdbc-driver </tt>respectively.&nbsp;

<p>

Parameters can be declared optional with the <a href="../javadocs/org/testng/annotations/Optional.html"><tt>Optional</tt></a> annotation:

<pre class="brush: java">
@Parameters("db")
@Test
public void testNonExistentParameter(@Optional("mysql") String db) { ... }
</pre>

If no parameter named "db" is found in your <tt>testng.xml</tt> file, your test method will receive the default value specified inside the <tt>@Optional</tt> annotation: "mysql".

<p>The <tt>@Parameters</tt> annotation can be placed at the following locations:</p><ul>
	<li>On any method that already has a <tt>@Test</tt>, <tt>@Before/After</tt> 
	or <tt>@Factory</tt> annotation.</li><li>On at most one constructor of your test class.&nbsp; In this case, 
	TestNG will invoke this particular constructor with the parameters 
	initialized to the values specified in <tt>testng.xml</tt> whenever it needs 
	to instantiate your test class.&nbsp; This feature can be used to initialize fields 
	inside your classes to values that will then be used by your
	test methods.</li></ul>
	<blockquote>
	<p><i>Notes:

</i>
	<ul>
		<li><i>The XML parameters are mapped to the Java parameters in the same order as 
they are found in the annotation, and TestNG will issue an error if the numbers 
don't match. </i>
		<li><i>Parameters are scoped. In <tt>testng.xml</tt>, you can declare them either under a 
		<tt>&lt;suite&gt;</tt> tag or under <tt>&lt;test&gt;</tt>. If two parameters have the same name, it's the one 
defined in <tt>&lt;test&gt;</tt> that has precedence. This is convenient if you need to specify 
a parameter applicable to all your tests and override its value only for certain 
tests. </i>
		</ul>
	<p></p>
</blockquote>


<h5><a class="section" indent="..." name="parameters-dataproviders">Parameters with DataProviders</a></h5>


<p>Specifying parameters in <tt>testng.xml</tt> might not be sufficient if you need to pass complex parameters, or parameters that need to be created  from Java (complex objects, objects read from a property file or a database, etc...). In this case, you can use a Data Provider to supply the values you need to test.&nbsp; A Data Provider is a method on your class that returns an array of array of objects.&nbsp; This method is annotated with <tt>@DataProvider</tt>:

<h3 class="sourcetitle">Java</h3>
<pre class="brush: java">
//This method will provide data to any test method that declares that its Data Provider
//is named "test1"
@DataProvider(name = "test1")
public Object[][] createData1() {
 return new Object[][] {
   { "Cedric", new Integer(36) },
   { "Anne", new Integer(37)}, 
 };
}

//This test method declares that its data should be supplied by the Data Provider
//named "test1"
@Test(dataProvider = "test1")
public void verifyData1(String n1, Integer n2) {
 System.out.println(n1 + " " + n2);
} 
</pre>
will print

<pre class="brush: text">
Cedric 36
Anne 37
</pre>

A <tt>@Test</tt> method specifies its Data Provider with the <tt>dataProvider</tt> attribute.&nbsp; 
This name must correspond to a method on the same class annotated with <tt>@DataProvider(name=&quot;...&quot;)</tt> 
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 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">
public class StaticProvider {
  @DataProvider(name = "create")
  public static Object[][] createData() {
    return new Object[][] {
      new Object[] { new Integer(42) }
    };
  }
}

public class MyTest {
  @Test(dataProvider = "create", dataProviderClass = StaticProvider.class)
  public void test(Integer n) {
    // ...
  }
}
</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>
<li>An array of array of objects (<tt>Object[][]</tt>) where the first dimension's size is the number of times the test method will be invoked and the second dimension size contains an array of objects that must be compatible with the parameter types of the test method. This is the cast illustrated by the example above.</li><li>An <tt>Iterator&lt;Object[]&gt;</tt>.  The only difference with <tt>Object[][]</tt> is that an <tt>Iterator</tt> lets you create your test data lazily.  TestNG will invoke the iterator and then the test method with the parameters returned by this iterator one by one.  This is particularly useful if you have a lot of parameter sets to pass to the method and you don't want to create all of them upfront.
</ul>
Here is an example of this feature:

<pre class="brush: java">
@DataProvider(name = "test1")
public Iterator&lt;Object[]> createData() {
  return new MyIterator(DATA);
} 
</pre>

If you declare your <tt>@DataProvider</tt> as taking a <tt>java.lang.reflect.Method</tt>
as first parameter, TestNG will pass the current test method for this
first parameter.  This is particularly useful when several test methods
use the same <tt>@DataProvider</tt> and you want it to return different
values depending on which test method it is supplying data for.
<p>
For example, the following code prints the name of the test method inside its <tt>@DataProvider</tt>:

<pre class="brush: java">
@DataProvider(name = "dp")
public Object[][] createData(Method m) {
  System.out.println(m.getName());  // print test method name
  return new Object[][] { new Object[] { "Cedric" }};
}

@Test(dataProvider = "dp")
public void test1(String s) {
}

@Test(dataProvider = "dp")
public void test2(String s) {
}
</pre>

and will therefore display:

<pre class="brush: text">
test1
test2
</pre>

Data providers can run in parallel with the attribute <tt>parallel</tt>:

<pre class="brush: java">
@DataProvider(parallel = true)
// ...
</pre>

Parallel data providers running from an XML file share the same pool of threads, which has a size of 10 by default.  You can modify this value in the <tt>&lt;suite&gt;</tt> tag of your XML file:


<pre class="brush: xml">
&lt;suite name="Suite1" data-provider-thread-count="20" &gt;
... 
</pre>

If you want to run a few specific data providers in a different thread pool, you need to run them from a different XML file.

<p>

<h5><a class="section" indent="..." name="parameters-reports">Parameters in reports</a></h5>

<p>

Parameters used to invoke your test methods are shown in the HTML reports generated by TestNG.  Here is an example:

<p align="center">
<img src="pics/parameters.png" />
</p>


</p>


<!-------------------------------------
  DEPENDENCIES
  ------------------------------------>


<h4><a class="section" indent=".." name="dependent-methods">Dependencies</a></h4>

<p>Sometimes, you need
your test methods to be invoked in a certain order.&nbsp; Here are a
few examples:

<ul>
<li>To make sure a certain number of test methods have completed and succeeded 
before running more test methods.
<li>To initialize your tests while wanting this initialization methods to be 
test methods as well (methods tagged with <tt>@Before/After</tt> will not be part of the 
final report).
</ul>

TestNG allows you to specify dependencies either with annotations or
in XML.

<h5><a class="section" indent="..." name="dependencies-with-annotations">Dependencies with annotations</a></h5>

<p>You can use the attributes <tt>dependsOnMethods</tt> or <tt>dependsOnGroups</tt>, found on the <tt>@Test</tt> annotation.</p>There are two kinds of dependencies:

<ul>
<li><b>Hard dependencies</b>.  All the methods you depend on must have run and succeeded for you to run.  If at least one failure occurred in your dependencies, you will not be invoked and marked as a SKIP in the report.
</li>
<li><b>Soft dependencies</b>.  You will always be run after the methods you depend on, even if some of them have failed.  This is useful when you just want to make sure that your test methods are run in a certain order but their success doesn't really depend on the success of others.  A soft dependency is obtained by adding <tt>"alwaysRun=true"</tt> in your <tt>@Test</tt> annotation.
</ul>

Here is an example of a hard dependency:

<pre class="brush: java">
@Test
public void serverStartedOk() {}

@Test(dependsOnMethods = { "serverStartedOk" })
public void method1() {}
</pre>

<p>In this example, <tt>method1()</tt> is declared as depending on method 
serverStartedOk(), which guarantees that serverStartedOk() 
will always be invoked first.</p><p>You can also have methods that depend on entire groups:</p>

<pre class="brush: java">
@Test(groups = { "init" })
public void serverStartedOk() {}

@Test(groups = { "init" })
public void initEnvironment() {}

@Test(dependsOnGroups = { "init.*" })
public void method1() {}
</pre>

<p>In this example, method1() is declared as depending on any group matching the 
regular expression &quot;init.*&quot;, which guarantees that the methods <tt>serverStartedOk()</tt> 
and <tt>initEnvironment()</tt> will always be invoked before <tt>method1()</tt>.&nbsp; </p>
<blockquote>
	<p><i>Note:&nbsp; as stated before, the order of invocation for methods that 
	belong in the same group is not guaranteed to be the same across test runs.</i></p></blockquote><p>If a method depended upon fails and you have a hard dependency on it (<tt>alwaysRun=false</tt>, which is the default), the methods that depend on it are <b>not</b> 
marked as <tt>FAIL</tt> but as <tt>SKIP</tt>.&nbsp; Skipped methods will be reported as such in 
the final report (in a color that is neither red nor green in HTML), 
which is important since skipped methods are not necessarily failures.</p><p>Both <tt>dependsOnGroups</tt> and <tt>dependsOnMethods</tt> accept regular 
expressions as parameters.&nbsp; For <tt>dependsOnMethods</tt>, if you are 
depending on a method which happens to have several overloaded versions, all the 
overloaded methods will be invoked.&nbsp; If you only want to invoke one of the 
overloaded methods, you should use <tt>dependsOnGroups</tt>.</p><p>For a more advanced example of dependent methods, please refer to 
<a href="http://beust.com/weblog/archives/000171.html">this article</a>, which 
uses inheritance to provide an elegant solution to the problem of multiple 
dependencies.</p>

By default, dependent methods are grouped by class. For example, if method <tt>b()</tt> depends on method <tt>a()</tt> and you have several instances of the class that contains these methods (because of a factory of a data provider), then the invocation order will be as follows:

<pre class="brush: plain">
a(1)
a(2)
b(2)
b(2)
</pre>

TestNG will not run <tt>b()</tt> until all the instances have invoked their <tt>a()</tt> method.

<p>

This behavior might not be desirable in certain scenarios, such as for example testing a sign in and sign out of a web browser for various countries. In such a case, you would like the following ordering:

<pre class="brush: plain">
signIn("us")
signOut("us")
signIn("uk")
signOut("uk")
</pre>

For this ordering, you can use the XML attribute <tt>group-by-instances</tt>. This attribute is valid either on &lt;suite&gt; or &lt;test&gt;:

<pre class="brush: xml">
  &lt;suite name="Factory" group-by-instances="true"&gt;
or
  &lt;test name="Factory" group-by-instances="true"&gt;
</pre>


<h5><a class="section" indent="..." name="dependencies-in-xml">Dependencies in XML</a></h5>

Alternatively, you can specify your group dependencies in the <tt>testng.xml</tt> file. You use the <tt>&lt;dependencies&gt;</tt> tag to achieve this:

<pre class="brush: xml">
  &lt;test name="My suite"&gt;
    &lt;groups&gt;
      &lt;dependencies&gt;
        &lt;group name="c" depends-on="a  b" /&gt;
        &lt;group name="z" depends-on="c" /&gt;
      &lt;/dependencies&gt;
    &lt;/groups&gt;
  &lt;/test&gt;
</pre>

The <tt>&lt;depends-on&gt;</tt> attribute contains a space-separated list of groups.


<!-------------------------------------
  FACTORIES
  ------------------------------------>

<h4><a class="section" indent=".." name="factories">Factories</a></h4>

Factories allow you to create tests dynamically. For example, imagine you 
want to create a test method that will access a page on a Web site several 
times, and you want to invoke it with different values:

<h3 class="sourcetitle">TestWebServer.java</h3>
<pre class="brush: java">
public class TestWebServer {
  @Test(parameters = { "number-of-times" })
  public void accessPage(int numberOfTimes) {
    while (numberOfTimes-- > 0) {
     // access the web page
    }
  }
}
</pre>

<h3 class="sourcetitle">testng.xml</h3>
<pre class="brush: java">
&lt;test name="T1"&gt;
&nbsp;&nbsp;&lt;parameter name="number-of-times" value="10"/&gt;
&nbsp;&nbsp;&lt;class name= "TestWebServer" /&gt;
&lt;/test&gt;

&lt;test name="T2"&gt;
&nbsp;&nbsp;&lt;parameter name="number-of-times" value="20"/&gt;
&nbsp;&nbsp;&lt;class name= "TestWebServer"/&gt;
&lt;/test&gt;

&lt;test name="T3"&gt;
&nbsp;&nbsp;&lt;parameter name="number-of-times" value="30"/&gt;
&nbsp;&nbsp;&lt;class name= "TestWebServer"/&gt;
&lt;/test&gt;
</pre>

This can become quickly impossible to manage, so instead, you should use a factory:

<h3 class="sourcetitle">WebTestFactory.java</h3>
<pre class="brush: java">
public class WebTestFactory {
  @Factory
  public Object[] createInstances() {
   Object[] result = new Object[10];  
   for (int i = 0; i < 10; i++) {
      result[i] = new WebTest(i * 10);
    }
    return result;
  }
}
</pre>

and the new test class is now:

<h3 class="sourcetitle">WebTest.java</h3>
<pre class="brush: java">
public class WebTest {
  private int m_numberOfTimes;
  public WebTest(int numberOfTimes) {
    m_numberOfTimes = numberOfTimes;
  }

  @Test
  public void testServer() {
   for (int i = 0; i < m_numberOfTimes; i++) {
     // access the web page
    }
  }
}
</pre>

<p>Your <tt>testng.xml</tt> only needs to reference the class that 
contains the factory method, since the test instances themselves will be created 
at runtime:</p>

<pre class="brush: java">
&lt;class name="WebTestFactory" /&gt;
</pre>

<p>The factory method can receive parameters just like <tt>@Test</tt> and <tt>@Before/After</tt> and it must return <tt>Object[]</tt>.&nbsp; 
The objects returned can be of any class (not necessarily the same class as the 
factory class) and they don't even need to contain TestNG annotations (in which 
case they will be ignored by TestNG).</p>

<p>

Factories can also be used with data providers, and you can leverage this functionality by putting the <tt>@Factory</tt> annotation either on a regular method or on a constructor. Here is an example of a constructor factory:

<pre class="brush:java">
  @Factory(dataProvider = "dp")
  public FactoryDataProviderSampleTest(int n) {
    super(n);
  }

  @DataProvider
  static public Object[][] dp() {
    return new Object[][] {
      new Object[] { 41 },
      new Object[] { 42 },
    };
  }
</pre>

The example will make TestNG create two test classes, on with the constructor invoked with the value 41 and the other with 42.



<!-------------------------------------
  CLASS LEVEL ANNOTATIONS
  ------------------------------------>

<h4><a class="section" indent=".." name="class-level">Class level annotations</a></h4>

The <tt>@Test</tt> annotation can be put on a class instead of a test method:

<h3 class="sourcetitle">Test1.java</h3>
<pre class="brush: java">
@Test
public class Test1 {
  public void test1() {
  }

  public void test2() {
  }
}
</pre>
The effect of a class level <tt>@Test</tt> annotation is to make all the public methods of this class to become test methods even if they are not annotated.  You can still repeat the <tt>@Test</tt> annotation on a method if you want to add certain attributes.
<p>

For example:

<h3 class="sourcetitle">Test1.java</h3>
<pre class="brush: java">
@Test
public class Test1 {
  public void test1() {
  }

  @Test(groups = "g1")
  public void test2() {
  }
}
</pre>
will make both <tt>test1()</tt> and <tt>test2()</tt> test methods but on top of that, <tt>test2()</tt> now belongs to the group "g1".
<p>



<!-------------------------------------
  PARALLEL RUNNING
  ------------------------------------>

<h4><a class="section" indent=".." name="parallel-running">Parallelism and time-outs</a></h4>

You can  instruct TestNG to run your tests in separate threads in various ways.

<h5><a class="section" indent="..." name="parallel-suites">Parallel suites</a></h5>

This is useful if you are running several suite files (e.g. "<tt>java org.testng.TestNG testng1.xml testng2.xml"</tt>) and you want each of these suites to be run in a separate thread. You can use the following command line flag to specify the size of a thread pool:

<pre class="brush: plain">
java org.testng.TestNG -suitethreadpoolsize 3 testng1.xml testng2.xml testng3.xml
</pre>

The corresponding ant task name is <tt>suitethreadpoolsize</tt>.

<h5><a class="section" indent="..." name="parallel-tests">Parallel tests, classes and methods</a></h5>
The <i>parallel</i> attribute on the &lt;suite&gt; tag can take one of following values:

<pre class="brush: xml">
&lt;suite name="My suite" parallel="methods" thread-count="5"&gt;
</pre>

<pre class="brush: xml">
&lt;suite name="My suite" parallel="tests" thread-count="5"&gt;
</pre>

<pre class="brush: xml">
&lt;suite name="My suite" parallel="classes" thread-count="5"&gt;
</pre>

<pre class="brush: xml">
&lt;suite name="My suite" parallel="instances" thread-count="5"&gt;
</pre>

<ul>
<li>
<b><tt>parallel="methods"</tt></b>:  TestNG will run all your test methods in separate threads. Dependent methods will also run in separate threads but they will respect the order that you specified.
</li>

<br>

<li>
<b><tt>parallel="tests"</tt></b>:  TestNG will run all the methods in the same &lt;test&gt; tag in the same thread, but each &lt;test&gt; tag will be in a separate thread.  This allows you to group all your classes that are not thread safe in the same &lt;test&gt; and guarantee they will all run in the same thread while taking advantage of TestNG using as many threads as possible to run your tests.
</li>

<br>

<li>
<b><tt>parallel="classes"</tt></b>:  TestNG will run all the methods in the same class in the same thread, but each class will be run in a separate thread.
</li>

<br/>

<li>
<b><tt>parallel="instances"</tt></b>:  TestNG will run all the methods in the same instance in the same thread, but two methods on two different instances will be running in different threads.
</li>

</ul>

<p>


Additionally, the attribute <i>
thread-count</i> allows you to specify how many threads should be allocated for 
this execution.<blockquote>
	<p><i>Note: the <tt>@Test</tt> attribute <tt>timeOut</tt> works in both 
	parallel and non-parallel mode.</i></p></blockquote>You can also specify that a <tt>@Test</tt> method should be invoked from different threads.  You can use the attribute <tt>threadPoolSize</tt> to achieve this result:

<pre class="brush: java">
@Test(threadPoolSize = 3, invocationCount = 10,  timeOut = 10000)
public void testServer() {
</pre>
In this example, the function <tt>testServer</tt> will be invoked ten times from three different threads.  Additionally, a time-out of ten seconds guarantees that none of the threads will block on this thread forever. 

<!-------------------------------------
  RERUNNING
  ------------------------------------>


<h4><a class="section" indent=".." name="rerunning">Rerunning failed tests</a></h4>

Every time tests fail in a suite, TestNG creates a file called <tt>testng-failed.xml</tt> in the output directory.
This XML file contains the necessary information to rerun only these methods 
that failed, allowing you to quickly reproduce the failures without having to 
run the entirety of your tests.&nbsp; Therefore, a typical session would look 
like this:

<pre class="brush: text">
java -classpath testng.jar;%CLASSPATH% org.testng.TestNG -d test-outputs testng.xml
java -classpath testng.jar;%CLASSPATH% org.testng.TestNG -d test-outputs test-outputs\testng-failed.xml
</pre>

<p>Note that <tt>testng-failed.xml</tt> will contain all the necessary dependent 
methods so that you are guaranteed to run the methods that failed without any 
SKIP failures.</p>

<h4><a class="section" indent=".." name="junit">JUnit tests</a></h4>

TestNG can run JUnit 3 and JUnit 4 tests.&nbsp; All you need to do is
put the JUnit jar file on the classpath, specify your JUnit test classes in the <tt>testng.classNames</tt>
property and set the <tt>testng.junit</tt> property to true:

<p></p>
<h3 class="sourcetitle">testng.xml</h3>
<pre class="brush: xml">
&lt;test name="Test1" junit="true"&gt;
  &lt;classes&gt;
    &lt;!-- ... --&gt;
</pre>

<p>The behavior of TestNG in this case is similar to JUnit depending on the JUnit version found on the class path:<br>
</p>
<ul>
    <li>JUnit 3:
<ul>
  <li>All methods starting with test* in your classes will be run</li><li>If there is a method setUp() on your test class, it will be invoked before 
	every test method</li><li>If there is a method tearDown() on your test class, it will be invoked 
	before after every test method</li><li>If your test class contains a method suite(), all the tests returned by 
	this method will be invoked</li></ul>
    </li>
    <li>JUnit 4:
        <ul>
            <li>TestNG will use the <tt>org.junit.runner.JUnitCore</tt> runner to run your tests</li>
        </ul>
    </li>
</ul>

<!-------------------------------------
  JUNIT
--------------------------------------->


<!-------------------------------------
  RUNNING TESTNG
 ------------------------------------>
<h4><a class="section" indent=".." name="running-testng-programmatically">Running TestNG programmatically</a></h4>

You can invoke TestNG from your own programs very easily:

<h3 class="sourcetitle">Java</h3>
<pre class="brush: java">
TestListenerAdapter tla = new TestListenerAdapter();
TestNG testng = new TestNG();
testng.setTestClasses(new Class[] { Run2.class });
testng.addListener(tla);
testng.run(); 
</pre>

This example creates a <tt><a href="http://testng.org/javadocs/org/testng/TestNG.html">TestNG</a></tt> object and runs the test class <tt>Run2</tt>.  It also adds a <tt>TestListener</tt>.  You can either use the adapter class <tt><a href="http://testng.org/javadocs/org/testng/TestListenerAdapter.html">org.testng.TestListenerAdapter</a></tt> or implement <tt><a href="http://testng.org/javadocs/org/testng/ITestListener.html">org.testng.ITestListener</a></tt> yourself.  This interface contains various callback methods that let you keep track of when a test starts, succeeds, fails, etc... 
<p>
Similary, you can invoke TestNG on a <tt>testng.xml</tt> file or you can create a virtual <tt>testng.xml</tt> file yourself.  In order to do this, you can use the classes found the package <tt><a href="http://testng.org/javadocs/org/testng/xml/package-frame.html">org.testng.xml</a></tt>:  <tt><a href="http://testng.org/javadocs/org/testng/xml/XmlClass.html">XmlClass</a></tt>, <tt><a href="http://testng.org/javadocs/org/testng/xml/XmlTest.html">XmlTest</a></tt>, etc...  Each of these classes correspond to their XML tag counterpart.
<p>
For example, suppose you want to create the following virtual file:

<pre class="brush: java">
&lt;suite name="TmpSuite" &gt;
  &lt;test name="TmpTest" &gt;
    &lt;classes&gt;
      &lt;class name="test.failures.Child"  /&gt;
    &lt;classes&gt;
    &lt;/test&gt;
&lt;/suite&gt;
</pre>

You would use the following code:

<pre class="brush: java">
XmlSuite suite = new XmlSuite();
suite.setName("TmpSuite");

XmlTest test = new XmlTest(suite);
test.setName("TmpTest");
List&lt;XmlClass&gt; classes = new ArrayList&lt;XmlClass&gt;();
classes.add(new XmlClass("test.failures.Child"));
test.setXmlClasses(classes) ;
</pre>
And then you can pass this <tt>XmlSuite</tt> to TestNG:

<pre class="brush: java">
List&lt;XmlSuite&gt; suites = new ArrayList&lt;XmlSuite&gt;();
suites.add(suite);
TestNG tng = new TestNG();
tng.setXmlSuites(suites);
tng.run(); 
</pre>

<p>Please see the <a href="../doc/javadocs/org/testng/package-summary.html" target="mainFrame">JavaDocs</a> for the entire API.</p><p>


<!-------------------------------------
  BEANSHELL
 ------------------------------------>
	
<h4><a class="section" indent=".." name="beanshell">BeanShell and advanced group selection</a></h4>


	<p>If the <tt>&lt;include&gt;</tt> and <tt>&lt;exclude&gt;</tt> tags in <tt>testng.xml</tt> are not enough for your needs, you can use a <a href="http://beanshell.org">BeanShell</a> expression to decide whether a certain test method should be included in a test run or not. You specify this expression just under the <tt>&lt;test&gt;</tt> tag:</p>

<h3 class="sourcetitle">testng.xml</h3>
<pre class="brush: xml">
&lt;test name="BeanShell test"&gt;
   &lt;method-selectors&gt;
     &lt;method-selector&gt;
       &lt;script language="beanshell"&gt;&lt;![CDATA[
         groups.containsKey("test1")
       ]]&gt;&lt;/script&gt;
     &lt;/method-selector&gt;
   &lt;/method-selectors&gt;
  &lt;!-- ... --&gt;
</pre>

When a <tt>&lt;script&gt;</tt> tag is found in <tt>testng.xml</tt>, TestNG will ignore subsequent <tt>&lt;include&gt;</tt> and <tt>&lt;exclude&gt;</tt> of groups and methods in the current <tt>&lt;test&gt;</tt> tag:&nbsp; your BeanShell expression will be the only way to decide whether a test method is included or not.</p><p>Here are additional information on the BeanShell script:</p><ul>
<li>
It must return a boolean value.&nbsp; Except for this constraint, any valid BeanShell code is allowed (for example, you might want to return <tt>true </tt>during week days and false during weekends, which would allow you to run tests differently depending on the date).<br>&nbsp;
</li>
<li>
TestNG defines the following variables for your convenience:<br>&nbsp; <b><tt>java.lang.reflect.Method method</tt></b>:&nbsp; the current test method.<br>&nbsp; <b>org.testng.ITestNGMethod testngMethod</b>:&nbsp; the description of the current test method.<br>&nbsp; <b><tt>java.util.Map&lt;String, String&gt; groups</tt></b>:&nbsp; a map of the groups the current test method belongs to.<br>&nbsp;
</li>
<li>
You might want to surround your expression with a <tt>CDATA</tt> declaration (as shown above) to avoid tedious quoting of reserved XML characters).<br>&nbsp;
</li>
</ul>

<!-------------------------------------
  ANNOTATION TRANSFORMERS
 ------------------------------------>
	
<h4><a class="section" indent=".." name="annotationtransformers">Annotation Transformers</a></h4>

TestNG allows you to modify the content of all the annotations at runtime.  This is especially useful if the annotations in the source code are right most of the time, but there are a few situations where you'd like to override their value.
<p>

In order to achieve this, you need to use an Annotation Transformer.

<p>

An Annotation Transformer is a class that implements the following interface:

<pre class="brush: java">
public interface IAnnotationTransformer {

  /**
   * This method will be invoked by TestNG to give you a chance
   * to modify a TestNG annotation read from your test classes.
   * You can change the values you need by calling any of the
   * setters on the ITest interface.
   * 
   * Note that only one of the three parameters testClass,
   * testConstructor and testMethod will be non-null.
   * 
   * @param annotation The annotation that was read from your
   * test class.
   * @param testClass If the annotation was found on a class, this
   * parameter represents this class (null otherwise).
   * @param testConstructor If the annotation was found on a constructor,
   * this parameter represents this constructor (null otherwise).
   * @param testMethod If the annotation was found on a method,
   * this parameter represents this method (null otherwise).
   */
  public void transform(ITest annotation, Class testClass,
      Constructor testConstructor, Method testMethod);
}
</pre>

Like all the other TestNG listeners, you can specify this class either on the command line or with ant:

<p>

<pre class="brush: java">
  java org.testng.TestNG -listener MyTransformer testng.xml
</pre>

or programmatically:

<p>

<pre class="brush: java">
  TestNG tng = new TestNG();
  tng.setAnnotationTransformer(new MyTransformer());
  // ...
</pre>

When the method <tt>transform()</tt> is invoked, you can call any of the setters on the <tt>ITest test</tt> parameter to alter its value before TestNG proceeds further.
<p>
For example, here is how you would override the attribute <tt>invocationCount</tt> but only on the test method <tt>invoke()</tt> of one of your test classes:

<pre class="brush: java">
  public class MyTransformer implements IAnnotationTransformer {
    public void transform(ITest annotation, Class testClass,
        Constructor testConstructor, Method testMethod)
    {
      if ("invoke".equals(testMethod.getName())) {
        annotation.setInvocationCount(5);
      }
    }
  }
</pre>

<tt>IAnnotationTransformer</tt> only lets you modify a <tt>@Test</tt> annotation.  If you need to modify another TestNG annotation (a configuration annotation, <tt>@Factory</tt> or <tt>@DataProvider</tt>), use an <tt>IAnnotationTransformer2</tt>.

<!-------------------------------------
  METHOD INTERCEPTORS
 ------------------------------------>
	
<h4><a class="section" indent=".." name="methodinterceptors">Method Interceptors</a></h4>

Once TestNG has calculated in what order the test methods will be invoked, these methods are split in two groups:

<ul>
  <li><em>Methods run sequentially</em>.  These are all the test methods that have dependencies or dependents.  These methods will be run in a specific order.
  <li><em>Methods run in no particular order</em>.  These are all the methods that don't belong in the first category.  The order in which these test methods are run is random and can vary from one run to the next (although by default, TestNG will try to group test methods by class).
</ul>

In order to give you more control on the methods that belong to the second category, TestNG defines the following interface:

<pre class="brush: java">
public interface IMethodInterceptor {
  
  List&lt;IMethodInstance&gt; intercept(List&lt;IMethodInstance&gt; methods, ITestContext context);

}

</pre>

The list of methods passed in parameters are all the methods that can be run in any order.  Your <tt>intercept</tt> method is expected to return a similar list of <tt>IMethodInstance</tt>, which can be either of the following:

<ul>
  <li>The same list you received in parameter but in a different order.
  <li>A smaller list of <tt>IMethodInstance</tt> objects.
  <li>A bigger list of <tt>IMethodInstance</tt> objects.
</ul>

Once you have defined your interceptor, you pass it to TestNG as a listener.  For example:

<p>

<h3 class="sourcetitle">Shell</h3>
<pre class="brush: text">
java -classpath "testng-jdk15.jar:test/build" org.testng.TestNG -listener test.methodinterceptors.NullMethodInterceptor
   -testclass test.methodinterceptors.FooTest
</pre>

For the equivalent <tt>ant</tt> syntax, see the <tt>listeners</tt> attribute in the <a href="ant.html">ant documentation</a>.
<p>
For example, here is a Method Interceptor that will reorder the methods so that test methods that belong to the group "fast" are always run first:

<pre class="brush: java">
public List&lt;IMethodInstance&gt; intercept(List&lt;IMethodInstance&gt; methods, ITestContext context) {
  List&lt;IMethodInstance&gt; result = new ArrayList&lt;IMethodInstance&gt;();
  for (IMethodInstance m : methods) {
    Test test = m.getMethod().getConstructorOrMethod().getAnnotation(Test.class);
    Set&lt;String&gt; groups = new HashSet&lt;String&gt;();
    for (String group : test.groups()) {
      groups.add(group);
    }
    if (groups.contains("fast")) {
      result.add(0, m);
    }
    else {
      result.add(m);
    }
  }
  return result;
}
</pre>


<!-------------------------------------
  TESTNG LISTENERS
 ------------------------------------>
	
<h4><a class="section" indent=".." name="testng-listeners">TestNG Listeners</a></h4>

There are several interfaces that allow you to modify TestNG's behavior.  These interfaces are broadly called "TestNG Listeners".  Here are a few listeners:

<ul>
  <li><tt>IAnnotationTransformer</tt> (<a href="#annotationtransformers">doc</a>, <a href="../javadocs/org/testng/IAnnotationTransformer.html">javadoc</a>)
  <li><tt>IAnnotationTransformer2</tt> (<a href="#annotationtransformers">doc</a>, <a href="../javadocs/org/testng/IAnnotationTransformer2.html">javadoc</a>)
  <li><tt>IHookable</tt> (<a href="#ihookable">doc</a>, <a href="../javadocs/org/testng/IHookable.html">javadoc</a>)
  <li><tt>IInvokedMethodListener</tt> (doc, <a href="../javadocs/org/testng/IInvokedMethodListener.html">javadoc</a>)
  <li><tt>IMethodInterceptor</tt> (<a href="#methodinterceptors">doc</a>, <a href="../javadocs/org/testng/IMethodInterceptor.html">javadoc</a>)
  <li><tt>IReporter</tt> (<a href="#logging-reporters">doc</a>, <a href="../javadocs/org/testng/IReporter.html">javadoc</a>)
  <li><tt>ISuiteListener</tt> (doc, <a href="../javadocs/org/testng/ISuiteListener.html">javadoc</a>)
  <li><tt>ITestListener</tt> (<a href="#logging-listeners">doc</a>, <a href="../javadocs/org/testng/ITestListener.html">javadoc</a>)
</ul>

When you implement one of these interfaces, you can let TestNG know about it with either of the following ways:

<ul>
  <li><a href="#running-testng">Using -listener on the command line.</a>
  <li><a href="ant.html">Using &lt;listeners&gt; with ant.</a>
  <li>Using &lt;listeners&gt; in your <tt>testng.xml</tt> file.
  <li>Using the <tt>@Listeners</tt> annotation on any of your test classes.
  <li>Using <tt>ServiceLoader</tt>.
</ul>

<h5><a class="section" indent="..." name="listeners-testng-xml">Specifying listeners with <tt>testng.xml</tt> or in Java</a></h5>

Here is how you can define listeners in your <tt>testng.xml</tt> file:

<pre class="brush: xml">
&lt;suite&gt;

  &lt;listeners&gt;
    &lt;listener class-name="com.example.MyListener" /&gt;
    &lt;listener class-name="com.example.MyMethodInterceptor" /&gt;
  &lt;/listeners&gt;

...

</pre>

Or if you prefer to define these listeners in Java:

<pre class="brush: java">
@Listeners({ com.example.MyListener.class, com.example.MyMethodInterceptor.class })
public class MyTest {
  // ...
}
</pre>

The <tt>@Listeners</tt> annotation can contain any class that extends <tt>org.testng.ITestNGListener</tt> <b>except</b> <tt>IAnnotationTransformer</tt> and <tt>IAnnotationTransformer2</tt>.  The reason is that these listeners need to be known very early in the process so that TestNG can use them to rewrite your annotations, therefore you need to specify these listeners in your <tt>testng.xml</tt> file.

<p>

Note that the <tt>@Listeners</tt> annotation will apply to your entire suite file, just as if you had specified it in a <tt>testng.xml</tt> file. If you want to restrict its scope (for example, only running on the current class), the code in your listener could first check the test method that's about to run and decide what to do then.

<h5><a class="section" indent="..." name="listeners-service-loader">Specifying listeners with <tt>ServiceLoader</tt></a></h5>

Finally, the JDK offers a very elegant mechanism to specify implementations of interfaces on the class path via the <tt><a href="http://download.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html">ServiceLoader</a></tt> class.

<p>
With ServiceLoader, all you need to do is create a jar file that contains your listener(s) and a few configuration files, put that jar file on the classpath when you run TestNG and TestNG will automatically find them.
<p>

Here is a concrete example of how it works.

<p>

Let's start by creating a listener (any TestNG listener should work):

<pre class="brush: java">
package test.tmp;

public class TmpSuiteListener implements ISuiteListener {
  @Override
  public void onFinish(ISuite suite) {
    System.out.println("Finishing");
  }

  @Override
  public void onStart(ISuite suite) {
    System.out.println("Starting");
  }
}
</pre>

Compile this file, then create a file at the location <tt>META-INF/services/org.testng.ITestNGListener</tt>, which will name the implementation(s) you want for this interface.

<p>

You should end up with the following directory structure, with only two files:

<pre class="brush: plain; highlight: [4, 7]">
$ tree
|____META-INF
| |____services
| | |____org.testng.ITestNGListener
|____test
| |____tmp
| | |____TmpSuiteListener.class

$ cat META-INF/services/org.testng.ITestNGListener
test.tmp.TmpSuiteListener
</pre>

Create a jar of this directory:

<pre class="brush: plain">
$ jar cvf ../sl.jar .
added manifest
ignoring entry META-INF/
adding: META-INF/services/(in = 0) (out= 0)(stored 0%)
adding: META-INF/services/org.testng.ITestNGListener(in = 26) (out= 28)(deflated -7%)
adding: test/(in = 0) (out= 0)(stored 0%)
adding: test/tmp/(in = 0) (out= 0)(stored 0%)
adding: test/tmp/TmpSuiteListener.class(in = 849) (out= 470)(deflated 44%)
</pre>

Next, put this jar file on your classpath when you invoke TestNG:

<pre class="brush: plain">
$ java -classpath sl.jar:testng.jar org.testng.TestNG testng-single.yaml
Starting
f2 11 2
PASSED: f2("2")
Finishing
</pre>

This mechanism allows you to apply the same set of listeners to an entire organization just be adding a jar file to the classpath, instead of asking every single developer to remember to specify these listeners in their testng.xml file. 

<!-------------------------------------
  DEPENDENCY INJECTION
 ------------------------------------>
	
<h4><a class="section" indent=".." name="dependency-injection">Dependency injection</a></h4>

TestNG supports two different kinds of dependency injection: native (performed by TestNG itself) and external (performed by a dependency injection framework such as Guice).

<h5><a class="section" indent="..." name="native-dependency-injection">Native dependency injection</a></h5>

TestNG lets you declare additional parameters in your methods.  When this happens, TestNG will automatically fill these parameters with the right value.  Dependency injection can be used in the following places:

<ul>
  
<li>
  Any @Before method or @Test method can declare a parameter of type <tt>ITestContext</tt>.
<li>
  Any @AfterMethod method can declare a parameter of type <tt>ITestResult</tt>, which will reflect the result of the test method that was just run.
<li>
  Any @Before and @After methods can declare a parameter of type <tt>XmlTest</tt>, which contain the current <tt>&lt;test&gt;</tt> tag.
<li>
  Any @BeforeMethod (and @AfterMethod) can declare a parameter of type
  <tt>java.lang.reflect.Method</tt>.  This parameter will receive the
  test method that will be called once this @BeforeMethod finishes (or
  after the method as run for @AfterMethod).
<li>
  Any @BeforeMethod can declare a parameter of type <tt>Object[]</tt>.  This parameter will receive the list of parameters that are about to be fed to the upcoming test method, which could be either injected by TestNG, such as <tt>java.lang.reflect.Method</tt> or come from a <tt>@DataProvider</tt>.
<li>
  Any @DataProvider can declare a parameter of type
  <tt>ITestContext</tt> or <tt>java.lang.reflect.Method</tt>.  The
  latter parameter will receive the test method that is about to be invoked.
</ul>

You can turn off injection with the <tt>@NoInjection</tt> annotation:

<pre class="brush: java; highlight: [9]">
public class NoInjectionTest {

  @DataProvider(name = "provider")
  public Object[][] provide() throws Exception {
      return new Object[][] { { CC.class.getMethod("f") } };
  }

  @Test(dataProvider = "provider")
  public void withoutInjection(@NoInjection Method m) {
      Assert.assertEquals(m.getName(), "f");
  }

  @Test(dataProvider = "provider")
  public void withInjection(Method m) {
      Assert.assertEquals(m.getName(), "withInjection");
  }
}
</pre>

<h5><a class="section" indent="..." name="guice-dependency-injection">Guice dependency injection</a></h5>

If you use Guice, TestNG gives you an easy way to inject your test objects with a Guice module:

<pre class="brush: java">
@Guice(modules = GuiceExampleModule.class)
public class GuiceTest extends SimpleBaseTest {

  @Inject
  ISingleton m_singleton;

  @Test
  public void singletonShouldWork() {
    m_singleton.doSomething();
  }

}
</pre>

In this example, <tt>GuiceExampleModule</tt> is expected to bind the interface <tt>ISingleton</tt> to some concrete class:

<pre class="brush: java">
public class GuiceExampleModule implements Module {

  @Override
  public void configure(Binder binder) {
    binder.bind(ISingleton.class).to(ExampleSingleton.class).in(Singleton.class);
  }

}
</pre>

If you need more flexibility in specifying which modules should be used to instantiate your test classes, you can specify a module factory:

<pre class="brush: java">
@Guice(moduleFactory = ModuleFactory.class)
public class GuiceModuleFactoryTest {

  @Inject
  ISingleton m_singleton;

  @Test
  public void singletonShouldWork() {
    m_singleton.doSomething();
  }
}
</pre>

The module factory needs to implement the interface <a href="../javadocs/org/testng/IModuleFactory.html">IModuleFactory</a>:

<pre class="brush: java">
public interface IModuleFactory {
 /**
   * @param context The current test context
   * @param testClass The test class
   *
   * @return The Guice module that should be used to get an instance of this
   * test class.
   */
  Module createModule(ITestContext context, Class&lt;?&gt; testClass);
}
</pre>

Your factory will be passed an instance of the test context and the test class that TestNG needs to instantiate. Your <tt>createModule</tt> method should return a Guice Module that will know how to instantiate this test class. You can use the test context to find out more information about your environment, such as parameters specified in <tt>testng.xml</tt>, etc...

You will get even more flexibility and Guice power with <tt>parent-module</tt> and <tt>guice-stage</tt> suite parameters.
<tt>guice-stage</tt> allow you to chose the <a href="https://github.com/google/guice/wiki/Bootstrap"><tt>Stage</tt></a> used to create the parent injector.
The default one is <tt>DEVELOPMENT</tt>. Other allowed values are <tt>PRODUCTION</tt> and <tt>TOOL</tt>.
Here is how you can define parent-module in your test.xml file:

<pre class="brush: xml">
<suite parent-module="com.example.SuiteParenModule" guice-stage="PRODUCTION">
</suite>
</pre>

TestNG will create this module only once for given suite. Will also use this module for obtaining instances of test specific Guice modules and module factories, then will create child injector for each test class.

With such approach you can declare all common bindings in parent-module also you can inject binding declared in parent-module in module and module factory. Here is an example of this functionality:

<pre class="brush: java">
package com.example;

public class ParentModule extends AbstractModule {
  @Override
  protected void conigure() {
    bind(MyService.class).toProvider(MyServiceProvider.class);
    bind(MyContext.class).to(MyContextImpl.class).in(Singleton.class);
  }
}
</pre>

<pre class="brush: java">
package com.example;

public class TestModule extends AbstractModule {
  private final MyContext myContext;

  @Inject
  TestModule(MyContext myContext) {
    this.myContext = myContext
  }
  
  @Override
  protected void configure() {
    bind(MySession.class).toInstance(myContext.getSession());
  }
}
</pre>

<pre class="brush: xml">
<suite parent-module="com.example.ParentModule">
</suite>
</pre>

<pre class="brush: java">
package com.example;

@Test
@Guice(modules = TestModule.class)
public class TestClass {
  @Inject
  MyService myService;
  @Inject
  MySession mySession;
  
  public void testServiceWithSession() {
    myService.serve(mySession);
  }
}
</pre>

As you see ParentModule declares binding for MyService and MyContext classes. Then MyContext is injected using constructor injection into TestModule class, which also declare binding for MySession. Then parent-module in test XML file is set to ParentModule class, this enables injection in TestModule. Later in TestClass you see two injections:
 * MyService - binding taken from ParentModule
 * MySession - binding taken from TestModule
This configuration ensures you that all tests in this suite will be run with same session instance, the MyContextImpl object is only created once per suite, this give you possibility to configure common environment state for all tests in suite. 

<!-------------------------------------
  INVOKED METHOD LISTENERS
 ------------------------------------>
	
<h4><a class="section" indent=".." name="invokedmethodlistener">Listening to method invocations</a></h4>

The listener <tt><a href="../javadocs/org/testng/IInvokedMethodListener.html">IInvokedMethodListener</a></tt> allows you to be notified whenever TestNG is about to invoke a test (annotated with <tt>@Test</tt>) or configuration (annotated with any of the <tt>@Before</tt> or <tt>@After</tt> annotation) method.  You need to implement the following interface:

<pre class="brush: java">
public interface IInvokedMethodListener extends ITestNGListener {
  void beforeInvocation(IInvokedMethod method, ITestResult testResult);
  void afterInvocation(IInvokedMethod method, ITestResult testResult);
}
</pre>

and declare it as a listener, as explained in <a href="#testng-listeners">the section about TestNG listeners</a>.

<p>


<!-------------------------------------
  IHOOKABLE AND ICONFIGURABLE
  ------------------------------------>

<h4><a class="section" indent=".." name="ihookable">Overriding test methods</a></h4>

TestNG allows you to override and possibly skip the invocation of test methods. One example of where this is useful is if you need to your test methods with a specific security manager. You achieve this by providing a listener that implements <a href="../javadocs/org/testng/IHookable.html"><tt>IHookable</tt></a>.
<p>
Here is an example with JAAS:

<pre class="brush: java">
public class MyHook implements IHookable {
  public void run(final IHookCallBack icb, ITestResult testResult) {
    // Preferably initialized in a @Configuration method
    mySubject = authenticateWithJAAs();
   
    Subject.doAs(mySubject, new PrivilegedExceptionAction() {
      public Object run() {
        icb.callback(testResult);
      }
    };
  }
}
</pre>

<!------------------------------------
  TEST SUCCESS
  ------------------------------------>

<h3><a class="section" indent="." name="test-results">Test results</a></h3>


<h4><a class="section" indent=".." name="success-failure">Success, failure and assert</a></h4>


<p>A test is considered successful if it completed without throwing any 
exception or if&nbsp; it threw an exception that was expected (see the 
documentation for the <tt>expectedExceptions</tt> attribute found on the <tt>@Test</tt> annotation).
</p>

<p>Your test methods will typically be made of calls that can throw an 
exception, or of various assertions (using the Java &quot;assert&quot; keyword).&nbsp; An 
&quot;assert&quot; failing will trigger an AssertionErrorException, which in turn will 
mark the method as failed (remember to use -ea on the JVM if you are not seeing 
the assertion errors).</p><p>Here is an example test method:</p>

<pre class="brush: java">
@Test
public void verifyLastName() {
  assert "Beust".equals(m_lastName) : "Expected name Beust, for" + m_lastName;
}
</pre>

TestNG also include JUnit's Assert class, which lets you perform 
assertions on complex objects:

<pre class="brush: java">
import static org.testng.AssertJUnit.*;
//...
@Test
public void verify() {
  assertEquals("Beust", m_lastName);
}
</pre>
<p>Note that the above code use a static import in order to be able to use the
<tt>assertEquals</tt> method without having to prefix it by its class.

<!-------------------------------------
  LOGGING
  ------------------------------------>
</p>

<h4><a class="section" indent=".." name="logging">Logging and results</a></h4>

The results of the test run are created in a file called <tt>index.html</tt> in the 
directory specified when launching SuiteRunner.&nbsp; This file points to 
various other HTML and text files that contain the result of the entire test 
run.&nbsp; You can see a typical example
<a href="http://testng.org/test-output/index.html">here</a>.

<p>
It's very easy to generate your own reports with TestNG with Listeners and Reporters:

<ul>
<li><b>Listeners</b> implement the interface <a href="../javadocs/org/testng/ITestListener.html"><tt>org.testng.ITestListener</tt></a> and are notified in real time of when a test starts, passes, fails, etc...</li><li><b>Reporters</b> implement the interface <a href="../javadocs/org/testng/IReporter.html"><tt>org.testng.IReporter</tt></a> and are notified when all the suites have been run by TestNG.  The IReporter instance receives a list of objects that describe the entire test run.</li></ul>For example, if you want to generate a PDF report of your test run, you don't need to be notified in real time of the test run so you should probably use an <tt>IReporter</tt>.  If you'd like to write a real-time reporting of your tests, such as a GUI with a progress bar or a text reporter displaying dots (".") as each test is invoked (as is explained below), <tt>ITestListener</tt> is your best choice.

<h5><a class="section" indent="..." name="logging-listeners">Logging Listeners</a></h5>

Here is a listener that displays a "." for each passed test, a "F" for each failure and a "S" for each skip:

<pre class="brush: java">
public class DotTestListener extends TestListenerAdapter {
  private int m_count = 0;

  @Override
  public void onTestFailure(ITestResult tr) {
    log("F");
  }

  @Override
  public void onTestSkipped(ITestResult tr) {
    log("S");
  }

  @Override
  public void onTestSuccess(ITestResult tr) {
    log(".");
  }

  private void log(String string) {
    System.out.print(string);
    if (++m_count % 40 == 0) {
      System.out.println("");
    }
  }
} 
</pre>

In this example, I chose to extend <a href="../javadocs/org/testng/TestListenerAdapter.html"><tt>TestListenerAdapter</tt></a>, which implements <a href="../javadocs/org/testng/ITestListener.html"><tt>ITestListener</tt></a> with empty methods, so I don't have to override other methods from the interface that I have no interest in.  You can implement the interface directly if you prefer.

<p>
Here is how I invoke TestNG to use this new listener:

<h3 class="sourcetitle">Shell</h3>
<pre class="brush: text">
java -classpath testng.jar;%CLASSPATH% org.testng.TestNG -listener org.testng.reporters.DotTestListener test\testng.xml
</pre>

and the output:

<p>

<h3 class="sourcetitle">Shell</h3>
<pre class="brush: text">
........................................
........................................
........................................
........................................
........................................
.........................
===============================================
TestNG JDK 1.5
Total tests run: 226, Failures: 0, Skips: 0
===============================================
</pre>

Note that when you use <tt>-listener</tt>, TestNG will automatically determine the type of listener you want to use.

<h5><a class="section" indent="..." name="logging-reporters">Logging Reporters</a></h5>

The <a href="../javadocs/org/testng/IReporter.html"><tt>org.testng.IReporter</tt></a> interface only has one method:

<pre class="brush: java">
public void generateReport(List&lt;ISuite</a>&gt; suites, String outputDirectory)
</pre>

This method will be invoked by TestNG when all the suites have been run and you can inspect its parameters to access all the information on the run that was just completed.

<p>

<h5><a class="section" indent="..." name="logging-junitreports">JUnitReports</a></h5>

<p>


TestNG contains a listener that takes the TestNG results 
and outputs an XML file that can then be fed to JUnitReport.  <a href="http://testng.org/test-report/junit-noframes.html">
Here</a> is an example, and the ant task to create this report:

<h3 class="sourcetitle">build.xml</h3>
<pre class="brush: xml">
&lt;target name="reports"&gt;
  &lt;junitreport todir="test-report"&gt;
    &lt;fileset dir="test-output"&gt;
      &lt;include name="*/*.xml"/&gt;
    &lt;/fileset&gt;
 
    &lt;report format="noframes"  todir="test-report"/&gt;
  &lt;/junitreport&gt;
&lt;/target&gt;
</pre>
<blockquote>
	<em>Note:&nbsp; a current incompatibility between the JDK 1.5 and JUnitReports 
prevents the frame version from working, so you need to specify &quot;noframes&quot; to 
get this to work for now.</em>
	</blockquote>

<h5><a class="section" indent="..." name="logging-reporter-api">Reporter API</a></h5>

<p>
If you need to log messages that should appear in the generated HTML reports, you can use the class <tt><a href="../javadocs/org/testng/Reporter.html">org.testng.Reporter</a></tt>:

<blockquote class="brush: text">
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">Reporter.log</font><font color="#000000">(</font><font color="#2a00ff">&#34;M3 WAS CALLED&#34;</font><font color="#000000">)</font><font color="#000000">;</font>

</blockquote>

<p align="center">

<img src="pics/show-output1.png" />
<img src="pics/show-output2.png" />

</p>

<h5><a class="section" indent="..." name="logging-xml-reports">XML Reports</a></h5>

<p>
TestNG offers an XML reporter capturing TestNG specific information that is not available in JUnit reports. This is particulary useful when the user's test environment needs to consume XML results with TestNG-specific data that the JUnit format can't provide.  Below is a sample of the output of such a reporter:
</p>

<pre class="brush: xml">
&lt;testng-results&gt;
  &lt;suite name=&quot;Suite1&quot;&gt;
    &lt;groups&gt;
      &lt;group name=&quot;group1&quot;&gt;
        &lt;method signature=&quot;com.test.TestOne.test2()&quot; name=&quot;test2&quot; class=&quot;com.test.TestOne&quot;/&gt;
        &lt;method signature=&quot;com.test.TestOne.test1()&quot; name=&quot;test1&quot; class=&quot;com.test.TestOne&quot;/&gt;
      &lt;/group&gt;
      &lt;group name=&quot;group2&quot;&gt;
        &lt;method signature=&quot;com.test.TestOne.test2()&quot; name=&quot;test2&quot; class=&quot;com.test.TestOne&quot;/&gt;
      &lt;/group&gt;
    &lt;/groups&gt;
    &lt;test name=&quot;test1&quot;&gt;
      &lt;class name=&quot;com.test.TestOne&quot;&gt;
        &lt;test-method status=&quot;FAIL&quot; signature=&quot;test1()&quot; name=&quot;test1&quot; duration-ms=&quot;0&quot;
              started-at=&quot;2007-05-28T12:14:37Z&quot; description=&quot;someDescription2&quot;
              finished-at=&quot;2007-05-28T12:14:37Z&quot;&gt;
          &lt;exception class=&quot;java.lang.AssertionError&quot;&gt;
            &lt;short-stacktrace&gt;
              &lt;![CDATA[
                java.lang.AssertionError
                ... Removed 22 stack frames
              ]]&gt;
            &lt;/short-stacktrace&gt;
          &lt;/exception&gt;
        &lt;/test-method&gt;
        &lt;test-method status=&quot;PASS&quot; signature=&quot;test2()&quot; name=&quot;test2&quot; duration-ms=&quot;0&quot;
              started-at=&quot;2007-05-28T12:14:37Z&quot; description=&quot;someDescription1&quot;
              finished-at=&quot;2007-05-28T12:14:37Z&quot;&gt;
        &lt;/test-method&gt;
        &lt;test-method status=&quot;PASS&quot; signature=&quot;setUp()&quot; name=&quot;setUp&quot; is-config=&quot;true&quot; duration-ms=&quot;15&quot;
              started-at=&quot;2007-05-28T12:14:37Z&quot; finished-at=&quot;2007-05-28T12:14:37Z&quot;&gt;
        &lt;/test-method&gt;
      &lt;/class&gt;
    &lt;/test&gt;
  &lt;/suite&gt;
&lt;/testng-results&gt;
</pre>
<p>This reporter is injected along with the other default listeners so you can get this type of output by default. The listener provides some properties that can tweak the reporter to fit your needs. The following table contains a list of these properties with a short explanation:
</p>
<table border="1" width="100%" id="table6">
  <tr>
    <th>Property</th>
    <th>Comment</th>
    <th>Default value</th>
  </tr>
  <tr>
    <td>outputDirectory</td>
    <td>A <tt>String</tt> indicating the directory where should the XML files be outputed.</td>
    <td>The TestNG output directory</td>
  </tr>
  <tr>
    <td>timestampFormat</td>
    <td>Specifies the format of date fields that are generated by this reporter</td>
    <td>yyyy-MM-dd'T'HH:mm:ss'Z'</td>
  </tr>
  <tr>
    <td>fileFragmentationLevel</td>
    <td>An integer having the values 1, 2 or 3, indicating the way that the XML files are generated:
      <br>
<pre>
   1 - will generate all the results in one file.
   2 - each suite is generated in a separate XML file that is linked to the main file.
   3 - same as 2 plus separate files for test-cases that are referenced from the suite files.
</pre>
    </td>
    <td>1</td>
  </tr>
  <tr>
    <td>splitClassAndPackageNames</td>
    <td>This boolean specifies the way that class names are generated for the <tt>&lt;class&gt;</tt> element.
      For example, you will get <tt>&lt;class class="com.test.MyTest"&gt;</tt> for false and <tt>&lt;class class="MyTest" package="com.test"&gt;</tt> for true.
    </td>
    <td>false</td>
  </tr>
  <tr>
    <td>generateGroupsAttribute</td>
    <td>A boolean indicating if a <tt>groups</tt> attribute should be generated for the <tt>&lt;test-method&gt;</tt> element. This feature aims at providing a
      straight-forward method of retrieving the groups that include a test method without having to surf through the <tt>&lt;group&gt;</tt> elements.
    </td>
    <td>false</td>
  </tr>
  <tr>
    <td>generateTestResultAttributes</td>
    <td>
      A boolean indicating if an <tt>&lt;attributes&gt;</tt> tag should be generated for each <tt>&lt;test-method&gt;</tt> element, containing the test result
      attributes (See <tt>ITestResult.setAttribute()</tt> about setting test result attributes). Each attribute <tt>toString()</tt> representation will be
      written in a <tt>&lt;attribute name="[attribute name]"&gt;</tt> tag.
    </td>
    <td>false</td>
  </tr>
  <tr>
    <td>stackTraceOutputMethod</td>
    <td>Specifies the type of stack trace that is to be generated for exceptions and has the following values:
         <br>
<pre>
   0 - no stacktrace (just Exception class and message).
   1 - a short version of the stack trace keeping just a few lines from the top
   2 - the complete stacktrace with all the inner exceptions
   3 - both short and long stacktrace
</pre>
    </td>
    <td>2</td>
  </tr>
  <tr>
    <td>generateDependsOnMethods</td>
    <td>Use this attribute to enable/disable the generation of a <tt>depends-on-methods</tt> attribute for the <tt>&lt;test-method&gt;</tt> element.
    </td>
    <td>true</td>
  </tr>
  <tr>
    <td>generateDependsOnGroups</td>
    <td>Enable/disable the generation of a <tt>depends-on-groups</tt> attribute for the <tt>&lt;test-method&gt;</tt> element.
    </td>
    <td>true</td>
  </tr>
</table>
<p>
  In order to configure this reporter you can use the <tt>-reporter</tt> option in the command line or the <a href="http://testng.org/doc/ant.html">Ant</a>
  task with the nested <tt>&lt;reporter&gt;</tt> element. For each of these you must specify the class <tt>org.testng.reporters.XMLReporter</tt>.
  Please note that you cannot configure the built-in reporter because this one will only use default settings. If you need just the XML report with custom settings
  you will have to add it manually with one of the two methods and disable the default listeners.
</p>

<!------------------------------------
  YAML
  ------------------------------------>

<h3><a class="section" name="yaml">YAML</a></h3>

TestNG supports <a href="http://www.yaml.org/">YAML</a> as an alternate way of specifying your suite file. For example, the following XML file:

<pre class="brush: xml">
<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >

<suite name="SingleSuite" verbose="2" thread-count="4" >

  &lt;parameter name="n" value="42" /&gt;

  <test name="Regression2">
    <groups>
      <run>
        &lt;exclude name="broken" /&gt;
      </run>
    </groups>

    <classes>
      &lt;class name="test.listeners.ResultEndMillisTest" /&gt;
    </classes>
  </test>
</suite>
</pre>
<p>and here is its YAML version:</p>
<pre class="brush: plain">
name: SingleSuite
threadCount: 4
parameters: { n: 42 }

tests:
  - name: Regression2
    parameters: { count: 10 }
    excludedGroups: [ broken ]
    classes:
      - test.listeners.ResultEndMillisTest
</pre>

Here is <a href="https://github.com/cbeust/testng/blob/master/src/test/resources/testng.xml">TestNG's own suite file</a>, and its <a href="https://github.com/cbeust/testng/blob/master/src/test/resources/testng.yaml">YAML counterpart</a>.

<p>

You might find the YAML file format easier to read and to maintain. YAML files are also recognized by the TestNG Eclipse plug-in. You can find more information about YAML and TestNG in this <a href="http://beust.com/weblog/2010/08/15/yaml-the-forgotten-victim-of-the-format-wars/">blog post</a>.


<!---------------------------------------------------------------------->

<a name="testng-dtd">
&nbsp;<hr width="100%">
<p>Back to my <a href="http://beust.com/weblog">home page</a>.</p><p>Or check out some of my other projects:</p><ul>
	<li><a href="http://beust.com/ejbgen">EJBGen</a>:&nbsp; an EJB tag 
	generator.</li><li><a href="http://testng.org">TestNG</a>:&nbsp; A testing framework using annotations, test groups and method parameters. </li><li><a href="http://beust.com/doclipse">Doclipse</a>:&nbsp; a JavaDoc tag 
	Eclipse plug-in.</li><li><a href="http://beust.com/j15">J15</a>:&nbsp; an Eclipse plug-in to help 
	you migrate your code to the new JDK 1.5 constructs..</li><li><a href="http://beust.com/sgen">SGen</a>:&nbsp; a replacement for 
	XDoclet with an easy plug-in architecture.</li><li><a href="http://beust.com/canvas">Canvas</a>:&nbsp; a template generator 
	based on the Groovy language.</li></ul><p>
</p>

<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-238215-2";
urchinTracker();
</script>
	
��������������������������������������������������������������������������������������testng-testng-6.9.5/doc/book.html�������������������������������������������������������������������0000644�0001750�0001750�00000007615�12551235562�016247� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html>
   <head>
       <title>Next Generation Java Testing</title>

       <link rel="stylesheet" href="testng.css" type="text/css" />
       <link type="text/css" rel="stylesheet" href="http://beust.com/beust.css"  />
       <script type="text/javascript" src="http://beust.com/prettify.js"></script>
       <script type="text/javascript" src="http://testng.org/doc/banner.js"></script>
     </head>

<body onload="prettyPrint()">

<script type="text/javascript">
   displayMenu("book.html");
</script>


<p align="center">
<a href="http://www.amazon.com/Next-Generation-Java-Testing-Advanced/dp/0321503104/ref=pd_bbs_sr_1/104-7105897-1187923?ie=UTF8&s=books&qid=1193417110&sr=8-1">
<img border="0" src="http://beust.com/pics/book-cover.jpg" />
</a>
</p>

Our book is now <a href="http://www.amazon.com/Next-Generation-Java-Testing-Advanced/dp/0321503104/ref=pd_bbs_sr_1/104-7105897-1187923?ie=UTF8&s=books&qid=1193417110&sr=8-1">available from Amazon</a> and various other retail stores (check out <a href="book-toc.html">the table of contents</a>).

<P>

<b>Book Description</b><br>
 <p>Enterprise Java developers must achieve broader, deeper test coverage, going beyond unit testing to implement functional and integration testing with systematic acceptance. <b><i>Next Generation Java Testing</i></b> introduces breakthrough Java testing techniques and TestNG, a powerful open source Java testing platform.</p><p>Cdric Beust, TestNG's creator, and leading Java developer Hani Suleiman, present powerful, flexible testing patterns that will work with virtually any testing tool, framework, or language. They show how to leverage key Java platform improvements designed to facilitate effective testing, such as dependency injection and mock objects. They also thoroughly introduce TestNG, demonstrating how it overcomes the limitations of older frameworks and enables new techniques, making it far easier to test today's complex software systems.</p><p>Pragmatic and results-focused, <b><i>Next Generation Java Testing</i></b> will help Java developers build more robust!
 code for today's mission-critical environments.</p><p>This book</p><ul><li>Illuminates the tradeoffs associated with testing, so you can make better decisions about what and how to test</li><li>Introduces TestNG, explains its goals and features, and shows how to apply them in real-world environments</li><li>Shows how to integrate TestNG with your existing code, development frameworks, and software libraries </li><li>Demonstrates how to test crucial code features, such as encapsulation, state sharing, scopes, and thread safety</li><li>Shows how to test application elements, including JavaEE APIs, databases, Web pages, and XML files </li><li>Presents advanced techniques: testing partial failures, factories, dependent testing, remote invocation, cluster-based test farms, and more</li><li>Walks through installing and using TestNG plug-ins for Eclipse, and IDEA</li><li>Contains extensive code examples</li></ul><p>Whether you use TestNG, JUnit, or another testing framework, the !
 testing design patterns presented in this book will show you how to im
prove your tests by giving you concrete advice on how to make your code and your design more testable.</p>


<br><br>
     <b>About the Author</b><br>
 <p><b>Cdric Beust,</b> a senior software engineer at Google, is an active member of the Java Community Process who has been extensively involved in the development of the latest Java release. He is the creator and main contributor to the TestNG project.</p><p><b>Hani Suleiman</b> is CTO of Formicary, a consulting and portal company specializing in financial applications. He is one of two individual members who has been elected to the Executive Committee of the Java Community Process.</p>



<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-238215-2";
urchinTracker();
</script>


</body>

</html>
 �������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/book-toc.html���������������������������������������������������������������0000644�0001750�0001750�00000241656�12551235562�017037� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><META http-equiv="Content-Type" content="text/html; charset=utf-8"><style type="text/css" media="print">.hide{display:none}</style></head>


<body style="margin:0;padding:0"><div class="hide">





<div bgcolor="#ffffff" vlink="blue" link="blue">
<table border="0" width="100%"><tr><td bgcolor="eeeeee" align="right"><font face="arial,sans-serif"><a name="0.1_1"><b>Page 1</b></a></font></td></tr></table><font size="3" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:1148;left:738">v</div>
</span></font>
<font size="6" face="Times"><span style="font-size:48px;font-family:Times">

<div style="position:absolute;top:355;left:162"><b>Contents</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:512;left:270">Foreword</div>
<div style="position:absolute;top:512;left:730">xiii</div>
<div style="position:absolute;top:530;left:270">Preface</div>
<div style="position:absolute;top:530;left:734">xv</div>
<div style="position:absolute;top:548;left:270">Acknowledgments</div>
<div style="position:absolute;top:548;left:730">xxi</div>
<div style="position:absolute;top:566;left:270">About the Authors</div>

<div style="position:absolute;top:566;left:723">xxiii</div>
</span></font>
<font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:611;left:162">Chapter 1</div>
<div style="position:absolute;top:611;left:270">Getting Started</div>
<div style="position:absolute;top:611;left:736">1</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:640;left:270">Beyond JUnit 3</div>
<div style="position:absolute;top:640;left:738">3</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:660;left:288">Stateful Classes</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:659;left:738">3</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:676;left:288">Parameters</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:675;left:738">4</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">

<div style="position:absolute;top:693;left:288">Base Classes</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:692;left:738">4</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:709;left:288">Exceptions Are Not That Exceptional</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:708;left:738">4</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:726;left:288">Running Tests</div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:725;left:738">5</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:743;left:288">Real-World Testing</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:741;left:738">6</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:759;left:288">Configuration Methods</div>
</span></font>

<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:758;left:738">6</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:775;left:288">Dependencies</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:774;left:738">6</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:792;left:288">Epiphanies</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">

<div style="position:absolute;top:791;left:738">7</div>
<div style="position:absolute;top:808;left:270">JUnit 4</div>
<div style="position:absolute;top:808;left:738">7</div>
<div style="position:absolute;top:828;left:270">Designing for Testability</div>
<div style="position:absolute;top:828;left:738">8</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:847;left:288">Object-Oriented Programming and Encapsulation</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:846;left:738">8</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:864;left:288">The Design Patterns Revolution</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:863;left:738">9</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:880;left:288">Identifying the Enemy</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:879;left:729">10</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:897;left:288">Recommendations</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:896;left:729">16</div>
<div style="position:absolute;top:913;left:270">TestNG</div>
<div style="position:absolute;top:913;left:729">17</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:933;left:288">Annotations</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">

<div style="position:absolute;top:932;left:729">17</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:950;left:288">Tests, Suites, and Configuration Annotations</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:948;left:729">18</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:966;left:288">Groups</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:965;left:729">20</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:983;left:288"><b>testng.xml</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:981;left:729">21</div>
<div style="position:absolute;top:999;left:270">Conclusion</div>
<div style="position:absolute;top:999;left:729">21</div>
</span></font>
<font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:1045;left:162">Chapter 2</div>
<div style="position:absolute;top:1045;left:270">Testing Design Patterns</div>

<div style="position:absolute;top:1045;left:725">23</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1075;left:270">Testing for Failures</div>
<div style="position:absolute;top:1075;left:729">23</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1094;left:288">Reporting Errors</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1093;left:729">24</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1111;left:288">Runtime and Checked Exceptions</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1110;left:729">25</div>
</span></font>
<font size="2" face="Times"><span style="font-size:8px;font-family:Times">
<div style="position:absolute;top:202;left:90">Beust.book  Page v  Thursday, August 16, 2007  10:22 AM</div>
</span></font>

<div style="position:absolute;top:1282;left:0"><hr><table border="0" width="100%"><tr><td bgcolor="eeeeee" align="right"><font face="arial,sans-serif"><a name="0.1_2"><b>Page 2</b></a></font></td></tr></table></div><font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:1387;left:117">vi</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1390;left:189">Contents</div>
<div style="position:absolute;top:1444;left:243">Testing Whether Your Code Handles Failures Gracefully</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1443;left:684">27</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1460;left:243">When Not to Use <b>expectedExceptions</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">

<div style="position:absolute;top:1459;left:684">31</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1477;left:243"><b>testng-failed.xml</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1476;left:684">32</div>
<div style="position:absolute;top:1493;left:225">Factories</div>
<div style="position:absolute;top:1493;left:684">34</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1513;left:243"><b>@Factory</b></div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1512;left:684">35</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1530;left:243"><b>org.testng.ITest</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1528;left:684">38</div>
<div style="position:absolute;top:1546;left:225">Data-Driven Testing</div>
<div style="position:absolute;top:1546;left:684">39</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1565;left:243">Parameters and Test Methods</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1564;left:684">42</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1582;left:243">Passing Parameters with <b>testng.xml</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1581;left:684">44</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1598;left:243">Passing Parameters with <b>@DataProvider</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1597;left:684">47</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1615;left:243">Parameters for Data Providers</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1614;left:684">50</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1631;left:243">The <b>Method </b>Parameter</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1630;left:684">50</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1648;left:243">The <b>ITestContext </b>Parameter</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">

<div style="position:absolute;top:1647;left:684">52</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1664;left:243">Lazy Data Providers</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1663;left:684">54</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1681;left:243">Pros and Cons of Both Approaches</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1680;left:684">59</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1697;left:243">Supplying the Data</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1696;left:684">60</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1714;left:243">Data Provider or Factory?</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1713;left:684">62</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1730;left:243">Tying It All Together</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1729;left:684">63</div>
<div style="position:absolute;top:1747;left:225">Asynchronous Testing</div>
<div style="position:absolute;top:1747;left:684">67</div>
<div style="position:absolute;top:1766;left:225">Testing Multithreaded Code</div>
<div style="position:absolute;top:1766;left:684">71</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">

<div style="position:absolute;top:1786;left:243">Concurrent Testing</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1785;left:684">72</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1803;left:243"><b>threadPoolSize</b>, <b>invocationCount</b>, and <b>timeOut</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1801;left:684">75</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1819;left:243">Concurrent Running</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1818;left:684">79</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1835;left:243">Turning on the Parallel Bit</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1834;left:684">82</div>
<div style="position:absolute;top:1852;left:225">Performance Testing</div>

<div style="position:absolute;top:1852;left:684">83</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1871;left:243">Algorithm Complexity</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1870;left:684">84</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1888;left:243">Testing Complexity</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1887;left:684">87</div>

<div style="position:absolute;top:1904;left:225">Mocks and Stubs</div>
<div style="position:absolute;top:1904;left:684">90</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1924;left:243">Mocks versus Stubs</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1923;left:684">90</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1940;left:243">Designing for Mockability</div>
</span></font>

<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1939;left:684">95</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1957;left:243">Mock Libraries</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1956;left:684">96</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1973;left:243">Selecting the Right Strategy</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">

<div style="position:absolute;top:1972;left:684">99</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:1990;left:243">Mock Pitfalls</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:1989;left:675">100</div>
<div style="position:absolute;top:2006;left:225">Dependent Testing</div>
<div style="position:absolute;top:2006;left:675">103</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2026;left:243">Dependent Code</div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2025;left:675">104</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2042;left:243">Dependent Testing with TestNG</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2041;left:675">105</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2059;left:243">Deciding Whether to Depend on Groups or on Methods</div>
</span></font>

<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2058;left:675">106</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2075;left:243">Dependent Testing and Threads</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2074;left:675">110</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2092;left:243">Failures of Configuration Methods</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">

<div style="position:absolute;top:2091;left:675">110</div>
<div style="position:absolute;top:2108;left:225">Inheritance and Annotation Scopes</div>
<div style="position:absolute;top:2108;left:675">113</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2128;left:243">The Problem</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2127;left:675">113</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2144;left:243">Pitfalls of Inheritance</div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2143;left:675">116</div>
<div style="position:absolute;top:2161;left:225">Test Groups</div>
<div style="position:absolute;top:2161;left:675">119</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2180;left:243">Syntax</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2179;left:675">120</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2197;left:243">Groups and Runtime</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2196;left:675">122</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2213;left:243">Running Groups</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2212;left:675">125</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">

<div style="position:absolute;top:2230;left:243">Using Groups Effectively</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2229;left:675">127</div>
</span></font>
<font size="2" face="Times"><span style="font-size:8px;font-family:Times">
<div style="position:absolute;top:1309;left:90">Beust.book  Page vi  Thursday, August 16, 2007  10:22 AM</div>
</span></font>

<div style="position:absolute;top:2389;left:0"><hr><table border="0" width="100%"><tr><td bgcolor="eeeeee" align="right"><font face="arial,sans-serif"><a name="0.1_3"><b>Page 3</b></a></font></td></tr></table></div><font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2497;left:620">Contents</div>
</span></font>

<font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:2494;left:729">vii</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2551;left:270">Code Coverage</div>
<div style="position:absolute;top:2551;left:720">132</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2570;left:288">A Coverage Example</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2569;left:720">133</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2587;left:288">Coverage Metrics</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2586;left:720">134</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2603;left:288">Coverage Tools</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2602;left:720">136</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2620;left:288">Implementation</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2619;left:720">146</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2636;left:288">Beware!</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2635;left:720">147</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">

<div style="position:absolute;top:2653;left:288">A Guide to Successful Coverage</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2652;left:720">147</div>
<div style="position:absolute;top:2669;left:270">Conclusion</div>
<div style="position:absolute;top:2669;left:720">150</div>
</span></font>
<font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:2716;left:162">Chapter 3</div>
<div style="position:absolute;top:2716;left:270">Enterprise Testing</div>
<div style="position:absolute;top:2716;left:715">153</div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2745;left:270">A Typical Enterprise Scenario</div>
<div style="position:absolute;top:2745;left:720">154</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2764;left:288">Participants</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2763;left:720">155</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2781;left:288">Testing Methodology</div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2780;left:720">155</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2797;left:288">Issues with the Current Approach</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2796;left:720">156</div>
<div style="position:absolute;top:2814;left:270">A Concrete Example</div>
<div style="position:absolute;top:2814;left:720">157</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2833;left:288">Goals</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2832;left:720">159</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2850;left:288">Nongoals</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2849;left:720">160</div>
<div style="position:absolute;top:2866;left:270">Test Implementation</div>

<div style="position:absolute;top:2866;left:720">160</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2886;left:288">Testing for Success</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2885;left:720">161</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2903;left:288">Building Test Data</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2901;left:720">163</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2919;left:288">Test Setup Issues</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2918;left:720">166</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2935;left:288">Error Handling</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2934;left:720">172</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2952;left:288">Emerging Unit Tests</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2951;left:720">175</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:2968;left:288">Coping with In-Container Components</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2967;left:720">177</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">

<div style="position:absolute;top:2985;left:288">Putting It All Together</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:2984;left:720">178</div>
<div style="position:absolute;top:3001;left:270">Exploring the Competing Consumers Pattern</div>
<div style="position:absolute;top:3001;left:720">182</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3021;left:288">The Pattern</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3020;left:720">182</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3038;left:288">The Test</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3036;left:720">184</div>
<div style="position:absolute;top:3054;left:270">The Role of Refactoring</div>
<div style="position:absolute;top:3054;left:720">186</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3074;left:288">A Concrete Example</div>
</span></font>

<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3072;left:720">187</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3090;left:288">An In-Container Approach</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3089;left:720">193</div>
<div style="position:absolute;top:3106;left:270">Conclusion</div>
<div style="position:absolute;top:3106;left:720">194</div>
</span></font>
<font size="8" face="Times"><span style="font-size:16px;font-family:Times">

<div style="position:absolute;top:3153;left:162">Chapter 4</div>
<div style="position:absolute;top:3153;left:270">Java EE Testing</div>
<div style="position:absolute;top:3153;left:715">197</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3182;left:270">In-Container versus Out-of-Container Testing</div>
<div style="position:absolute;top:3182;left:720">198</div>
<div style="position:absolute;top:3202;left:270">In-Container Testing</div>
<div style="position:absolute;top:3202;left:720">200</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3221;left:288">Creating a Test Environment</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3220;left:720">200</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3238;left:288">Identifying Tests</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3237;left:720">201</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">

<div style="position:absolute;top:3254;left:288">Registering Tests</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3253;left:720">203</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3271;left:288">Registering a Results Listener</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3270;left:720">204</div>
<div style="position:absolute;top:3287;left:270">Java Naming and Directory Interface (JNDI)</div>
<div style="position:absolute;top:3287;left:720">207</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3307;left:288">Understanding JNDI\u2019s Bootstrapping</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3306;left:720">207</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3323;left:288">Spring\u2019s <b>SimpleNamingContextBuilder</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3322;left:720">209</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3340;left:288">Avoiding JNDI</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3339;left:720">210</div>
</span></font>
<font size="2" face="Times"><span style="font-size:8px;font-family:Times">
<div style="position:absolute;top:2416;left:90">Beust.book  Page vii  Thursday, August 16, 2007  10:22 AM</div>
</span></font>

<div style="position:absolute;top:3496;left:0"><hr><table border="0" width="100%"><tr><td bgcolor="eeeeee" align="right"><font face="arial,sans-serif"><a name="0.1_4"><b>Page 4</b></a></font></td></tr></table></div><font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:3601;left:117">viii</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3604;left:189">Contents</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3658;left:225">Java Database Connectivity (JDBC)</div>
<div style="position:absolute;top:3658;left:675">210</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3677;left:243">c3p0</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3676;left:675">212</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3694;left:243">Commons DBCP</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3693;left:675">213</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3710;left:243">Spring</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3709;left:675">213</div>
<div style="position:absolute;top:3727;left:225">Java Transaction API (JTA)</div>

<div style="position:absolute;top:3727;left:675">215</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3746;left:243">Java Open Transaction Manager (JOTM)</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3745;left:675">217</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3763;left:243">Atomikos TransactionEssentials </div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3762;left:675">218</div>

<div style="position:absolute;top:3779;left:225">Java Messaging Service (JMS)</div>
<div style="position:absolute;top:3779;left:675">219</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3799;left:243">Creating a Sender/Receiver Test</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3798;left:675">219</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3815;left:243">Using ActiveMQ for Tests</div>
</span></font>

<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3814;left:675">221</div>
<div style="position:absolute;top:3832;left:225">Java Persistence API (JPA)</div>
<div style="position:absolute;top:3832;left:675">225</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3851;left:243">Configuring the Database</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3850;left:675">227</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">

<div style="position:absolute;top:3868;left:243">Configuring the JPA Provider</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3867;left:675">227</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3884;left:243">Writing the Test</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3883;left:675">229</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3901;left:243">Simulating a Container</div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3900;left:675">230</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3917;left:243">Using Spring as the Container</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3916;left:675">231</div>
<div style="position:absolute;top:3934;left:225">Enterprise Java Beans 3.0 (EJB3)</div>
<div style="position:absolute;top:3934;left:675">236</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3953;left:243">Message-Driven Beans</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3952;left:675">237</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:3970;left:243">Session Beans</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3969;left:675">240</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">

<div style="position:absolute;top:3986;left:243">Another Spring Container</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:3985;left:675">243</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4003;left:243">Disadvantages of a Full Container</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4002;left:675">244</div>
<div style="position:absolute;top:4019;left:225">Java API for XML Web Services (JAX-WS)</div>
<div style="position:absolute;top:4019;left:675">246</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4039;left:243">Recording Requests</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4038;left:675">248</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4055;left:243">Setting Up the Test Environment</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4054;left:675">248</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4072;left:243">Creating the Service Test</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4071;left:675">251</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4088;left:243">XPath Testing</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4087;left:675">253</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">

<div style="position:absolute;top:4105;left:243">Testing Remote Services</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4104;left:675">254</div>
<div style="position:absolute;top:4121;left:225">Servlets</div>
<div style="position:absolute;top:4121;left:675">255</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4141;left:243">In-Container Testing</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4140;left:675">255</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4157;left:243">Mock/Stub Objects</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4156;left:675">255</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4174;left:243">Refactoring</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4173;left:675">257</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4190;left:243">Embedded Container</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4189;left:675">257</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4207;left:243">In-Memory Invocation</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4206;left:675">260</div>
<div style="position:absolute;top:4223;left:225">XML</div>

<div style="position:absolute;top:4223;left:675">262</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4243;left:243">Using dom4j</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4242;left:675">263</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4259;left:243">Using XMLUnit</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4258;left:675">264</div>

<div style="position:absolute;top:4276;left:225">Conclusion</div>
<div style="position:absolute;top:4276;left:675">266</div>
</span></font>
<font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:4322;left:117">Chapter 5</div>
<div style="position:absolute;top:4322;left:225">Integration</div>
<div style="position:absolute;top:4322;left:670">269</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4351;left:225">Spring</div>
<div style="position:absolute;top:4351;left:675">270</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4371;left:243">Spring\u2019s Test Package Features</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4370;left:675">271</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4388;left:243">Test Class Hierarchy</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4386;left:675">272</div>
<div style="position:absolute;top:4404;left:225">Guice</div>

<div style="position:absolute;top:4404;left:675">280</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4424;left:243">The Issue with Spring</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4422;left:675">280</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4440;left:243">Enter Guice</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4439;left:675">281</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4456;left:243">A Typical Dependency Scenario</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4455;left:675">282</div>
</span></font>
<font size="2" face="Times"><span style="font-size:8px;font-family:Times">
<div style="position:absolute;top:3523;left:90">Beust.book  Page viii  Thursday, August 16, 2007  10:22 AM</div>
</span></font>

<div style="position:absolute;top:4603;left:0"><hr><table border="0" width="100%"><tr><td bgcolor="eeeeee" align="right"><font face="arial,sans-serif"><a name="0.1_5"><b>Page 5</b></a></font></td></tr></table></div><font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4711;left:620">Contents</div>

</span></font>
<font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:4708;left:733">ix</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4765;left:288">The Object Factory</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4764;left:720">284</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4781;left:288">Guice Configuration</div>
</span></font>

<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4780;left:720">286</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4798;left:288">Guice-Based Test</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4797;left:720">290</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4814;left:288">Grouping Test Dependencies</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">

<div style="position:absolute;top:4813;left:720">291</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4831;left:288">Injecting Configuration</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4830;left:720">293</div>
<div style="position:absolute;top:4847;left:270">DbUnit</div>
<div style="position:absolute;top:4847;left:720">295</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4867;left:288">Configuration</div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4866;left:720">295</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4883;left:288">Usage</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4882;left:720">297</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4900;left:288">Verifying Results</div>
</span></font>

<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4899;left:720">299</div>
<div style="position:absolute;top:4916;left:270">HtmlUnit</div>
<div style="position:absolute;top:4916;left:720">303</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:4936;left:288">Configuration</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4935;left:720">304</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">

<div style="position:absolute;top:4952;left:288">Usage</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:4951;left:720">305</div>
<div style="position:absolute;top:4969;left:270">Selenium</div>
<div style="position:absolute;top:4969;left:720">310</div>
<div style="position:absolute;top:4988;left:270">Swing UI Testing</div>
<div style="position:absolute;top:4988;left:720">312</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5008;left:288">Testing Approach</div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5007;left:720">312</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5024;left:288">Configuration</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5023;left:720">313</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5041;left:288">Usage</div>
</span></font>

<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5040;left:720">314</div>
<div style="position:absolute;top:5057;left:270">Tests for Painting Code</div>
<div style="position:absolute;top:5057;left:720">316</div>
<div style="position:absolute;top:5077;left:270">Continuous Integration</div>
<div style="position:absolute;top:5077;left:720">320</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5096;left:288">Why Bother?</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">

<div style="position:absolute;top:5095;left:720">320</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5113;left:288">CI Server Features</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5112;left:720">320</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5129;left:288">TestNG Integration</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5128;left:720">321</div>

<div style="position:absolute;top:5146;left:270">Conclusion</div>
<div style="position:absolute;top:5146;left:720">322</div>
</span></font>
<font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:5192;left:162">Chapter 6</div>
<div style="position:absolute;top:5192;left:270">Extending TestNG</div>
<div style="position:absolute;top:5192;left:715">325</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5221;left:270">The TestNG API</div>
<div style="position:absolute;top:5221;left:720">325</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5242;left:288"><b>org.testng.TestNG</b>, <b>ITestResult</b>, <b>ITestListener</b>, </div>
<div style="position:absolute;top:5258;left:306"><b>ITestNGMethod</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5256;left:720">325</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">

<div style="position:absolute;top:5274;left:288">A Concrete Example</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5273;left:720">328</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5290;left:288">The XML API</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5289;left:720">331</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5307;left:288">Synthetic XML Files</div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5306;left:720">333</div>
<div style="position:absolute;top:5323;left:270">BeanShell</div>
<div style="position:absolute;top:5323;left:720">335</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5343;left:288">BeanShell Overview</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5342;left:720">335</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5360;left:288">TestNG and BeanShell</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5358;left:720">337</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5376;left:288">Interactive Execution</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5375;left:720">339</div>
<div style="position:absolute;top:5392;left:270">Method Selectors</div>

<div style="position:absolute;top:5392;left:720">341</div>
<div style="position:absolute;top:5412;left:270">Annotation Transformers</div>
<div style="position:absolute;top:5412;left:720">346</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5432;left:288">Annotation History</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5430;left:720">346</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5448;left:288">Pros and Cons</div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5447;left:720">348</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5464;left:288">Using TestNG Annotation Transformers</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5463;left:720">348</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5481;left:288">Possible Uses of Annotation Transformers</div>
</span></font>

<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5480;left:720">353</div>
<div style="position:absolute;top:5497;left:270">Reports</div>
<div style="position:absolute;top:5497;left:720">355</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5517;left:288">Default Reports</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5516;left:720">355</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">

<div style="position:absolute;top:5534;left:288">The Reporter API</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5533;left:720">360</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5550;left:288">The Report Plug-in API</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5549;left:720">360</div>
</span></font>
<font size="2" face="Times"><span style="font-size:8px;font-family:Times">
<div style="position:absolute;top:4630;left:90">Beust.book  Page ix  Thursday, August 16, 2007  10:22 AM</div>

</span></font>

<div style="position:absolute;top:5710;left:0"><hr><table border="0" width="100%"><tr><td bgcolor="eeeeee" align="right"><font face="arial,sans-serif"><a name="0.1_6"><b>Page 6</b></a></font></td></tr></table></div><font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:5815;left:117">x</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5818;left:189">Contents</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5872;left:225">Writing Custom Annotations</div>
<div style="position:absolute;top:5872;left:675">366</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5891;left:243">Implementation</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5890;left:675">367</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:5908;left:243">Testing</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:5907;left:675">371</div>
<div style="position:absolute;top:5924;left:225">Conclusion</div>

<div style="position:absolute;top:5924;left:675">375</div>
</span></font>
<font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:5971;left:117">Chapter 7</div>
<div style="position:absolute;top:5971;left:225">Digressions</div>
<div style="position:absolute;top:5971;left:670">377</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6000;left:225">Motivation</div>
<div style="position:absolute;top:6000;left:675">377</div>
<div style="position:absolute;top:6019;left:225">The TestNG Philosophy</div>

<div style="position:absolute;top:6019;left:675">378</div>
<div style="position:absolute;top:6039;left:225">The Care and Feeding of Exceptions</div>
<div style="position:absolute;top:6039;left:675">378</div>
<div style="position:absolute;top:6058;left:225">Stateful Tests</div>
<div style="position:absolute;top:6058;left:675">382</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6078;left:243">Immutable State</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6077;left:675">382</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6094;left:243">Mutable State</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6093;left:675">383</div>
<div style="position:absolute;top:6111;left:225">The Pitfalls of Test-Driven Development</div>
<div style="position:absolute;top:6111;left:675">385</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6130;left:243">TDD Promotes Microdesign over Macrodesign</div>
</span></font>

<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6129;left:675">385</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6147;left:243">TDD Is Hard to Apply</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6146;left:675">386</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6163;left:243">Extracting the Good from Test-Driven Development</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">

<div style="position:absolute;top:6162;left:675">388</div>
<div style="position:absolute;top:6180;left:225">Testing Private Methods</div>
<div style="position:absolute;top:6180;left:675">388</div>
<div style="position:absolute;top:6199;left:225">Testing versus Encapsulation</div>
<div style="position:absolute;top:6199;left:675">391</div>
<div style="position:absolute;top:6219;left:225">The Power of Debuggers</div>
<div style="position:absolute;top:6219;left:675">392</div>
<div style="position:absolute;top:6238;left:225">Logging Best Practices</div>
<div style="position:absolute;top:6238;left:675">394</div>

<div style="position:absolute;top:6258;left:225">The Value of Time</div>
<div style="position:absolute;top:6258;left:675">397</div>
<div style="position:absolute;top:6277;left:225">Conclusion</div>
<div style="position:absolute;top:6277;left:675">399</div>
</span></font>
<font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:6324;left:117">Appendix A IDE Integration</div>
<div style="position:absolute;top:6324;left:670">401</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6353;left:225">Eclipse</div>

<div style="position:absolute;top:6353;left:675">401</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6373;left:243">Installing the Plug-in</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6372;left:675">401</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6389;left:243">Verifying the Installation</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6388;left:675">404</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6406;left:243">Creating a Launch Configuration</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6405;left:675">404</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6422;left:243">Configuring Preferences</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6421;left:675">410</div>
</span></font>

<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6439;left:243">Converting JUnit Tests</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6438;left:675">410</div>
<div style="position:absolute;top:6455;left:225">IntelliJ IDEA</div>
<div style="position:absolute;top:6455;left:675">411</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6475;left:243">Installing the Plug-in</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">

<div style="position:absolute;top:6474;left:675">411</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6491;left:243">Running Tests</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6490;left:675">412</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6508;left:243">Running Shortcuts</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6507;left:675">417</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6524;left:243">Viewing Test Results</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6523;left:675">418</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6541;left:243">Running Plug-in Refactorings</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6540;left:675">419</div>
</span></font>

<font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:6584;left:117">Appendix B TestNG Javadocs</div>
<div style="position:absolute;top:6584;left:670">421</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6613;left:225">JDK 1.4 and JDK 5</div>
<div style="position:absolute;top:6613;left:675">421</div>
<div style="position:absolute;top:6633;left:225">Shortcut Syntax for JDK 5 Annotations</div>
<div style="position:absolute;top:6633;left:675">423</div>
</span></font>
<font size="2" face="Times"><span style="font-size:8px;font-family:Times">

<div style="position:absolute;top:5737;left:90">Beust.book  Page x  Thursday, August 16, 2007  10:22 AM</div>
</span></font>

<div style="position:absolute;top:6817;left:0"><hr><table border="0" width="100%"><tr><td bgcolor="eeeeee" align="right"><font face="arial,sans-serif"><a name="0.1_7"><b>Page 7</b></a></font></td></tr></table></div><font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6925;left:620">Contents</div>
</span></font>
<font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:6922;left:733">xi</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6979;left:270">Annotation Javadocs</div>
<div style="position:absolute;top:6979;left:720">423</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:6999;left:288"><b>@<a href="mailto:DataProvider/@testng.data-provider" target="_blank">DataProvider/@testng.data<WBR>-provider</a></b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:6997;left:720">425</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7015;left:288"><b>@<a href="mailto:Factory/@testng.factory" target="_blank">Factory/@testng.factory</a></b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">

<div style="position:absolute;top:7014;left:720">426</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7032;left:288"><b>@<a href="mailto:Parameters/@testng.parameters" target="_blank">Parameters/@testng.parameters</a></b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7030;left:720">426</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7048;left:288"><b>@<a href="mailto:Test/@testng.test" target="_blank">Test/@testng.test</a></b></div>
</span></font>

<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7047;left:720">427</div>
<div style="position:absolute;top:7064;left:270">The </div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7066;left:298"><b>org.testng.TestNG</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7064;left:441">Class</div>
<div style="position:absolute;top:7064;left:720">428</div>
<div style="position:absolute;top:7084;left:270">The XML API</div>

<div style="position:absolute;top:7084;left:720">432</div>
</span></font>
<font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:7130;left:162">Appendix C <b>testng.xml</b></div>
<div style="position:absolute;top:7131;left:715"><b>435</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7159;left:270">Overview</div>
<div style="position:absolute;top:7159;left:720">436</div>
<div style="position:absolute;top:7179;left:270">Scopes</div>

<div style="position:absolute;top:7179;left:720">437</div>
<div style="position:absolute;top:7198;left:270">XML Tags</div>
<div style="position:absolute;top:7198;left:720">437</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7219;left:288"><b>&lt;suite&gt;</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7217;left:720">437</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7235;left:288"><b>&lt;packages&gt; </b>and <b>&lt;package&gt;</b></div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7233;left:720">440</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7252;left:288"><b>&lt;parameter&gt;</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7250;left:720">441</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7268;left:288"><b>&lt;suite-files&gt; </b>and <b>&lt;suite-file&gt;</b></div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7266;left:720">442</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7285;left:288"><b>&lt;method-selectors&gt;</b>, <b>&lt;method-selector&gt;</b>, </div>
<div style="position:absolute;top:7301;left:306"><b>&lt;selector-class&gt;</b>, and <b>&lt;script&gt;</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">

<div style="position:absolute;top:7299;left:720">443</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7318;left:288"><b>&lt;test&gt;</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7316;left:720">444</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7334;left:288"><b>&lt;groups&gt;</b>, <b>&lt;define&gt;</b>, and <b>&lt;run&gt;</b></div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7332;left:720">446</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7351;left:288"><b>&lt;classes&gt; </b>and <b>&lt;class&gt;</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7349;left:720">446</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">

<div style="position:absolute;top:7367;left:288"><b>&lt;methods&gt;</b></div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7365;left:720">447</div>
</span></font>
<font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:7410;left:162">Appendix D Migrating from JUnit</div>
<div style="position:absolute;top:7410;left:715">449</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7441;left:270"><b>JUnitConverter</b></div>
</span></font>

<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7439;left:720">449</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7459;left:288">From the Command Line</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7458;left:720">449</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7475;left:288">From <b>ant</b></div>
</span></font>

<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7474;left:720">452</div>
<div style="position:absolute;top:7492;left:270">Integrated Development Environments</div>
<div style="position:absolute;top:7492;left:720">453</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7511;left:288">Eclipse</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7510;left:720">453</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">

<div style="position:absolute;top:7528;left:288">IDEA</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7527;left:720">454</div>
<div style="position:absolute;top:7544;left:270">Incremental Migration and JUnit Mode</div>
<div style="position:absolute;top:7544;left:720">455</div>
<div style="position:absolute;top:7564;left:270">Converting JUnit Code</div>
<div style="position:absolute;top:7564;left:720">456</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7583;left:288">Assertions</div>

</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7582;left:720">457</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7600;left:288">Running a Single Test</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7599;left:720">458</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7616;left:288">Maintaining State between Invocations</div>
</span></font>

<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7615;left:720">461</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7633;left:288">Suite-wide Initialization</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7632;left:720">463</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7649;left:288">Class-wide Initialization</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">

<div style="position:absolute;top:7648;left:720">463</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7666;left:288">The AllTests Pattern</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7665;left:720">463</div>
</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7682;left:288">Testing Exceptions</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7681;left:720">467</div>

</span></font>
<font size="8" face="Times"><span style="font-size:11px;font-family:Times">
<div style="position:absolute;top:7699;left:288">The Parameterized Test Case Pattern</div>
</span></font>
<font size="8" face="Times"><span style="font-size:12px;font-family:Times">
<div style="position:absolute;top:7698;left:720">469</div>
</span></font>
<font size="8" face="Times"><span style="font-size:16px;font-family:Times">
<div style="position:absolute;top:7742;left:270">Index</div>
<div style="position:absolute;top:7742;left:715">471</div>
</span></font>
<font size="2" face="Times"><span style="font-size:8px;font-family:Times">
<div style="position:absolute;top:6844;left:90">Beust.book  Page xi  Thursday, August 16, 2007  10:22 AM</div>

</span></font>

<div style="position:absolute;top:7924;left:0"><hr><table border="0" width="100%"><tr><td bgcolor="eeeeee" align="right"><font face="arial,sans-serif"><a name="0.1_8"><b>Page 8</b></a></font></td></tr></table></div><font size="2" face="Times"><span style="font-size:8px;font-family:Times">
<div style="position:absolute;top:7951;left:90">Beust.book  Page xii  Thursday, August 16, 2007  10:22 AM</div>
</span></font>
</div>

</div></body></html>
����������������������������������������������������������������������������������testng-testng-6.9.5/doc/banner.js�������������������������������������������������������������������0000644�0001750�0001750�00000004435�12551235562�016227� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//****************************************************************
// Writes a table data element to the document. If pHRef equals
// pCurrentPage then 'class="current"' is added to the td element.
// For example:
//    writeTD("a.html", "a.html", "b")
// Would write
//    <td class="current"><a href="a.html">b</a><td>
//
// @param pCurrentPage the current page. For example "index.html"
// @param pHRef the string that should apear in the href
// @param pValue the string that should apear as the value
//****************************************************************
function writeTD(pCurrentPage, pHRef, pValue)
{
   document.write('                <td')
   document.write(pCurrentPage == pHRef ? ' class="current"' : '')
   document.write('><a href="')
   document.write(pHRef)
   document.write('">')
   document.write(pValue)
   document.writeln('</a></td>')
}

//******************************************************************
// Writes the main menu to the document.
// @param pCurrentPage the current page. For example "index.html"
//******************************************************************
function displayMenu(pCurrentPage) {
   document.writeln('<div id="topmenu">')
   document.writeln('    <table width="100%">')
   document.writeln('            <tr>')
       writeTD(pCurrentPage,             "index.html", "Welcome")
       writeTD(pCurrentPage,          "download.html", "Download")
       writeTD(pCurrentPage,"documentation-main.html", "Documentation")
       writeTD(pCurrentPage,         "migrating.html", "Migrating from JUnit")
       writeTD(pCurrentPage, "../javadocs/index.html", "JavaDoc")
       writeTD(pCurrentPage, "selenium.html", "Selenium")
   document.writeln('            </tr>')
   document.writeln('            <tr>')
       writeTD(pCurrentPage,           "eclipse.html", "Eclipse")
       writeTD(pCurrentPage,              "idea.html", "IDEA")
       writeTD(pCurrentPage,             "maven.html", "Maven")
       writeTD(pCurrentPage,               "ant.html", "Ant")
       writeTD(pCurrentPage,              "misc.html", "Miscellaneous")
       writeTD(pCurrentPage,              "book.html", "Book")
   document.writeln('            </tr>')
   document.writeln('        </table>')
   document.writeln('    </div>')

}

�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/doc/ant.html��������������������������������������������������������������������0000644�0001750�0001750�00000034024�12551235562�016071� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<html>
    <head>
        <title>TestNG - Ant</title>

        <link rel="stylesheet" href="testng.css" type="text/css" />
        <link type="text/css" rel="stylesheet" href="http://beust.com/beust.css"  />
        <script type="text/javascript" src="http://beust.com/prettify.js"></script>
        <script type="text/javascript" src="banner.js"></script>

        <script type="text/javascript" src="http://beust.com/scripts/shCore.js"></script>
        <script type="text/javascript" src="http://beust.com/scripts/shBrushJava.js"></script>
        <script type="text/javascript" src="http://beust.com/scripts/shBrushXml.js"></script>
        <script type="text/javascript" src="http://beust.com/scripts/shBrushBash.js"></script>
        <script type="text/javascript" src="http://beust.com/scripts/shBrushPlain.js"></script>
        <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shCore.css"/>
        <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shThemeCedric.css"/>
        <script type="text/javascript">
          SyntaxHighlighter.config.clipboardSwf = 'scripts/clipboard.swf';
          SyntaxHighlighter.defaults['gutter'] = false;
          SyntaxHighlighter.all();
        </script>

</head>

<body onLoad="prettyPrint()">

<script type="text/javascript">
    displayMenu("ant.html")
</script>

<h2 align="center">TestNG Ant Task</h2>
<p>You define the TestNG ant task as follows:</p>

<pre class="brush: xml">
&lt;taskdef resource="testngtasks" classpath="testng.jar"/&gt;
</pre>

This task runs TestNG tests and is always run in a forked JVM.&nbsp; It 
accepts the following attributes: <br>
&nbsp;<table border="2" id="table1">
	<tr>
		<th>Attribute </th>
		<th>Description </th>
		<th>Required </th>
	</tr>
	<tr>
		<td><tt>classfilesetref</tt> </td>
		<td>A reference to a
		<a href="http://ant.apache.org/manual/Types/resources.html#collection">ResourceCollection</a>
		containing the test classes to be run. Only File based
                <a href="http://ant.apache.org/manual/Types/resources.html#collection">ResourceCollection</a>s
                are supported (ie. <a href="http://ant.apache.org/manual/Types/fileset.html">FileSet</a>).</td>
		<td>&nbsp; </td>
	</tr>
	<tr>
		<td><tt>classpath</tt> </td>
		<td>A PATH-like structure for the tests to be run. </td>
		<td>&nbsp; </td>
	</tr>
	<tr>
		<td><tt>classpathref</tt> </td>
		<td>A reference to a PATH-like structure for the tests to be run. </td>
		<td>&nbsp; </td>
	</tr>
	<tr>
		<td><tt>configFailurePolicy</tt> </td>
		<td>Whether TestNG should <tt>continue</tt> to execute the remaining tests in the suite or <tt>skip</tt> them if an @Before* method fails.</td>
		<td>No. Defaults to <tt>skip</tt></td>
	</tr>
	<tr>
		<td><tt>dataProviderThreadCount</tt> </td>
		<td>The number of threads to use for data providers
		for this run. Ignored unless the parallel mode is also specified</td>
		<td>1</td>
	</tr>
	<tr>
		<td><tt>delegateCommandSystemProperties</tt> </td>
		<td>Pass the command line properties as system properties.</td>
		<td>No. Defaults to false </td>
	</tr>
	<tr>
		<td><tt>dumpCommand</tt> </td>
		<td>Print the TestNG launcher command. </td>
		<td>No. Defaults to false </td>
	</tr>
	<tr>
		<td><tt>failureProperty</tt> </td>
		<td>The name of a property to set in the event of a failure. It is used 
		only if the <tt>haltonfailure</tt> is not set. </td>
		<td>No.</td>
	</tr>
	<tr>
		<td><tt>haltonfailure</tt> </td>
		<td>Stop the build process if a failure has occurred during the test 
		run. </td>
		<td>No. Defaults to false 
		</td>
		<td>&nbsp;</td>
	</tr>
	<tr>
		<td><tt>haltonskipped</tt> </td>
		<td>Stop the build process if there is at least on skipped test. </td>
		<td>No. Default to false </td>
	</tr>
	<tr>
	  <td><tt>groups</tt></td>
	  <td>
   	The list of groups to run, separated by spaces or commas.</td>
	  <td>
   	</td>
	</tr>
	<tr>
	  <td><tt>excludedgroups</tt></td>
	  <td>
   	The list of groups to exclude, separated by spaces or commas</td>
	  <td>
   	</td>
	</tr>
	<tr>
		<td><tt>jvm</tt></td>
		<td>The JVM to use, which will be run by <tt>Runtime.exec()</tt></td>
		<td><tt>java</tt></td>
	</tr>
	<tr>
		<td><tt>listeners</tt></td>
		<td>A comma or space-separated list of fully qualified classes that are TestNG listeners (for example<tt>
		<a href="http://testng.org/javadocs/org/testng/ITestListener.html">
		org.testng.ITestListener</a></tt> or <tt>
		<a href="http://testng.org/javadocs/org/testng/IReporter.html">
		org.testng.IReporter</a>)</tt></td>
		<td>No.</td>
	</tr>

        <tr>
		<td><tt>methods</tt></td>
		<td>A comma separated list of fully qualified class name and method. For example <tt>com.example.Foo.f1,com.example.Bar.f2</tt>.</td>
		<td>No.</td>
        </tr>

        <tr>
		<td><tt>mode</tt></td>
                <td>Either <tt>"testng"</tt>, <tt>"junit"</tt> or <tt>"mixed"</tt>. Whether TestNG should run only TestNG tests, JUnit tests or both.</td>
		<td>No. Defaults to "testng".</td>
        </tr>

	<tr>
		<td><tt>outputdir</tt> </td>
		<td>Directory for reports output. 
		</td>
		<td>No. Defaults to <tt>test-output</tt>. </td>
	</tr>
	<tr>
		<td><tt>skippedProperty</tt> </td>
		<td>The name of a property to set in the event of a skipped test. It is 
		used only if the <tt>haltonskipped</tt> is not set. </td>
		<td>No. </td>
	</tr>
	<tr>
		<td><tt>suiteRunnerClass</tt> </td>
		<td>A fully qualified name of a TestNG starter. </td>
		<td>
		<p align="left">No.&nbsp; Defaults to <tt>
		<a href="http://testng.org/javadocs/org/testng/TestNG.html">org.testng.TestNG</a> </tt></td>
	</tr>
	
	<tr>
		<td><tt>suiteThreadPoolSize</tt> </td>
		<td>The size of a thread pool to run suites.</td>
		<td>
		<p align="left">No.&nbsp; Defaults to 1.</td>
	</tr>

	<tr>
		<td><tt>parallel</tt> </td>
		<td>The parallel mode to use for running the tests - either methods or tests</td>
		<td>No - if not present, parallel mode will not be selected</td>
	</tr>

	<tr>
		<td><tt>suitename</tt> </td>
		<td>Sets the default name of the test suite, if one is not specified in a suite xml file or in the source code</td>
		<td>No. Defaults to "Ant suite"</td>
	</tr>

	<tr>
		<td><tt>testJar</tt> </td>
		<td>Path to a jar containing tests and a suite definition. </td>
		<td>&nbsp;</td>
	</tr>

	<tr>
		<td><tt>testname</tt> </td>
		<td>Sets the default name of the test, if one is not specified in a suite xml file or in the source code</td>
		<td>No. defaults to "Ant test"</td>
	</tr>

	<tr>
		<td><tt>testnames</tt> </td>
		<td>A comma separated list of test names, as defined
		in the &lt;test&gt; tag. Only these tests will be run.</td>
		<td>No. defaults to "Ant test"</td>
	</tr>

	<tr>
		<td><tt>threadCount</tt> </td>
		<td>The number of threads to use for this run. Ignored unless the parallel mode is also specified</td>
		<td>1</td>
	</tr>

	<tr>
		<td><tt>timeOut</tt></td>
		<td>The maximum time out in milliseconds that all the tests should run 
		under.</td>
		<td>&nbsp;</td>
	</tr>

	<tr>
		<td><tt>useDefaultListeners</tt></td>
		<td>Whether the default listeners and reporters should be used.</td>
		<td>Defaults to true.</td>
	</tr>
	<tr>
		<td><tt>workingDir</tt></td>
		<td>The directory where the ant task should change to before running 
		TestNG.</td>
		<td>&nbsp;</td>
	</tr>
	<tr>
		<td><tt>xmlfilesetref</tt> </td>
		<td>A reference to a
		<a href="http://ant.apache.org/manual/Types/resources.html#collection">ResourceCollection</a>
		containing the suite definitions to be run. Only File based
                <a href="http://ant.apache.org/manual/Types/resources.html#collection">ResourceCollection</a>s
                are supported (ie. <a href="http://ant.apache.org/manual/Types/fileset.html">FileSet</a>).</td>
		<td>&nbsp; </td>
	</tr>

	<tr>
		<td><tt>xmlPathInJar</tt></td>
		<td>The path of the XML file inside the jar file, only applicable if <tt>testJar</tt> was specified</td>
		<td>testng.xml</td>
	</tr>
</table>
<br>
One of attributes <tt>classpath</tt>, <tt>classpathref</tt> or nested <tt>
&lt;classpath&gt;</tt> must be used for providing the tests classpath. 
<p>One of the attributes <tt>xmlfilesetref</tt>, <tt>classfilesetref</tt> or 
nested <tt>&lt;xmlfileset&gt;</tt>, respectively <tt>&lt;classfileset&gt;</tt> must be used 
for providing the tests. </p>

<h3>TestNG modes</h3>
<p>The TestNG mode gets applied when tests are passed to TestNG using <tt>classfilesetref</tt>, <tt>methods</tt>
or nested <tt>&lt;classfileset&gt;</tt> and tells TestNG what kind of
tests it should look for and run:

<ul>
  <li><tt>"testng"</tt>: find and run TestNG tests.
  <li><tt>"junit"</tt>: find and run JUnit tests.
  <li><tt>"mixed"</tt>: run both TestNG and JUnit tests.
</ul>

<p><em>Note</em>: <tt>"junit"</tt> and <tt>"mixed"</tt> modes require the JUnit jar file on the classpath.</p>

<h3><a name="nested">Nested Elements</a></h3>
<h4>classpath</h4>
<p>The <tt>&lt;testng&gt;</tt> task supports a nested <tt>&lt;classpath&gt;</tt> element 
that represents a <em>PATH</em>-like structure. </p>
<h4>bootclasspath</h4>
<p>The location of bootstrap class files can be specified using this <em>
PATH-like</em> structure - will be ignored if <tt>fork </tt>is not set. </p>
<h4>xmlfileset</h4>
<p>The suite definitions (<tt>testng.xml</tt>) can be passed to the task with a
<tt><a href="http://ant.apache.org/manual/Types/fileset.html">FileSet</a></tt>
structure. </p>
<h4>classfileset</h4>
<p>TestNG can also run directly on classes, also supplied with a <tt>
<a href="http://ant.apache.org/manual/Types/fileset.html">FileSet</a></tt>
structure.</p>
<h4>jvmarg</h4>
<p>Additional parameters may be passed to the new VM via nested <tt>&lt;jvmarg&gt;</tt> 
elements. For example: </p>

<pre class="brush: xml">
&lt;testng&gt;
   &lt;jvmarg value="-Djava.compiler=NONE" /&gt;
   &lt;!-- ... --&gt;
&lt;/testng&gt;
</pre>

<h4>sysproperty</h4>
<p>Use nested <tt>&lt;sysproperty&gt;</tt> elements to specify system properties 
required by the class. These properties will be made available to the virtual 
machine during the execution of the test. The attributes for this element are 
the same as for <em>environment variables</em>:</p>

<pre class="brush: xml">
&lt;testng&gt;
   &lt;sysproperty key="basedir" value="${basedir}"/&gt;
   &lt;!-- ... --&gt;
&lt;/testng&gt;
</pre>

<p>will run the test and make the <code>basedir</code> property 
available to the test.</p>

<h4>propertyset</h4>
<p>You may also use a nested <tt>&lt;propertyset&gt;</tt> element to specify a set of system properties that are defined 
outside of the TestNG ant task. This allows for more flexible definitions of system properties, for instance selecting
all properties with a specific prefix or matching a regex. See the 
<a href="http://ant.apache.org/manual/Types/propertyset.html">PropertySet page</a> in the 
<a href="http://ant.apache.org/manual/">Ant manual</a> for full details. Here's a simple example:</p>
<pre class="brush: xml">
      &lt;property name="myprop1" value="value 1"/&gt;
      &lt;property name="myprop2" value="value 2"/>
	
      &lt;propertyset id="propset1"&gt;
          &lt;propertyref name="myprop1"/&gt;
          &lt;propertyref name="myprop2"/&gt;
      &lt;/propertyset&gt;

      &lt;testng outputdir="${testng.report.dir}" classpathref="run.cp"&gt;
          &lt;xmlfileset dir="${test15.dir}" includes="testng-single3.xml"/&gt;
          &lt;propertyset refid="propset1"/&gt;
      &lt;/testng&gt;
</pre>
<p>In this case, the system properties named "myprop1" and "myprop2" are passed along to the TestNG process.</p>

<h4>reporter</h4>
<p>An inner <tt>&lt;reporter&gt;</tt> element is an alternative way to inject a
custom report listener allowing the user to set custom properties in order to fine-tune
the behavior of the reporter at run-time.
<br>
The element has one <tt>classname</tt> attribute which is mandatory, indicating
the class of the custom listener. In order to set the properties of the reporter, the
<tt>&lt;reporter&gt;</tt> element can contain several nested <tt>&lt;property&gt;</tt>
elements which will provide the <tt>name</tt> and <tt>value</tt> attributes as seen below:
</p>
<pre class="brush: xml">
&lt;testng ...&gt;
   ...
   &lt;reporter classname="com.test.MyReporter"&gt;
      &lt;property name="methodFilter" value="*insert*"/&gt;
      &lt;property name="enableFiltering" value="true"/&gt;
   &lt;/reporter&gt;
   ...
&lt;/testng&gt;
</pre>
<pre class="brush: java">
public class MyReporter {

  public String getMethodFilter() {...}
  public void setMethodFilter(String methodFilter) {...}
  public boolean isEnableFiltering() {...}
  public void setEnableFiltering(boolean enableFiltering) {...}
  ...
}
</pre>
You have to consider though that for the moment only a limited set of property types are supported:
<tt>String, int, boolean, byte, char, double, float, long, short</tt>.

<h4>env</h4>
<p>It is possible to specify environment variables to pass to the TestNG forked 
virtual machine via nested <tt>&lt;env&gt;</tt> elements. For a description of the <tt>
&lt;env&gt;</tt> element's attributes, see the description in the <em>
<a href="http://ant.apache.org/manual/CoreTasks/exec.html">exec</a></em> task.</p>
<h3>Examples</h3>
<h4>Suite xml</h4>

<pre class="brush: text">
&lt;testng classpathref="run.cp"
        outputDir="${testng.report.dir}"
        sourcedir="${test.src.dir}"
        haltOnfailure="true"&gt;
 
   &lt;xmlfileset dir="${test14.dir}" includes="testng.xml"/&gt;
&lt;/testng&gt;
</pre>

<h4>Class FileSet</h4>
<pre class="brush: xml">
&lt;testng classpathref="run.cp"
		outputDir="${testng.report.dir}"
		haltOnFailure="true" verbose="2"&gt;
	&lt;classfileset dir="${test.build.dir}" includes="**/*.class" /&gt;
&lt;/testng&gt;
</pre>

<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-238215-2";
urchinTracker();
</script>

</body>

</html>
������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/bundle-pom.xml������������������������������������������������������������������0000644�0001750�0001750�00000004127�12551235562�016441� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <!--
    This POM cannot be used to build TestNG; it should only be used as part of a Maven
    repository upload bundle.
    
    See the guide to creating a bundle here:
    http://maven.apache.org/guides/mini/guide-central-repository-upload.html
    -->
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <name>TestNG</name>
    <version>5.12.1</version>
    <description>TestNG is a testing framework inspired from JUnit and NUnit but introducing some new functionalities that make it more powerful and easier to use.</description>
    <url>http://testng.org</url>
    
    <licenses>
        <license>
            <name>Apache License, Version 2.0</name>
            <url>http://apache.org/licenses/LICENSE-2.0</url>
        </license>
    </licenses>

    <scm>
        <connection>scm:svn:http://testng.googlecode.com/svn/trunk/</connection>
        <developerConnection>scm:svn:http://testng.googlecode.com/svn/trunk/</developerConnection>
        <url>http://testng.googlecode.com/svn/trunk</url>
    </scm>
    
    <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.10</version>
        </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>

    </dependencies>    
    
</project>
�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/build.gradle��������������������������������������������������������������������0000644�0001750�0001750�00000006302�12551235562�016131� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������buildscript {

    def a_user = hasProperty('artifactory_user') ? artifactory_user : System.getenv('artifactory_user')
    def a_password = hasProperty('artifactory_password') ? artifactory_password : System.getenv('artifactory_password')

    repositories {
        mavenCentral()
        jcenter()
        maven {
            url 'http://dl.bintray.com/cbeust/maven'
        }
        maven {
            url 'http://oss.jfrog.org/artifactory/plugins-release'
            credentials {
                username = "${a_user}"
                password = "${a_password}"
            }
        }
    }

    dependencies {
        //Check for the latest version here: http://plugins.gradle.org/plugin/com.jfrog.artifactory
        classpath "org.jfrog.buildinfo:build-info-extractor-gradle:3.0.3"
    }
}

plugins {
    id "com.jfrog.bintray" version "1.1"
    id "com.jfrog.artifactory" version "3.1.1"
}

version = '6.9.6-SNAPSHOT'

apply plugin: 'java'

repositories {
    mavenCentral()
    jcenter()
    maven {
        url 'http://dl.bintray.com/cbeust/maven'
    }
}

dependencies {
    compile 'org.apache.ant:ant:1.7.0'
    compile 'junit:junit:4.10'
    compile 'org.beanshell:bsh:2.0b4'
    compile 'com.google.inject:guice:4.0:no_aop'
    compile 'com.beust:jcommander:1.48'
    compile 'org.yaml:snakeyaml:1.15'

    testCompile 'org.assertj:assertj-core:2.0.0'
    testCompile 'org.testng:testng:6.9.4'
}

task sourceJar(type: Jar) {
    group 'Build'
    description 'An archive of the source code'
    classifier 'sources'
    from sourceSets.main.allSource
}

artifacts {
    sourceJar
}

import org.apache.tools.ant.filters.ReplaceTokens

def generatedSourcesFolder = projectDir.toString() + '/src/generated/java'

def dirFrom = projectDir.toString() + '/src/main/resources/org/testng/internal'
def dirTo = generatedSourcesFolder + "/org/testng/internal"
def fileFrom = 'VersionTemplateJava'
def fileTo = 'Version.java'

task removeVersion {
    delete dirTo + fileTo
}

sourceSets {
    generated {
        java {
            srcDir 'src/generated/java'
        }
        resources {
            srcDir 'src/generated/resources'
        }
    }
}

sourceSets {
    main {
        compileClasspath += generated.output
        runtimeClasspath += generated.output
    }
}

gradle.projectsEvaluated {
    compileJava.dependsOn(myDir)
}

task myDir {
    delete dirTo + "/" + fileTo
    mkdir(dirTo)
}

// Include the generated Version.class in the jar
jar {
    from "$buildDir/classes/generated"
}

task createVersion(type: Copy, dependsOn: myDir) {
    println("Creating Version file: ${version} in ${dirTo}")
    from dirFrom
    include fileFrom
    into(dirTo)
    rename(fileFrom, fileTo)
    filter(ReplaceTokens, tokens: [version: version])
}

compileJava.dependsOn(createVersion)

test {
    useTestNG() {
        suites 'src/test/resources/testng.xml'
    }
//    testLogging.showStandardStreams = true
    systemProperties = System.getProperties()
    systemProperties['test.resources.dir'] = 'build/resources/test/'
}

if (JavaVersion.current().isJava8Compatible()) {
    allprojects {
        tasks.withType(Javadoc) {
            options.addStringOption('Xdoclint:none', '-quiet')
        }
    }
}

apply from: 'gradle/publishing.gradle'
������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/build-with-maven����������������������������������������������������������������0000755�0001750�0001750�00000001647�12551235562�016763� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Two different POMs are needed to build TestNG with Maven because it's not
# allowed to have circular dependencies.
# - pom.xml defines the project version "n-SNAPSHOT", builds, jars and deploys (but doesn't
# run the tests).
# - pom-test.xml declares a test dependency on "n-SNAPSHOT", which it will find
# in the local repository (~/.m2/repository). All it does then is run the tests.


mvn clean install -Dgpg.skip=true
#or if you want to sign the jar, uncomment this:
#mvn clean install

mvn -f pom-test.xml test


echo
echo "To run the tests: mvn -f pom-test.xml test"
echo "To deploy to the snapshot repository: mvn deploy"
echo "To deploy to the release directory: mvn release:clean release:prepare release:perform"
echo "Nexus UI:  https://oss.sonatype.org/index.html"
echo "Wiki: https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide"

# deploy without tagging: mvn deploy -DperformRelease


�����������������������������������������������������������������������������������������testng-testng-6.9.5/build-with-gradle���������������������������������������������������������������0000755�0001750�0001750�00000000061�12551235562�017100� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������./gradlew --daemon --stacktrace clean build test
�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/bin/����������������������������������������������������������������������������0000755�0001750�0001750�00000000000�12551235562�014421� 5����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/bin/testng.sh�������������������������������������������������������������������0000755�0001750�0001750�00000000352�12551235562�016264� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ROOT=~/java/testng
VERSION=5.0
JAR14=$ROOT/testng-$VERSION-jdk14.jar
JAR15=$ROOT/testng-$VERSION-jdk15.jar

java -ea -classpath $ROOT/test/build:$ROOT/3rdparty/junit.jar:$JAVA_HOME/lib/tools.jar:$JAR15:$CLASSPATH org.testng.TestNG $*
��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/bin/testng.bat������������������������������������������������������������������0000644�0001750�0001750�00000000435�12551235562�016417� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������set ROOT=c:\java\TestNG
set JAR=%ROOT%\testng-5.2beta-jdk15.jar;%ROOT%\test\build
	rem set JAR=%ROOT%\testng-4.5-jdk14.jar;%ROOT%\test-14\build

java -ea -classpath %ROOT%\3rdparty\junit.jar;%JAVA_HOME%\lib\tools.jar;%JAR%;%CLASSPATH% org.testng.TestNG %1 %2 %3 %4 %5 %6 %7 %8 %9
�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/bin/slave.bat�������������������������������������������������������������������0000644�0001750�0001750�00000000051�12551235562�016217� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng -d client-output -slave %1 %2 %3
���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/bin/run-tests.sh����������������������������������������������������������������0000755�0001750�0001750�00000001316�12551235562�016725� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ROOT=~/java/testng
VERSION=5.0
JAR14=$ROOT/testng-$VERSION-jdk14.jar
JAR15=$ROOT/testng-$VERSION-jdk15.jar

java -ea -classpath test/build:$ROOT/3rdparty/junit.jar:$JAVA_HOME/lib/tools.jar:$JAR15:$CLASSPATH org.testng.TestNG test/testng.xml

java -ea -classpath test/v4/build:$ROOT/3rdparty/junit.jar:$JAVA_HOME/lib/tools.jar:$JAR15:$CLASSPATH org.testng.TestNG test/v4/testng.xml

java -ea -classpath test-14/build:$ROOT/3rdparty/junit.jar:$JAVA_HOME/lib/tools.jar:$JAR14:$CLASSPATH org.testng.TestNG -sourcedir test-14/src test-14/testng.xml

java -ea -classpath test-14/v4/build:$ROOT/3rdparty/junit.jar:$JAVA_HOME/lib/tools.jar:$JAR14:$CLASSPATH org.testng.TestNG -sourcedir test-14/v4/src test-14/v4/testng.xml


������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/bin/master.bat������������������������������������������������������������������0000644�0001750�0001750�00000000131�12551235562�016377� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng -hostfile test\hosts.properties -d test\test-output %1 %2 %3 %4 %5 test\testng.xml���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/bin/junitconverter.bat����������������������������������������������������������0000644�0001750�0001750�00000000464�12551235562�020176� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������set ROOT=c:\java\TestNG
set JAR=%ROOT%\testng-4.5-jdk15.jar;%ROOT%\test\build
	rem set JAR=%ROOT%\testng-4.5-jdk14.jar;%ROOT%\test-14\build

java -ea -classpath %ROOT%\3rdparty\junit.jar;%JAVA_HOME%\lib\tools.jar;%JAR%;%CLASSPATH% org.testng.JUnitConverter -restore -overwrite -annotation -srcdir src

������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/appveyor.yml��������������������������������������������������������������������0000644�0001750�0001750�00000000751�12551235562�016244� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������version: "{branch} {build}"
skip_tags: true
clone_depth: 10

build:
  verbosity: detailed

build_script:
  - gradlew.bat assemble --info --no-daemon

test_script:
  - gradlew.bat test --info --no-daemon

environment:
  matrix:
  - JAVA_HOME: C:\Program Files\Java\jdk1.7.0
  - JAVA_HOME: C:\Program Files\Java\jdk1.8.0
  - JAVA_HOME: C:\Program Files (x86)\Java\jdk1.7.0
  - JAVA_HOME: C:\Program Files (x86)\Java\jdk1.8.0

matrix:
  fast_finish: true

cache:
  - C:\Users\appveyor\.gradle�����������������������testng-testng-6.9.5/ant/����������������������������������������������������������������������������0000755�0001750�0001750�00000000000�12564576474�014451� 5����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/ant/old/������������������������������������������������������������������������0000755�0001750�0001750�00000000000�12551235562�015211� 5����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/ant/old/build-sample.xml��������������������������������������������������������0000644�0001750�0001750�00000001611�12551235562�020310� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<project name="testng" default="run" basedir=".">

	<property name="testng.home" value="c:/java/testng" />
    <property name="lib.dir" value="${testng.home}/lib"/>
    <property name="testng.jar" value="${testng.home}/testng-2.5-jdk15.jar" />

	<path id="run.cp">
		<!--
      <path refid="compile.cp"/>
-->
		<pathelement location="build" />
		<pathelement location="${lib.dir}/qdox-1.5.jar"/>
		<pathelement location="${java.home}/../lib/tools.jar"/>
	</path>

	<target name="run" description="Run tests" >
		<echo>Defining task from ${testng.jar}</echo>
		<taskdef name="testng"
              classname="org.testng.TestNGAntTask"
              classpath="${testng.jar}" />

		<testng classpathref="run.cp"
        dumpcommand="true" verbose="9" outputdir="test-outputs">
			<classfileset dir="build">
				<include name="**/justin/*Test*.class" />
			</classfileset>
		</testng>
	</target>

</project>
�����������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/ant/old/build-dogfood.xml�������������������������������������������������������0000644�0001750�0001750�00000001733�12551235562�020455� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<project name="testng" default="run" basedir=".">
	<property name="testng.home" value="${basedir}/../" />
    <property name="lib.dir" value="${testng.home}/3rdparty"/>
 	<property file="../build.properties"/>

	<path id="run.cp">
		<pathelement location="../z_build" />
		<fileset dir="${lib.dir}">
			<include name="junit.jar"/>
			<include name="${beanshell.jar}"/>
			<include name="${qdox.jar}"/>
		</fileset>
 		<pathelement location="${java.home}/../lib/tools.jar"/>
	</path>

	<target name="run" description="Run tests" >
		<echo>Defining task from ${basedir}/../${jdk15.testng.jar}</echo>
		<taskdef name="testng"
              classname="org.testng.TestNGAntTask"
              classpath="${basedir}/../${jdk15.testng.jar}" />

		<testng classpathref="run.cp"
        dumpcommand="true" verbose="9" outputdir="test-outputs" haltonfailure="true">
			<xmlfileset dir="${basedir}">
				<include name="testng-single.xml" />
			</xmlfileset>
		</testng>
	</target>

</project>
�������������������������������������testng-testng-6.9.5/ant/ivy.xml���������������������������������������������������������������������0000644�0001750�0001750�00000001011�12551235562�015755� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<ivy-module version="2.0">
  <info organisation="org.testng" module="testng" revision="6.5beta"/>

  <dependencies>
    <dependency org="org.apache.ant" name="ant" rev="1.7.0" />
    <dependency org="junit" name="junit" rev="4.10" />
    <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.15" />
    <dependency org="com.beust" name="jcommander" rev="1.48" />
  </dependencies>
</ivy-module>

�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/ant/build.xml�������������������������������������������������������������������0000644�0001750�0001750�00000041215�12551235562�016257� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<project name="testng" default="dev" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">
  
  <!-- ====================================================================== -->
  <!-- TestNG build file                                                      -->
  <!-- Created cbeust, April 26th, 2004                                       -->
  <!-- ====================================================================== -->

  <property file="build.properties" />
  <property name="optimize" value="false" />

  <!-- ====================================================================== -->
  <!-- PREPARE                                                                -->
  <!-- ====================================================================== -->
  <target name="prepare" depends="retrieve-dependencies"
          description="Performs all preparations required to build.">
    <tstamp />
    <mkdir dir="${build.dir}" />
    <mkdir dir="${other.jars.dir}" />
  </target>

  <!-- ====================================================================== -->
  <!-- DUMP                                                                   -->
  <!-- ====================================================================== -->
  <target name="dump" description="Dumps all properties." depends="prepare">
    <echoproperties />
  </target>

	<!-- ====================================================================== -->
  <!-- VALIDATE                                                               -->
  <!-- ====================================================================== -->

  <target name="validate" description="Validates the build environment.">
    <!-- 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" />
      </or>
    </condition>
    <fail unless="requiredJavaVersion"
          message="Java version 1.7 required." />
    <!-- validate ant version too ... -->
  </target>

  <!-- ==================================================================== -->
  <!-- COPY-RESOURCES                                                       -->
  <!-- ==================================================================== -->

  <target name="copy-resources" description="Copies resources.">
    <copy verbose="false"
          file="${src.resources.dir}/testngtasks"
          todir="${build.dir}" />
    <copy todir="${build.dir}">
      <fileset dir="${src.resources.dir}">
        <exclude name="**/.*" />
        <exclude name="**/CVS/*" />
      </fileset>
    </copy>
  </target>


  <target name="dev"
          depends="prepare,validate,copy-resources,build,tests" />

  <target name="all"
          depends="prepare,validate,copy-resources,build,dist,tests,test-ant,javadocs,dist" />

  <target name="build" depends="prepare,compile,testng-jar-all" />

  <target name="testng-jar-all">
    <antcall target="create-jar">
      <param name="jar.file" value="${testng.jar}" />
    </antcall>
    <jar jarfile="${testng.jar}" update="true">
      <zipfileset src="${lib.dir}/${beanshell.jar}" />
      <zipfileset src="${lib.dir}/${jcommander.jar}" />
      <zipfileset src="${lib.dir}/${yaml.jar}" />
    </jar>

  </target>

  <target name="single">
    <ant antfile="build-tests.xml" target="run:single"/>
  </target>

  <!-- ==================================================================== -->
  <!-- Compile                                                              -->
  <!-- ==================================================================== -->

  <path id="compile2.cp">
    <fileset dir="${lib.dir}" includes="${all.jar.files}" />
  </path>

  <target name="compile"
          depends="prepare,copy-resources"
          description="Compiles sources">
    <echo message="                                 -- Compiling sources --" />

    <echo>Src:${src.dir}</echo>
    <javac classpathref="compile2.cp"
           verbose="false"
           target="1.7"
           debug="true"
           optimize="${optimize}"
           destdir="${build.dir}">
      <src path="${src.dir}" />
    </javac>
  </target>

  <target name="compile:all" depends="compile" />

  <target name="examples">
    <ant inheritall="no" antfile="examples/build.xml" />
  </target>

  <target name="tests" depends="build" description="runs all JDK5 tests with JDK5 distro">
    <ant inheritall="no" antfile="build-tests.xml" />
  </target>
  
  <target name="test-ant" depends="build">
    <echo message="                                 -- Testing ant testng task functionality --" />
    <ant inheritall="no" antfile="build-ant.xml" />
  </target>

  <!-- ==================================================================== -->
  <!-- Documentation                                                        -->
  <!-- ==================================================================== -->

  <target name="javadocs" depends="build,javadocs-current" />

  <target name="doclava">
    <javadoc
      docletpath="3rdparty/doclava-1.0.3.jar"
      bootclasspath="${javahome}/jre/lib/rt.jar"
      classpath="${testng.jar}:lib/${ant.jar}:lib/${guice2.jar}:lib/aopalliance-1.0.jar"
      maxmemory="2048M"
      additionalparam="-quiet"
      verbose="false"
      destdir="javadocs"
      >
      <fileset dir="${src.dir}" defaultexcludes="yes">
        <include name="org/testng/*.java" />
      </fileset>
      <fileset dir="${src.dir}" defaultexcludes="yes">
        <include name="org/testng/xml/Xml*.java" />
      </fileset>
      <fileset dir="${src.dir}" defaultexcludes="yes">
        <include name="org/testng/annotations/**" />
      </fileset>
      <doclet name="com.google.doclava.Doclava">
        <param name="-stubs" value="build/stubs" />
        <param name="-hdf"/>
        <param name="project.name" value="TestNG" />
        <!-- versioning -->
        <param name="-since"/>
        <param name="doclava/previous.xml"/>
        <param name="v1" />
        <param name="-apiversion" value="v2"/>
        <!-- federation -->
        <param name="-federate" />
        <param name="JDK"/>
        <param name="http://download.oracle.com/javase/6/docs/api/index.html?"/>
        <param name="-federationxml"/><param name="JDK"/>
        <param name="http://doclava.googlecode.com/svn/static/api/openjdk-6.xml"/>
      </doclet>
    </javadoc>
  </target>

  <target name="javadocs-current">
    <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" />
      </fileset>
      <fileset dir="${src.dir}" defaultexcludes="yes">
        <include name="org/testng/xml/Xml*.java" />
      </fileset>
      <fileset dir="${src.dir}" defaultexcludes="yes">
        <include name="org/testng/annotations/**" />
      </fileset>
    </javadoc>
  </target>

  <!-- ==================================================================== -->
  <!-- Distribution                                                         -->
  <!-- ==================================================================== -->

  <target name="dist" depends="build,all-jar-flavors,dist-all-zip,eclipse" />

  <target name="all-jar-flavors" depends="dist-junit,dist-nobsh-guice,dist-bsh-noguice,dist-nobsh-noguice,dist-testng-dist,dist-testng-javadoc" />

  <target name="dist-junit">
    <antcall target="create-jar">
      <param name="jar.file" value="${other.jars.dir}/${testng.junit.jar}" />
    </antcall>
    <jar jarfile="${other.jars.dir}/${testng.junit.jar}" update="true">
      <zipfileset src="${lib.dir}/${beanshell.jar}" />
      <zipfileset src="${lib.dir}/${jcommander.jar}" />
      <zipfileset src="${lib.dir}/${junit.jar}" />
      <zipfileset src="${lib.dir}/${yaml.jar}" />
    </jar>
  </target>

  <target name="dist-nobsh-guice">
    <antcall target="create-jar">
      <param name="jar.file" value="${other.jars.dir}/${testng.nobsh.guice.jar}" />
    </antcall>
    <jar jarfile="${other.jars.dir}/${testng.nobsh.guice.jar}" update="true">
      <zipfileset src="${lib.dir}/${guice2.jar}" />
      <zipfileset src="${lib.dir}/${jcommander.jar}" />
      <zipfileset src="${lib.dir}/${junit.jar}" />
    </jar>
  </target>

  <target name="dist-bsh-noguice">
    <antcall target="create-jar">
      <param name="jar.file" value="${other.jars.dir}/${testng.bsh.noguice.jar}" />
    </antcall>
    <jar jarfile="${other.jars.dir}/${testng.bsh.noguice.jar}" update="true">
      <zipfileset src="${lib.dir}/${beanshell.jar}" />
      <zipfileset src="${lib.dir}/${jcommander.jar}" />
      <zipfileset src="${lib.dir}/${junit.jar}" />
    </jar>
  </target>

  <target name="dist-nobsh-noguice">
    <antcall target="create-jar">
      <param name="jar.file" value="${other.jars.dir}/${testng.nobsh.noguice.jar}" />
    </antcall>
    <jar jarfile="${other.jars.dir}/${testng.bsh.noguice.jar}" update="true">
      <zipfileset src="${lib.dir}/${jcommander.jar}" />
      <zipfileset src="${lib.dir}/${junit.jar}" />
    </jar>
  </target>

  <target name="dist-testng-dist">
    <antcall target="create-jar">
      <param name="jar.file" value="${other.jars.dir}/${testng.dist.jar}" />
    </antcall>
    <jar jarfile="${other.jars.dir}/${testng.dist.jar}" update="true">
      <zipfileset src="${lib.dir}/${jcommander.jar}" />
    </jar>
  </target>

  <target name="dist-testng-javadoc" depends="javadocs">
    <zip destfile="${other.jars.dir}/${testng.javadoc.zip}">
        <fileset dir="javadocs"/>
    </zip>
  </target>

  <target name="create-jar" description="Create a jar file with the Testng classes and nothing else" 
          depends="compile">
    <delete file="${jar.file}" />
    <jar destfile="${jar.file}" >
      <manifest>
        <attribute name="Main-Class" value="org.testng.TestNG" />
        <attribute name="Implementation-Version" value="${testng.version}-${DSTAMP}${TSTAMP}" />
      </manifest>
      <fileset dir="${build.dir}" />
      <fileset file="TESTNG-${testng.version}" />
    </jar>
  </target>

  <target name="dist-all-zip" depends="dist-prepare,javadocs">
    <property name="zip.dir" value="testng-${testng.version}" />
    <echo>Adding ${testng.fullname}</echo>
    <zip zipfile="${testng.zip}">
      <zipfileset prefix="${zip.dir}" dir="${target}">
        <include name="${testng.fullname}.jar" />
      </zipfileset>
      <zipfileset prefix="${zip.dir}" dir="${basedir}" includesfile="FILES" />
      <zipfileset dir="${other.jars.dir}" prefix="${zip.dir}/other-jars"/>
      <zipfileset dir="javadocs" prefix="${zip.dir}/javadocs" />
      <zipfileset dir="src" prefix="${zip.dir}/src" />
      <zipfileset dir="spring" prefix="${zip.dir}/spring" />
      <zipfileset dir="doc" prefix="${zip.dir}/doc" />
      <zipfileset dir="${src.resources.dir}"
               prefix="${zip.dir}/resources" 
            includes="**/*.css"/>
    </zip>
  </target>
  
<!--
  <target name="dist-maven-bundle" depends="dist-all-zip">
    <mkdir dir="${build.maven-bundle.dir}" />
    <copy file="bundle-pom.xml" tofile="${build.maven-bundle.dir}/pom.xml" overwrite="true">
      <filterchain>
        <expandproperties/>
      </filterchain>
    </copy>
    <jar destfile="${build.maven-bundle.dir}/${sources.testng.jar}">
      <fileset dir="${src.dir}" />
    </jar>

    <exec executable="gpg">
      <arg value="- -yes" />
      <arg value="-ab" />
      <arg value="${testng.jar}" />
    </exec>

    <exec executable="gpg">
      <arg value="- -yes" />
      <arg value="-ab" />
      <arg value="${build.maven-bundle.dir}/pom.xml" />
    </exec>

    <exec executable="gpg">
      <arg value="- -yes" />
      <arg value="-ab" />
      <arg value="${build.maven-bundle.dir}/${sources.testng.jar}" />
    </exec>

    <jar destfile="${testng.maven-bundle}">
      <fileset file="${build.maven-bundle.dir}/pom.xml" />
      <fileset file="${build.maven-bundle.dir}/${sources.testng.jar}" />
      <fileset file="${build.maven-bundle.dir}/*asc" />
      <fileset file="${testng.jar}" />
      <fileset file="${testng.jar}.asc" />
    </jar>
  </target>
-->

  <target name="dist-prepare" depends="update-readme">
    <delete file="{other.jars.dir}/${testng.nobsh.jar}" />
    <mkdir dir="${other.jars.dir}" />
  </target>

  <target name="update-readme">
    <copy file="README.template" tofile="README.md" />
    <replace file="README.md" token="${version}" value="${testng.version}" />
    <touch file="TESTNG-${testng.version}" />
  </target>
      
  <target name="eclipse" description="Used by Cedric to build distributions">
    <property name="jdk15.jar"
              value="${testng-eclipse.dir}/lib/testng.jar" />

    <delete file="${jdk15.jar}" />
    <copy file="${testng.jar}" tofile="${jdk15.jar}" />

    <!-- sources -->
    <property name="sources" value="${testng-eclipse.dir}/lib/testng-sources.jar"/>
    <echo>Sources: ${sources}</echo>
    <jar destfile="${sources}" basedir="src/main/java/" />
  </target>

  <target name="ftp">
    <!--
          <ftp action="put"
             server="beust.com"
             remotedir="w/testng/test-output"
             userid="${userid}"
             password="${password}">
              <fileset dir="c:\weblogic\dev\sandbox\cbeust\testng\test\test-output">
                <include name="index.html" />
                <include name="main.html" />
                <include name="toc.html" />
                <include name="*egression*" />
             </fileset>
        </ftp>
      -->
    <ftp action="put"
         server="beust.com"
         remotedir="w/testng"
         userid="${userid}"
         password="${password}">
      <fileset dir="${root.dir}">
        <include name="${testng.zip}" />
        <include name="javadocs/**" />
        <include name="testng-1.0.dtd" />
      </fileset>
      <fileset dir="${root.dir}/doc">
        <include name="*.html" />
      </fileset>
    </ftp>

  </target>

  <target name="ftp2">
    <ftp action="put"
         server="beust.com"
         remotedir="w/testng"
         userid="${userid}"
         password="${password}">
      <fileset dir="${root.dir}/test">
        <include name="test-output/*" />
      </fileset>
      <fileset dir="${root.dir}/test">
        <include name="test-report/*" />
      </fileset>
    </ftp>
  </target>

  <target name="clean">
    <delete dir="${build.dir}" />
    <delete dir="${target}" />
    <delete dir="${build.maven-bundle.dir}" />
    <delete failonerror="false">
      <fileset dir="." includes="testng*.jar,*.zip" />
    </delete>
    <delete dir="test-output" failonerror="false" />
    <delete dir="test-output-tests" failonerror="false" />
    <ant antfile="build-tests.xml" target="clean" />
    <ant dir="examples" target="clean" />
  </target>

  <!-- ==================================================================== -->
  <!-- Maven1/2 Distribution                                                -->
  <!-- ==================================================================== -->

<!--
  <target name="maven-plugin">
    <jar destfile="maven-testng-plugin-${testng-maven.version}.jar"
         basedir="./maven/" />
  </target>
-->

  <!-- ==================================================================== -->
  <!-- Ivy                                                                  -->
  <!-- ==================================================================== -->

  <target name="retrieve-dependencies" description="Retrieve dependencies with ivy">
    <ivy:retrieve log="quiet" />
  </target>

  <target name="publish">
    <ivy:resolve />
    <mkdir dir="dist/jars" />
    <copy file="${testng.jar}" todir="dist/jars" />
    <ivy:publish organisation="org.testng" resolver="local" overwrite="true"/>
  </target>

  <target name="pom">
    <ivy:makepom ivyfile="ivy.xml" pomfile="ivy-pom.xml" />
  </target>

  <!-- ==================================================================== -->
  <!-- Code coverage                                                        -->
  <!-- ==================================================================== -->

<!--
  <property name="cobertura.dir" value="../cobertura-1.9.4.1" />

  <path id="cobertura.classpath">
      <fileset dir="${cobertura.dir}">
          <include name="cobertura.jar" />
          <include name="lib/**/*.jar" />
      </fileset>
  </path>

  <taskdef classpathref="cobertura.classpath" resource="tasks.properties" />

  <target name="coverage:create">
    <cobertura-instrument classpath="cobertura-1.9.4.1/lib/*" todir="target/instrumented-classes">
      <fileset dir="${build.dir}">
        <include name="**/*.class" />
      </fileset>
    </cobertura-instrument>
  </target>

  <target name="coverage">
    <cobertura-report srcdir="${src.dir}" destdir="target/coverage-report"/>
  </target>
-->

</project>
�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/ant/build.properties������������������������������������������������������������0000644�0001750�0001750�00000003666�12551235562�017663� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#
# TestNG distribution
#
testng.basename=testng
testng.version=6.8.14-SNAPSHOT
testng.fullname=${testng.basename}-${testng.version}

#
# Global directories
#
root.dir=${basedir}
build.3rdparty.dir=${root.dir}/build3rdparty
build.maven-bundle.dir=${build.dir}/maven-bundle
target=${root.dir}/target
lib.dir=${basedir}/lib
lib-supplied.dir=${basedir}/lib-supplied
src.dir=${basedir}/src/main/java
src.resources.dir=${basedir}/src/main/resources
build.dir=${target}/classes
test.dir=${basedir}/src/test/java
test.build.dir=${target}/test-classes
test.output.dir=${target}/test-output
test.resources.dir=${basedir}/src/test/resources
example.dir=${basedir}/examples

#
# Jar files
#
beanshell.jar=bsh-2.0b4.jar
guice2.jar=guice-2.0.jar
junit.jar=junit-4.10.jar
ant.jar=ant-1.7.0.jar
jcommander.jar=jcommander-1.27.jar
yaml.jar=snakeyaml-1.12.jar

all.jar.files=${beanshell.jar},${junit.jar},${ant.jar},${jcommander.jar},${yaml.jar},${guice2.jar}

#
# Names of distributions
#
testng.jar=${target}/${testng.fullname}.jar
testng.dist.jar=${testng.fullname}-dist.jar
sources.testng.jar=${testng.fullname}-sources.jar
testng.junit.jar=${testng.fullname}-junit.jar
testng.nobsh.noguice.jar=${testng.fullname}-nobsh-noguice.jar
testng.bsh.noguice.jar=${testng.fullname}-bsh-noguice.jar
testng.nobsh.guice.jar=${testng.fullname}-nobsh-guice.jar
testng.ibiblio.jar=${testng.fullname}-bundle.jar
testng.zip=${target}/${testng.fullname}.zip
testng.maven-bundle=${target}/${testng.fullname}-bundle.jar
testng.javadoc.zip=${testng.fullname}-javadoc.zip

other.jars.dir=${target}/other-jars

#
# Test locations
#
test.location.msg=Test results can be found in\n\
test/test-output/index.html

#
# Eclipse plug-in
#
testng-eclipse.dir=../testng-eclipse

#
# Maven plug-in version
# Note, this version number is appended to the resulting plug-in jar
#
testng-maven.version=1.2

#
# JDK 1.4 for sanity checking before a distribution
#
java14.home=jdk-1.5.0_04
#java14.home=c:/java/jdk-1.4.2_08
��������������������������������������������������������������������������testng-testng-6.9.5/ant/build-tests.xml�������������������������������������������������������������0000644�0001750�0001750�00000014531�12551235562�017420� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<project name="testng" default="all" basedir=".">

  <property file="build.properties"/>

  <property name="report.dir" value="${test.output.dir}"/>
  <property name="junit.report.dir" value="${report.dir}/test-tmp"/>
  <property name="testng.report.dir" value="${report.dir}"/>

  <target name="all" depends="prepare,compile,run,reports,done"/>

  <!-- ==================================================================== -->
  <!-- Compile                                                              -->
  <!-- ==================================================================== -->
  <path id="compile.cp">
    <pathelement location="${testng.jar}" />
    <fileset dir="${lib.dir}" includes="${guice2.jar}" />
    <fileset dir="${lib.dir}" includes="${junit.jar}" />
    <fileset dir="${lib.dir}" includes="aopalliance-1.0.jar" />
  </path>

  <target name="env:info">
    <echo>
BASEDIR          =${basedir}
TEST.DIR         =${test.dir}
TEST.BUILD.DIR   =${test.build.dir}
REPORT.DIR       =${report.dir}
JUNIT.REPORT.DIR =${junit.report.dir}
TESTNG.REPORT.DIR=${testng.report.dir}
    </echo>
  </target>

  <target name="compile" depends="prepare">
    <echo message="                                 -- Compiling tests --"/>

    <property name="build.compiler" value="modern"/>
    <javac debug="true"
           source="1.7"
           classpathref="compile.cp"
           srcdir="${test.dir}"
           destdir="${test.build.dir}"
    />

  </target>

  <target name="prepare">
    <tstamp/>
    <mkdir dir="${test.build.dir}"/>
    <mkdir dir="${junit.report.dir}"/>
    <mkdir dir="${testng.report.dir}"/>

  <taskdef name="testng"
             classname="org.testng.TestNGAntTask"
             classpath="${build.dir}"/>
  </target>

<!--
  <property name="cobertura.dir" value="../cobertura-1.9.4.1" />

  <path id="cobertura.classpath">
      <fileset dir="${cobertura.dir}">
          <include name="cobertura.jar" />
          <include name="lib/**/*.jar" />
      </fileset>
  </path>
-->

  <!-- ==================================================================== -->
  <!-- Run                                                             -->
  <!-- ==================================================================== -->

  <path id="run.cp">
<!--
  	<path location="target/instrumented-classes" />
  	<path refid="cobertura.classpath" />
-->
    <path refid="compile.cp"/>
    <pathelement location="${test.build.dir}"/>
  </path>

  <target name="run" description="Run tests" depends="compile,copy-resources">
    <echo message="                                 -- Running tests --"/>
    <echo message="                                 -- ${testng.jar} --" />
    <testng classpathref="run.cp"
            outputdir="${testng.report.dir}">
      <xmlfileset dir="${test.resources.dir}" includes="testng.xml"/>
      <jvmarg value="-Dtest.resources.dir=${test.resources.dir}" />
      <jvmarg value="-Dsun.io.serialization.extendedDebugInfo=true" />
    </testng>
  </target>

  <target name="copy-resources" description="Copies resources.">
    <copy verbose="false"
          file="${src.resources.dir}/testngtasks"
          todir="${build.dir}" />
    <copy todir="${build.dir}">
      <fileset dir="${src.resources.dir}">
        <exclude name="**/.*" />
        <exclude name="**/CVS/*" />
      </fileset>
    </copy>
  </target>

  <target name="run:single" description="Run 1 property file named with the ant property test" depends="compile">
      <echo message="                                 -- testng-tests-run1 --"/>

    <testng outputdir="${testng.report.dir}"
        classpathref="run.cp"
        useDefaultListeners="true"
        outputDir="${testng.report.dir}">
      <xmlfileset dir="${test.resources.dir}" includes="testng-single.xml"/>
     </testng>

      <echo>Report created in    open ${testng.report.dir}/index.html</echo>
  </target>

  <target name="run:antprop" description="Run a test to see if ant system propertes are passed correctly" depends="compile">
      <echo message="                                 -- testng-tests-run-antprop --"/>
      <property name="syspropset1" value="value 1"/>
      <property name="syspropset2" value="value 2"/>
      <propertyset id="propset1">
          <propertyref name="syspropset1"/>
          <propertyref name="syspropset2"/>
      </propertyset>

      <testng outputdir="${testng.report.dir}"
              classpathref="run.cp">
          <xmlfileset dir="${test.resources.dir}" includes="testng-single3.xml"/>
          <propertyset refid="propset1"/>
          <sysproperty key="sysprop1" value="value 3"/>
      </testng>
  </target>

  <!-- ==================================================================== -->
  <!-- Run specific configuration                                           -->
  <!-- ==================================================================== -->
  <target name="run:conf"
          if="testng.conf"
          depends="clean:reports,compile"
          description="Run specified tests">
    <echo message="                                 -- testng-tests-run --"/>
    <echo message="using: ${testng.conf}.xml"/>

    <testng classpathref="run.cp"
            outputDir="${testng.report.dir}">
        <xmlfileset dir="${test.resources.dir}" includes="${testng.conf}.xml"/>
    </testng>

    <antcall target="clean.tmp"/>
  </target>


  <!-- ==================================================================== -->
  <!-- Reports                                                              -->
  <!-- ==================================================================== -->

  <target name="reports">
    <junitreport todir="${junit.report.dir}">
      <fileset dir="${testng.report.dir}">
        <include name="*.xml"/>
        <exclude name="testng-failed.xml"/>
        <exclude name="testng-results.xml" />
      </fileset>
      <report format="noframes" todir="${junit.report.dir}"/>
    </junitreport>
  </target>


  <target name="clean.tmp">
      <delete dir="${test.output.dir}"/>
  </target>

  <target name="clean:reports">
      <delete dir="${report.dir}"/>
      <delete dir="${junit.report.dir}"/>
  </target>

  <target name="clean" depends="clean.tmp,clean:reports">
    <echo message="                                 -- test clean --"/>

    <delete dir="${test.build.dir}"/>
  </target>

  <target name="done">
    <echo>Reports can be found in:    open ${testng.report.dir}/index.html</echo>
  </target>

</project>
�����������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/ant/build-ant.xml���������������������������������������������������������������0000644�0001750�0001750�00000005463�12551235562�017044� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<project name="testng" default="all" basedir=".">

  <property file="build.properties"/>
  <property name="this.directory" value="${test.dir}" />
  <property name="test-output" value="${this.directory}/test-output" />

  <taskdef name="testng" classname="org.testng.TestNGAntTask" classpath="${testng.jar}" />

  <target name="all">
    <echo>This dir: ${this.directory}</echo>
    <delete failonerror="false" dir="${this.directory}/build" />
  	<mkdir dir="${this.directory}/build" />
  	
  	<javac classpath="${testng.jar}"
  		  destdir="${this.directory}/build" srcdir="${this.directory}" includes="test/ant/*.java" />

<!--
    <testng classpath="build;../../testng-5.2beta-jdk15.jar"
            outputdir="test-output"
    	      dumpcommand="true">
        <xmlfileset dir="." includes="testng.xml"/>
    </testng>
-->
	<delete failonerror="false">
	<fileset dir="${test-output}" includes="**"/></delete>
  	
    <testng classpath="${this.directory}/build;${testng.jar}"
            outputdir="${test-output}"
  	    parallel="methods"
  	    threadcount="5"
    	listeners = "org.testng.reporters.FailedReporter, org.testng.reporters.DotTestListener"
    	haltonfailure="true"
    	>
        <classfileset dir="${this.directory}/build">
        	<include name="test/ant/NoPackageTest.class" />
        	<include name="test/ant/MultipleThreadTest.class" />
        </classfileset>
    </testng>
  	
  	<available file="${test-output}/Ant suite/Ant test.xml" 
  		type="file" property="test.exists"/>
  	<fail unless="test.exists" 
  		message="The appropriately named output should have been created"/>
  	
    <testng classpath="${this.directory}/build;${testng.jar}"
            outputdir="${test-output}"
	   	listeners = "org.testng.reporters.FailedReporter, org.testng.reporters.DotTestListener"
    	haltonfailure="true"
    	suitename="Test Ant Suite"
    	testname="Test Ant Test"
    	>
        <classfileset dir="${this.directory}/build">
        	<include name="test/ant/DontOverrideSuiteNameTest.class" />
         </classfileset>
    </testng>
  	
  	<available file="${test-output}/Test Ant Suite/Test Ant Test.xml" 
  		type="file" property="test2.exists"/>
  	<fail unless="test2.exists" message="The appropriately named output should have been created"/>
  	
  	<!-- Ensure standard tests get run -->
    <testng classpath="${this.directory}/build;${testng.jar}"
            outputdir="${test-output}"
    	listeners = "org.testng.reporters.FailedReporter, org.testng.reporters.DotTestListener"
    	haltonfailure="true"
    	>
        <xmlfileset file="${test.resources.dir}/testng-ant.xml"/>
    </testng>
  	<available file="${test-output}/Suitename from xml/TestName.xml" 
  		type="file" property="test3.exists"/>
  	<fail unless="test3.exists" message="The appropriately named output should have been created"/>

  </target>
</project>
�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/ant/README.template�������������������������������������������������������������0000644�0001750�0001750�00000000731�12551235562�017126� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[![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,
you will not be able to build the software with them because we decided
not to include the external jar files in order to keep the size down.

If you want to build TestNG, please sync to the GitHub repository at https://github.com/cbeust/testng.

--
The TestNG team
���������������������������������������testng-testng-6.9.5/TODO.txt������������������������������������������������������������������������0000644�0001750�0001750�00000016345�12551235562�015170� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������                                       TODO for TestNG

* Pass the XmlTest in @Before/@After methods
* Allow a testng.xml file to be passed when -testjar is used
* Add onStart to IConfigurationListener (create a new interface, actually)
* Add timeout to @Before/@After
* Pass parameters from ant
* Make it possible to specify groups on command line and classes in testng.xml
(and any combinations thereof:  command line, ant, testng.xml)
* DataProvider index in testng.xml
* Create a servlet for remote driving
* Add time-outs at the testng.xml.  Also:  test and suite time-outs? http://tinyurl.com/kbwxq
* Add working dir to the ant task
* Add a servlet so TestNG can be invoked from a web browser
* Make it possible to add listeners from the Eclipse plug-in

Doc:

* Document the fact that @Test methods with return values are ignored.

===========================================================================
Older TODO's:

* Show enabled=false methods in the reports, as well as methods
in groups that were not run
* Multi-threading for invocationCount and maybe for <test> too
* Annotation to specify that a method should be called concurrently by n threads 
(on second thought, we should do that for an entire group)
* more thread ideas: http://www.theserverside.com/news/thread.tss?thread_id=38922
* package support for command line and ant
* Parameters for classes (to be passed as parameters to constructors)
* testng-dist.zip should contain a top-level directory
* For dependent methods, if the user is trying to run an incomplete graph
(A depends on B but B is being excluded from the run), what to do?  Ignore
the exclusion on B and run it anyway, or abort with an exception explaining
what's happening?)
* Make timeOut() work with milliseconds (but keep seconds for backward
compatibility)
* Improve the plug-in API so people can add listeners without having to
modify TestRunner
* Use factories for the programmatic API.
* Add dynamic generation of tests
* Make Javadoc comments over methods appear in the final report

Documentation:
* IHookable
* List<IReporter>


DONE

* Retry patch
* If a method with invocationCount fails, don't run the others
* Allow multiple listeners in ant task
* Add working dir to the ant task
* Introduce "test" and "suite" parameters to @Test at the class level to
avoid having to use testng.xml
* Remove TestNG stack traces from the report
* When 0 tests were run, exit with an error http://tinyurl.com/ftng6
* Show all the extra output for all methods in a single 
dedicated page
* report API
* Show parameters used to invoke a specific test
* show skipped groups/methods in HTML report
* beforeTestGroups
* <testng classfileset> doesn't add to classpath
* threadPoolSize
* Parameter logging
* JavaDoc for org.testng.TestNG
* org.testng.Reporter in the HTML report (screenshot ready)
* Document @Parameters only works for @Test (should mention @Factory and @Configuration)
* Document: <testng classfileset> doesn't add to classpath
* Document org.testng.Reporter in the HTML report (screenshot ready)
* Document parameter logging
* JavaDoc for org.testng.TestNG
* Document threadPoolSize
* Make sure it can run several times in the same JVM
* Implement invocationCount and successPercentage
* Support multiple testng.xml (TestNG allows it but not the reporters
yet)
* The HTML reporter collapses all the suites into one report, we should
create one HTML report per suite
* testng-failed.xml should contain the parameters of testng.xml (if any)
* Create a testng-failed.xml that includes dependent methods
* Generic reported with compare(ITestResult, ITestResult) for
easier reporter for "slowest method first" or generate testng-failed.xml
* Iterator factories
* configuration methods don't respect inheritance
- build.xml should issue a clear error message if trying to build with JDK1.4
- Implement <tasdkdef resource="testnganttasks"> so we can define
ant tasks for TestNG and JUnitConverter automatically
- Write documentation to declare ant task in section 3.2.8
- Documentation for alwaysRun
- Allow to specify packages or prefix in the <classes> tag:
   <classes prefix="com.beust.testng"><class name="A"><class name="B"> />
- New assert classes
- New ways to launch 
- JUnitConverter documentation
- new beforeSuite/afterSuite

* in testng-failures.xml include the beforeSuite/afterSuite methods (very tricky)
* Provide log.properties configuration (not using log any more)
* Make @ExpectedExceptions fail if no exception is thrown
* Make timeOut() work in non-parallel mode (the default mode needs to become
parallel=true thread-count=1
* The exception thrown when a test passes with a @ExpectedExceptions is not 
available via the TestNG API: ITestResult.getThrowable().
* Add assert API for arrays and collections (undecided yet:  partial asserting)
* dependsOnMethods
Allow to specify <groups> at the <suite> level
Make TestNG run on class files and not just on testng.xml
Make TestNG run on a jar file that has a testng.xml file in its root or just on all
  the classes inside that jar file.

Implement parameter passing of tests:  define a property in the properties
file and pass it to the test method:

@Test(params = { "${fn}", "${ln}" }
public void testNames(String firstName, String lastName) {
}

Run groups of groups
List all tests that will be run, or show methods per group
HTML generation
Make test and class methods discoverable
  JUnit adapter
Multiple ExpectedException
Inheritance
Test listeners
Group regexps for launching

====

A new comment has been posted on your blog Otaku, Cedric's weblog, on entry
#149 (The poor shape of Unit Testing).
http://beust.com/weblog/archives/000149.html

IP Address: 68.72.49.189
Name: Curt Cox
Email Address: curtcox@gmail.com
URL: 

Comments:

For whatever its worth, here are my problems with JUnit.  I've largely developed work-arounds.

1. Interface-based testing is awkward.
2. Only fast-fail tests are supported.
3. The design is brittle, poorly documented, and thus hard to extend.

How should interface-based testing be handled in TestNG?  A nice feature would be bundled tests for interfaces in the java* namespace that are automatically applied.  In other words:
- all classes will fail a (supressible) test if they violate the contract for equals() and hashCode()
- classes that implement Comparable will fail a test if they fail to implement Comparable
- and likewise for java.io.Serializable, java.util.Map, java.util.List, etc...

When I say all tests are fast-fail in JUnit, what I mean is that the first failed assertion in a method causes the test to exit.  While this is usually desirable, a more conversational style of tests can sometimes be much easier to read and write.  Such a conversational test doesn't generate a simple failure, but rather a score.  The score could be either x of y passed or x percent passed.  The important part is that the first failure doesn't terminate the test.

As I said, I've largely developed work-arounds for doing these in JUnit, but developing tools for conversational tests that play nice with the various JUnit runners was a real challenge.  The exact contract that Eclipse expects of JUnit tests turns out to be different than what either of the bundled runners or the Ant task expect.  Anyone who considers either the JUnit code or interfaces well-documented has a much different concept of well-documented than I do.


�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/TESTNG-5.11beta�����������������������������������������������������������������0000644�0001750�0001750�00000000000�12551235562�016004� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/README.md�����������������������������������������������������������������������0000644�0001750�0001750�00000002076�12551235562�015135� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[![Build Status](http://img.shields.io/travis/cbeust/testng.svg)](https://travis-ci.org/cbeust/testng)
[![Java9 EA Build Status](https://img.shields.io/jenkins/s/https/adopt-openjdk.ci.cloudbees.com/TestNG.svg?label="Java9 EA build")](https://adopt-openjdk.ci.cloudbees.com/job/TestNG)
[![AppVeyor](https://ci.appveyor.com/api/projects/status/github/cbeust/testng?svg=true)](https://ci.appveyor.com/project/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).
������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/README.dev����������������������������������������������������������������������0000644�0001750�0001750�00000001662�12551235562�015313� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������New installation:

Install GPG at http://www.gpgtools.org/gpgmail/index.html
Generate new key with gpg --gen-key
build-with-maven
gpg --list-keys
Send the public key:
  gpg --keyserver hkp://pool.sks-keyservers.net --send-keys <public_key>
  or wwwkeys.at.pgp.net


  instructions at https://docs.sonatype.org/display/Repository/How+To+Generate+PGP+Signatures+With+Maven


Configure ~/.m2/settings.xml with Nexus user/password:

  <settings>
    <servers>
      <server>
        <id>sonatype-nexus-snapshots</id>
        <username>***</username>
        <password>***</password>
      </server>
      <server>
        <id>sonatype-nexus-staging</id>
        <username>***</username>
        <password>***</password>
      </server>
    </servers>
  </settings>

Snaphot deploy:
mvn -Dgpg.passphrase= -Dgpg.keyname=<public_key> deploy

Staging deploy:
mvn -Dgpg.passphrase= -Dgpg.keyname=<public_key> release:clean release:prepare release:perform
������������������������������������������������������������������������������testng-testng-6.9.5/README.build��������������������������������������������������������������������0000644�0001750�0001750�00000000355�12551235562�015632� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������You need to install ivy in order to build.

You can either download it from the ivy site or more simply,
copy ivy-2.1.0.jar included in the root directory to ~/.ant/lib.

After this, "ant" will build the distribution and run the tests.

�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/README-publish������������������������������������������������������������������0000644�0001750�0001750�00000001215�12551235562�016174� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������To publish:

- ./gradlew bintrayUpload will upload the release to JCenter. It will fail if the version is a SNAPSHOT
- ./gradlew uploadArchives will upload the snapshot to https://oss.sonatype.org/content/repositories/snapshots and the release to https://oss.sonatype.org/service/local/staging/deploy/maven2. For a release, you then need to go to https://oss.sonatype.org/index.html#stagingRepositories to manually close and release the distribution.

Note that `./gradlew uploadArchives` is run by Travis after each new push to deploy the latest HEAD to the snapshot directory. As such, the version number of `build.gradle` should always be -SNAPSHOT.
�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/README��������������������������������������������������������������������������0000644�0001750�0001750�00000000726�12551235562�014536� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[![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,
you will not be able to build the software with them because we decided
not to include the external jar files in order to keep the size down.

If you want to build TestNG, please sync to the GitHub repository at https://github.com/cbeust/testng.

--
The TestNG team
������������������������������������������testng-testng-6.9.5/NOTES���������������������������������������������������������������������������0000644�0001750�0001750�00000004233�12551235562�014466� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������=====
Maven
=====

If you ran the full dist build, it should have generated a file on your hard drive called
"testng-5.12-bundle.jar".

Testing:

-> Update <version>5.12</version> in bundle-pom.xml to the correct version
  mvn install:install-file -DpomFile=bundle-pom.xml -Dfile=testng-5.12.1.jar
  cd /tmp
  svn co http://svn.apache.org/repos/asf/maven/surefire/trunk/surefire-integration-tests/src/test/resources/testng-simple/
  cd testng-simple
-> Update <testNgVersion> in pom.xml to the correct version
-> Remove <classifier> in pom.xml if it's still there
  mvn -DtestNgVersion=5.12.1 -Dsurefire.version=2.5 clean test
-> Send bundle to Brett Porter <brett.porter@gmail.com>

=======
Eclipse
=======

I ended up doing the launch configuration, and just for information, here are the parameters:

Run Configuration / Eclipse application.

Check "Run an application" in "Program to run", and select org.eclipse.equinox.p2.metadata.generator.EclipseGenerator

The program arguments are (replace the update site directory appropriately):

Linux:
-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl}    -application org.eclipse.equinox.p2.metadata.generator.EclipseGenerator -updateSite /usr/local/cbeust/java/testng-eclipse-update-site -site file:/usr/local/cbeust/java/testng-eclipse-update-site/site.xml  -metadataRepository file:/usr/local/cbeust/java/testng-eclipse-update-site/  -artifactRepository file:/usr/local/cbeust/java/testng-eclipse-update-site -artifactRepositoryName "Ganymede Artifacts" -compress  -append  -reusePack200Files  -noDefaultIUs  -vmargs -Xmx256m

Mac
-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl}    -application org.eclipse.equinox.p2.metadata.generator.EclipseGenerator -updateSite /Users/cbeust/java/testng-eclipse-update-site -site file:/Users/cbeust/java/testng-eclipse-update-site/site.xml  -metadataRepository file:/Users/cbeust/java/testng-eclipse-update-site/  -artifactRepository file:/Users/cbeust/java/testng-eclipse-update-site -artifactRepositoryName "Ganymede Artifacts" -compress  -append  -reusePack200Files  -noDefaultIUs  -vmargs -Xmx256m

This will generate the site in ~/java/testng-eclipse-update-site
���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/LICENSE.txt���������������������������������������������������������������������0000644�0001750�0001750�00000026135�12551235562�015503� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/FILES���������������������������������������������������������������������������0000644�0001750�0001750�00000000300�12551235562�014427� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������build.properties
build.xml
lib/DTDDoc.jar
examples/build.xml
examples/testng.properties
examples/testng.xml
examples/src/
maven-testng-plugin-1.1.jar
CHANGES.txt
LICENSE.txt
README
��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/CHECKLIST�����������������������������������������������������������������������0000644�0001750�0001750�00000000210�12551235562�015076� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Check list for releases:

pom.xml
pom-test.xml
Version.java
build.properties

doc/index.html
doc/documentation-main.html
doc/maven.html
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/CHANGES.txt���������������������������������������������������������������������0000644�0001750�0001750�00000166303�12551235562�015473� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Current

6.9.5

Fixed: The ServiceLoaderTest on Windows (Mathieu Sebire)
Fixed: GITHUB-691: Fix classloading issue when using TestNG 6.9.4 and JMockit. (Mathieu Sebire)
Fixed: GITHUB-686: IAnnotationTransformer.transform is called for methods with testClass populated. (Łukasz Rekucki & Julien Herr)
Fixed: GITHUB-420: Before/AfterSuite methods may not run, when use inheritance, and enabled=false (Jakub Tokaj & Julien Herr)
Fixed: GITHUB-697: Make addFailedInvocationNumber thread-safe (Ryan Schmitt)
Fixed: GITHUB-698: Fix exit code reporting when IRetryAnalyzer is used (Ryan Schmitt)
Fixed: GITHUB-465: assertEquals(Collection, Collection) prints "null" when collections are different sizes (Michael Diamond)
New: GITHUB-710: AppVeyor is used for continuous integration on Windows (Julien Herr)
Fixed: GITHUB-599: IHookable ignored when a timeout is set (@ryanlevell & Julien Herr)
New: GITHUB-723: Allow users to add their own suite parser (Julien Herr)
Fixed: Allow '-testnames' option to work with '-xmlpathinjar' (@earthling)
Fixed: GITHUB-739: TestNG skips all test classes from suite when a @BeforeClass fails (Priyanshu Shekhar & Julien Herr)
Fixed: GITHUB-471: If @beforeMethod or @afterMethod fails then all children of the same base class will be skipped (Anton Panferov & Julien Herr)
Fixed: GITHUB-595: testng hang at switching test cases when running test cases with high thread count (vit0rg)

Eclipse:

Fixed: The 57% freeze bug (Patrick Hensley and @denyska)

6.9.4:
2015/05/09

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)
New: GITHUB-663: Add Guice Stage configuration for a suite (Clément Guillaume)

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
Fixed: XmlTest#setGroupInstances was not being shown in toXml().
Fixed: GITHUB-376: Some results can be lost (Konstantin Savin).
Fixed: Handle relative paths of Suite XML files properly (Nalin Makar)

6.8.5:
2013/05/13

Fixed: the OutOfMemoryException in reports
Fixed: Surefire + listeners "Can't load class" problem

===========================================================================
6.8.1
2013/03/30

Added: Descriptions in the HTML reports
Added: Various improvements to EmailableReporter (Abraham Lin)
Added: Allow injection of java.lang.reflect.Constructor and org.testng.ITestNGMethod into DataProvide (Vladislav Rassokhin)
Fixed: Assertions in the Assertions class were not failing properly.
Fixed: GITHUB-337: ConfigurationMethod#m_instance set to Boolean.FALSE due to incorrect constructor call in clone() + auto-boxing (davidely)
Fixed: Fix NPE for dependency methods/groups (Krishnan Mahadevan)
Fixed: preserve-order bug (found by VladSarrokhin). 
Fixed: GITHUB-300: OutOfMemoryException from reporters when there are a lot of tests
Fixed: GITHUB-137: Main parameters with a default value should be overridden if a main parameter is specified 
Fixed: GITHUB-107: Allow enum values without converting them to uppercase.
Fixed: @Guice with no modules specified is now supported
Fixed: Reporter.log() invoked from listeners were being discarded

Eclipse:
Added: Predefined listeners (Tim Wu)
Fixed: Compare dialog

===========================================================================
6.7
2012/07/15

Added: Big performance improvement when generating the reports (Frank Pavageau)
Added: <dependencies> allows you to specify group dependencies in testng.xml
Added: Blow up early if trying to include/exclude an unknown method
Added: <parameters> can now be specified under <include> (Storm Qi)
Added: GITHUB-243: Add Reporter Output per Test in XMLReporter (dunse) 
Fixed: Better HTML escaping of the stack traces
Fixed: The failed assertions now use [] as delimiters instead of <> (better for the HTML reports)
Fixed: GITHUB-237: Wrong time format in XML reporter
Fixed: Threads were started sequentially instead of being interleaved
Fixed: dataProvider(parallel = true) was not killing its threads properly
Fixed: XmlSuite#toXml wasn't outputting the <groups> tag correctly
Fixed: testng-failed.xml was not carrying over the parameters from the original testng.xml
Fixed: BeforeClass failing in parent failed to skip methods in sub classes
Fixed: Better error message if <suite name=""> is missing
Fixed: GITHUB-221: Honor excludeGroups on testng tests when run in mixed mode (criccio)
Fixed: dependsOnGroups = {regexp} wasn't working properly (Alistair Ward)
Fixed: GITHUB-205: white-space was spelled whitespace in testng.css (carlin-scott)

Eclipse:
Fixed: Environment is not transferred when rerunning failed tests.
Fixed: Rerunning failed tests will preserve the environment of the original launch

===========================================================================

6.5.1
04/10/2012

Added: <suite allow-return-values="true"> (and in <test> as well)
Added: data-provider attribute to testng-results.xml
Added: Reporter display the results in the same order as test methods (Libor Zoubek)
Added: Support for running JUnit 4 tests (Lukas Jungmann)
Added: Ability to auto-detect JUnit tests ('-mixed' mode) (Lukas Jungmann)
Added: Support for ResourceCollections in an Ant tasks (requires Ant >= 1.7.0) (Lukas Jungmann)
Fixed: GITHUB-198: JUnitReportsReporter use commas in certain locales, which JUnitReports doesn't like
Fixed: GITHUB-173: Dependent methods executed out-of-order if method names match across classes (jjedMoriAnktah)
Fixed: ThreadLocal<ITestResult> leak (aslakknutsen)
Fixed: In the HTML reports, only show the first 100 characters of the parameters
Fixed: SkippedException are considered as real exception with @Test(expectedExceptions)

Eclipse:
Fixed: Java constants are properly resolved if they are used as group names (susanin)
Fixed: @Test(groups = Foo.CONSTANT) (susanin)
Fixed: Failed tests with allow-return-values="true" were not rerun
Added: <suite allow-return-values="true"> (and in <test> as well)

===========================================================================

6.4:
02/15/2012

Added: @DataProvider(indices) to return specific indices of a data provider
Added: New HTML reports
Added: configfailurepolicy=continue with DataProviders (toddq)
Added: ITestResult#getTestContext (bpedman)
Fixed: invocationCount > 1 + timeOut wasn't timing out properly
Fixed: When running TestNG programmatically, child xml suites are not run (when added using setSuiteFIles()) (Gaurav Gupta)
Fixed: GITHUB-145: Excessive test method execution (githubCast)
Fixed: GITHUB-149: reversed arguments in failAssertEqualsNoOrder().
Fixed: EmailableReporter: methods are now *really* sorted chronologically.

Eclipse:

Added: You can now add the testng.jar sources as a library (Nick Tan)
Added: Upgraded the plug-in to 3.4+ (Nick Tan)
Added: dependsOnGroups now fully supported
Fixed: @Parameters now works with both ("foo") and ({"foo"}) (davekerber)

===========================================================================
6.3.1
10/22/2011

Added: New system property: dataproviderthreadcount (Bill Ross)
Fixed: Configuration methods were reported incorrectly in listeners.
Fixed: Was creating too many listeners (Jacek Pulut)
Fixed: IAnnotationTransformer2 beforeTest/afterTest booleans were not being set
Fixed: GITHUB-92: @BeforeTest method in a super class will be called multiple time when alwayRun = true (Bubuntux)
Fixed: GITHUB-111: @AfterClass on base classes run once too many (lrivera)
Fixed: GITHUB-107: Displaying 0 tests run if a listener modifies the parameters of the suite

===========================================================================
6.3
10/17/2011

Added: "description" attribute on <include>, made available on ITestNGMethod#getDescription
Added: RemoteTestNG waits infinitely for a connection (Aleksey Kabanov)
Fixed: A method that's both a test and a factory would not invoke its data provider
Fixed: @AfterClass was not called if one of the methods was not enabled (Aleksey Kabanov)
Fixed: Groovy access bug
Fixed: The XML parser doesn't recognize parallel="instances"
Fixed: NPE when using inner classes
Fixed: GITHUB-90: @AfterClass not being run when the class contains included and not included methods
Fixed: @AfterClass not being run in some subclassing situations

Eclipse:

Fixed: Verbose levels specified in suites not respected
Fixed: Variable substitution in VM arguments is not working properly (svenhoff)

===========================================================================

6.2
08/18/2011

Added: xmlpathinjar to the TestNG ant task
Added: TestNG can now invoke package protected constructors
Added: Injectors created by the @Guice annotation are now shared at the <test> level
Added: IConfigurationListener is now a public listener, along with a new one: IConfigurationListener2
Added: When a method fails, only dependents of the same instance will be skipped
Added: parallel=instances for factory instance parallel runs
Added: @Factory(enabled)
Fixed: JUnitReports reports now report the cumulated time @{Before,After}Method+@Test for each test method
Fixed: JUnitReports reports have the name of the <test> instead of that of the first class
Fixed: Using preserve-order with a factory that creates instances of a different class causes NPE
Fixed: GITHUB-74: Bad ordering of test methods when using a @Factory constructor with dataProvider
Fixed: Changing the test result from success to failure in a listener would still count the test as a success
Fixed: ServiceLoader wasn't resolving correctly if no service loader classloader was specified
Fixed: Better ordering with mixed priorities and dependencies
Fixed: Improved detection of graph cycles in parallel runs
Fixed: @BeforeTest was invoked multiple times if a factory is used
Fixed: GITHUB-57: Allow usage of package protected constructor of test classes
Fixed: Injecting both Object[] and Method in @BeforeMethod didn't always work
Fixed: testng-results.xml now lists the results chronologically
Fixed: @Listeners specified on a base class will only be run once per listener class (dbriones)
Fixed: -groups and -excludegroups were no longer overriding testng.xml

Eclipse:

Added: Each data provider method now has a separate node entry in the TestNG view
Fixed: Nodes in error would sometimes remain green
Fixed: The TestNG context menu no longer appears where it shouldn't

===========================================================================

6.1.1
7/5/2011

Fixed: https://github.com/cbeust/testng/issues/56 testng-results.xml was reporting the instance name instead of the method name
Fixed: NPE when using preserve-order and factories.
Fixed: Depending on a skipped method would not cause a method to be skipped

===========================================================================

6.1
6/30/2011

Possible backward incompatible changes:

- Don't mutate the value returned by XmlTest#getIncludedGroups and XmlTest#getExcludedGroups.
Instead, use addIncludedGroup/addExcludedGroup.
- Failing methods that have dependees will only cause skips in the same instance. Different
test instances will not be affected

Added: Support for ServiceLoader for ITestNGListener
Added: @Factory(dataProvider / dataProviderClass) on constructors
Added: assertNotEquals() to Assert
Added: assertArrayEquals() to AssertJUnit
Added: Nested classes are now automatically added for consideration for inclusion
Added: <suite preserve-order="true"> will cause this attribute to be propagated to all <test> tags
Added: <groups> can now be specified under a <suite>
Added: Tycho compatibility (Aleksander Pohl)
Added: New <test> and <suite> flag: group-by-instances
Added: -xmlpathinjar to specify the path of testng.xml inside a test jar file
Added: ISuite#getAllMethods, to retrieve all the methods at the start of a suite.
Added: Output ITestResult attributes in xml report (nguillaumin)
Fixed: Thread safety problem in MethodInvocationHelper (Baron Roberts)
Fixed: Group dependencies were not being skipped properly.
Fixed: Dependency failures only impact the same instance
Fixed: Static classes could cause a StackOverFlowError
Fixed: IConfigurationListener was not extending ITestNGListener
Fixed: IConfigurationListener#onConfigurationFailure was never called
Fixed: TESTNG-476: <test> tags are now run in the order found in testng.xml
Fixed: Now showing failed/skipped error messages on the console for verbose >= 2
Fixed: ITestResult#getEndMillis() return 0
Fixed: TESTNG-410: Clearer error message
Fixed: TESTNG-475: @DataProvider doesn't support varargs
Fixed: Performance problems in EmailableReporter
Fixed: TESTNG-472: Better output for assertNull()
Fixed: ConcurrentModificationException when using parallel data providers.
Fixed: TESTNG-282: Problem when including+excluding packages (addicted)
Fixed: TESTNG-471: assertEquals(Map, Map) fails if a map is a subset of the other
Fixed: JUnitReporter generates an <error> tag for successful expectedExceptions tests
Fixed: ISSUE-47: Don't allow two <test>s with same name within same suite (Nalin Makar)
Fixed: If a listener implements both ISuiteListener and IInvokedMethodListener, only one of them gets invoked

Eclipse:

Added: New quick fix "Add static import org.testng.AssertJUnit.assertXXX"
Added: New workspace wide setting: excluded stack traces, to provide shorter stack traces in the view
Added: New "Clear results" icon in the tool bar
Added: When the search filter is modified, don't update the tree live if it is too big 
Added: Two new @Test refactorings (pull to class level, push to method level)
Added: JUnit conversion: @Ignore
Added: JUnit conversion: assertArrayEquals()
Added: JUnit conversion: @RunWith(Parameterized.class)
Added: Support for Hamcrest failed assertions in the compare dialog
Added: JUnit conversion: suite() methods can now either be removed, commented out or left untouched
Fixed: JUnit conversion: super.setUp()/tearDown() were being removed when extending a class other than TestCase
Fixed: "Run as" menu not appearing for methods that take a generic parameter.
Fixed: The tree was incorrect if the same class is used in different <test> tags
Fixed: When creating a new Run/Debug configuration, "Launch.label" was displayed
Fixed: TESTNG-459: TestNG menu should not always be present in context menu (Mykola Nikishov)
Fixed: Performance problems in the plug-in
Fixed: Workspace-wide XML template files are not being honored.
Fixed: @BeforeClass/@AfterClass from JUnit4 are not being properly converted
Fixed: Conversions generate @Test() instead of @Test

===========================================================================

6.0
2011/03/16

Added: @Guice(moduleFactory) and IModuleFactory
Added: @Guice(module)
Added: timeOut for configuration methods
Added: -randomizesuites (Nalin Makar)
Added: IConfigurable
Fixed: @Test(priority) was not being honored in parallel mode
Fixed: @Test(timeOut) was causing threadPoolSize to be ignored
Fixed: TESTNG-468: Listeners defined in suite XML file are ignored (Michael Benz)
Fixed: TESTNG-465: Guice modules are bound individually to an injector meaning that multiple modules can't be effectively used (Danny Thomas)
Fixed: Method selectors from suites were not properly initialized (toddq)
Fixed: Throw an error when two data providers have the same name
Fixed: Better handling of classes that don't have any TestNG annotations
Fixed: XmlTest#toXml wasn't displaying the thread-count attribute
Fixed: TESTNG-438: Regression in 5.14.1: JUnit Test Execution no longer working
Fixed: TESTNG-436: Deep Map comparison for assertEquals() (Nikolay Metchev)
Fixed: Skipped tests were not always counted.
Fixed: test listeners that throw were not reporting correctly (ansgarkonermann)
Fixed: <suite junit="true"> wasn't working.
Fixed: In parallel "methods" mode, method interceptors that remove methods would cause a lock up
Fixed: EmailableReporter now sorts methods chronologically
Fixed: TESTNG-411: Throw exception on mismatch of parameter values (via DP and/or Inject) and test parameters
Fixed: IDEA-59073: exceptions that don't match don't have stack trace printed in console (Anna Kozlova)
Fixed: IDEA's plug-in was not honoring ITest (fixed in TestResultMessage)
Fixed: Methods depending on a group they belong were skipped instead of throwing a cycle exception
Fixed: TESTNG-401: ClassCastException when using a listener from Maven
Fixed: TESTNG-186: Rename IWorkerApadter to IWorkerAdapter (Tomas Pollak)
Fixed: TESTNG-415: Assert.assertEquals() for sets and maps fails with 'null' as arguments
Fixed: typo -testRunFactory
Fixed: NPE while printing results for an empty suite (Nalin Makar)
Fixed: Invoke IInvokedMethodListener.afterInvocation after fixing results for tests expecting exceptions (Nalin Makar)
Fixed: TESTNG-441: NPE in SuiteHTMLReporter#generateMethodsChronologically caused by a race condition (Slawomir Ginter)

Eclipse:
Added: Convert to YAML
Added: New global preference: JVM args
Added: Eclipse can now monitor a test-output/ directory and update the view when a new result is created
Added: Right clicking on a class/package/project now offers a menu "TestNG/Convert to TestNG"
Added: Excluded methods are now listed in the Summary tab
Added: "Description" column in the excluded methods table
Added: Dialog box when the plug-in can't contact RemoteTestNG
Added: Double clicking on an excluded method in the Summary tab will take you to its definition
Added: If you select a package before invoking the "New TestNG class" wizard, the source and package text boxes will be auto-filled
Added: When an item is selected in a tab, the same item will be selected when switching tabs
Added: A new "Summary" tab that allows the user to see a summary of the tests, sort them by time, name, etc...
Added: It's now possible "Run/Debug As" with a right click from pretty much any element that makes sense in the tree.
Added: JUnit conversion: correctly replaces assertNull and assertNotNull
Added: JUnit conversion: removes super.setUp() and super.tearDown()
Added: JUnit conversion: removes @Override
Added: JUnit conversion: replaces @Test(timeout) with @Test(timeOut) (5.14.2.4)
Added: JUnit conversion: replaces @Test(expected) with @Test(expectedExceptions) (5.14.2.4)
Added: JUnit conversion: replaces fail() with AssertJUnit.fail() (5.14.2.2)
Added: JUnit conversion: replaces Assert with AssertJUnit (5.14.2.1)
Added: The progress bar is now orange if the suite contained skipped tests and no failures
Added: Skipped test and suite icons are now orange (previously: blue)
Added: New method shortcuts: "Alt+Shift+X N", "Alt+Shift+D N" (Sven Johansson)
Added: "Create TestNG class" context menu
Added: When generating a new class, handle overridden methods by generating mangled test method names
Fixed: Green nodes could override red parent nodes back to green
Fixed: Was trying to load the classes found in the XML template file
Fixed: Stack traces of skipped tests were not showing in the Exception view
Fixed: XML files should be run in place and not copied.
Fixed: NPE when you select a passed test and click on the Compare Result icon (Mohamed Mansour)
Fixed: When the run is over, the plug-in will no longer force the focus back to the Console view
Fixed: The counter in the progress bar sometimes went over the total number of test methods (5.14.2.9)
Fixed: org.eclipse.ui.internal.ErrorViewPart cannot be cast to org.testng.eclipse.ui.TestRunnerViewPart (5.14.2.9)
Fixed: Workspace preferences now offer the "XML template" option as well as the project specific preferences (Asiel Brumfield)
Fixed: TESTNG-418: Only last suite-file in testng.xml run by Eclipse plugin

Documentation:
Added: Section on Selenium (Felipe Knorr Kuhn)
Added: Link to an article on TestNG, Mockito and Emma in the Misc section

===========================================================================

5.14.7
2011/01/27

Release for IDEA

===========================================================================

5.14.1
2010/10/2

Fixed: TESTNG-401: ClassCastException when using a listener from Maven

===========================================================================

5.14
2010/08/28

Added: test suites can now be run in parallel with -suitethreadpoolsize
Fixed: @Listeners now aggregate through base classes
Fixed: ISuite was no longer serializable
Fixed: Injection was sometimes not working properly when used with @Parameters
Fixed: TESTNG-400: afterMethod was called after onTestFailure()
Fixed: "excludedgroups" was not working on the ant task because of a typo
Fixed: ant task error if <classfileset> is used with no classes (welex91)
Fixed: TESTNG-404: threaded tests fail due to use of non-threadsafe collections (Marcus Better)
Fixed: preserve-order was not preserving class order with dependent methods
Fixed: RetryAnalyzer wasn't working properly with factories
Fixed: The ant task was no longer supporting ',' for testclass

Eclipse:

Fixed: The plug-in wasn't running Groovy tests correctly (Andrew Eisenberg)
Fixed: TESTNG-402 [Eclipse Plug-In] NPE occurred when I run twice a custom "Run configuration" on a group

===========================================================================

5.13.1
2010/08/05

Added: -methods
Added: -configfailurepolicy (Todd Quessenberry)
Added: -methodselectors (Todd Quessenberry)
Added: @NoInjection
Added: <test preserve-order="true">
Added: -testnames (command line) and testnames (ant)
Added: New ant task tag:  propertyset (Todd Wells)
Added: ITestNGListenerFactory
Added: Passing command line properties via the ant task and doc update (Todd Wells)
Added: Hierarchical XmlSuites (Nalin Makar) 
Added: Reporter#clear()
Fixed: NullPointerException when a suite produces no results (Cefn Hoile)
Fixed: Identical configuration methods were not always invoked in the correct order in superclasses (Nalin Makar) 
Fixed: @DataProvider(parallel = true) was passing incorrect parameters with injection
Fixed: Replaced @Test(sequential) with @Test(singleThreaded)
Fixed: If inherited configuration methods had defined deps, they could be invoked in incorrect order (Nalin Makar)
Fixed: Initialize all Suite/Test runners at beginning to catch configuration issues right at start (Nalin Makar)
Fixed: Issue7: Issue86 Incorrect dates reported for configuration methods
Fixed: Issue24: OOM errors in SuiteHTMLReporter (Nalin Makar)
Fixed: Time outs specified in XML were not honored for <suite parallel="tests">
Fixed: <suite> and <test> time outs were hardcoded, they now honor their time-out attribute
Fixed: TestNG was hanging if no test methods were found
Fixed: onTestSuccess() was called after @AfterMethod instead of after the test method (test: test.listener.ListenerTest)
Fixed: XML test results contained skipfailedinvocationCounts instead of skipfailedinvocationcounts
Fixed: Issue4 assertEquals for primitive arrays, Issue34 assertNull javadoc updated
Fixed: Issue78 NPE with non-public class. Now throws TestNG exception
Fixed: NPE with @Optional null parameters (Yves Dessertine)
Fixed: TESTNG-387 TestNG not rerunning test method with the right data set from Data Provider (Francois Reynaud)
Fixed: Show correct number of pass/failed numbers for tests using @DataProvider
Fixed: Return correct method status and exception (if any) in InvokedMethodListener.afterInvocation() 
Fixed: Trivial fixes: TESTNG-241 (log message at Info), Issue2 (throw SAXException and not NPE for invalid testng xml) 
Fixed: Configuration methods couldn't depend on an abstract method (Nalin Makar) 
Fixed: TestNG#setTestClasses was not resetting m_suites
Fixed: Exceptions thrown by IInvokedMethodListeners were not caught (Nalin Makar)
Fixed: @Listeners now works on base classes as well
Fixed: Test priorities were not working properly in non-parallel mode
Fixed: @Listeners wasn't working properly with ITestListener

Eclipse

Fixed: TESTNG-395 New wizard was creating classes called "NewTest"
Fixed: TESTNG-397 Class level @Test was preventing groups from showing up in the launch configuration

Doc
Updated Maven documentation (Brett Porter)

===========================================================================

5.12.1
2010/03/29

Maven update

===========================================================================
5.12

Removed: Javadoc annotation support

Added: @Listeners
Added: IAttributes#getAttributeNames and IAttributes#removeAttribute
Added: testng-results.xml now includes test duration in the <suite> tag (Cosmin Marginean)
Added: Injection now works for data providers
Added: TestNG#setObjectFactory(IObjectFactory)
Added: Priorities: @Test(priority = -1)
Added: New attribute invocation-numbers in <include>
Added: testng-failed.xml only contains the data provider invocations that failed
Added: IInvokedMethodListener2 to have access to ITestContext in listeners (Karthik Krishnan)
Fixed: @Before methods run from factories were not properly interleaved
Fixed: The TextReporter reports skipped tests as PASSED (Ankur Agrawal)

Eclipse:

Added: New file wizard: can now create a class with annotations, including @DataProvider
Added: You can now select multiple XML suites to be run in the launch dialog
Fixed: @Test(groups = <constant>) was taking name of the constant instead of its value.
Fixed: http://jira.codehaus.org/browse/GRECLIPSE-476 NPE with Groovy Tests (Andrew Eisenberg)
Fixed: The custom XML file is now created in the temp directory instead of inside the project
Fixed: In the launch dialog, now display an error if trying to pick groups when no project is selected
Fixed: Was not setting the parallel attribute correctly on the temporary XML file

===========================================================================
5.11
2009/12/08

Added: Dependent methods can now run in their own thread
Added: dataProviderThreadCount can be set from the command line and from ant (Adrian Grealish)
Added: ITestAnnotation#setDataProvider
Added: Assert#assertEquals() methods for Sets and Maps
Fixed: The text reporter was no longer reporting stack traces for verbose >= 2
Fixed: dataProviderClass was not respecting inheritance (like most attributes still)
Fixed: @BeforeSuite/@AfterSuite would run multiple times when used in a @Factory
Fixed: packages=".*" wasn't working properly (sandopolus)
Fixed: TestResult#getName now returns the description instead of the method
Fixed: @DataProvider and dependent methods were not skipping correctly (Francois Reynaud)
Fixed: TESTNG-347 suite with parallel="tests" and test with parallel="classes" doesn't work correctly (Rob Allen)
Fixed: TESTNG-67: @Configuration/@Factory methods in base class being ignored
Fixed: Inner test classes were not excluded properly (Carsten Gubernator)
Fixed: threadPoolSize without invocationCount was causing reporters not to be invoked
Fixed: A @Factory throwing an exception did not cause any error
Fixed: <classfilesetref> was not working properly in the ant task (Ed Randall)
Fixed: @BeforeClass methods were not running in parallel (Aidan Short)
Fixed: Test class with @ObjectFactory doesn't get instantiated via the factory
Fixed: Allow IObjectFactory to load from non-standard classloader (for PowerMock support)

Eclipse 5.11.0.19:
Added: New "parallel" preference setting (Windows / Preferences / TestNG)
Fixed: IIinvokedMethodListeners were not invoked

===========================================================================
5.10

Added: The output in the testng-results.xml is now sorted by the starting timestamp (Daniel Rudman)
Added: Better display of the test name and method description in the default and Emailable report
Added: If both -testjar and an XML file are provided on the command line, the latter will be used
Added: @Before and @After methods can be injected with the current XmlTest
Added: Methods that time out now display the stack trace showing where the time out occurred
Added: ITestResult#getAttribute and ITestResult#setAttribute
Added: @After methods can now be injected with an ITestResult
Added: @BeforeMethod and @AfterMethod methods can now be injected an ITestResult
Added: ISuite#getAttribute and ISuite#setAttribute to share data within a suite
Added: @Test(expectedExceptionsMessageRegExp = ".*foo.*")
Added: @DataProvider(parallel=true)
Fixed: @Test(dataProvider) was not working at the class level
Fixed: Display a better error message if the wrong exception is thrown with an expectedExceptions
Fixed: Classes created by factories were not run in the order they were created
Fixed: Dependent methods are now run closer to methods within their class
Fixed: xmlFileSet in ant was not working correctly (Sean Shou)
Fixed: Various oversights in the DTD (Will McQueen)
Fixed: XMLUtils was not escaping XML attribute values
Fixed: TESTNG-317: Sequence order mis-calculation: testing using suite in sequence for classes and same method names creates non-sequential order
Fixed: Test names (classes that implement org.testng.ITest) now appear more prominently in the HTML reports
Fixed: expectedExceptions=RuntimeException.class was not failing when no exception was throw
Fixed: TESTNG-291: Exceptions thrown by Iterable DataProviders are not caught, no failed test reported (Roberto Tyley)
Fixed: TESTNG-301: Need to include parameters in testNG report for test created by @Factory
Fixed: testng-failed.xml now includes skipped tests
Fixed: TestNG couldn't find Groovy files (Haw-Bin)

Eclipse

Fixed: TESTNG-313: Provide extension point to contribute test and report listeners (Erik Putrycz)
Fixed: Quick fixes no longer introduce deprecated annotations (Greg Turnquist)

===========================================================================
5.9
2009/04/09

Added: New ant task boolean flag: delegateCommandSystemProperties (Justin) 
Added: skipfailedinvocations under <suite> in testng-1.0.dtd (Gael Marziou / Stevo Slavic) 
Added: -testrunfactory on the command line and in the ant task (Vitalyi Pamajonkov)
Added: TESTNG-298: parallel="classes", which allows entire classes to be run in the same thread
Added: @BeforeMethod can now declare Object[] as a parameter, which will be filled by the parameters of the test method
Added: IAnnotationTransformer2
Added: @Test(invocationTimeOut), which lets you set a time out for the total time taken by invocationCount
Added: IInvokedMethodListener
Added: -testjar supports jar file with no testng.xml file
Fixed: IInvokedMethodListener wasn't properly recognized from the command line (Leonardo Rafaeli)
Fixed: TESTNG-309 Illegal default value for attribute in DTD file
Fixed: TESTNG-192: JUnit XML output includes wrong tests (Aleksandar Borojevic)
Fixed: Set a generated suite to default to non-parallel (Mark Derricutt)
Fixed: -testJar command line parsing bug
Fixed: testng-failed.xml didn't include the listeners
Fixed: annotation transformers were not run when specified in testng.xml
Fixed: TESTNG-192: JUnit XML output includes wrong tests (Borojevic)
Fixed: @Parameters was not working correctly on @BeforeMethods with @DataProvider used on @Test methods
Fixed: testng-failed.xml was sometimes incorrectly generated (Borojevic)
Fixed: TestNG-228: Assert.assertEqualsNoOrder
Fixed: TestNG-229: Assert.assertEquals does not behave properly when arguments are sets
Fixed: TESTNG-36: assertEquals(Collection actual, Collection expected, String message) may have bug
Fixed: TESTNG-296: Malformed jar URLs breaking -testJar
Fixed: TESTNG-297: TestNG seemingly never stops running while building failed test suite (Gregg Yost)
Fixed: TESTNG-285: @Test(sequential=true) works incorrectly for classes with inheritance
Fixed: TESTNG-254: XMLSuite toXML() ignores listeners
Fixed: TESTNG-276: Thread safety problem in Reporter class
Fixed: TESTNG-277: Make Reporter.getCurrentTestResult() public
Fixed: Potential NPE in XmlTest#getVerbose (Ryan Morgan)
Fixed: EmailableReporter only displayed the first group for each test method
Fixed: time-outs were not working in <test> and <suite>
Fixed: @BeforeTest failing in a base class would not cause subsequent test methods to be skipped
Fixed: TESTNG-195: @AfterMethod has no way of knowing if the current test failed
Fixed: TESTNG-249: Overridden test methods were shadowing each other if specified with <include>
Fixed: DataProviders from @Factory-created tests were all invoked from the same instance
Fixed: enabled was not working on configuration methods
Fixed: IIinvokedMethodListener was not correctly added in TestNG
Fixed: NPE in XmlSuite#toXml
Fixed: TESTNG-231: NullPointerException thrown converting a suite to XML (Mark)

Doc:
Added: 5.20: IInvokedMethodListener
Added: -testjar

===========================================================================
5.8

Fixed: TestNG-220: Ignore class definition/loader issues when scanning classpath for implicit classes
Fixed: TestNG-224: Fix for relative suite filenames in XML file
Added: TestNG-213: @Optional on a method parameter to allow optional @Parameters
Fixed: TestNG-214: SkipException and TimeBombSkipException should accept nested exceptions
Fixed: TestNG-211: new Parser(inputStream) doesn't work
Added: Methods that form a cycle are now shown when the cycle is detected
Added: Support for <listeners> in testng.xml
Added: IMethodInterceptor
Added: @TestInstance on a data provider method parameter
Fixed: @AfterMethod(lastTimeOnly) didn't work properly with data providers
Added: antlib.xml to allow autodiscovery of Ant task definition
Fixed: name attribute on <test> is required

Doc:
Added: Method Interceptor
Added: @Optional
Added: Doc for IMethodInterceptor (5.16) and TestNG listeners (5.18)
Added: 5.19: Dependency injection

===========================================================================
5.7

Added: @BeforeMethod(firstTimeOnly) and @AfterMethod(lastTimeOnly)
Added: @BeforeMethods can now take a Method and ITestContext parameters (like @DataProvider)
Fixed: logging about abstract classes moved to level 5
Added: if @Parameter is missing from testng.xml then it is read from the System properties
Fixed: Don't run a @DataProvider method as a test when a class-level @Test is present
Added: Attribute @Test#skipFailedInvocations
Fixed: TESTNG-169 Error message: <method> is depending on nonexistent method null ("null" is uninformative)
Fixed: -listener takes comma-separated classes
Added: RetryAnalyzer (experimental) (Jeremie)

===========================================================================
5.6
2007/06/14

Added: SkipException/TimeBombedSkipException for manual skipping
Added: <tests> can now be disabled at xml level using <test enabled="false">
Added: Suite files that only contain other suites do not get reported
Fixed: @BeforeClass methods would incorrectly report cyclic graphs
Added: get/setAttribute to ITestContext
Added: plugging in factory objects to handle the actual instantiation of tests
Added: dataProvider to @Factory
Added: ISuite now gives access to the current XmlSuite
Fixed: TESTNG-139 dependsOnMethods gets confused when dependency is "protected"
Fixed: TESTNG-141 junit attribute set to false in testng-failed.xml when it should be true
Fixed: TESTNG-142 Exceptions in DataProvider are not reported as failed test
Added: Improved behavior for @Before/@AfterClass when using @Factory 
(http://forums.opensymphony.com/thread.jspa?threadID=6594&messageID=122294#122294)
Added: Support for concurrent execution for invocationCount=1 threadPoolSize>1 and @DataProvider
(http://forums.opensymphony.com/thread.jspa?threadID=64738&tstart=0)
Added: New TestNG specific XML report, generated by default in 'xml' subdirectory of test-output
Added: support in strprotocol for passing the ITest.getTestName() information
Fixed: TESTNG-152 If DataProvider is not found, the exception message should tell exactly what happened

Eclipse plug-in

Fixed: Bug that made group launch configurations unusable
Fixed: The plugin doesn't create the correct launch configuration for @Factory
Fixed: Method based launchers cannot be editted
Fixed: Plugin hangs while executing test with dataprovider that sends \n, \r messages
Added: display ITest.getTestName()

IDEA plug-in

Fixed: IDEA 7.0 compatibility
Fixed: occasional 'illegal arguments exception'
Fixed: TESTNG-151 Final passing test result is not properly hidden
Added: Auto-completion for dependsOnMethods
Added: Highlighting of invalid groups/methods in dependsOn*

===========================================================================
5.5
2007/01/25

Fixed: @BeforeGroup methods were run twice when in a base class
Fixed: @BeforeGroup methods were run twice with a @Test at class level
Fixed: parallel="tests" didn't work as advertised
Added: Support for thread-count at test level
Added: Method selectors receive a Context and can stop the chain with setStopped()
Fixed: XmlMethodSelector was always run first regardless of its priority
Added: @BeforeGroups/@AfterGroups can live in classes without @Test methods
Added: DataProvider can now take an ITestContext parameter
Fixed: Wasn't parsing <selector-class-name> correctly 
Fixed: Annotation Transformers now work on class-level annotations
Fixed: Some class-level @Test attributes were not always honored
Added: Clean separation between @Test invocation events and @Configuration invocation events
       (see also TESTNG-111)
Added: Test instances created by @Factory now run in multiple threads in parallel mode
Fixed: @Before/@AfterGroups invocation order
Fixed: TESTNG-27: Parameters are not used on <test> level anymore
Fixed: TESTNG-107 don't create an output directory if "outputDirectory" is null
Fixed: TESTNG-127 UseDefaultListeners in Ant Task does not work
Fixed: TESTNG-119 Running TestNG runner with invalid '-sourcedir' on JDK14 JavaDoc annotated test classes won't fail.
Fixed: TESTNG-113 Dependent methods within the same static inner class are not found
Fixed: TESTNG-125 TestNG failed for test classes under *.java*.* pakages

Eclipse plug-in
Fixed: issue with launch configuration
Fixed: TESTNG-124: setting location of testng reports output

===========================================================================
5.4

Fixed: Ant task issue with paths containing spaces
Added: for @BeforeGroups and @AfterGroups specifying the groups() attribute will auto-include the method
			 into those groups by default (previously you had to also provide the value() attribute).
Added: the load @Tests (invocationCount + threadPoolSize) are triggered simultaneous
Fixed: reports are correctly displaying the thread info
Added: @DataProvider name defaults to method name
Added: support for remote protocol to pass parameter information
Fixed: TextReporter logs information about the parameters of the test methods
Fixed: concurrency issue in JUnitXMLReporter
Fixed: output of JUnitXMLReporter must be CDATA
Fixed: XML unsupported annotations/parallel attribute values are reported

Eclipse plug-in
Fixed: groups with multi-attribute javadoc annotations
Fixed: consistent behavior for dependsOnMethods
Fixed: consistent behavior for tests with dependsOnGroups (a warning is emitted)
Fixed: consistent merge of configuration arguments when an existing launch configuration exists 
===========================================================================
5.3
2006/10/30

Fixed: use a single instance of bsh.Interpreter
Added: @Before/@AfterMethod can declare a java.lang.reflect.Method parameter to be informed about the @Test method
Fixed: super classes must not be listed in testng-failures.xml
Fixed: parallel attribute must not appear if empty or null in testng-failures.xml
Fixed: parsing for javadoc annotations is done on request only
Added: improved multiple suite summary page report
Added: -target option deprecated in favor of -annotations javadoc|jdk
Fixed: filesets in the ant task didn't work if the paths have spaces in them
Fixed: Before/After Suite were behaving wrong in parallel execution
Added: A generic/extensible RemoteTestNG was added to the core
Fixed: Before/AfterGroup-s were behaving wrong when using invocationCount, dataProvider and threadPoolSize
Fixed: improved support for running different annotation type tests in the same suite
Fixed: testng-failed.xml was generated even if there were no failures/skipps
Fixed: -usedefaultlisteners was wrongly passed to JVM instead of TestNG options
Added: Attribute dataProviderClass for @Test and @testng.test
Fixed: Forgot to account for cases where both invocationCount and DataProviders are present
Fixed: AfterGroups were invoked out of order with invocationCount and DataProviders
Fixed: Reporter.getOutput() returned an empty array if a timeOut was specified
Added: testng.xml now supports <suite-files>
Added: ant task can receive several listeners
Fixed: TESTNG-109 Skipped tests with expected exceptions are reported as failures
Added: ant task can now select the parallel mode for running tests
Fixed: ant task correctly deals with empty groups and excludedgroups parameters
Added: ant task can override default suite and test names
Added: comand line support for setting parallel mode, suite and test names

Eclipse plug-in
Added: Support for configuring per project usedefaultlisteners
Added: Contextual drop-down menu on failures tab of the TestNG view to enable running/debugging method failure only
Added: Suppport for configuring per project TestNG jar usage (project provided one or plugin provided one)

===========================================================================
5.2

Added: "-usedefaultlisteners true/false" to command line and ant
Added: EmailableReporter (from Paul Mendelson)
Added: parallel can now be "methods" or "tests". Boolean version deprecated
Added: TestNGAntTask now uses the @ syntax to invoke TestNG
Added: Command line understands @ syntax
Added: JUnitConverter uses the new syntax
Added: -groups to JUnitConverter
Fixed: Throw proper exception when a DataProvider declares parameters
Added: completely revamped JUnit support (should run all kind of JUnit tests)
Fixed: TESTNG-40 (Bug in testng-failed.xml generation)
Fixed: TESTNG-106 (Failed "@BeforeSuite" method just skipps the last test in xml-file)
Fixed: Success on 0 tests (http://forums.opensymphony.com/thread.jspa?threadID=41213)

Eclipse plug-in
Added: TESTNG-105 Automaticaly define TESTNG_HOME classpath variable

===========================================================================
5.1
2006/08/18

Added: @Test(sequential = true)
Fixed: TESTNG-102 (Incorrect ordering of @BeforeMethod calls when a dependency is specified)
Fixed: TESTNG-101 (HTML output contains nested <P> tags and a missing <tr> tag)
Added: support for specifying test-only classpath (http://forums.opensymphony.com/thread.jspa?messageID=78048&tstart=0)
Fixed: TESTNG-93 (method selectors filtering @BeforeMethod)
Fixed: TESTNG-81 (Assert.assertFalse() displays wrong expected, actual value)
Fixed: TESTNG-59 (multiple method selectors usage results in no tests run)
Fixed: TESTNG-56 (invocation of @Before/AfterClass methods in parallel/sequential scenarios)
Fixed: TESTNG-40 (failures suite does not contain @Before/After Suite/Test methods)
Fixed: TESTNG-37 (allow passing null parameter value from testng.xml)
Fixed: TESTNG-7 (display classname when hovering method)


Eclipse plug-in

Added: run contextual test classes with parameters from suite definition files
Added: TESTNG-100 (Show HTML reports after running tests)
Added: TESTNG-97 (Double click top stack to raise comparison)
Added: TESTNG-84 (plug-in UI for suite option should support absolute path)
Added: TESTNG-20 (copy stack trace)

Fixed: TESTNG-72 (display groups with non-array values)
Fixed: TESTNG-64 (Eclipse plug-in applies added groups to all launch configurations)
Fixed: TESTNG-28 (Cannot select groups from dependent eclipse projects)
Fixed: TESTNG-25 (do not display fully qualified method name when running contextual test class)

Improved behavior:
	TESTNG-98 (temporary files have guaranteed fixed names)
	TESTNG-95 (Assertion failed comparison trims trailing ">")
	TESTNG-70 (TestNG prevents eclipse from opening an older CVS version of a java class)
	display of test hierarchy information (TESTNG-29)

===========================================================================

5.0.1

Eclipse plug-in

Added: Output directory for the tests
Added: Can now specify listener classes

===========================================================================
5.0.1

Fixed: reports generated by SuiteHTMLReporter do not work with JDK1.4
			 
===========================================================================

5.0
2009/04/01

Added: Ant task: support for JVM, workingDir, timeout
Added: Stack traces can be interactively shown in the HTML reports
Added: Link to testng.xml in the reports
Added: New structure for reports, suites go in their individual directory
Added: @Test(suiteName) and @Test(testName)
Added: The stack traces in reports do not include TestNG frames (system property testng.exception)
			 (see: http://groups.google.com/group/testng-dev/browse_thread/thread/9f4d46ade10b0fda)
Fixed: Exit with error when no methods are run
			 (see: http://groups.google.com/group/testng-dev/browse_thread/thread/3c26e8a5658f22ac)
Added: List of methods in alphabetical order
Fixed: Class-scoped annotations were not recognized when inherited
Added: Deprecated @Configuration and introduced @BeforeSuite/Test/Class/TestMethod
Added: Deprecated @ExpectedExceptions and moved it into @Test
Added: expectedExceptions to @Test, deprecated @ExpectedExceptions
Added: New annotations:  @BeforeSuite, @BeforeTest, etc...
Fixed: Was returning an exit code of 0 if a cyclic graph was detected
Added: Interface org.testng.ITest so that tests can declare a name
Fixed: The Text reporter was reporting the square of the actual number of methods
Fixed: Bug reported by Eran about dependencies with an afterClass method
Added: IHookCallBack now receives the ITestResult in its run() method
Added: Name of suite for command line can be set with -Dtestng.suite.name=xxx
Fixed: TestNGAntTask was hardcoding m_haltOnFSP to true
Fixed: Passing a null parameter caused an NPE in the reports
Added: "listener" to the ant task (and documentation)
Added: if patch-testng-sourcedir.properties is found in the classpath
       with a property "sourcedir" containing a ; separated list of
       directories, this list will override -sourcedir.

===========================================================================


4.7

Added: Maven 2 plug-in
Fixed: Message formattings in TestNG assertion utility class
Fixed: @Factory methods were counted as @Test as well
       http://jira.opensymphony.com/browse/TESTNG-51
Fixed: All DataProvider parameters were shown in the HTML report
Fixed: Bug in testng-failed.xml generation
Fixed: <packages> bug when using a jar file to load the test classes
Added: alwaysRun for before @Configuration methods
       http://jira.opensymphony.com/browse/TESTNG-35
Fixed: groupless @Configurations were not invoked if a method depends on a group
       http://jira.opensymphony.com/browse/TESTNG-45
Added: beforeGroups/afterGroups to @Configuration

Eclipse plugin:

Added: last contextual launch is available in Eclipse launcher lists
Fixed: 3.2M5 integration (removed dependency on non-existing class)
Fixed: testng-failures.xml generation

===========================================================================

4.6
2006/27/02

Added: Documentation contains the new reports
Added: TestNG.setUseDefaultListeners(boolean)
Added: Descriptions now appear in TextReporter (verbose>=2) and the HTML reports
Added: description attribute to @Test and @Configuration
Added: combined Reporter output in the reports
Added: methods not run in the reports
Added: org.testng.IReporter
Added: threadPoolSize to @Test
Added: Reports now show relative timings (start at 0)
Added: Reports now show different colors depending on the methods' classes
Added: Reports now show all parameters used to invoke the test method
Added: org.testng.Reporter
Added: DataProviders can accept a Method as first parameter
Fixed: Extraneous implicit inclusion of a method

Eclipse plugin:

Added: Run/Debug as TestNG test from the editor contextual menu
Fixed: TESTNG-24: 'Run as testng test' does not appear of the Test annotation does not have a group
Fixed: TESTNG-18: Eclipse plugin ignores Factory annotation
Fixed: TESTNG-21: Show differences when double clicking assertion exceptions
Added: UI allows setting orientation (even more space)
	   http://forums.opensymphony.com/thread.jspa?threadID=17225&messageID=33805#33805
	   
===========================================================================

4.5
2007/07/02

Core:

Fixed: Methods were not implicitly included, only groups
Fixed: Bug with failed parent @Configuration don't skip child @Configuration/@Test invocations
Fixed: Bug with overridding @Configuration methods (both parent and child were run)
Fixed: Bug when overriding beforeClass methods in base class (cyclic graph)
Added: Support for JAAS (see org.testng.IHookable)
Fixed: Problem with nested classes inside <package name="foo.*"
Fixed: If a group is not found, mark the method as a skip instead of aborting
Fixed: testng-failed.xml was not respecting dependencies
Fixed: class/include method in testng.xml didn't work on default package
Fixed: DTD only allowed one <define>
Fixed: ArrayIndexOutOfBoundsException for jMock
Added: dependsOnMethods can contain methods from another class
Fixed: JUnitConverter required -restore, not any more (option is now a no-op)
Fixed: JUnit mode wasn't invoking setName() on test classes
Added: Regular expressions for classes in <package>
Added: Distributed TestNG
Fixed: Command line parameters and testng.xml are now cumulative
Fixed: Reports now work for multiple suites
Fixed: Was ignoring abstract classes even if they have non-abstract instances
Fixed: If setUp() failed, methods were not skipped
Fixed: Was not clearly indicating when beforeSuite fails
Added: @Configuration.inheritGroups
Fixed: inconsistency between testng.xml and objects regarding method selectors

Eclipse plug-in:

New look for the progress view.

===========================================================================

4.4

Core:

Fixed: testng-failures.xml was not excluding methods from base classes
Fixed: Bug in suites of suites for JUnit mode

===========================================================================

4.3

Core:

Fixed: testng-failures.xml was not excluding methods from base classes
Fixed: Bug in suites of suites for JUnit mode
Added: Excluded groups on command line and ant task
Fixed: When including a group, implicitly include groups depended upon
Fixed: When depending on several groups, wasn't skipped if one of them failed
Fixed: Failures weren't reported accurately in the JUnitReports report
Fixed: Wasn't throwing an exception if depending on a non-existing group

===========================================================================

4.2

Core:

Fixed: wasn't excluding methods in base classes
Added: alwaysRun for tests (soft dependencies)
Fixed: Class-level enabled=false were not honored
Fixed: Bug with multiple dataproviders on same class
Fixed: Bug with dataprovider defined in the parent class
Fixed: Bug with dataprovider defined in a subclass
Fixed: Bug with dataprovider defined in an abstract class
Fixed: testng-failures generation was excluding the methods even if a failed test depended on it

===========================================================================

4.1

Core:

Added: @DataProviders can return Iterable<Object[]>
Fixed: Superclass test methods were not called in the presence of a class @Test
Added: Reporter class to log messages in the HTML reports

===========================================================================

4.0
2005/11/10

Core:

Fixed: suite methods now invoked only once in a hierarchy
Added: @DataProvider and @testng.data-provider
Fixed: Interleave order now respected for before/afterClass methods
Added: Can now invoke java -jar testng-2.6.jar <...>
Added: Support for BeanShell
Added: Method Selectors (IMethodSelector)
Fixed: In the absence of dependencies, @Configuration methods respect inheritance
Fixed: Bug in multithreaded dependencies on methods
Fixed: dependsOnGroups wasn't working on regular expressions
Fixed: Bug in <package> when directories contain spaces in their names
Fixed: Introduced a JDK5 dependency in the JDK1.4 build (getEnclosingClass())
Fixed: Output directory in ant task was not honored if it didn't exist
Fixed: Problem with timeout according to 
       http://forums.opensymphony.com/thread.jspa?threadID=6707

Eclipse plug-in:

Fixed: Wasn't handling linked directories correctly
Fixed: Bug in QuickFix implementation
Added: Quick Fix for JUnit conversion (Annotations and JavaDoc)
Fixed: Methods Run as TestNG test
Added: Package level Run as TestNG test
Fixed: Resources from the linked directories are using a wrong path when 
       passed to command line TestNG

IDEA plug-in:

Added: Support for JDK 1.4 (both projects and IDEA itself)
Fixed: Classes that contained only configuration were ignored

===========================================================================

2.5
2005/08/08

Added: ITestListener.onTestStart(ITestResult)
Added: Support for <packages>
Added: Resource files for easier ant taskdefs
Fixed: @Configuration methods were not invoked with individual test methods
Fixed: Bug with ExpectedExceptions
Fixed: Didn't support nested factory classes
Fixed: NPE if -target is omitted with JDK 1.4
Fixed: @Configuration failures in a class would cause other classes to fail
Added: alwaysRun
Fixed: beforeTestClass/afterTestClass were broken for a pathological case
Added: @Configuration(alwaysRun)
Added: JUnitConverter task
Fixed: < and > characters in reports were not escaped

Eclipse plug-in:

Fixed: Class dialog wasn't showing @Factory classes

IDEA plug-in:

First release!

Documentation:

Added: Brand new look!!!
Added: Section on testng.xml
Fixed: Numbering of sections

===========================================================================

2.4
2005/07/05

Changed: New package:  testng.org
Fixed: Bug with @ExpectedException occuring the parallel mode
Fixed: Bug with parameters and beforeTest
Added: IInstanceInfo support
Fixed: methods were not excluded when included by groups
Fixed: testng-failures.xml is now including also the beforeSuite/afterSuite methods
Fixed: generating the testng-failures.xml is now working as expected
Fixed: Factories call all the tests even if some of them fail along the way
Fixed: Better JUnit support (wasn't creating individual instances)
Fixed: dependsOnGroups didn't work across different classes
Added: command line (and Ant) -groups option
Added: @Parameters (and made parameters attribute deprecated)
Added: Parameters for constructors
Fixed: Better interleaving of before/afterTestMethods
Fixed: Ant task
Fixed: TestNGException thrown when TestNG conditions are not fulfilled

Documentation:
- New assert classes
- New ways to launch 
- JUnitConverter documentation
- new beforeSuite/afterSuite

===========================================================================

2.3
2005/04/12

Fixed: Spaces are now legal in JavaDoc comments
Added: documentation for @Factory
Fixed: factories were called multiple times
Added: beforeSuite and afterSuite
Fixed: inheritance and scope now working properly for annotations
Fixed: dependsOnMethods wasn't working for 1.4
Added: Better stack traces
Added: Better syntax for included/excluded methods
Fixed: Better verbose support
Fixed: Various fixes for the Eclipse plug-in
Added: Can specify a class name on the command line
Fixed: Default package bug in JUnitConverter
Added: Regression tests for JUnitConverter
Added: -quiet option to JUnitConverter

===========================================================================

2.2

Fixed: Wasn't handling several testng.xml files correctly
Fixed: Renamed -src to -sourcedir
Fixed: Complains if no sourcedir is specified in 1.4
Added: In 1.4, don't require annotations="javadoc"
Fixed: If setUp fails, complain and mark test methods as skips
Fixed: Dependent methods weren't working for 1.4

===========================================================================

2.1
2005/02/12

Added: Parser can accept an InputStream for testng.xml
Fixed: expected-exceptions now fails if test passes
Fixed: reports now use the suite name in HTML
Added: invocationCount and successPercentage
Added: dependsOnMethods
Added: timeOut works in non-parallel mode

===========================================================================

2.0
2004/12/06

Added: port on JDK 1.4

===========================================================================

1.3

Added: new view:  classes (still experimental)
Added: timeout on methods
Added: thread-count
Added: TestNG is now multithread, see "parallel" in <suite>

===========================================================================

1.2

Added: JUnitConverter
Fixed: Bug with afterClasses (test: AfterClassCalledAtTheEnd)

===========================================================================

1.1

Added: new links for methods and groups in the HTML report
Added: <methods>
Added: <fileset> to <testng>

===========================================================================

1.0
2004/04/28
http://beust.com/weblog/2004/04/28/

Fixed: Updated to the new DTD
Fixed: Suite table of contents displays failures first
Fixed: Bug in afterTestClass
Added: Validating testng.xml
Added: Scoped parameters
Added:  testng.xml
Removed: Property quiet
Changed: Verbose is now an integer
Added:  Dependent methods

===========================================================================

0.9

Added:  Groups of groups
Added:  Groups for Configuration methods
Added:  Parameters

===========================================================================

0.2

Fixed:  Merged TestMethod and TestClass into Test
Added: HTML report
Added: Regexps for groups
Fixed:  Inheritance of methods
Fixed:  ExpectedException is now called ExpectedExceptions
�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/ANNOUNCEMENT.txt����������������������������������������������������������������0000644�0001750�0001750�00000010546�12551235562�016312� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������javalobby.org
testdriven.com
opensourcetesting.org
http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=forum&f=68
java.net
comp.lang.java.programmer

==========

The TestNG team is happy to announce the immediate availability of TestNG 4.5. 

This release contains a lot of bug fixes and a few new features.  It also 
includes the first phase of Distributed TestNG, a work in progress designed 
to transparently distribute tests on many machines and collect their results.

Announcement:

http://beust.com/weblog/archives/000361.html

Details on Distributed TestNG:  

http://beust.com/weblog/archives/000362.html


==========

The TestNG team is happy to announce the immediate availability of TestNG 4.0, with a lot of improvements and new features.

The announcement, along with a few examples and summary of the new features, can be found here:

    http://tinyurl.com/dxlbh

-- 
Cdric
http://testng.org

================

Announcing TestNG 2.3

The TestNG team is happy to announce the availability of TestNG 2.3.

The version is available at http://beust.com/testng as well as the new documentation, which has been considerably improved (highlighted code snippets, detailed DTD, ant task and description of all the new features).

What's new:

    * beforeSuite, afterSuite, beforeTest, afterTest
    * Revamped ant task with haltonfailure and other helpful flags
    * Better stack traces and improved level control for verbosity
    * Better syntax for including and excluding methods in testng.xml
    * Test classes can be invoked on the command line
    * ... and many bug fixes.

For Eclipse users, a new version (1.1.1) of the Eclipse plug-in that includes this new TestNG version is available on the remote update site or for direct download.

Also, TestNG has joined OpenSymphony (big thanks to Patrick and Hani for setting this up).  As a consequence of this move, there is now a TestNG users forum as well as a Wiki and JIRA for issue tracking.

The users mailing-list has been moved to Google Groups and is connected to the forum, so you only need to subscribe to one.

Try it and let us know what you think!

===

I am happy to announce the availability of TestNG 2.1 (http://beust.com/testng).  

TestNG is a testing framework inspired from JUnit and NUnit but introducing some new functionalities that make it more powerful and easier to use, such as:

    * JSR 175 Annotations (JDK 1.4 is also supported with JavaDoc annotations).
    * Flexible test configuration.
    * Default JDK functions for runtime and logging (no dependencies).
    * Powerful execution model (no more TestSuite).
    * Supports dependent methods.

Some of the new features in this version include:

    * invocationCount and successPercentage, which I described in a previous entry (http://beust.com/weblog/archives/000236.html), and which allow you to invoke a test method a certain number of times while allowing some of these invocations to fail.  If the number of failures is under a certain threshold, the test is still considered a success.
       
    * timeOut is now applicable to all test methods.  Whether you are running your tests in parallel or not, you can specify a time-out for your test method and if it fails to complete within the given amount of time, TestNG will mark it as a failure.
       
    * dependsOnMethods was the most requested feature.  You can now specify dependencies on a method-based basis (no need to specify a group if your dependency graph is simple).  You can even mix dependsOnMethods and dependsOnGroups.
       
    * ... and of course, numerous bug fixes and other additions.

A special thanks to Alexandru Popescu who has pulled all-nighters to make this release happen!

We have an exciting list of new features lined up for our next version, among which a plug-in API, but in the meantime, enjoy TestNG 2.1.

======

Announcing TestNG for Eclipse

The TestNG team is happy to announce the first release of the TestNG plug-in for Eclipse.

http://beust.com/testng

This first release covers the basic functionalities of TestNG, among which:

    * Multiple ways to launch tests (from a method, from a class, groups or an entire suite).
    * Convenient report view that lets you directly jump to failed tests.

A more detailed overview can be found here:

http://beust.com/weblog/archives/000261.html

and the documentation and snapshots here:

http://beust.com/testng/main.html#eclipse

-- 
Cedric
����������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/.travis.yml���������������������������������������������������������������������0000644�0001750�0001750�00000000423�12551235562�015761� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������language: java
jdk:
  - oraclejdk8
  - oraclejdk7
  - openjdk7

#before_install: bash "gradle/uploadSnapshot.sh"
script: ./gradlew clean test
after_success: test "${TRAVIS_PULL_REQUEST}" == "false" && test "${TRAVIS_JDK_VERSION}" == "oraclejdk7" && ./gradlew uploadArchives

���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/.project������������������������������������������������������������������������0000644�0001750�0001750�00000001107�12551235562�015317� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
	<name>testng</name>
	<comment></comment>
	<projects>
	</projects>
	<buildSpec>
		<buildCommand>
			<name>org.eclipse.jdt.core.javabuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>org.eclipse.m2e.core.maven2Builder</name>
			<arguments>
			</arguments>
		</buildCommand>
	</buildSpec>
	<natures>
		<nature>org.eclipse.pde.PluginNature</nature>
		<nature>org.eclipse.m2e.core.maven2Nature</nature>
		<nature>org.eclipse.jdt.core.javanature</nature>
	</natures>
</projectDescription>
���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/.gitignore����������������������������������������������������������������������0000644�0001750�0001750�00000000464�12551235562�015645� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.ant-targets*
.classpath
.gitignore
.gradle
.idea
.project
.settings
/_eclipse/
TESTNG-*
build
eclipse-build
ivy*
javadocs
lib
maven-testng-plugin-1.2.jar
nb-configuration.xml
src/generated
src/test/java/test/ignore
target
test-output
test-output-tests
testng.iml
z_build
gradle.properties
/local.properties
������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/.classpath-mac������������������������������������������������������������������0000644�0001750�0001750�00000001106�12551235562�016370� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?>
<classpath>
  <classpathentry kind="src" path="src/main/java"/>
  <classpathentry kind="src" path="src/test/java"/>
  <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/JVM 1.6"/>
  <classpathentry kind="lib" path="lib/ant-1.6.5.jar"/>
  <classpathentry kind="lib" path="lib/bsh-2.0b4.jar"/>
  <classpathentry kind="lib" path="lib/guice-2.0.jar"/>
  <classpathentry kind="lib" path="lib/junit-3.8.1.jar"/>
  <classpathentry kind="output" path="z_build"/>
</classpath>
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/.classpath-linux����������������������������������������������������������������0000644�0001750�0001750�00000001106�12551235562�016767� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?>
<classpath>
  <classpathentry kind="src" path="src/main/java"/>
  <classpathentry kind="src" path="src/test/java"/>
  <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/JVM 1.6"/>
  <classpathentry kind="lib" path="lib/ant-1.6.5.jar"/>
  <classpathentry kind="lib" path="lib/bsh-2.0b4.jar"/>
  <classpathentry kind="lib" path="lib/guice-2.0.jar"/>
  <classpathentry kind="lib" path="lib/junit-3.8.1.jar"/>
  <classpathentry kind="output" path="z_build"/>
</classpath>
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������testng-testng-6.9.5/.classpath����������������������������������������������������������������������0000644�0001750�0001750�00000002200�12551235562�015626� 0����������������������������������������������������������������������������������������������������ustar  �eugene��������������������������eugene�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?>
<classpath>
	<classpathentry kind="src" output="target/classes" path="src/main/java">
		<attributes>
			<attribute name="optional" value="true"/>
			<attribute name="maven.pomderived" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="src" path="src/generated/java"/>
	<classpathentry kind="src" path="src/test/java"/>
	<classpathentry kind="src" path="src/main/resources"/>
	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
		<attributes>
			<attribute name="maven.pomderived" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry exported="true" kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
		<attributes>
			<attribute name="maven.pomderived" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
		<attributes>
			<attribute name="maven.pomderived" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="output" path="target/classes"/>
</classpath>
������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������