Skip to content

Commit

Permalink
Merge branch 'main' into bump-maven-3-9-7
Browse files Browse the repository at this point in the history
  • Loading branch information
diemol authored Jun 4, 2024
2 parents 73821cd + ac129ba commit d6eb54d
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 29 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@
<dependency>
<groupId>com.saucelabs</groupId>
<artifactId>saucerest</artifactId>
<version>2.4.0</version>
<version>2.5.0</version>
<scope>compile</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
Expand All @@ -34,6 +35,8 @@
public abstract class AbstractSauceTunnelManager implements SauceTunnelManager {

protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractSauceTunnelManager.class);
private static final Duration READINESS_CHECK_TIMEOUT = Duration.ofSeconds(15);
private static final Duration READINESS_CHECK_POLLING_INTERVAL = Duration.ofSeconds(3);

/** Should Sauce Connect output be suppressed? */
protected boolean quietMode;
Expand Down Expand Up @@ -498,8 +501,10 @@ public Process openConnection(

} else {
// everything okay, continue the build
if (outputGobbler.getTunnelId() != null) {
tunnelInformation.setTunnelId(outputGobbler.getTunnelId());
String provisionedTunnelId = outputGobbler.getTunnelId();
if (provisionedTunnelId != null) {
tunnelInformation.setTunnelId(provisionedTunnelId);
waitForReadiness(provisionedTunnelId);
}
logMessage(
printStream, "Sauce Connect " + getCurrentVersion() + " now launched for: " + name);
Expand Down Expand Up @@ -537,7 +542,34 @@ public Process openConnection(
}
}

public SystemErrorGobbler makeErrorGobbler(PrintStream printStream, InputStream errorStream) {
private void waitForReadiness(String tunnelId) {
long pollingIntervalMillis = READINESS_CHECK_POLLING_INTERVAL.toMillis();
long endTime = System.currentTimeMillis() + READINESS_CHECK_TIMEOUT.toMillis();
try {
do {
long iterationStartTime = System.currentTimeMillis();
Boolean isReady = scEndpoint.getTunnelInformation(tunnelId).isReady;
if (Boolean.TRUE.equals(isReady)) {
LOGGER.info("Tunnel with ID {} is ready for use", tunnelId);
return;
}
LOGGER.info("Waiting for readiness of tunnel with ID {}", tunnelId);
long iterationEndTime = System.currentTimeMillis();

long iterationPollingTimeout = pollingIntervalMillis - (iterationEndTime - iterationStartTime);
if (iterationPollingTimeout > 0) {
TimeUnit.MILLISECONDS.sleep(iterationPollingTimeout);
}
}
while (System.currentTimeMillis() <= endTime);
LOGGER.warn("Wait for readiness of tunnel with ID {} is timed out", tunnelId);
}
catch (IOException | InterruptedException e) {
LOGGER.warn("Unable to check readiness of tunnel with ID {}", tunnelId, e);
}
}

public SystemErrorGobbler makeErrorGobbler(PrintStream printStream, InputStream errorStream) {
return new SystemErrorGobbler("ErrorGobbler", errorStream, printStream);
}

Expand All @@ -563,24 +595,17 @@ private TunnelInformation getTunnelInformation(String name) {
*/
private String activeTunnelID(String username, String tunnelName) {
try {
List<String> tunnels = scEndpoint.getTunnelsForAUser();
if (tunnels.isEmpty()) {
// no active tunnels
return null;
}
// iterate over elements
for (String tunnelId : tunnels) {

com.saucelabs.saucerest.model.sauceconnect.TunnelInformation tunnelInformation =
scEndpoint.getTunnelInformation(tunnelId);
List<com.saucelabs.saucerest.model.sauceconnect.TunnelInformation> tunnelsInformation =
scEndpoint.getTunnelsInformationForAUser();

for (com.saucelabs.saucerest.model.sauceconnect.TunnelInformation tunnelInformation : tunnelsInformation) {
String configName = tunnelInformation.tunnelIdentifier;
String status = tunnelInformation.status;
if ("running".equalsIgnoreCase(status)
&& ("null".equalsIgnoreCase(configName) && tunnelName.equals(username))
|| !"null".equalsIgnoreCase(configName) && configName.equals(tunnelName)) {
// we have an active tunnel
return tunnelId;
return tunnelInformation.id;
}
}
} catch (JSONException | IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ public class SauceConnectFourManager extends AbstractSauceTunnelManager
/** Remove all created files and directories on exit */
private boolean cleanUpOnExit;

/** System which runs SauceConnect, this info is added to '--extra-info' argument */
private final String runner;

/** Represents the operating system-specific Sauce Connect binary. */
public enum OperatingSystem {
OSX("osx", "zip", null, UNIX_TEMP_DIR),
Expand Down Expand Up @@ -140,13 +143,33 @@ public SauceConnectFourManager() {
this(false);
}

/**
* Constructs a new instance with quiet mode disabled.
*
* @param runner System which runs SauceConnect, this info is added to '--extra-info' argument
*/
public SauceConnectFourManager(String runner) {
this(false, runner);
}

/**
* Constructs a new instance.
*
* @param quietMode indicates whether Sauce Connect output should be suppressed
*/
public SauceConnectFourManager(boolean quietMode) {
this(quietMode, "jenkins");
}

/**
* Constructs a new instance.
*
* @param quietMode indicates whether Sauce Connect output should be suppressed
* @param runner System which runs SauceConnect, this info is added to '--extra-info' argument
*/
public SauceConnectFourManager(boolean quietMode, String runner) {
super(quietMode);
this.runner = runner;
}

/**
Expand Down Expand Up @@ -285,9 +308,9 @@ protected String[] addExtraInfo(String[] args) {
String[] result;
OperatingSystem operatingSystem = OperatingSystem.getOperatingSystem();
if (operatingSystem == OperatingSystem.WINDOWS) {
result = joinArgs(args, "--extra-info", "{\\\"runner\\\": \\\"jenkins\\\"}");
result = joinArgs(args, "--extra-info", "{\\\"runner\\\": \\\"" + runner + "\\\"}");
} else {
result = joinArgs(args, "--extra-info", "{\"runner\": \"jenkins\"}");
result = joinArgs(args, "--extra-info", "{\"runner\": \"" + runner + "\"}");
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,13 @@
@ExtendWith(MockitoExtension.class)
class SauceConnectFourManagerTest {

private static final String STARTED_SC_LOG = "/started_sc.log";
private static final String STARTED_TUNNEL_ID = "a3ccd3985ed04e7ba0fefc7fa401e9c8";

@Mock private Process mockProcess;
@Mock private SauceREST mockSauceRest;
@Mock private SauceConnectEndpoint mockSCEndpoint;
@Spy private final SauceConnectFourManager tunnelManager = new SauceConnectFourManager(false);
@Spy private final SauceConnectFourManager tunnelManager = new SauceConnectFourManager();

private final PrintStream ps = System.out;

Expand All @@ -57,15 +60,18 @@ private InputStream getResourceAsStream(String resourceName) {
@ParameterizedTest
@ValueSource(booleans = {true, false})
void testOpenConnectionSuccessfully(boolean cleanUpOnExit) throws IOException {
when(mockSCEndpoint.getTunnelsForAUser()).thenReturn(List.of());
when(mockSCEndpoint.getTunnelsInformationForAUser()).thenReturn(List.of());
TunnelInformation readyTunnel = new TunnelInformation();
readyTunnel.isReady = true;
when(mockSCEndpoint.getTunnelInformation(STARTED_TUNNEL_ID)).thenReturn(readyTunnel);
tunnelManager.setCleanUpOnExit(cleanUpOnExit);
Process process = testOpenConnection("/started_sc.log");
Process process = testOpenConnection(STARTED_SC_LOG);
assertEquals(mockProcess, process);
}

@Test
void openConnectionTest_closes() throws IOException, InterruptedException {
when(mockSCEndpoint.getTunnelsForAUser()).thenReturn(List.of());
when(mockSCEndpoint.getTunnelsInformationForAUser()).thenReturn(List.of());
when(mockProcess.waitFor(30, TimeUnit.SECONDS)).thenReturn(true);
assertThrows(AbstractSauceTunnelManager.SauceConnectDidNotStartException.class, () -> testOpenConnection(
"/started_sc_closes.log"));
Expand All @@ -74,8 +80,14 @@ void openConnectionTest_closes() throws IOException, InterruptedException {

@Test
void testOpenConnectionWithExtraSpacesInArgs() throws IOException {
when(mockSCEndpoint.getTunnelsForAUser()).thenReturn(List.of());
testOpenConnection("/started_sc.log", " username-with-spaces-around ");
when(mockSCEndpoint.getTunnelsInformationForAUser()).thenReturn(List.of());
TunnelInformation notReadyTunnel = new TunnelInformation();
notReadyTunnel.isReady = false;
TunnelInformation readyTunnel = new TunnelInformation();
readyTunnel.isReady = true;
when(mockSCEndpoint.getTunnelInformation(STARTED_TUNNEL_ID)).thenReturn(notReadyTunnel,
readyTunnel);
testOpenConnection(STARTED_SC_LOG, " username-with-spaces-around ");
}

private Process testOpenConnection(String logFile) throws IOException {
Expand All @@ -95,7 +107,7 @@ private Process testOpenConnection(String logFile, String username) throws IOExc
return tunnelManager.openConnection(
username, apiKey, dataCenter, port, null, " ", ps, false, "");
} finally {
verify(mockSCEndpoint).getTunnelsForAUser();
verify(mockSCEndpoint).getTunnelsInformationForAUser();
ArgumentCaptor<String[]> argsCaptor = ArgumentCaptor.forClass(String[].class);
verify(tunnelManager).createProcess(argsCaptor.capture(), any(File.class));
String[] actualArgs = argsCaptor.getValue();
Expand All @@ -121,15 +133,15 @@ void openConnectionTest_existing_tunnel() throws IOException {
TunnelInformation started = new TunnelInformation();
started.tunnelIdentifier = "8949e55fb5e14fd6bf6230b7a609b494";
started.status = "running";
started.isReady = true;

when(mockSCEndpoint.getTunnelsForAUser()).thenReturn(List.of(started.tunnelIdentifier));
when(mockSCEndpoint.getTunnelInformation(started.tunnelIdentifier)).thenReturn(started);
when(mockSCEndpoint.getTunnelsInformationForAUser()).thenReturn(List.of(started));
when(mockSCEndpoint.getTunnelInformation(STARTED_TUNNEL_ID)).thenReturn(started);

Process process = testOpenConnection("/started_sc.log");
Process process = testOpenConnection(STARTED_SC_LOG);
assertEquals(mockProcess, process);

verify(mockSCEndpoint).getTunnelInformation(started.tunnelIdentifier);
verify(mockSCEndpoint).getTunnelsForAUser();
verify(mockSCEndpoint).getTunnelsInformationForAUser();
}

@ParameterizedTest
Expand Down

0 comments on commit d6eb54d

Please sign in to comment.