Skip to content

Commit

Permalink
8264190: Harden TLS interop tests
Browse files Browse the repository at this point in the history
Reviewed-by: rhalade
  • Loading branch information
fguallini authored and rhalade committed Apr 12, 2021
1 parent 18bec9c commit f4e6395
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 55 deletions.
44 changes: 40 additions & 4 deletions test/jdk/javax/net/ssl/TLSCommon/interop/BaseInteropTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public abstract class BaseInteropTest<U extends UseCase> {

protected final Product serverProduct;
protected final Product clientProduct;
private static final int MAX_SERVER_RETRIES = 3;

public BaseInteropTest(Product serverProduct, Product clientProduct) {
this.serverProduct = serverProduct;
Expand Down Expand Up @@ -169,8 +170,7 @@ protected Status runTestCase(TestCase<U> testCase) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(1);
AbstractServer server = null;
try {
server = createServer(testCase.serverCase);
executor.submit(new ServerTask(server));
server = startAndGetServer(testCase.serverCase, executor);
int port = server.getPort();
System.out.println("Server is listening " + port);
serverStatus = Status.PASS;
Expand Down Expand Up @@ -225,6 +225,33 @@ protected Status runTestCase(TestCase<U> testCase) throws Exception {
return caseStatus;
}

/*
* Return a server once it is properly started to avoid client connection issues.
* Retry operation if needed, server may fail to bind a port
*/
protected AbstractServer startAndGetServer(U useCase, ExecutorService executor)
throws Exception {
int maxRetries = getServerMaxRetries();
boolean serverAlive;
AbstractServer server;

do {
server = createServer(useCase, executor);
serverAlive = Utilities.waitFor(Server::isAlive, server);
if (!serverAlive) {
server.signalStop();
}

maxRetries--;
} while (!serverAlive && maxRetries > 0);

if (!serverAlive) {
throw new RuntimeException("Server failed to start");
}

return server;
}

/*
* Handles server side exception, and determines the status.
*/
Expand All @@ -251,8 +278,10 @@ private Status handleException(Exception exception) {
/*
* Creates server.
*/
protected AbstractServer createServer(U useCase) throws Exception {
return createServerBuilder(useCase).build();
protected AbstractServer createServer(U useCase, ExecutorService executor) throws Exception {
AbstractServer server = createServerBuilder(useCase).build();
executor.submit(new ServerTask(server));
return server;
}

protected AbstractServer.Builder createServerBuilder(U useCase)
Expand All @@ -279,6 +308,13 @@ protected AbstractClient.Builder createClientBuilder(U useCase)
.setCertTuple(useCase.getCertTuple());
}

/*
* Returns the maximum number of attempts to start a server.
*/
protected int getServerMaxRetries() {
return MAX_SERVER_RETRIES;
}

/*
* Determines the negotiated application protocol.
* Generally, using JDK client to get this value.
Expand Down
2 changes: 1 addition & 1 deletion test/jdk/javax/net/ssl/TLSCommon/interop/JdkServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public boolean isAlive() {

@Override
public void close() throws IOException {
if (isAlive()) {
if (!serverSocket.isClosed()) {
serverSocket.close();
}
}
Expand Down
79 changes: 77 additions & 2 deletions test/jdk/javax/net/ssl/TLSCommon/interop/ProcUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
* questions.
*/

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

Expand All @@ -40,15 +42,15 @@ public class ProcUtils {
*/
public static OutputAnalyzer java(Path javaPath, Class<?> clazz,
Map<String, String> props) {
ProcessBuilder pb = createProcessBuilder(javaPath, clazz, props);
ProcessBuilder pb = createJavaProcessBuilder(javaPath, clazz, props);
try {
return ProcessTools.executeCommand(pb);
} catch (Throwable e) {
throw new RuntimeException("Executes java program failed!", e);
}
}

private static ProcessBuilder createProcessBuilder(Path javaPath,
private static ProcessBuilder createJavaProcessBuilder(Path javaPath,
Class<?> clazz, Map<String, String> props) {
List<String> cmds = new ArrayList<>();
cmds.add(javaPath.toString());
Expand All @@ -66,4 +68,77 @@ private static ProcessBuilder createProcessBuilder(Path javaPath,
pb.redirectErrorStream(true);
return pb;
}

/*
* Executes a shell command and return a OutputAnalyzer wrapping the process.
*/
public static OutputAnalyzer shell(String command, Map<String, String> env)
throws IOException {
Process process = shellProc(command, null, env);
return getProcessOutput(process);
}

/*
* Executes win command and return a OutputAnalyzer wrapping the process.
*/
public static OutputAnalyzer win(String command, Map<String, String> env)
throws IOException {
Process process = winProc(command, null, env);
return getProcessOutput(process);
}

/*
* Executes a shell command and return the process.
*/
public static Process shellProc(String command, Path outputPath,
Map<String, String> env) throws IOException {
String[] cmds = new String[3];
cmds[0] = "sh";
cmds[1] = "-c";
cmds[2] = command;
return startAndGetProc(cmds, outputPath, env);
}

/*
* Executes a win command and returns the process.
*/
public static Process winProc(String command, Path outputPath,
Map<String, String> env)
throws IOException {
String[] cmds = new String[3];
cmds[0] = "cmd.exe";
cmds[1] = "/C";
cmds[2] = command;
return startAndGetProc(cmds, outputPath, env);
}

/*
* Returns a OutputAnalyzer wrapping the process.
*/
private static OutputAnalyzer getProcessOutput (Process process) throws IOException {
OutputAnalyzer oa = new OutputAnalyzer(process);
try {
process.waitFor();
return oa;
} catch (InterruptedException e) {
throw new RuntimeException("Process is interrupted!", e);
}
}

/*
* Executes a command, redirects the output to a local file and returns the process.
*/
private static Process startAndGetProc(String[] cmds, Path outputPath, Map<String,
String> env) throws IOException {
System.out.println("command to run: " + Arrays.toString(cmds));
ProcessBuilder pb = new ProcessBuilder(cmds);
if (env != null) {
pb.environment().putAll(env);
}
pb.redirectErrorStream(true);
if (outputPath != null) {
pb.redirectOutput(outputPath.toFile());
}
return pb.start();
}
}
2 changes: 1 addition & 1 deletion test/jdk/javax/net/ssl/TLSCommon/interop/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public interface Server extends Peer {
/*
* Checks if the peer is alive.
*/
public boolean isAlive() throws IOException;
public boolean isAlive();

/*
* Signals the server to stop if necessary.
Expand Down
54 changes: 7 additions & 47 deletions test/jdk/javax/net/ssl/TLSCommon/interop/Utilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -219,15 +219,17 @@ public static void writeOut(OutputStream output, String content)
*/
public static <T> boolean waitFor(Predicate<T> predicate, T t) {
long deadline = System.currentTimeMillis() + Utilities.TIMEOUT * 1000;
while (!predicate.test(t) && System.currentTimeMillis() < deadline) {
boolean predicateResult = predicate.test(t);
while (!predicateResult && System.currentTimeMillis() < deadline) {
try {
TimeUnit.SECONDS.sleep(1);
predicateResult = predicate.test(t);
} catch (InterruptedException e) {
throw new RuntimeException("Sleep is interrupted.", e);
}
}

return predicate.test(t);
return predicateResult;
}

/*
Expand Down Expand Up @@ -277,48 +279,6 @@ public static <T extends Enum<T>> T[] strToEnums(Class<T> enumType,
(T[]) Array.newInstance(enumType, 0));
}

/*
* Executes shell command and return a OutputAnalyzer wrapping the process.
*/
public static OutputAnalyzer shell(String command) throws IOException {
Process process = shellProc(command);
OutputAnalyzer oa = new OutputAnalyzer(process);
try {
process.waitFor();
return oa;
} catch (InterruptedException e) {
throw new RuntimeException("Shell process is interruptted!", e);
}
}

/*
* Executes shell command and redirect the output to a local file,
* and return the process.
*/
public static Process shellProc(String command, Path outputPath)
throws IOException {
String[] cmds = new String[3];
cmds[0] = "sh";
cmds[1] = "-c";
cmds[2] = command;
if (DEBUG) {
System.out.println("[sh -c " + command + "]");
}
ProcessBuilder pb = new ProcessBuilder(cmds);
pb.redirectErrorStream(true);
if (outputPath != null) {
pb.redirectOutput(outputPath.toFile());
}
return pb.start();
}

/*
* Executes shell command and return the process.
*/
public static Process shellProc(String command) throws IOException {
return shellProc(command, null);
}

/*
* Determines if the specified process is alive.
*/
Expand Down Expand Up @@ -377,14 +337,14 @@ private static boolean delete(Path filePath) {
*/
public static boolean isSessionResumed(ResumptionMode mode,
byte[] firstSessionId, byte[] secondSessionId,
long secondConnStartTime, long secondSessionCreationTime) {
long firstSessionCreationTime, long secondSessionCreationTime) {
System.out.println("ResumptionMode: " + mode);
System.out.println("firstSessionId: " + Arrays.toString(firstSessionId));
System.out.println("secondSessionId: " + Arrays.toString(secondSessionId));
System.out.println("secondConnStartTime: " + secondConnStartTime);
System.out.println("firstSessionCreationTime: " + firstSessionCreationTime);
System.out.println("secondSessionCreationTime: " + secondSessionCreationTime);

boolean resumed = secondConnStartTime > secondSessionCreationTime;
boolean resumed = firstSessionCreationTime == secondSessionCreationTime;
if (mode == ResumptionMode.ID) {
resumed = resumed && firstSessionId.length > 0
&& Arrays.equals(firstSessionId, secondSessionId);
Expand Down

1 comment on commit f4e6395

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.