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

NPE is thrown when running with Thread affinity #2110

Closed
3 of 7 tasks
krmahadevan opened this issue Jul 12, 2019 · 10 comments · Fixed by #2113
Closed
3 of 7 tasks

NPE is thrown when running with Thread affinity #2110

krmahadevan opened this issue Jul 12, 2019 · 10 comments · Fixed by #2113
Assignees

Comments

@krmahadevan
Copy link
Member

krmahadevan commented Jul 12, 2019

TestNG Version

Note: only the latest version is supported

7.0.0-beta7

Expected behavior

No NPE's should be thrown

Actual behavior

NPE is thrown

Is the issue reproductible on runner?

  • Shell
  • Maven
  • Gradle
  • Ant
  • Eclipse
  • IntelliJ
  • NetBeans

Test case sample

Please, share the test case (as small as possible) which shows the issue

import org.testng.annotations.Test;

public class TestClass2 {
  @Test()
  public void test0() {
    System.out.println("TestClass2 - test0. Thread " + Thread.currentThread().getId());
  }

  @Test
  public void test1() {
    System.out.println("TestClass2 - test1. Thread " + Thread.currentThread().getId());
  }

  @Test(dependsOnMethods = "test1")
  public void test2() {
    System.out.println("TestClass2 - test2. Thread " + Thread.currentThread().getId());
  }

  @Test(dependsOnMethods = "test2")
  public void test3() {
    System.out.println("TestClass2 - test3. Thread " + Thread.currentThread().getId());
  }

  @Test()
  public void test4() {
    System.out.println("TestClass2 - test4. Thread " + Thread.currentThread().getId());
  }
}
import java.io.File;
import java.util.Collections;
import org.testng.TestNG;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlSuite.ParallelMode;
import org.testng.xml.XmlTest;

public class TestRunner {

  public static void main(String[] args) {
    System.err.println("TestNG Version " + getTestNGVersion());
    System.setProperty("testng.thread.affinity", "true");
    System.err.println("Running WITH Thread Affinity");
    runTestNGTest();
  }

  private static void runTestNGTest() {
    TestNG testNG = new TestNG();
    testNG.setVerbose(2);
    testNG.setXmlSuites(Collections.singletonList(createXmlSuite()));
    testNG.run();
  }

  private static String getTestNGVersion() {
    String file = TestNG.class.getProtectionDomain().getCodeSource().getLocation().getFile();
    return new File(file).getParentFile().getName();
  }

  private static XmlSuite createXmlSuite() {
    XmlSuite xmlSuite = new XmlSuite();
    xmlSuite.setParallel(ParallelMode.CLASSES);
    xmlSuite.setThreadCount(50);
    xmlSuite.setName("1185_suite");
    XmlTest xmlTest = new XmlTest(xmlSuite);
    xmlTest.setName("1185_test");
    XmlClass xmlClass = new XmlClass(TestClass2.class);
    xmlTest.setXmlClasses(Collections.singletonList(xmlClass));
    System.err.println("Generated Xml File ");
    System.err.println(xmlSuite.toXml());
    return xmlSuite;
  }
}

Issue has been created from this comment

@krmahadevan krmahadevan self-assigned this Jul 12, 2019
krmahadevan added a commit to krmahadevan/testng that referenced this issue Jul 14, 2019
Closes testng-team#2110

When there is just one test class and user does the
following:

1. Enables thread affinity 
2. Chooses to run with parallel=“classes”

TestNG is throwing a NPE. Fixed the problem.
krmahadevan added a commit to krmahadevan/testng that referenced this issue Jul 14, 2019
Closes testng-team#2110

When there is just one test class and user does the
following:

1. Enables thread affinity 
2. Chooses to run with parallel=“classes”

TestNG is throwing a NPE. Fixed the problem.
krmahadevan added a commit that referenced this issue Jul 14, 2019
Closes #2110

When there is just one test class and user does the
following:

1. Enables thread affinity 
2. Chooses to run with parallel=“classes”

TestNG is throwing a NPE. Fixed the problem.
@mstancl
Copy link

mstancl commented Jul 16, 2019

@krmahadevan Hi,
I see this has been fixed,
I suppose it will be working in next release ? When that might be ?

By the way huge respect for doing that. You guys are doing incredible job and both thumbs up.

Thanks.

@krmahadevan
Copy link
Member Author

@mstancl - It would take sometime before the next beta version gets published.

By the way huge respect for doing that. You guys are doing incredible job and both thumbs up.

No worries. It was fun fixing this bug :) Learnt some new stuff.

@mstancl
Copy link

mstancl commented Jul 18, 2019

Hi krmahadevan,

I tried to compile the GraphThreadPoolExecutor class from this commit da1fa33
that should be fixing this bug,

It indeed does not throw the NPE anymore but its not working correctly.

I noticed that, when i tried to run xml like this :

<suite name="tests" >
    <test  name="testNG tests"  thread-count="50" parallel="classes" >
        <classes>
            <class name="TestClass2"/>
            <class name="TestClass1"/>
        </classes>
    </test>
</suite>

with TestClass1 :

public class TestClass1  {
    
    @Test
    public void test1() {
        System.out.println("TestClass1 - test1. Thread " + Thread.currentThread().getId());
    }
    @Test
    public void test2() {
        System.out.println("TestClass1 - test2. Thread " + Thread.currentThread().getId());
    }
}

and TestClass2 :

public class TestClass2  {

    @Test()
    public void test3() {
        System.out.println("TestClass2 - test3. Thread " + Thread.currentThread().getId());
    }

    @Test(dependsOnMethods = {"test3"})
    public void test4() {
        System.out.println("TestClass2 - test4. Thread " + Thread.currentThread().getId());
    }

    @Test(dependsOnMethods = "test4")
    public void test5() {
        System.out.println("TestClass2 - test5. Thread " + Thread.currentThread().getId());
    }
}

the output looks like this, which is incorrect :

TestClass2 - test3. Thread 9
TestClass1 - test1. Thread 10
TestClass1 - test2. Thread 10
TestClass2 - test4. Thread 10
TestClass2 - test5. Thread 10

I noticed it works fine when i run it like this

<classes>
            <class name="TestClass1"/>
            <class name="TestClass2"/>
</classes>

instead of

<classes>
            <class name="TestClass2"/>
            <class name="TestClass1"/>
</classes>

Is it possible that the numeric order breaks it ?

Thank you very much for your answer,

Martin

@krmahadevan
Copy link
Member Author

@mstancl - Were you using the thread affinity enforcing JVM argument ?

@mstancl
Copy link

mstancl commented Jul 18, 2019

yes i was.
When i tried it without it the output looked like this :

TestClass2 - test3. Thread 9
TestClass1 - test1. Thread 10
TestClass1 - test2. Thread 10
TestClass2 - test4. Thread 11
TestClass2 - test5. Thread 12

@krmahadevan
Copy link
Member Author

@mstancl - I am for now going to be reopening this issue. But I don't know when I will be able to get to this to find out what is going on.

@krmahadevan krmahadevan reopened this Jul 18, 2019
@mstancl
Copy link

mstancl commented Jul 18, 2019

@krmahadevan thanks. Appreciate this.

@mstancl
Copy link

mstancl commented Jul 18, 2019

I was able to make a workaround for myself.

The XML's have to be provided from A-Z order
so for example :

<test  name="Login" >
        <classes>
            <class name="AnnotationAtest"/>
            <class name="AnnotationBtest"/>
            <class name="AnnotationCtest"/>
        </classes>
    </test>

or it won't work (threads will be scrambled)

if you create the XML programmatically you have to sort the XML the other way around (from Z-A, dont know why) and then it also works.

Tried it few times and was able to reproduce the issue when it was not sorted but it was working fine when it was sorted.
Hope this helps you fixing the bug.

Cheers,
Martin


EDIT :
Just found out that this works only when tests have no dependsOnMethods.
With tests dependencies it still not working.
It executes the first 'level' of dependencies correctly but then it puts the whole test execution 'queue' into one Thread.
It is very confusing,

If you try to run 2 classes where the 1st has no dependencies while the 2nd has, it works.
If both have tests with dependencies its not working.

@zqiw
Copy link

zqiw commented Jan 15, 2020

If both have tests with dependencies its not working.

@mstancl - I'm facing the same issue now. Did you figure out any workaround?

@krmahadevan
Copy link
Member Author

This is now closed via #2368

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

Successfully merging a pull request may close this issue.

3 participants