Merge "Acceptance-tests: Fix 'Address already in use' bug"
This commit is contained in:
commit
a8de646463
@ -493,34 +493,17 @@ heap size:
|
||||
EOF
|
||||
----
|
||||
|
||||
== Sporadic failures of unit tests
|
||||
== Rerun unit tests
|
||||
|
||||
Due to implementation of ephemeral port assignment for HTTP and SSH daemons,
|
||||
(the reason is explained in depth in this thread:
|
||||
https://groups.google.com/forum/#!topic/repo-discuss/db14RJ59ubs),
|
||||
unit tests can randomly fail with "BindException: Address already in use".
|
||||
In this case, failed tests need to be repeated:
|
||||
|
||||
----
|
||||
FAIL 32,0s 7 Passed 1 Failed com.google.gerrit.acceptance.rest.group.AddRemoveGroupMembersIT
|
||||
FAILURE includeRemoveGroup: Cannot bind to localhost:40955
|
||||
at com.google.gerrit.sshd.SshDaemon.start(SshDaemon.java:281)
|
||||
at com.google.gerrit.lifecycle.LifecycleManager.start(LifecycleManager.java:74)
|
||||
at com.google.gerrit.pgm.Daemon.start(Daemon.java:288)
|
||||
at com.google.gerrit.acceptance.GerritServer.start(GerritServer.java:81)
|
||||
[...]
|
||||
Caused by: java.net.BindException: Address already in use
|
||||
at sun.nio.ch.Net.bind0(Native Method)
|
||||
----
|
||||
|
||||
Because the test execution results are cached by Buck, they must be removed
|
||||
before retrying:
|
||||
If for some reasons tests, that were already run must be repeated, unit test
|
||||
cache must be removed fist. That's because the test execution results are
|
||||
cached by Buck:
|
||||
|
||||
----
|
||||
$ rm -rf buck-out/bin/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/group/.AddRemoveGroupMembersIT/
|
||||
----
|
||||
|
||||
After clearing the cache and repeating of the failed tests, they are successful:
|
||||
After clearing the cache test can be rerun again:
|
||||
|
||||
----
|
||||
$ buck test //gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/group:AddRemoveGroupMembersIT
|
||||
|
@ -36,7 +36,6 @@ import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.URI;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
@ -123,23 +122,18 @@ public class GerritServer {
|
||||
|
||||
private static void mergeTestConfig(Config cfg)
|
||||
throws IOException {
|
||||
InetSocketAddress http = newPort();
|
||||
InetSocketAddress sshd = newPort();
|
||||
String url = "http://" + format(http) + "/";
|
||||
|
||||
String forceEphemeralPort = String.format("%s:0",
|
||||
getLocalHost().getHostName());
|
||||
String url = "http://" + forceEphemeralPort + "/";
|
||||
cfg.setString("gerrit", null, "canonicalWebUrl", url);
|
||||
cfg.setString("httpd", null, "listenUrl", url);
|
||||
cfg.setString("sshd", null, "listenAddress", format(sshd));
|
||||
cfg.setString("sshd", null, "listenAddress", forceEphemeralPort);
|
||||
cfg.setString("cache", null, "directory", null);
|
||||
cfg.setBoolean("sendemail", null, "enable", false);
|
||||
cfg.setInt("cache", "projects", "checkFrequency", 0);
|
||||
cfg.setInt("plugins", null, "checkFrequency", 0);
|
||||
}
|
||||
|
||||
private static String format(InetSocketAddress s) {
|
||||
return String.format("%s:%d", s.getAddress().getHostAddress(), s.getPort());
|
||||
}
|
||||
|
||||
private static Injector createTestInjector(Daemon daemon) throws Exception {
|
||||
Injector sysInjector = get(daemon, "sysInjector");
|
||||
Module module = new FactoryModule() {
|
||||
@ -160,15 +154,6 @@ public class GerritServer {
|
||||
return (T) f.get(obj);
|
||||
}
|
||||
|
||||
private static final InetSocketAddress newPort() throws IOException {
|
||||
ServerSocket s = new ServerSocket(0, 0, getLocalHost());
|
||||
try {
|
||||
return (InetSocketAddress) s.getLocalSocketAddress();
|
||||
} finally {
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static InetAddress getLocalHost() throws UnknownHostException {
|
||||
return InetAddress.getLoopbackAddress();
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.escape.Escaper;
|
||||
import com.google.common.html.HtmlEscapers;
|
||||
import com.google.common.io.ByteStreams;
|
||||
@ -103,16 +104,33 @@ public class JettyServer {
|
||||
|
||||
static class Lifecycle implements LifecycleListener {
|
||||
private final JettyServer server;
|
||||
private final Config cfg;
|
||||
|
||||
@Inject
|
||||
Lifecycle(final JettyServer server) {
|
||||
Lifecycle(final JettyServer server, @GerritServerConfig final Config cfg) {
|
||||
this.server = server;
|
||||
this.cfg = cfg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
try {
|
||||
String origUrl = cfg.getString("httpd", null, "listenUrl");
|
||||
boolean rewrite = !Strings.isNullOrEmpty(origUrl)
|
||||
&& origUrl.endsWith(":0/");
|
||||
server.httpd.start();
|
||||
if (rewrite) {
|
||||
Connector con = server.httpd.getConnectors()[0];
|
||||
if (con instanceof ServerConnector) {
|
||||
@SuppressWarnings("resource")
|
||||
ServerConnector serverCon = (ServerConnector)con;
|
||||
String host = serverCon.getHost();
|
||||
int port = serverCon.getLocalPort();
|
||||
String url = String.format("http://%s:%d", host, port);
|
||||
cfg.setString("gerrit", null, "canonicalWebUrl", url);
|
||||
cfg.setString("httpd", null, "listenUrl", url);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Cannot start HTTP daemon", e);
|
||||
}
|
||||
@ -259,7 +277,7 @@ public class JettyServer {
|
||||
} else {
|
||||
final URI r = u.parseServerAuthority();
|
||||
c.setHost(r.getHost());
|
||||
c.setPort(0 < r.getPort() ? r.getPort() : defaultPort);
|
||||
c.setPort(0 <= r.getPort() ? r.getPort() : defaultPort);
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalArgumentException("Invalid httpd.listenurl " + u, e);
|
||||
|
@ -18,6 +18,8 @@ import static com.google.gerrit.server.ssh.SshAddressesModule.IANA_SSH_PORT;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gerrit.common.Version;
|
||||
import com.google.gerrit.extensions.events.LifecycleListener;
|
||||
@ -51,11 +53,11 @@ import org.apache.sshd.common.cipher.AES128CTR;
|
||||
import org.apache.sshd.common.cipher.AES192CBC;
|
||||
import org.apache.sshd.common.cipher.AES256CBC;
|
||||
import org.apache.sshd.common.cipher.AES256CTR;
|
||||
import org.apache.sshd.common.cipher.ARCFOUR128;
|
||||
import org.apache.sshd.common.cipher.ARCFOUR256;
|
||||
import org.apache.sshd.common.cipher.BlowfishCBC;
|
||||
import org.apache.sshd.common.cipher.CipherNone;
|
||||
import org.apache.sshd.common.cipher.TripleDESCBC;
|
||||
import org.apache.sshd.common.cipher.ARCFOUR128;
|
||||
import org.apache.sshd.common.cipher.ARCFOUR256;
|
||||
import org.apache.sshd.common.compression.CompressionNone;
|
||||
import org.apache.sshd.common.file.FileSystemFactory;
|
||||
import org.apache.sshd.common.file.FileSystemView;
|
||||
@ -100,6 +102,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.InvalidKeyException;
|
||||
@ -144,6 +147,7 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
private final boolean keepAlive;
|
||||
private final List<HostKey> hostKeys;
|
||||
private volatile IoAcceptor acceptor;
|
||||
private final Config cfg;
|
||||
|
||||
@Inject
|
||||
SshDaemon(final CommandFactory commandFactory, final NoShell noShell,
|
||||
@ -155,6 +159,7 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
@SshAdvertisedAddresses final List<String> advertised) {
|
||||
setPort(IANA_SSH_PORT /* never used */);
|
||||
|
||||
this.cfg = cfg;
|
||||
this.listen = listen;
|
||||
this.advertised = advertised;
|
||||
keepAlive = cfg.getBoolean("sshd", "tcpkeepalive", true);
|
||||
@ -276,7 +281,14 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
acceptor = createAcceptor();
|
||||
|
||||
try {
|
||||
String listenAddress = cfg.getString("sshd", null, "listenAddress");
|
||||
boolean rewrite = !Strings.isNullOrEmpty(listenAddress)
|
||||
&& listenAddress.endsWith(":0");
|
||||
acceptor.bind(listen);
|
||||
if (rewrite) {
|
||||
SocketAddress bound = Iterables.getOnlyElement(acceptor.getBoundAddresses());
|
||||
cfg.setString("sshd", null, "listenAddress", format((InetSocketAddress)bound));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Cannot bind to " + addressList(), e);
|
||||
}
|
||||
@ -286,6 +298,10 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener {
|
||||
}
|
||||
}
|
||||
|
||||
private static String format(InetSocketAddress s) {
|
||||
return String.format("%s:%d", s.getAddress().getHostAddress(), s.getPort());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void stop() {
|
||||
if (acceptor != null) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user