Trouble understanding how expect.expect() works

152 views
Skip to first unread message

danper...@gmail.com

unread,
Sep 25, 2016, 11:32:35 PM9/25/16
to Yet another Expect for Java
I have been unable to understand how the expect logic works. I am able to get some commands to work but not others. Changing the matcher produces unexpected results. For example I extract the hostname and store it in a variable. After a command is entered I make it look for the hostname with expect.expect(contains(Hostaname)); but that does not work.

I have revered to using the match all regex but that seems to not work all the time as well. I guess I just don't understand how it works.

Below I can get the wall announcement to work after I enter enable mode(cpmmands in the if(Hostname.contains(">")){). However I can not get the output from the for loop after. I know the for loop is working because I see the red test in the Eclipse terminal.

public static void SSHConnect(List<String> commands, String IPAddress, String Username, String Password,
String EnablePassword) throws IOException, InterruptedException, JSchException {

StringBuilder wholeBuffer = new StringBuilder();
List<String> Responses = new ArrayList<String>();
JSch jSch = new JSch();

Session session = jSch.getSession(Username, IPAddress, 22);


session.setPassword(Password);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);

//Attempt to connect. if unable catch exception and return response
try {
session.connect();
} catch (JSchException e) {
e.printStackTrace();
String error = e.toString();
if(error.contains("UnknownHostException")){
CPE.infoBox("Unable to connect to: " + IPAddress + "\n", "Connection Error" );
}
if(error.contains("Auth fail")){
e.printStackTrace();
CPE.infoBox("Authentication failed for: " + IPAddress + "\n", "Connection Error" );
}
return;
}
Channel channel = session.openChannel("shell");
channel.connect();

Expect expect = new ExpectBuilder()
.withOutput(channel.getOutputStream())
.withInputs(channel.getInputStream(), channel.getExtInputStream())
.withEchoInput(System.out)
.withEchoInput(wholeBuffer)
.withEchoOutput(System.err)

.withInputFilters(removeColors(), removeNonPrintable())
.withExceptionOnFailure()
.build();
try {

Thread.sleep(500);
//Wait a little bit for the buffer to fill. then convert to init
String init = wholeBuffer.toString();
//Grab the Hostname so we can tell if we are in enabled mode, pos +1 because we dont actually want the new line char
String Hostname = init.substring(init.lastIndexOf("\n") + 1, init.length());
//If Hostname contains > we need to enable. if not we can go straight to entering commands
if(Hostname.contains(">")){
expect.expect(contains(">"));
expect.sendLine("enable");
expect.expect(contains("Password:"));
expect.sendLine(EnablePassword);
expect.expect(regexp((".*")));
expect.sendLine("Wall this works");
expect.sendLine();
}

Thread.sleep(500);
init = wholeBuffer.toString();
if(init.contains("% Incorrect password")){
CPE.infoBox("The enable password was incorrect", "Bad Enable Password");
}

expect.expect(regexp((".*")));
commands.add("wall why doesnt this work?");
for(int i = 0; i < commands.size(); ++i){
expect.sendLine(commands.get(i));
}

} finally {
expect.close();
channel.disconnect();
session.disconnect();
}
}

danper...@gmail.com

unread,
Sep 25, 2016, 11:40:29 PM9/25/16
to Yet another Expect for Java, danper...@gmail.com

Additionally something like this does not work as well

commands.add("wall what doesnt this work?");
expect.expect(anyString());

danper...@gmail.com

unread,
Sep 26, 2016, 12:34:12 AM9/26/16
to Yet another Expect for Java, danper...@gmail.com
This semi works. I cant explain why. I am not sure why the Thread.sleep is messing with it. However with this I am only getting some of the commands to execute. However I need to Thread.sleep to wait for the buffer to catch up so I can make sure the user entered the correct enable password

if(Hostname.contains(">")){
expect.expect(contains(">"));
expect.sendLine("enable");
expect.expect(contains("Password:"));
expect.sendLine(EnablePassword);
expect.expect(regexp((".*")));

expect.sendLine("Wall works");
expect.sendLine();
}

commands.add("wall test from loop 1");
commands.add("wall test from loop 2");
commands.add("wall test from loop 3");
commands.add("wall test from loop 4");
commands.add("wall test from loop 5");



for(int i = 0; i < commands.size(); ++i){

expect.expect(regexp((".*")));
expect.sendLine(commands.get(i));
}


In the router I am only getting the following:
VoIPLab-TA916e#Broadcast (WALL) from: SSH 1 (MY IP:52254)
works
Broadcast (WALL) from: SSH 1 (MY IP:52254)
test from loop 1
Broadcast (WALL) from: SSH 1 (MY IP:52254)
test from loop 2

danper...@gmail.com

unread,
Sep 26, 2016, 12:39:04 AM9/26/16
to Yet another Expect for Java, danper...@gmail.com
Here is another strange thing. With that error check function commented out none of the commands in the for loop get executed at all. Even though its functionally the same

if(Hostname.contains(">")){
expect.expect(contains(">"));
expect.sendLine("enable");
expect.expect(contains("Password:"));
expect.sendLine(EnablePassword);
expect.expect(regexp((".*")));

expect.sendLine("Wall works");

}

//Thread.sleep(500);
//init = wholeBuffer.toString();
//if(init.contains("% Incorrect password")){
//CPE.infoBox("The enable password was incorrect", "Bad Enable Password");
//}


commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");
expect.expect(regexp((".*")));

danper...@gmail.com

unread,
Sep 26, 2016, 12:46:42 AM9/26/16
to Yet another Expect for Java, danper...@gmail.com
One more example. First section works. Second section does not

if(Hostname.contains(">")){
expect.expect(contains(">"));
expect.sendLine("enable");
expect.expect(contains("Password:"));
expect.sendLine(EnablePassword);
expect.expect(regexp((".*")));

expect.sendLine("Wall works");
expect.sendLine();
}

//These Successfully get sent to the router


commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");

expect.expect(contains("#"));


for(int i = 0; i < commands.size(); ++i){

expect.sendLine(commands.get(i));
}

Thread.sleep(500);
init = wholeBuffer.toString();
if(init.contains("% Incorrect password")){
CPE.infoBox("The enable password was incorrect", "Bad Enable Password");
}

//These do not get sent to the router


commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");

expect.expect(contains("#"));

danper...@gmail.com

unread,
Sep 26, 2016, 12:48:50 AM9/26/16
to Yet another Expect for Java, danper...@gmail.com
Removing the Thread.sleep and the error checking broke both of them. None of the commands in either for loop at sent to the router

if(Hostname.contains(">")){
expect.expect(contains(">"));
expect.sendLine("enable");
expect.expect(contains("Password:"));
expect.sendLine(EnablePassword);
expect.expect(regexp((".*")));

expect.sendLine("Wall works");
expect.sendLine();


}

//These do not get sent to the router
commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");
expect.expect(contains("#"));

for(int i = 0; i < commands.size(); ++i){

expect.sendLine(commands.get(i));
}

//These do not get sent to the router
commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");
commands.add("wall test from loop");
expect.expect(contains("#"));

Alexey Gavrilov

unread,
Sep 26, 2016, 12:29:32 PM9/26/16
to danper...@gmail.com, Yet another Expect for Java
Hi,

I suspect that the problem is that you are sending commands in a loop without waiting for the result from previous command.
Can you modify your code in a way to always expect the command prompt after sending sendLine() calling method?

Also try to avoid using too generic matchers like .* regular expression. That is because the expect library tries to match the buffer for every data chunk received from a server.
The size of the data chunk can vary from kilobytes to just one character. It is unpredictable and depends on the to underlying server connection implementation.

For example, if you have a matcher like regexp(“.*”) that may be triggered right after the first byte has been received. So if you, say, send the ‘pwd’ command you will get only the first character (‘/‘) while the rest will be appended to the internal buffer and considered when your call the expect method again.

Hope this helps,
Alexey
> --
> You received this message because you are subscribed to the Google Groups "Yet another Expect for Java" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to java-expecti...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

danper...@gmail.com

unread,
Sep 26, 2016, 8:00:44 PM9/26/16
to Yet another Expect for Java, danper...@gmail.com, Alexey1....@gmail.com
Thank you for the reply Alexey. I was able to get it working
Reply all
Reply to author
Forward
0 new messages