I am trying to write tests that interact with GDB but am having trouble capturing the output. I would like for a log file to be generated which looks like what would have been seen in a terminal had the test been executed by hand. GDB is proving to be very stubborn when it comes to capturing its output however.
I've been able to write Expect scripts which are able to interact with GDB and whose output can be redirected to a log file but I don't want to write my tests in TCL. I'm hoping to use Groovy, which is compatible with Java. For some reason with Perl's Expect and ExpectJ the program output always goes to the terminal and can't be redirected to a file.
I tried starting a GDB process from Java using ProcessBuilder and it mostly works but the output of print statements never appear on stdout and can't be captured. I thought if Expect works then I'd launch expect from Java and have it interact with GDB but in this case most of the program output is lost, never appearing in the stdout of the created process.
So my question is, how can I write a test in Groovy (Java would be fine as well) which interacts with GDB and can capture all of the output?
Pseudo-code:
process = "gdb -q".execute()
waitForPrompt()
send("file exec")
waitForPrompt()
send("run")
send("quit")
Log file:
(gdb) file exec
Reading symbols from exec...done.
(gdb) run
Starting program: exec
<... output ...>
Program exited normally.
(gdb) quit
One possibility is that the GDB output is being dumped on standard error and you are only capturing standard output. You should be able to fix this with a redirect, something like this I think:
process = "gdb -q 2&>1".execute()
A second guess is that it may be worth checking what "show interactive-mode" says in the working and non-working cases. If they differ try "set interactive-mode off" before you do anything else.
A third option is to use GDB's logging facility to write the log file ("set logging file " and "set logging on") and avoid having to capture the output yourself.
If your test involves using gdb to actually debug something, as opposed to testing gdb itself, you should probably look into using the gdb/mi interface.
Related
I built a GUI in JavaFX with FXML for running a bunch of different Python scripts. The Python scripts continuously collect data from a device and print it to the console as it's collected in a loop at anywhere from around 10 to 70 Hz depending on which script was being run, and they don't stop on their own.
I want the end-user to be able to click a button on my GUI which launches the scripts and lets them see the output. Currently, the best I have done was using Runtime.exec() with the command "cmd /c start cmd /k python some_script.py" which opens the windows command prompt, runs python some_script.py in it, and keeps the command prompt open so that you can see the output. The problem with this is that it only works on Windows (my OS) but I need to have universal OS support and that it relies on Java starting an external program which I hear is not very elegant.
I then tried to remedy this by executing the python some_script.py command in Java, capturing the process output with BufferedReader, creating a new JavaFX scene with just a TextArea in an AnchorPane to be a psuedo-Java-console and then calling .setText() on that TextArea to put the script output in it.
This kinda worked, but I ran into many problems in that the writing to the JavaFX console would jump in big chunks of several dozens of lines instead of writing to it line by line as the Python code was making Print() calls. Also, I got a bunch of NullPointerException and ArrayIndexOutOfBoundsException somewhat randomly in that Java would write a couple of hundred lines correctly but then throw those errors and freeze the program. I'm pretty sure both of these issues were due to having so much data at such high data rates which overflowed the BufferedReader buffer and/or the TextArea.setText() cache or something similar.
What I want to know is what approach I should take at this. I cannot migrate the Python code to Java since it relies on someone else's Python library to collect its data. Should I try to keep with the pseudo-Java-console idea and see if I can make that work? Should I go back to opening a command prompt window from Java and running the Python scripts and then add support for doing the same with Terminal in Mac and Linux? Is there a better approach I haven't thought of? Is the idea of having Java code call Python code and handle its output just disgusting and a horrible idea?
Please let me know if you would like to see any code (there is quite a lot) or if I can clarify anything, and I will try my best to respond quickly. Thank you!
My solution was to still call the Python code from the Java Processbuilder, but use the -u option like python -u scriptname.py to specify unbuffered Python output.
I am trying to call WMIC.EXE from Java to acquire battery information.
Here is the source in JavaX (an extended Java dialect): http://tinybrain.de/1001824
To see the equivalent Java source, look here (just the first 60 lines are important, really).
You can run this program with x30.jar - or by just compiling and running the Java source.
Basically it just produces a process (via a .bat file) and gets its output. The "backtick" function works fine with everything else, including stuff on Windows. Just not with WMIC - everything hangs.
The command run is this:
WMIC Path Win32_Battery Get EstimatedChargeRemaining /Format:List
Running this in the command prompt works fine... just not in Java. Java is weird with subprocesses, really.
Any ideas? Thanks...
I believe this is a duplicate of https://stackoverflow.com/a/13367685/3196753.
Quoting:
You will need to get and close your OutputStream before getting and using your InputStream. That will confirm to the process that you've started that you have finished sending input (in this case, no input) to the process.
p.getOutputStream().close();
Remember that on the Process object, getInputStream() input comes from the output stream of the process, and getOutputStream() output goes to the input stream of the process.
I have a Java application which invokes (using Runtime.getRuntime().exec) a bash script like this:
read -e -p "Are you sure you want to do this? (y/n)? "
echo "$REPLY"
The problem is, I never get the prompt part from the bash script (the "Are you sure..." text).
Is there a way to invoke an interactive bash script from Java so that I can read its output? I need it in order to be able to determine which question I'm being asked by the script (in reality it's a much bigger script than described here).
If I run the process from Java through SSH channel with the -t flag (accent on the t flag, without that it won't work), it works fine. But I would like to avoid having to ssh to myself in order to run the script properly, or more precisely, to read its output properly.
From the bash man page when talking about read:
-p prompt
Display prompt on standard error, without a trailing new‐
line, before attempting to read any input. The prompt is
displayed only if input is coming from a terminal.
So you should make sure you are also capturing stderr if you want to see that message. You can perhaps do this when invoking it from java by adding 2>&1 but I'm not positive that java's invocation will honor that.
If you're using ProcessBuilder to invoke it, you should add a call to redirectErrorStream(true) on the process to get stderr visible via stdout reading.
I have not tried to verify this myself, but this page suggests redirecting stdout for the process to /dev/tty to make it think it's connected directly to the tty for the java process. So you'd add a &>/dev/tty to redirect stdout and stderr to /dev/tty, and hopefully that will get it to show up--though that may have it show up on stderr of the controlling Java process instead of the subprocess. I'm not too sure about that.
If you can't do that, another thing to consider would be to try to modify the script so it does an echo -n "<msg>"; read REPLY so the prompt will be displayed on stdout by echo instead of not at all by read
OK, here' the deal.
As Eric pointed out, prompt is displayed only if input is coming from a terminal, so I needed a pseudo terminal to fool the bash script. I managed to do it by using JPty library.
I'm writing a shell script that's supposed to do the following.
- run a Java application that produces output
- run a shell command that produces output
- gather both outputs and send them out in an email
I have control of the source code of all the steps above.
Is there a best practice in gathering output from different sources? Should I redirect everything to a single temp file? Should I write different output to different files then concatenate them? What are the pros and cons of each approach?
If you don't worry about using just Java you could use the Runtime class to execute the shell command withing java (through exec) command, this will return you a Process object on which you have either getInputStream and getOutputStream so you will then be able to process the output of both the Java program and the shell command inside just one place and do whatever you want (keeping it in memory and directly send it by redirecting the outputstream to the inputstream of what you use to send the mail, with another exec) or saving it or whatever.
I'd favor using a second wrapper script which
calls the java program
calls the shell script
Captures output to a single file
reformats that output
suitable for mailing out Actually
does the mailing
Assuming you are using a unix shell, mailing/formatting and shell script calls are much simpler from the command line.
I found a bug in an application that completely freezes the JVM. The produced stacktrace would provide valuable information for the developers and I would like to retrieve it from the Java console. When the JVM crashes, the console is frozen and I cannot copy the contained text anymore.
Is there way to pipe the Java console directly to a file or some other means of accessing the console output of a Java application?
Update: I forgot to mention, without changing the code. I am a manual tester.
Update 2: This is under Windows XP and it's actually a web start application. Piping the output of javaws jnlp-url does not work (empty file).
Actually one can activate tracing in the Java Control Panel. This will pipe anything that ends up in the Java console in a tracing file.
The log files will end up in:
<user.home>/.java/deployment/log on Unix/Linux
<User Application Data Folder>\Sun\Java\Deployment\log on Windows
/~/Library/Caches/Java/log on OS X
(If you can modify the code) you can set the System.out field to a different value:
System.setOut(new PrintStream(new FileOutputStream(fileName)));
If you are running a script (invoking the program via java) from Unix you could do:
/path/to/script.sh >& path/to/output.log
In Mac 10.8.2 logs could be found at /Users/<userName>/Library/Application Support/Oracle/Java/Deployment/log/.
Before you have to enable logging from Java Control Panel. Option "Enable logging" is at tab "Advanced". Java Control Panel could be started from "System preferences".
A frozen console probably means a deadlock (it could also mean repeated throwing of an exception). You can get a stack dump using jstack. jps may make finding the process easier.
try this guide it works for me. it also guides you that how you can set "System.setOut(fileStream);", "System.setErr(fileStream);"