From 4d1b3f1c19bc892ef1b9a136c9966f430878d33f Mon Sep 17 00:00:00 2001 From: dianny chen Date: Thu, 12 Aug 2021 15:46:18 +0800 Subject: [PATCH] Fix GITHUB-2558 Now the listener start method and finished method worked with insertion order, this commit changes the finished method worked with reverse order. --- CHANGES.txt | 1 + .../main/java/org/testng/collections/Lists.java | 6 ++++++ .../src/main/java/org/testng/SuiteRunner.java | 10 +++++++--- testng-core/src/main/java/org/testng/TestNG.java | 11 ++++++++--- .../src/main/java/org/testng/TestRunner.java | 14 ++++++++++---- .../org/testng/internal/TestListenerHelper.java | 5 ++++- .../org/testng/internal/invokers/BaseInvoker.java | 8 +++++++- .../org/testng/internal/invokers/TestInvoker.java | 8 +++++++- .../java/org/testng/junit/JUnitTestRunner.java | 10 ++++++---- .../src/test/java/test/listeners/ListenerTest.java | 12 ++++++------ 10 files changed, 62 insertions(+), 23 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 0e6bf590ec..4db1e73220 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ Current +Fixed: GITHUB-2558:Make IExecutionListener, ITestListener, IInvokedMethodListener, IConfigurationListener, ISuiteListener finish method with reverse order (dianny) Fixed: GITHUB-2532: Apply commandline switches for suites in jar files (Dzmitry Sankouski). Fixed: GITHUB-2558: Make IExecutionListener, ITestListener, IInvokedMethodListener, IConfigurationListener, ISuiteListener execute in the order of insertion (Krishnan Mahadevan) Fixed: GITHUB-2611: Config Failures not included in testng-failed.xml when its part of a different test class (Krishnan Mahadevan) diff --git a/testng-collections/src/main/java/org/testng/collections/Lists.java b/testng-collections/src/main/java/org/testng/collections/Lists.java index 61ac5e114e..f2daa94ad0 100644 --- a/testng-collections/src/main/java/org/testng/collections/Lists.java +++ b/testng-collections/src/main/java/org/testng/collections/Lists.java @@ -76,4 +76,10 @@ public static List merge(List l1, BiPredicate condition, List }); return result; } + + public static List newReversedArrayList(Collection c) { + List list = newArrayList(c); + Collections.reverse(list); + return list; + } } diff --git a/testng-core/src/main/java/org/testng/SuiteRunner.java b/testng-core/src/main/java/org/testng/SuiteRunner.java index 3cf15bfacd..c8e7a6a603 100644 --- a/testng-core/src/main/java/org/testng/SuiteRunner.java +++ b/testng-core/src/main/java/org/testng/SuiteRunner.java @@ -252,10 +252,14 @@ public void setReportResults(boolean reportResults) { } private void invokeListeners(boolean start) { - for (ISuiteListener sl : Lists.newArrayList(listeners.values())) { - if (start) { + if (start) { + for (ISuiteListener sl : Lists.newArrayList(listeners.values())) { sl.onStart(this); - } else { + } + } else { + List suiteListenersReversed = new ArrayList<>(listeners.values()); + Collections.reverse(suiteListenersReversed); + for (ISuiteListener sl : suiteListenersReversed) { sl.onFinish(this); } } diff --git a/testng-core/src/main/java/org/testng/TestNG.java b/testng-core/src/main/java/org/testng/TestNG.java index 6620faa400..36735488d7 100644 --- a/testng-core/src/main/java/org/testng/TestNG.java +++ b/testng-core/src/main/java/org/testng/TestNG.java @@ -1083,10 +1083,15 @@ private void runSuiteAlterationListeners() { } private void runExecutionListeners(boolean start) { - for (IExecutionListener l : m_configuration.getExecutionListeners()) { - if (start) { + List executionListeners = m_configuration.getExecutionListeners(); + if (start) { + for (IExecutionListener l : executionListeners) { l.onExecutionStart(); - } else { + } + } else { + List executionListenersReversed = new ArrayList<>(executionListeners); + Collections.reverse(executionListenersReversed); + for (IExecutionListener l : executionListenersReversed) { l.onExecutionFinish(); } } diff --git a/testng-core/src/main/java/org/testng/TestRunner.java b/testng-core/src/main/java/org/testng/TestRunner.java index 8cc307f444..6b7c15670e 100644 --- a/testng-core/src/main/java/org/testng/TestRunner.java +++ b/testng-core/src/main/java/org/testng/TestRunner.java @@ -6,6 +6,7 @@ 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; @@ -90,7 +91,7 @@ public class TestRunner /** ITestListeners support. */ private final List m_testListeners = Lists.newArrayList(); - private final Set m_configurationListeners = Sets.newHashSet(); + private final Set m_configurationListeners = Sets.newLinkedHashSet(); private final Set visualisers = Sets.newHashSet(); private final IConfigurationListener m_confListener = new ConfigurationListener(); @@ -931,10 +932,15 @@ private void logStart() { * finish */ private void fireEvent(boolean isStart) { - for (ITestListener itl : m_testListeners) { - if (isStart) { + if (isStart) { + for (ITestListener itl : m_testListeners) { itl.onStart(this); - } else { + } + + } else { + List testListenersReversed = new ArrayList<>(m_testListeners); + Collections.reverse(testListenersReversed); + for (ITestListener itl : testListenersReversed) { itl.onFinish(this); } } diff --git a/testng-core/src/main/java/org/testng/internal/TestListenerHelper.java b/testng-core/src/main/java/org/testng/internal/TestListenerHelper.java index 430d910531..07ca69df44 100644 --- a/testng-core/src/main/java/org/testng/internal/TestListenerHelper.java +++ b/testng-core/src/main/java/org/testng/internal/TestListenerHelper.java @@ -1,5 +1,6 @@ package org.testng.internal; +import java.util.Collections; import java.util.List; import org.testng.IClass; import org.testng.IConfigurationListener; @@ -35,7 +36,9 @@ public static void runPreConfigurationListeners( public static void runPostConfigurationListeners( ITestResult tr, ITestNGMethod tm, List listeners) { - for (IConfigurationListener icl : listeners) { + List listenersreversed = Lists.newArrayList(listeners); + Collections.reverse(listenersreversed); + for (IConfigurationListener icl : listenersreversed) { switch (tr.getStatus()) { case ITestResult.SKIP: icl.onConfigurationSkip(tr); diff --git a/testng-core/src/main/java/org/testng/internal/invokers/BaseInvoker.java b/testng-core/src/main/java/org/testng/internal/invokers/BaseInvoker.java index 10cfb0e826..13000535cc 100644 --- a/testng-core/src/main/java/org/testng/internal/invokers/BaseInvoker.java +++ b/testng-core/src/main/java/org/testng/internal/invokers/BaseInvoker.java @@ -10,6 +10,7 @@ import org.testng.ITestResult; import org.testng.SkipException; import org.testng.SuiteRunState; +import org.testng.collections.Lists; import org.testng.collections.Maps; import org.testng.internal.IConfiguration; import org.testng.internal.ITestResultNotifier; @@ -54,7 +55,12 @@ protected void runInvokedMethodListeners( InvokedMethodListenerInvoker invoker = new InvokedMethodListenerInvoker(listenerMethod, testResult, testResult.getTestContext()); - for (IInvokedMethodListener currentListener : m_invokedMethodListeners) { + boolean isBeforeInvocation = InvokedMethodListenerMethod.BEFORE_INVOCATION == listenerMethod; + Collection listeners = + isBeforeInvocation + ? m_invokedMethodListeners + : Lists.newReversedArrayList(m_invokedMethodListeners); + for (IInvokedMethodListener currentListener : listeners) { try { invoker.invokeListener(currentListener, invokedMethod); } catch (SkipException e) { diff --git a/testng-core/src/main/java/org/testng/internal/invokers/TestInvoker.java b/testng-core/src/main/java/org/testng/internal/invokers/TestInvoker.java index ce5abc7189..ef0301f42d 100644 --- a/testng-core/src/main/java/org/testng/internal/invokers/TestInvoker.java +++ b/testng-core/src/main/java/org/testng/internal/invokers/TestInvoker.java @@ -28,6 +28,7 @@ import org.testng.ISuite; import org.testng.ITestClass; import org.testng.ITestContext; +import org.testng.ITestListener; import org.testng.ITestNGMethod; import org.testng.ITestResult; import org.testng.Reporter; @@ -232,7 +233,12 @@ public FailureContext retryFailed( } public void runTestResultListener(ITestResult tr) { - TestListenerHelper.runTestListeners(tr, m_notifier.getTestListeners()); + boolean isStarted = tr.getStatus() == ITestResult.STARTED; + List listeners = + isStarted + ? m_notifier.getTestListeners() + : Lists.newReversedArrayList(m_notifier.getTestListeners()); + TestListenerHelper.runTestListeners(tr, listeners); } private Collection dataProviderListeners() { diff --git a/testng-core/src/main/java/org/testng/junit/JUnitTestRunner.java b/testng-core/src/main/java/org/testng/junit/JUnitTestRunner.java index 6635a0d254..feaedf81cf 100644 --- a/testng-core/src/main/java/org/testng/junit/JUnitTestRunner.java +++ b/testng-core/src/main/java/org/testng/junit/JUnitTestRunner.java @@ -15,9 +15,6 @@ import junit.framework.TestResult; import junit.framework.TestSuite; import org.testng.*; -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.TestListenerHelper; @@ -87,7 +84,12 @@ public void endTest(Test test) { org.testng.internal.TestResult tr = recordResults(test, tri); - TestListenerHelper.runTestListeners(tr, m_parentRunner.getTestListeners()); + boolean isStarted = tr.getStatus() == ITestResult.STARTED; + List listeners = + isStarted + ? m_parentRunner.getTestListeners() + : Lists.newReversedArrayList(m_parentRunner.getTestListeners()); + TestListenerHelper.runTestListeners(tr, listeners); } public void setInvokedMethodListeners(Collection listeners) { diff --git a/testng-core/src/test/java/test/listeners/ListenerTest.java b/testng-core/src/test/java/test/listeners/ListenerTest.java index 556c801836..9827735111 100644 --- a/testng-core/src/test/java/test/listeners/ListenerTest.java +++ b/testng-core/src/test/java/test/listeners/ListenerTest.java @@ -380,26 +380,26 @@ public void ensureInsertionOrderIsHonouredByListeners() { prefix + "ClassMethodListenersHolder$ClassMethodListenerA.onBeforeClass()", prefix + "ClassMethodListenersHolder$ClassMethodListenerB.beforeInvocation()", prefix + "ClassMethodListenersHolder$ClassMethodListenerA.beforeInvocation()", - prefix + "ClassMethodListenersHolder$ClassMethodListenerB.afterInvocation()", prefix + "ClassMethodListenersHolder$ClassMethodListenerA.afterInvocation()", + prefix + "ClassMethodListenersHolder$ClassMethodListenerB.afterInvocation()", prefix + "ClassMethodListenersHolder$ClassMethodListenerB.onBeforeClass()", prefix + "ClassMethodListenersHolder$ClassMethodListenerA.onBeforeClass()", prefix + "ClassMethodListenersHolder$ClassMethodListenerB.onBeforeClass()", prefix + "ClassMethodListenersHolder$ClassMethodListenerA.onBeforeClass()", prefix + "ClassMethodListenersHolder$ClassMethodListenerB.beforeInvocation()", prefix + "ClassMethodListenersHolder$ClassMethodListenerA.beforeInvocation()", - prefix + "ClassMethodListenersHolder$ClassMethodListenerB.afterInvocation()", prefix + "ClassMethodListenersHolder$ClassMethodListenerA.afterInvocation()", + prefix + "ClassMethodListenersHolder$ClassMethodListenerB.afterInvocation()", prefix + "ClassMethodListenersHolder$ClassMethodListenerB.onBeforeClass()", prefix + "ClassMethodListenersHolder$ClassMethodListenerA.onBeforeClass()", - prefix + "TestListenersHolder$TestListenerB.onFinish(ctx)", prefix + "TestListenersHolder$TestListenerA.onFinish(ctx)", - prefix + "SuiteListenersHolder$SuiteListenerB.onFinish()", + prefix + "TestListenersHolder$TestListenerB.onFinish(ctx)", prefix + "SuiteListenersHolder$SuiteListenerA.onFinish()", + prefix + "SuiteListenersHolder$SuiteListenerB.onFinish()", prefix + "ReportersHolder$ReporterB.generateReport()", prefix + "ReportersHolder$ReporterA.generateReport()", - prefix + "ExecutionListenersHolder$ExecutionListenerB.onExecutionFinish()", - prefix + "ExecutionListenersHolder$ExecutionListenerA.onExecutionFinish()" + prefix + "ExecutionListenersHolder$ExecutionListenerA.onExecutionFinish()", + prefix + "ExecutionListenersHolder$ExecutionListenerB.onExecutionFinish()" }; List> listeners = Arrays.asList(