Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

D-27727 - failure with INTERACTIVE_SUDO connection type #313

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.not;

public class ReplacingInputStreamTest {

Expand Down Expand Up @@ -67,6 +69,98 @@ public void shouldThrowExceptionOnPatternNull() {
@Test(expectedExceptions = NullPointerException.class)
public void shouldThrowExceptionOnInputStreamNull() throws IOException {
ReplacingInputStream foo = new ReplacingInputStream(null, "SudoPassword", "ReplacePassword");
foo.readAllBytes();
}

@Test
public void shouldReplaceTextWithEmptyInInputStream() throws IOException {
InputStream is = new ByteArrayInputStream(("echo SudoPassword:").getBytes());

ReplacingInputStream foo = new ReplacingInputStream(is, "SudoPassword", "");
String replaceStreamResult = new String(foo.readAllBytes());
assertThat(replaceStreamResult, equalTo("echo :"));
}

@Test
public void shouldReplaceTextWithLineFeedInInputStream() throws IOException {
InputStream is = new ByteArrayInputStream(("echo \\n\\r SudoPassword:").getBytes());

ReplacingInputStream foo = new ReplacingInputStream(is, "SudoPassword", "");
String replaceStreamResult = new String(foo.readAllBytes());
assertThat(replaceStreamResult, equalTo("echo \\n\\r :"));
}

@Test
public void shouldExitFineWhenPatternNotFoundInByteArrayInputStream() throws IOException {
InputStream is = new ByteArrayInputStream(("echo SudoPassword:").getBytes());

ReplacingInputStream foo = new ReplacingInputStream(is, "notexisting", "");
String replaceStreamResult = new String(foo.readAllBytes());
assertThat(replaceStreamResult, equalTo("echo SudoPassword:"));
}

@Test
public void shouldExitFineWhenPatternNotFoundInInputStream() throws IOException, TimeoutException {
Process process = new ProcessBuilder("sleep", "100").start();
InputStream is = process.getInputStream();
// process.waitFor();

ReplacingInputStream foo = new ReplacingInputStream(is, "notexisting", "replaced string");
InputStreamReader isr = new TimedoutInputStreamReader(foo, 10 * 1000);
StringBuilder sbr = new StringBuilder();
try {
for (;;) {
int i = isr.read();
if (i == -1) {
break;
}
sbr.append((char) i);
}
} catch (IOException ioe) {
if (ioe.getMessage().contains("Input stream read timeout")) {
throw new TimeoutException();
}
}

String replaceStreamResult = sbr.toString();
assertThat(replaceStreamResult, not(containsString("replaced string")));
}
}

class TimedoutInputStreamReader extends InputStreamReader {

private final int readTimeout;
private final ExecutorService executor = Executors.newFixedThreadPool(1);

/**
* TimedoutInputStreamReader
*
* @param in - input stream
* @param readTimeout Zero or -ve timeout means indefinite wait else read will timeout after given milliseconds
*/
public TimedoutInputStreamReader(InputStream in, int readTimeout) {
super(in);
this.readTimeout = readTimeout;
}

@Override
public int read() throws IOException {
if(readTimeout > 0) {
return tryRead();
} else {
return super.read();
}
}

private int tryRead() throws IOException {
Future<Integer> future = executor.submit(() -> super.read());
try {
return future.get(readTimeout, TimeUnit.MILLISECONDS);
} catch (TimeoutException ex) {
System.out.println("Input stream read timeout");
throw new IOException("Input stream read timeout");
} catch (Exception ex) {
throw new IOException(ex);
}
}
}