Run GraphicsMagick compare command using im4java + gm4java - java

I am trying to do a GraphicsMagick compare using im4java and gm4java. The GraphicsMagick command I'm using is like this:
gm compare -maximum-error 0 -metric MAE -highlight-style xor -hilight-color red -file C:/output/diffFile.pdf C:/input/file1.pdf C:/input/file2.pdf
I'm trying to translate that into Java. I know that im4java was originally built for ImageMagick and their commands may differ. Is it possible to run the above compare using im4java plus gm4java?
I've tried this:
SimpleGMService service = new SimpleGMService();
service.setGMPath("C:/path/to/graphicsMagick/gm.exe");
try
{
GMConnection connection = service.getConnection();
try {
GMBatchCommand command = new GMBatchCommand(service, "compare");
// create the operation, add images and operators/options
IMOperation op = new IMOperation();
op.metric("MAE");
op.addRawArgs("-file C:/output/diffFile.pdf");
op.addImage();
op.addImage();
ArrayListOutputConsumer output = new ArrayListOutputConsumer();
command.setOutputConsumer(output);
//debug
command.createScript("C:/output/myscript.bat",op);
command.run(op, "C:/input/file1.pdf", "C:/input/file2.pdf");
....
The above gives me the error:
org.im4java.core.CommandException: compare: Unrecognized option (-file C:/output/diffFile.pdf)

You can attain this by using im4java alone or im4java+gm4java. What gm4java gives you is the performance when you need to process a large number of images.
The problem you are getting is due to the improper use of the addRawArgs() method. Each argument you have in your command line needs to be added as individual arguments instead of all together in one string.
Try:
op.addRawArgs("-file", "C:/output/diffFile.pdf");

Related

How to execute bash script using karate and fail if script fails

I'm trying to execute bash script using karate. I'm able to execute the script from karate-config.js and also from .feature file. I'm also able to pass the arguments to the script.
The problem is, that if the script fails (exits with something else than 0) the test execution continues and finishes as succesfull.
I found out that when the script echo-es something then i can access it as a result of the script so I could possibly echo the exit value and do assertion on it (in some re-usable feature), but this seems like a workaround rather than a valid clean solution. Is there some clean way of accessing the exit code without echo-ing it? Am I missing on something?
script
#!/bin/bash
#possible solution
#echo 3
exit 3;
karate-config.js
var result = karate.exec('script.sh arg1')
feture file
def result = karate.exec('script.sh arg1')
Great timing. We very recently did some work for CLI testing which I am sure you can use effectively. Here is a thread on Twitter: https://twitter.com/maxandersen/status/1276431309276151814
And we have just released version 0.9.6.RC4 and new we have a new karate.fork() option that returns an instance of Command on which you can call exitCode
Here's an example:
* def proc = karate.fork('script.sh arg1')
* proc.waitSync()
* match proc.exitCode == 0
You can get more ideas here: https://github.com/intuit/karate/issues/1191#issuecomment-650087023
Note that the argument to karate.fork() can take multiple forms. If you are using karate.exec() (which will block until the process completes) the same arguments work.
string - full command line as seen above
string array - e.g. ['script.sh', 'arg1']
json where the keys can be
line - string (OR)
args - string array
env - optional environment properties (as JSON)
redirectErrorStream - boolean, true by default which means Sys.err appears in Sys.out
workingDir - working directory
useShell - default false, auto-prepend cmd /c or sh -c depending on OS
And since karate.fork() is async, you need to call waitSync() if needed as in the example above.
Do provide feedback and we can tweak further if needed.
EDIT: here's a very advanced example that shows how to listen to the process output / log, collect the log, and conditionally exit: fork-listener.feature
Another answer which can be a useful reference: Conditional match based on OS
And here's how to use cURL for advanced HTTP tests ! https://stackoverflow.com/a/73230200/143475
In case you need to do a lot of local file manipulation, you can use the karate.toJavaFile() utility so you can convert a relative path or a "prefixed" path to an absolute path.
* def file = karate.toJavaFile('classpath:some/file.txt')
* def path = file.getPath()

Java Process object fails to execute given command

I am trying to run a piece of Python code via a Java application. The command when put directly into Command Prompt cd'd to the working directory runs exactly as intended. However, my attempts to use the Runtime and ProcessBuilder classes in conjunction with the Process class has yielded no sign of correct function which would be the creation of a CSV file for every call of the code.
I am running this program using Intellij on Windows 10. I have added each directory I am using to my environmental PATH variable as well as attempting full paths in my commands and just file names. The only source of life I can find is that if I include a .waitFor() method a .isAlive() method will return true before the .waitFor() method is called.
I have searched through various similar questions and concluded that using a ProcessBuilder object is the best way to go and that the biggest issue is probably the structure of my command. However, I have made many iterations and have found nothing that changes the caught error to anything useful.
Here is the privacy augmented code that I have been running, I wrote out the command in full in the process builder as that is the last iteration I have attempted.
for (int y = 1; y < iterator; y++) {
try {
String command =
"C:\\Users\\myName\\AppData\\Local\\Programs\\Python\\Python37\\python C:\\Users\\myName\\IdeaProjects\\projectApplication\\script.py ";
String pythonInputPath = " C:\\Users\\myName\\IdeaProjects\\projectApplication\\bin\\output" + y + ".wav ";
ProcessBuilder pb = new ProcessBuilder(command+Arrays.toString(pythonCommandString).replaceAll("\\s","")+pythonInputPath+Integer.toString(y));
Process p = pb.start();
//Process checks
System.out.println(p.isAlive());
p.waitFor();
System.out.println(p.isAlive());
//Destroying process once complete to ensure smooth iterations
p.destroy();
} catch (Exception ex) {
System.out.println("Problems with python script execution: " + ex);
}
}
They python code takes in a WAV file (pythonInputPath) that is a product of earlier part of the application, an Integer[] that usually includes ~20 values (pythonCommandString), and a single iteration integer (y).
The first call to .isAlive() is true and the second is false as expected however the script normally creates a CSV that should be output to a bin file that exists in the working director and that fails to occur when running from Java. From other examples I expected using the Process builder as opposed to the Runtime stream to work, however, there is no difference in my implementation.
Do not concatenate the program with its arguments. Quoting Oracle ProcessBuilder docs
Each process builder manages these process attributes: a command, a
list of strings which signifies the external program file to be
invoked and its arguments, if any
and
ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2");
Just use the constructor you use, but pass each argument as a separate string, otherwise the OS will try to find an application that is named as a whole command line you gave, and obviously there is no such program

Run external app by userinput

So I'm creating a Java program and I want to make it so that you can ask it to open a program.
But, here's the catch, I want the program it opens to be taken from the user input, right now I'm trying to change this
try{Process p = Runtime.getRuntime().exec("notepad.exe");}
catch(Exception e1){}
Into something that opens a program that you asked it to open.
Here's an example of what I want:
User: Can you open chrome?
Program: Of course, here you go!
chrome opens
Could anyone tell me how I would be able to do this?
You can do it in two ways:
1.By Using Runtime:
Runtime.getRuntime().exec(...)
So, for example, on Windows,
Runtime.getRuntime().exec("C:\application.exe -arg1 -arg2");
2.By Using ProcessBuilder:
ProcessBuilder b = new ProcessBuilder("C:\application.exe", "-arg1", "-arg2");
or alternatively
List<String> params = java.util.Arrays.asList("C:\application.exe", "-arg1", "-arg2");
ProcessBuilder b = new ProcessBuilder(params);
or
ProcessBuilder b = new ProcessBuilder("C:\application.exe -arg1 -arg2");
The difference between the two is :
Runtime.getRuntime().exec(...)
takes a single string and passes it directly to a shell or cmd.exe process. The ProcessBuilder constructors, on the other hand, take a varargs array of strings or a List of strings, where each string in the array or list is assumed to be an individual argument.
So,Runtime.getRuntime.exec() will pass the line C:\application.exe -arg1 -arg2 to cmd.exe, which runs a application.exe program with the two given arguments. However, ProcessBuilder method will fail, unless there happens to be a program whose name is application.exe -arg1 -arg2 in C:.
You can try it with like. Pass whole path of where you install chrome.
try{
Process p = Runtime.getRuntime().exec("C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe");
}
catch(Exception e1){
}
When using exec, it is essentially the same as if you were using the command line on windows. Open Command Prompt, type open, and see if it gives details as to how it opens files. If not, find the opener. Usually when dealing with command line operations, there are multiple parameters that are required for opening files/applications. An example of this would be for opening the "TextEdit.app" application on a mac.
Process p = Runtime.getRuntime().exec("open -a TextEdit.app");
Terminal(for mac) would open the app using the -a flag, meaning "application." You could open a file doing:
Process p = Runtime.getRuntime().exec("open filename.file_ext -a TextEdit.app");
The second one will tell the computer to find the application named <app_name>.app and open the file filename.file_ext
I know this is not going to work for a windows machine, but it's only to show how to use the command line operations for opening files and applications. It should be similar for windows though.
Hope this helps

Execute *nix find command using java code [duplicate]

This question already has answers here:
Java execute command line program 'find' returns error
(2 answers)
Closed 10 years ago.
I am trying to execute a find command using java code. I did the following:
sysCommand = "find . -name '*out*' > file1"
Runtime runtimeObj = Runtime.getRuntime();
try {
Process processObj = runtimeObj.exec(sysCommand);
processObj.waitFor();
...
This Linux command is executed when I use command line but fails in Java, why?
As far as I know, it is not allowable to use any form of piping operator in Runtime.exec. If you want to move the results to a file, you will have to do that part in Java through Process.getInputStream.
If you are interested in doing this in Java then you will want to do something like this:
public void find(File startDirectory, FileFilter filter, List<File> matches) {
File[] files = startDirectory.listFiles(filter);
for (File file:files) {
if(file.isDirectory()) {
find(file, filter, matches);
} else {
matches.add(file);
}
}
}
Then you need but write the FileFilter to accept directories and files that match your pattern.
This question is probably a duplicate or a duplicate.
Anyway, you could use File.list, providing a Filter on the type
of files you want. You could call it recursively to get all sub-directories. I don't love this answer. You would think there is a simpler way.
A friend of mine recommended Commons-Exec from Apache for running a command. It allows you to use a time out on the command. He recommended it because Runtime can have issues with large stdout and stderr.

Different output -- when running mathtext in command line and when the command is executed from a java program using apache-commons-exec

I am trying to run mathtext from a java program using apache-commons-exec. The problem is I am getting different output when I run the same command from a java program and when I run it through shell.
so if run mathtext like this in the shell:
./mathtext test.png "\$\frac{{\left( {{p^2} - {q^2}} \right)}}{2}\$"
in a shell I get the perfect png
but when I run the same thing using apache-commons-exec
Map map = new HashMap();
map.put("target", new File(trgtFileName));
DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
Executor exec = new DefaultExecutor();
exec.setWorkingDirectory(/*I set the working directory where the mathtext is*/);
CommandLine cl = new CommandLine("./mathtext");
cl.addArgument("${target}");
cl.addArgument(latex);
cl.setSubstitutionMap(map);
// Logger.log4j.info("command is:::"+cl.toString());
ExecuteWatchdog watchdog = new ExecuteWatchdog(5000);
exec.setWatchdog(watchdog);
exec.execute(cl,EnvironmentUtils.getProcEnvironment(),resultHandler);
resultHandler.waitFor();
I get the image, not the equation but the raw TeX string :(
Can somebody please help me in solving the issue? I want to get the exact output.
Thanks.
I figured out where the problem was:
$ is a special character for the unix shell and not for java. So even if in the command line the input needs to escape $ like:
"\$\frac{{\left( {{p^2} - {q^2}} \right)}}{2}\$"
inside the java program I dont need to escape the '$' or put " (double quotes) at the beginning and at the end.I had to put the command like:
$\frac{{\left( {{p^2} - {q^2}} \right)}}{2}$
Hope this helps somebody :)
--Shankhoneer

Categories

Resources