Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClassCastException when use shouldUseGlobalThreadPool(true) property #3179

Open
X-NoNAME opened this issue Sep 24, 2024 · 1 comment
Open

Comments

@X-NoNAME
Copy link

TestNG Version

7.10.2

Expected behavior

no exceptions

Actual behavior

there is exception:

java.lang.ClassCastException: class org.testng.internal.thread.graph.TestNGFutureTask cannot be cast to class org.testng.internal.thread.Async$AsyncTask (org.testng.internal.thread.graph.TestNGFutureTask and org.testng.internal.thread.Async$AsyncTask are in unnamed module of loader 'app')
	at org.testng.internal.thread.Async$AsyncTask.compareTo(Async.java:22)
	at java.base/java.util.concurrent.PriorityBlockingQueue.siftUpComparable(PriorityBlockingQueue.java:353)
	at java.base/java.util.concurrent.PriorityBlockingQueue.offer(PriorityBlockingQueue.java:475)
	at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1357)
	at org.testng.internal.thread.Async.run(Async.java:18)
	at org.testng.internal.invokers.MethodRunner.runInParallel(MethodRunner.java:143)
	at org.testng.internal.invokers.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:982)
	at org.testng.internal.invokers.TestInvoker.invokeTestMethods(TestInvoker.java:203)
	at org.testng.internal.invokers.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:154)
	at org.testng.internal.invokers.TestMethodWorker.run(TestMethodWorker.java:134)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at org.testng.internal.thread.graph.TestNGFutureTask.run(TestNGFutureTask.java:22)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:840)

Is the issue reproducible on runner?

  • Gradle

Test case sample

public class ClassCastExceptionExample implements IAlterSuiteListener {
  @Override
  public void alter(List<XmlSuite> suites) {
    suites.get(0).shouldUseGlobalThreadPool(true);
    suites.get(0).setThreadCount(3);
    suites.get(0).setParallel(XmlSuite.ParallelMode.METHODS);
  }

  @DataProvider(parallel = true)
  public Object[] dp() {return new Object[]{1};}

  @Test(dataProvider = "dp") public void test1(int dp) {}
  @Test(dataProvider = "dp") public void test3(int dp) {}
  @Test public void test2() {}
  @Test public void test4() {}
}
//gradle
tasks.test {
    useTestNG() {
        testNameIncludePatterns = ["ClassCastExceptionExample.*"]
        listeners.add('ClassCastExceptionExample')
    }
}

Contribution guidelines

Incase you plan to raise a pull request to fix this issue, please make sure you refer our Contributing section for detailed set of steps.

@krmahadevan
Copy link
Member

krmahadevan commented Feb 18, 2025

The root cause of the problem is how TestNG determines if it should use a LinkedBlockingQueue or a PriorityBlockingQueue

  • PriorityBlockingQueue is to be used when TestNG detects that there are tests that have priorities defined.
  • `LinkedBlockingQueue1 is to be used for all other cases.

The flaw lies with how we determine which of the queues to use.

Currently the logic considers both priority as well if any org.testng.IMethodInterceptor have been wired in. See here

When

//gradle
tasks.test {
    useTestNG() {
        testNameIncludePatterns = ["ClassCastExceptionExample.*"]
        listeners.add('ClassCastExceptionExample')
    }
}

is used, Gradle sees that there is filtering enabled via testNameIncludePatterns = ["ClassCastExceptionExample.*"] it ends up adding an implementation of IMethodInterceptor

See here and here

Now because the number of method interceptors is more than 1, TestNG ends up trying to add a PriorityBlockingQueue which causes this issue

This should be fixed in a day or two (I have the fix ready)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants