{"action":"created","issue":{"url":"https://api.github.com/repos/cbeust/testng/issues/690","repository_url":"https://api.github.com/repos/cbeust/testng","labels_url":"https://api.github.com/repos/cbeust/testng/issues/690/labels{/name}","comments_url":"https://api.github.com/repos/cbeust/testng/issues/690/comments","events_url":"https://api.github.com/repos/cbeust/testng/issues/690/events","html_url":"https://github.com/cbeust/testng/issues/690","id":76478975,"number":690,"title":"NPE in DependencyMap.getMethodDependingOn() with filtering IMethodInterceptor","user":{"login":"lbergelson","id":4700332,"avatar_url":"https://avatars3.githubusercontent.com/u/4700332?v=4","gravatar_id":"","url":"https://api.github.com/users/lbergelson","html_url":"https://github.com/lbergelson","followers_url":"https://api.github.com/users/lbergelson/followers","following_url":"https://api.github.com/users/lbergelson/following{/other_user}","gists_url":"https://api.github.com/users/lbergelson/gists{/gist_id}","starred_url":"https://api.github.com/users/lbergelson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lbergelson/subscriptions","organizations_url":"https://api.github.com/users/lbergelson/orgs","repos_url":"https://api.github.com/users/lbergelson/repos","events_url":"https://api.github.com/users/lbergelson/events{/privacy}","received_events_url":"https://api.github.com/users/lbergelson/received_events","type":"User","site_admin":false},"labels":[{"id":230596133,"url":"https://api.github.com/repos/cbeust/testng/labels/Feature:%20interceptor","name":"Feature: interceptor","color":"0e8a16","default":false}],"state":"closed","locked":false,"assignee":{"login":"krmahadevan","id":909773,"avatar_url":"https://avatars0.githubusercontent.com/u/909773?v=4","gravatar_id":"","url":"https://api.github.com/users/krmahadevan","html_url":"https://github.com/krmahadevan","followers_url":"https://api.github.com/users/krmahadevan/followers","following_url":"https://api.github.com/users/krmahadevan/following{/other_user}","gists_url":"https://api.github.com/users/krmahadevan/gists{/gist_id}","starred_url":"https://api.github.com/users/krmahadevan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/krmahadevan/subscriptions","organizations_url":"https://api.github.com/users/krmahadevan/orgs","repos_url":"https://api.github.com/users/krmahadevan/repos","events_url":"https://api.github.com/users/krmahadevan/events{/privacy}","received_events_url":"https://api.github.com/users/krmahadevan/received_events","type":"User","site_admin":false},"assignees":[{"login":"krmahadevan","id":909773,"avatar_url":"https://avatars0.githubusercontent.com/u/909773?v=4","gravatar_id":"","url":"https://api.github.com/users/krmahadevan","html_url":"https://github.com/krmahadevan","followers_url":"https://api.github.com/users/krmahadevan/followers","following_url":"https://api.github.com/users/krmahadevan/following{/other_user}","gists_url":"https://api.github.com/users/krmahadevan/gists{/gist_id}","starred_url":"https://api.github.com/users/krmahadevan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/krmahadevan/subscriptions","organizations_url":"https://api.github.com/users/krmahadevan/orgs","repos_url":"https://api.github.com/users/krmahadevan/repos","events_url":"https://api.github.com/users/krmahadevan/events{/privacy}","received_events_url":"https://api.github.com/users/krmahadevan/received_events","type":"User","site_admin":false}],"milestone":null,"comments":2,"created_at":"2015-05-14T20:25:06Z","updated_at":"2018-04-01T06:42:52Z","closed_at":"2018-04-01T06:42:52Z","author_association":"NONE","body":"I have a CI system that runs one build on multiple nodes, and provides each node with environment variables that say how many nodes there are total, and what number node you're currently running on.  I want to evenly split my tests across the nodes by distributing them according to some value mod the number of total nodes.  \n\nI wrote a custom IMethodInterceptor to implement this, but it usually crashes with a NPE\n\n```\n  public class ParallelSplittingListener implements org.testng.IMethodInterceptor {\n        private final int totalNodes;\n        private final int nodeNumber;\n\n        public ParallelSplittingListener(){\n            String totalString = System.getenv(\"CIRCLE_NODE_TOTAL\");\n            String indexString = System.getenv(\"CIRCLE_NODE_INDEX\");\n            if ( totalString != null && indexString != null) {\n                this.totalNodes = Integer.valueOf(totalString);\n                this.nodeNumber = Integer.valueOf(indexString);\n            } else {\n                this.totalNodes = -1;\n                this.nodeNumber = 1;\n            }\n        }\n\n        @Override\n        public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {\n            if (totalNodes > 1 && nodeNumber > -1 ) {\n                List<IMethodInstance> result = new ArrayList<>();\n                for (IMethodInstance m : methods) {\n                    int shard = m.getMethod().getMethodName().hashCode() % totalNodes;\n                    if (shard == nodeNumber) {\n                        result.add(m);\n                    }\n                }\n                return result;\n            } else {\n                return methods;\n            }\n        }\n    }\n```\n\nI'm invoking my tests through gradle, so the stack trace includes gradle stuff, but the cause seems to be `DependencyMap.getMethodDependingOn`  \n\n```\norg.gradle.api.internal.tasks.testing.TestSuiteExecutionException: Could not complete execution for Gradle Test Executor 1.\n    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)\n    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n    at java.lang.reflect.Method.invoke(Method.java:497)\n    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)\n    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)\n    at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)\n    at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)\n    at com.sun.proxy.$Proxy2.stop(Unknown Source)\n    at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:116)\n    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n    at java.lang.reflect.Method.invoke(Method.java:497)\n    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)\n    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)\n    at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:360)\n    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)\n    at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)\n    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)\n    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)\n    at java.lang.Thread.run(Thread.java:745)\nCaused by: java.lang.NullPointerException\n    at org.testng.DependencyMap.getMethodDependingOn(DependencyMap.java:58)\n    at org.testng.TestRunner.createDynamicGraph(TestRunner.java:1062)\n    at org.testng.TestRunner.privateRun(TestRunner.java:734)\n    at org.testng.TestRunner.run(TestRunner.java:617)\n    at org.testng.SuiteRunner.runTest(SuiteRunner.java:348)\n    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:343)\n    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:305)\n    at org.testng.SuiteRunner.run(SuiteRunner.java:254)\n    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)\n    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)\n    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)\n    at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)\n    at org.testng.TestNG.run(TestNG.java:1057)\n    at org.gradle.api.internal.tasks.testing.testng.TestNGTestClassProcessor.runTests(TestNGTestClassProcessor.java:136)\n    at org.gradle.api.internal.tasks.testing.testng.TestNGTestClassProcessor.stop(TestNGTestClassProcessor.java:80)\n    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:59)\n    ... 22 more\n```\n\nThe documentation on  `IMethodInterceptor` says \n\n> Only methods that have no dependents and that don't depend on any other test methods will\n> be passed in parameter.  Implementers of this interface need to return a list of {@link IMethodInstance}\n> that represents the list of test methods they want run.  TestNG will run these methods in the\n> same order found in the returned value.\n\nThat makes me think that I should be able to arbitrarily filter this list without causing any problems, but it seems like it does cause problems.  I did see #215, but I'm not sure it addressed the issue I'm having, since I'm not editing any dependencies at all, I just want to filter tests out.  \n"},"comment":{"url":"https://api.github.com/repos/cbeust/testng/issues/comments/377766619","html_url":"https://github.com/cbeust/testng/issues/690#issuecomment-377766619","issue_url":"https://api.github.com/repos/cbeust/testng/issues/690","id":377766619,"user":{"login":"krmahadevan","id":909773,"avatar_url":"https://avatars0.githubusercontent.com/u/909773?v=4","gravatar_id":"","url":"https://api.github.com/users/krmahadevan","html_url":"https://github.com/krmahadevan","followers_url":"https://api.github.com/users/krmahadevan/followers","following_url":"https://api.github.com/users/krmahadevan/following{/other_user}","gists_url":"https://api.github.com/users/krmahadevan/gists{/gist_id}","starred_url":"https://api.github.com/users/krmahadevan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/krmahadevan/subscriptions","organizations_url":"https://api.github.com/users/krmahadevan/orgs","repos_url":"https://api.github.com/users/krmahadevan/repos","events_url":"https://api.github.com/users/krmahadevan/events{/privacy}","received_events_url":"https://api.github.com/users/krmahadevan/received_events","type":"User","site_admin":false},"created_at":"2018-04-01T06:42:52Z","updated_at":"2018-04-01T06:42:52Z","author_association":"COLLABORATOR","body":"I am not able to reproduce this problem using TestNG `6.14.3` (the latest released version). Please comment if this is still a problem and also help share a reproducible test."}}
{"actor":{"display_login":"krmahadevan"}}