I am asking this question particularly for an Expect implementation in Java. However, I would like to know general suggestions as well.
In Expect programming, is it possible to expect exactly what is prompted after spawning a new process?
For example, instead of expecting some pattern or a fixed string, isn't it better to just expect what is prompted. I feel this should be really helpful at times(especially when there's no conditional sending).
Consider the sample java code here that uses JSch and Expect4j java libraries to do ssh and execute list of commands(ls,pwd,mkdir testdir) on the remote machine.
My question here is why is it necessary to specify a pattern for the prompt? Is it not possible it to get the exact prompt from Channel itself and expect it?
I've programmed in "expect" and in "java".
I think you misunderstand what "expect" basically does. It doesn't look for exact items prompted after spawning a new process.
An expect program basically consists of:
Something that reads the terminal
A set of patterns (typically regular expressions), coupled to a blocks of code.
So, when a new process is spawned, there's a loop that looks something like this
while (terminal.hasMoreText()) {
buffered_text += terminal.readInput();
for (Pattern pattern : patterns) {
if (pattern.matches(buffered_text)) {
String match = pattern.getMatch(buffered_text);
bufferedText.removeAllTextBefore(match);
bufferedText.removeText(match);
pattern.executeBlock();
}
}
}
Of course, this is a massive generalization. But it is close enough to illustrate that expect itself doesn't "exactly expect" anything after launching a process. The program provided to the expect interpreter (which primarily consists of patterns and blocks of code to execute when the patterns match) contains the items which the interpreter's loop will use to match the process's output.
This is why you see some pretty odd expect scripts. For example, nearly everyone "expects" "ogin:" instead of "Login:" because there's little consistency on whether the login prompt is upper or lower case.
You don't have to expect anything. You're free to just send commands immediately and indiscriminately.
It's considered good practice to only reply to specific prompts so that you don't accidentally ruin something by saying the wrong thing at the wrong time, but you're entirely free to ignore this.
The main consideration is that while your normal flow might be:
$ create-backup
$ mkdir latest
$ mv backup.tar.gz latest
With no expectations and just blindly writing input, you can end up with this:
$ create-backup
Disk full, cleanup started...
Largest file: precious-family-memories.tar (510MB)
[R]emove, [S]ave, [A]bort
Invalid input: m
Invalid input: k
Invalid input: d
Invalid input: i
Removing file...
$ latest
latest: command not found
$ mv backup.tar.gz latest
whereas a program that expects $ before continuing would just wait and eventually realize that things are not going according to plan.
A few commands are sensitive to timing (e.g. telnet), but other than that you can send commands whenever you want, with or without waiting for anything at all.
Related
I am going through the Java IO. Just started with standard input and output streams. Please look at the simple program given below,
public static void main(String args[]){
Scanner scanner = new Scanner(System.in);
System.out.println("Give us your input");
String str = scanner.nextLine();
System.out.println("Standard Output: " + str);
System.err.println("Standard Error Output: " +str );
}
The output varies while running this two or three times. Please find couple of the outputs below,
Running for the first time:
Give us your input
my Name
Standard Error Output: my Name
Standard Output: my Name
Process finished with exit code 0
Running second time with the same code:
Give us your input
my Name
Standard Output: my Name
Standard Error Output: my Name
Process finished with exit code 0
I would like to know why the output changes with System.err
Your program will write to first System.out and then System.err (and println will flush these streams as well), but there is no guarantee in which order/interleaving the two streams will appear in your console.
Since you are writing to them at practically the same time, you will get both combinations. I suppose you might even get half-line interleavings.
System.out and System.err write to different streams that are connected via different pipes to your command shell. The command shell will then read from these pipes and write the data to your console application. That will ultimately write to your screen.
There are a number of places where data written to one stream could "overtake" data written to the other one.
It could possibly occur in the JVM itself, since the Java specs make no guarantees about which stream gets written first. (In fact, this is unlikely if there is only one thread doing the writing. With current Java implementations, the behavior will probably be deterministic ... though unspecified.)
It could be happening in the OS, since there are no guarantees on the order of delivery of data written to two independent pipes.
It could be happening in the shell, since nothing in the shell specs place any priority of reading from the pipes.
In short, there are lots of areas where the behavior is unspecified.
It is also worth noting that the observed behavior is liable to depend on the version of Java you use, the OS and OS tools, your hardware, and the load on your system.
Finally, there is probably nothing that you could do to guarantee that the observed interleaving (or not) are consistent. If you need consistency, write your output to one stream or the other exclusively.
no guarantee of order for System.out, System.in, System.err anything can be appeared first so order of these streams are not fixed
In c++ we could use macro as
#define check_and_log_warning(x) if (!(x)) {log_error(#x); cout<<__LINE__;}
I want to get values of a boolean expression and also use it as a string.
Getting the line number inside macro would be added benefit.
Can something like this macro be written in Java ?
I recently moved from c/c++ to java, so I am wondering could such thing be done in c++ without macro ?
Preprocessor is what I miss from C/C++ in Java. There are ways ..., but they are Java ways.
1/ Assertions:
http://docs.oracle.com/javase/7/docs/technotes/guides/language/assert.html
2/ Logs:
The one that I use is https://commons.apache.org/proper/commons-logging/
(over log4J or whatever you want)
To print line numbers in log messages, you can use something like:
int lineNo = Thread.currentThread().getStackTrace()[2].getLineNumber();
Edit:
Be warned: unlike __LINE__ in C++ getting the stack trace incurs a performance penalty. Be nice :)
There is no macro facility in Java.
You would be using a logging framework (of which there are plenty to choose from).
if (! theActualConditionNotJustX) myLogger.error("describe problem here");
The logging backend (if configured that way) makes sure to capture and display line numbers. There is some runtime cost for this, but it is usually negligable, especially where actual "errors" are involved (it can get a bit costly for trace-level logging).
I have the following code for logging all the errors after every command I run in cmd with my tool. (It runs p4 integrate commands, about 1000-1500/task)
if (errorArrayList.size() > 0) {
LoggerSingleton.I.writeDebugInfoTimeStampedLog("[INFO-CMD] CommandExecuter.java -> runAndGetResults: errors happened while running the following command: [ " + commandResultBean.getCommand() + " ]");
for (int i = 0; i < errorArrayList.size(); i++) {
LoggerSingleton.I.writeDebugErrorTimeStampedLog(errorArrayList.get(i));
commandResultBean.addToCLI_Error(errorArrayList.get(i));
}
LoggerSingleton.I.writeDebugInfoTimeStampedLog("[INFO-CMD] CommandExecuter.java -> runAndGetResults: Listing errors of command [" + commandResultBean.getCommand() + "] finished");
}
The feature that I'm working on right now is check the error I get, and if that's on a predefined error list (list of errors that doesn't matter, and in fact not real errors, for example "all revision(s) already integrated") do nothing else, but when it's a "real" error, write it to an other log file too (Because these debug logs way too long for the users of the tool, it's made for the developers more likely).
The question is, what is the best way for this?
I want to avoid big deceleration. I have many commands, but the number of errors less then the commands, but that is not unusual at all that I get 700-800 "irrelevant" errors in one task.
I will use another class to make the I/O part, and that is not a problem to extend the running time in case we catch a "real" error.
The list is constant, it is okay if it can be modified only by coding.
At the moment I don't know what type to use (2-3 single Strings, List, Array ...). What type should I use? I never used enums in Java before, in this one should I?
I guess a for or foreach and errorArrayList.get(i).contains(<myVariable>)in a method is the only option for the checking.
If I'm wrong, there is a better way to do this?
EDIT
If I have an ArrayList<String>called knownErrors with the irrelevant errors (can define only parts of it), and I use the following code will better performance than a method wrote above? Also, can I use it if I have only parts of the String? How?
if (errorArrayList.removeAll(knownErrors) {
//do the logging and stuff
}
ArrayList itself has a method removeAll(Collection c) which removes all the elements which are matching with input collection elements. Below program show it evidently. So if you have the known error to be skipped in arraylist and pass it to removeall method it will remove the known errors and errorArrayList will have only new errors.
This has been asked before, but was not clarified to the point where I get it. Similar to the one or two other threads I've seen on this subject, I'm working on a chat client with command line inputs for logging in/off, disconnecting, etc. and I am unsure how to simulate this in a JUnit test case. Other responses indicated that I should try changing the System.in to a separate InputStream but...then what?
tl;dr: I have a method in my actual code for parsing command line input, and need a JUnit way of testing that these were entered and appropriately processed.
EDIT: It seems I misunderstood the question. I usually use the term "command line input" to refer to command line arguments given to the process to start with, rather than interactive console input. However...
Handing your real code either a different InputStream or possibly even a Reader or Scanner would indeed help - anything to separate the "getting input" part from the console. You can then fake the input all in one go pretty easily, using a String as input in your test code, and then either converting it to bytes and wrapping those bytes in a ByteArrayInputStream or wrapping the string directly in StringReader.
The downside of this is that there's no easy way of making this "pause" after one command in order to check the results.
You may want to alter the design somewhat so that the part which reads the input is separated from the part which handles the input. The reading part could be a very simple loop, on the order of:
String line;
while ((line = reader.readLine()) != null) {
handleInput(line);
}
You could then potentially leave that part untested by unit tests, or write some relatively primitive tests - but you can then test handleInput extensively, as it's now separated from the input source.
Original answer
If you've extracted the parsing code from the code which really starts the application, it's easy: run that code, and check the results. This will be easiest if you have some sort of class encapsulating the options, of course. For example, your main method might look like this:
public static void main(String[] args) {
Options options = Options.parse(args);
// Use options here
}
Then you can just test Options.parse very easily.
I have a question which is described below:
What problems would arise for testing a Java class which counts number of words in a file?
The function's signature is below:
public int wordCount(String filename)
Well, this is a junit testing question.
If you know the problem, what is the solution of that?
So your question is what to test for? If yes, I'd say you should check if the definition of "word" is implemented correctly (e.g. is "stack-overflow" one word or two), are new lines handled correctly, are numbers counted as words (e.g. difference between "8" and "eight"), are (groups of special) characters (e.g. a hyphen) counted correctly.
Additionally, you should test whether the method returns the expected value (or exception) if the file does not exist.
This should be a good starting point.
To sfussenegger's list, I'd add the file handling checks: does the method respond correctly to files not found (including null filename), or lacking read permission?
Also, to sfussenegger's correctness list, I'd add whether duplicates count and case sensitivity rules, as well.
Of course, all of this requires that you know how the method is supposed to behave for all of these specifics. It's easy to tell someone to "go count words", but there are subtleties to that assignment.
Which is one of the big benefits of writing a good set of unit tests.
This really sounds like a task for FIT: Framework for Integrated Test. It's an acceptance testing framework that works with ant and JUnit.
One docent of mine did such a task and used this framework. It allows you to write a whole bunch of test cases within one html/wiki table. FIT will interpret each line as a parameter set for the function under test and checks the output.
For example:
This table displays the result of three test cases. Two passed, one failed.
You can use fit if you write sentences and define the number of words in your table. With FIT, they're executed and the result is displayed in a new table.
For further information, please read Introduction to FIT.