Testing a multithreaded application with JUnit5, the automated tests run just fine.
But in manual debugging, the environment misbehaves, and I would like to know how to get it to act as it should.
IntelliJ (using the Java VM + its debugger) has two general options to suspend on breakpoints: either "All" = all threads, or "Thread" = the current thread only.
(Which thread is "the current thread" may be unclear and causing issues, but that's been discussed separately, see other issues here on stackOverflow.)
Wanted behaviour:
a breakpoint to suspend a specific thread, and the JUnit test environment, which is part of the IDE debugging.
Actual behaviour:
either all threads are suspended, even those which should be running
or only a single thread is suspended, and JUnit #AfterEach/#AfterAll annotations kill the resources currently debugged, terminating the threads that should be running, etc.
How to achieve the Wanted behaviour?
(Environment: AdoptOpenJDK8, AdoptOpenJDK11 in Java 9 mode, IntelliJ 2020.3, JUnit-Jupiter 5.7.0)
You can use two breakpoints. The one you're really interested in and another one in your unit test (somewhere between calling the code under test and cleaning up). Set both to only suspend the current thread.
Related
I'm trying to test existing software and I'm running into an issue; if, during a junit test suite, I close a gui window, the whole test suite just ends. No errors, failures, or successes. It definitely ends too, because it closes all other windows as well, and terminates the thread.
I'm not using junit to the test the GUI - that's more of a system test obviously, and I'm using GUI automation software for that. However, in order to test a method in one of the classes in the software, I have to have stuff going on with the gui. At the end of the tests, I need to close the windows or they will remain open and will actually interfere with the other tests (it's networked software). However, as said, sending an onclosing event to any window immediately ends the test suite.
I became curious about the whole thing and slowly came to realize, to my horror, that even in normal execution, if I close a window, it's not handled within the software, it just magically stops executing! The main driver's loop doesn't even have any exit condition whatsoever, just while(true) with no breaks! My thinking is this must be related to why everything just stops when I close a window during the tests.
Anyways, I still don't fully understand what's happening, so if someone could fill me in, that would be great. But my main question is how can I fix/ get around this issue and close windows without killing the whole test suite.
Note: I can't change the behavior of the software. (As you may have guessed, this is for a class)
Sounds like the window close is calling System.exit(). If you have the ability to remove that, you could do so. If you don't, you could install a SecurityManager that prevents the call during testing. Example here: Preventing System.exit() from API
I have written tests for my windows based application in TestNG. Sometimes my tests will result in BSOD of windows, so the test will run waiting for the Windows to be up till timeout and fail.
I have written a Listener for BSOD detection and handling, so that whenever the test starts the BSOD detector will start as listener and handle if the BSOD occurs. But still I have no way to notify my test that it has to halt. It still continues to execute till timeout.
How can solve this problem? Is there a way to notify the test to terminate it from Listener?
I think you may be out of luck.
The discussion at https://groups.google.com/forum/#!topic/testng-users/BkIQeI0l0lc clearly indicates that, as of August 2012 there was no way to stop a running test suite.
That combined with a much older post (https://groups.google.com/forum/#!topic/testng-users/FhC3rqs1yDM) from February 2010 suggests it has been a shortcoming of TestNG for a while.
The current TestNG documentation does not describe any methods for stopping the suite.
From what I can see in the source code (although I have not traced through all paths) at https://github.com/cbeust/testng/blob/master/src/main/java/org/testng/TestNG.java, it simply creates new tasks for each test and runs them, providing no way to break early.
Perhaps you could modify your tests to have access to some flag that indicates if subsequent tests should be skipped (triggered by, e.g., the BSOD detector). Then all of your subsequent tests are responsible for indicating themselves as skipped if this flag is set. It might not be ideal, but one way to think about it is: Any test should be skipped if a BSOD (or other terminal event) was detected prior to that test.
You could request this feature on the TestNG Google Group (linked above). If you are so inclined, you could also perhaps customize the TestNG source.
I have a Windows MFC application that:
(1) Loads the JVM (JNI_CreateJavaVM())
(2) Attaches the main thread to the JVM (AttachCurrentThread())
(3) Loads some Java classes and methods (FindClass() and GetMethodID() / GetStaticMethodID())
(4) Registers some native callbacks for use by Java code (RegisterNatives())
(5) Detaches the thread from JVM (DetachCurrentThread())
(6) Destroys the JVM (DestroyJavaVM())
All of the above functions succeed every other time I run the application. I know they succeed, because, additionally to the above, I interact with the application and successfully call Java static methods, and these Java methods successfully call my native callbacks. My application exits gracefully, and it is certain that the expected Java functions, and native callbacks, have been executed.
However, every other time that I run the application, the call to JNI_CreateJavaVM() fails (not populating the JavaVM *). Absolutely nothing changes between runs of the application. I simply run it once (successfully, even without doing anything except the above 6 steps), quit gracefully, run again, and it fails, back and forth. There are no exceptions to the back-and-forth success/failure - I can run it dozens of times, and it oscillates precisely every other time between success, and failing on the JNI_CreateJavaVM() line.
If necessary, I will paste more code. However, I hope somebody has an insight with what I've provided. (Note: this is a BCGSoft MFC property-sheet application, though I strongly doubt that matters.)
It looks like you are running into this bug (restated here) that is probably never going to be fixed.
Despite its name, DestroyJavaVM() does not actually destroy the JVM. What it does is signal the JVM that it should shut down, but the JVM actually waits until all the threads other than the Main thread have stopped before it actually shuts down. In fact, even then it does not fully clean up after itself, as the documentation states (quite cryptically): "The JDK/JRE still does not support VM unloading, however."
Also, I'm concerned about your step 2, "Attaches the main thread to the JVM". You do not need to attach the thread that created the JVM to the JVM and you may not detach that thread. If you really are doing that, then it's possible that is what is messing up your system. (The thread that creates the JVM is the JVM's "Main" thread. You only need to attach/detach other native threads to the JVM if they need access to it.)
By the way, JNI_CreateJavaVM() returns 0 on success, and you say it returns 0 the "failed" times, so in what sense is it failing? Which JVM (version, vendor) are you using?
I'm developing an artificial intelligent program to explore a given space for resources.
I'd like to run multiple scenarios in order to collect data and output to a file.
I used the "multiple runs" option in the gui and i do stop() when one module run is finished (all the resources have been explored). The problem is when It runs the model a second turn, it doesn't work properly.
What I mean is that after running once I always need to kill the application by exiting because the restart option doesn't work properly.
Is there anything that "restart" forgets to do? Because if I exit the application and run it again it works perfectly
Edited so it's more clear:
I use the Repast platform in order to simulate an exploration to Mars. I have 3 kinds of agents, scouting, digging and transporting. They communicate among them to schedule tasks and other things.
The first time I run the simulation everything runs smoothly. And when all the mineral resources of the planet have been explored I restart the model and try again so I can collect data.
The problem is, when I use the "restart" option the Simulation doesn't run well. But if I exit (not restart) and run it again it works fine.
What I'd like to know is if the restart option of Repast GUI misses any steps..
Thanks in advance
PS: If you guys think that it's absolutely necessary I can post some code...but the project is quite big
Don't use Thread.stop() method. It is deprecated. Thread.stop is being deprecated because it is inherently unsafe. Stopping a thread causes it to unlock all the monitors that it has locked. (The monitors are unlocked as the ThreadDeath exception propagates up the stack.) If any of the objects previously protected by these monitors was in an inconsistent state, other threads might view these objects in an inconsistent state. Such objects are said to be damaged. Threads operating on damaged objects can behave arbitrarily, either obviously or not. Unlike other unchecked exceptions, ThreadDeath kills threads silently; thus, the user has no warning that the program may be corrupted. The corruption can manifest itself at an unpredictable time after the damage occurs. Substitute any use of Thread.stop with code that provides for a gentler termination.
http://docs.sun.com/app/docs/doc/805-4031/6j3qv1of1?a=view
Consider thread stopping either via Thread.interrupt() or via setting cancel flag. Look at Java Concurrency in Practice, Section 7.1. Task Cancellation.
I have a program 'foo' running different threads, fooT1, fooT2, .. fooTn.
Now if I want write another program 'bar', which could kill the thread fooTr, is that possible?
Reason: One of the thread fooTr tracks product license. If this thread is killed; one may run this product indefinitely. And killing 'foo' itself is tolerable as 'foo' as that is exactly what is being done on license expiry.
System: Fedora Distribution of Linux
Note: The commands which start JVM and program foo are placed in /etc/init.d and anyone who has a decent knowledge of rc.1/rc.2/rc.3 structure can change/add the starting parameters to these.
I hope my question is clear. If not, I can always edit it.
Actually the java debugger will allow you to kill a thread by injecting an exception into it. I was just trying to work out how to use this feature to kill a thread without wiping out the whole jvm, when I came across this question. If you run the jvm with command line options like:
java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8888 your.app.Main
and connect the debugger with something like:
jdb -attach 127.0.0.1:8888
you can type:
threads
to get a list of the running threads, and use the kill command to kill a running thread. The bit I'm currently not sure about is the syntax of this kill command, I have tried the obvious:
kill 0xe2e new java.lang.IllegalArgumentException("er");
and I get the messages:
killing thread: Swank REPL Thread
Thread not suspended
Expression must evaluate to an object
("Swank REPL Thread" is the thread I want to kill, and yes, I've tried suspending it first ;)
Still my inability to use the java debugger aside, it looks to me like a thread can be killed at random. Maybe you can just make sure you ignore all exceptions and keep running and that will be enough, but I'm not sure about that.
To my knowledge it is not possible to do this directly. What you could consider however is to create some kind of service on your 'foo' that can be called from 'bar' to kill the thread. There are, of course, hundreds of ways to implement this. My first thought would be to do this using RMI.
You could do this even without a separate application. Write your own startup class, which performs a pass-through of parameters to the original startup class of the application. Your class's main method though would create a thread that periodically checks the list of all threads (e.g., Thread.getAllStackTraces or Thread.enumerate), finds the offending thread, and invokes stop() on it. Although Thread.stop is deprecated, it still works.
Another option is to run the application under a Java debugger, say, jdb and then suspend/kill the required thread. You could also add parameters to the application's startup so that the JVM can be attached to, then attach jdb to the running JVM and suspect/kill the thread.
Until now isnĀ“t possible to run to diferent programs in the same JVM, but some people is investigating it, in order to reduce the startup time and the memory and cpu usage of diferent java programs runing in the same machine