Run most acceptance tests in-memory
This allows the tests to run faster, with lower system overheads.
The new @UseLocalDisk annotation must be added to any test method
that wants the classical init and daemon testing strategy.
A new sshd.requestLog configuration variable is introduced to
permit tests to disable the SSH command log.
Timing for `buck test --all` on my Linux desktop:
before 3m37.129s
after 2m18.789s
Change-Id: I18c07ef2d913f6abbb3925b3e7d3df5d28668497
(cherry picked from commit 318bfcae5c
)
This commit is contained in:
@@ -30,7 +30,8 @@ public abstract class AbstractDaemonTest {
|
||||
return new Statement() {
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
beforeTest(config(description));
|
||||
boolean mem = description.getAnnotation(UseLocalDisk.class) == null;
|
||||
beforeTest(config(description), mem);
|
||||
base.evaluate();
|
||||
afterTest();
|
||||
}
|
||||
@@ -53,8 +54,8 @@ public abstract class AbstractDaemonTest {
|
||||
}
|
||||
}
|
||||
|
||||
private void beforeTest(Config cfg) throws Exception {
|
||||
server = GerritServer.start(cfg);
|
||||
private void beforeTest(Config cfg, boolean memory) throws Exception {
|
||||
server = GerritServer.start(cfg, memory);
|
||||
server.getTestInjector().injectMembers(this);
|
||||
}
|
||||
|
||||
|
@@ -14,18 +14,19 @@
|
||||
|
||||
package com.google.gerrit.acceptance;
|
||||
|
||||
import com.google.gerrit.lifecycle.LifecycleManager;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gerrit.pgm.Daemon;
|
||||
import com.google.gerrit.pgm.Init;
|
||||
import com.google.gerrit.server.config.FactoryModule;
|
||||
import com.google.gerrit.server.config.GerritServerConfig;
|
||||
import com.google.gerrit.server.util.SocketUtil;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.Module;
|
||||
|
||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
import org.eclipse.jgit.lib.RepositoryCache;
|
||||
import org.eclipse.jgit.storage.file.FileBasedConfig;
|
||||
import org.eclipse.jgit.util.FS;
|
||||
|
||||
import java.io.File;
|
||||
@@ -46,8 +47,7 @@ import java.util.concurrent.TimeUnit;
|
||||
public class GerritServer {
|
||||
|
||||
/** Returns fully started Gerrit server */
|
||||
static GerritServer start(Config base) throws Exception {
|
||||
final File site = initSite(base);
|
||||
static GerritServer start(Config base, boolean memory) throws Exception {
|
||||
final CyclicBarrier serverStarted = new CyclicBarrier(2);
|
||||
final Daemon daemon = new Daemon(new Runnable() {
|
||||
public void run() {
|
||||
@@ -61,21 +61,34 @@ public class GerritServer {
|
||||
}
|
||||
});
|
||||
|
||||
ExecutorService daemonService = Executors.newSingleThreadExecutor();
|
||||
daemonService.submit(new Callable<Void>() {
|
||||
public Void call() throws Exception {
|
||||
int rc = daemon.main(new String[] {"-d", site.getPath(), "--headless" });
|
||||
if (rc != 0) {
|
||||
System.out.println("Failed to start Gerrit daemon. Check "
|
||||
+ site.getPath() + "/logs/error_log");
|
||||
serverStarted.reset();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
});
|
||||
|
||||
serverStarted.await();
|
||||
System.out.println("Gerrit Server Started");
|
||||
final File site;
|
||||
ExecutorService daemonService = null;
|
||||
if (memory) {
|
||||
site = null;
|
||||
Config cfg = base != null ? base : new Config();
|
||||
mergeTestConfig(cfg);
|
||||
cfg.setBoolean("httpd", null, "requestLog", false);
|
||||
cfg.setBoolean("sshd", null, "requestLog", false);
|
||||
daemon.setDatabaseForTesting(ImmutableList.<Module>of(
|
||||
new InMemoryTestingDatabaseModule(cfg)));
|
||||
daemon.start();
|
||||
} else {
|
||||
site = initSite(base);
|
||||
daemonService = Executors.newSingleThreadExecutor();
|
||||
daemonService.submit(new Callable<Void>() {
|
||||
public Void call() throws Exception {
|
||||
int rc = daemon.main(new String[] {"-d", site.getPath(), "--headless" });
|
||||
if (rc != 0) {
|
||||
System.out.println("Failed to start Gerrit daemon. Check "
|
||||
+ site.getPath() + "/logs/error_log");
|
||||
serverStarted.reset();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
});
|
||||
serverStarted.await();
|
||||
System.out.println("Gerrit Server Started");
|
||||
}
|
||||
|
||||
Injector i = createTestInjector(daemon);
|
||||
return new GerritServer(site, i, daemon, daemonService);
|
||||
@@ -91,14 +104,22 @@ public class GerritServer {
|
||||
throw new RuntimeException("Couldn't initialize site");
|
||||
}
|
||||
|
||||
InetSocketAddress http = newPort();
|
||||
InetSocketAddress sshd = newPort();
|
||||
String url = "http://" + format(http) + "/";
|
||||
MergeableFileBasedConfig cfg = new MergeableFileBasedConfig(
|
||||
new File(new File(tmp, "etc"), "gerrit.config"),
|
||||
FS.DETECTED);
|
||||
cfg.load();
|
||||
cfg.merge(base);
|
||||
mergeTestConfig(cfg);
|
||||
cfg.save();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private static void mergeTestConfig(Config cfg)
|
||||
throws IOException {
|
||||
InetSocketAddress http = newPort();
|
||||
InetSocketAddress sshd = newPort();
|
||||
String url = "http://" + format(http) + "/";
|
||||
|
||||
cfg.setString("gerrit", null, "canonicalWebUrl", url);
|
||||
cfg.setString("httpd", null, "listenUrl", url);
|
||||
cfg.setString("sshd", null, "listenAddress", format(sshd));
|
||||
@@ -106,8 +127,6 @@ public class GerritServer {
|
||||
cfg.setBoolean("sendemail", null, "enable", false);
|
||||
cfg.setInt("cache", "projects", "checkFrequency", 0);
|
||||
cfg.setInt("plugins", null, "checkFrequency", 0);
|
||||
cfg.save();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private static String format(InetSocketAddress s) {
|
||||
@@ -169,11 +188,8 @@ public class GerritServer {
|
||||
this.daemon = daemon;
|
||||
this.daemonService = daemonService;
|
||||
|
||||
FileBasedConfig cfg = new FileBasedConfig(
|
||||
new File(new File(sitePath, "etc"), "gerrit.config"),
|
||||
FS.DETECTED);
|
||||
cfg.load();
|
||||
|
||||
Config cfg = testInjector.getInstance(
|
||||
Key.get(Config.class, GerritServerConfig.class));
|
||||
url = cfg.getString("gerrit", null, "canonicalWebUrl");
|
||||
URI uri = URI.create(url);
|
||||
|
||||
@@ -200,12 +216,15 @@ public class GerritServer {
|
||||
}
|
||||
|
||||
void stop() throws Exception {
|
||||
LifecycleManager manager = get(daemon, "manager");
|
||||
System.out.println("Gerrit Server Shutdown");
|
||||
manager.stop();
|
||||
daemonService.shutdownNow();
|
||||
daemonService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
|
||||
TempFileUtil.recursivelyDelete(sitePath);
|
||||
daemon.getLifecycleManager().stop();
|
||||
if (daemonService != null) {
|
||||
System.out.println("Gerrit Server Shutdown");
|
||||
daemonService.shutdownNow();
|
||||
daemonService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
|
||||
}
|
||||
if (sitePath != null) {
|
||||
TempFileUtil.recursivelyDelete(sitePath);
|
||||
}
|
||||
RepositoryCache.clear();
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,129 @@
|
||||
// Copyright (C) 2013 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.acceptance;
|
||||
|
||||
import static com.google.inject.Scopes.SINGLETON;
|
||||
|
||||
import com.google.gerrit.extensions.events.LifecycleListener;
|
||||
import com.google.gerrit.lifecycle.LifecycleModule;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.config.GerritServerConfig;
|
||||
import com.google.gerrit.server.config.SitePath;
|
||||
import com.google.gerrit.server.config.SitePaths;
|
||||
import com.google.gerrit.server.config.TrackingFooters;
|
||||
import com.google.gerrit.server.config.TrackingFootersProvider;
|
||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||
import com.google.gerrit.server.schema.DataSourceType;
|
||||
import com.google.gerrit.server.schema.SchemaModule;
|
||||
import com.google.gerrit.server.schema.SchemaVersion;
|
||||
import com.google.gerrit.testutil.InMemoryDatabase;
|
||||
import com.google.gerrit.testutil.InMemoryH2Type;
|
||||
import com.google.gerrit.testutil.InMemoryRepositoryManager;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.gwtorm.server.OrmRuntimeException;
|
||||
import com.google.gwtorm.server.SchemaFactory;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
import org.apache.sshd.common.KeyPairProvider;
|
||||
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
class InMemoryTestingDatabaseModule extends AbstractModule {
|
||||
private final Config cfg;
|
||||
|
||||
InMemoryTestingDatabaseModule(Config cfg) {
|
||||
this.cfg = cfg;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(Config.class)
|
||||
.annotatedWith(GerritServerConfig.class)
|
||||
.toInstance(cfg);
|
||||
|
||||
bind(File.class)
|
||||
.annotatedWith(SitePath.class)
|
||||
.toInstance(new File("UNIT_TEST_GERRIT_SITE"));
|
||||
|
||||
bind(GitRepositoryManager.class)
|
||||
.toInstance(new InMemoryRepositoryManager());
|
||||
|
||||
bind(DataSourceType.class).to(InMemoryH2Type.class);
|
||||
bind(InMemoryDatabase.class).in(SINGLETON);
|
||||
bind(new TypeLiteral<SchemaFactory<ReviewDb>>() {})
|
||||
.to(InMemoryDatabase.class);
|
||||
|
||||
install(new LifecycleModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
listener().to(CreateDatabase.class);
|
||||
}
|
||||
});
|
||||
|
||||
bind(SitePaths.class);
|
||||
bind(TrackingFooters.class)
|
||||
.toProvider(TrackingFootersProvider.class)
|
||||
.in(SINGLETON);
|
||||
|
||||
install(new SchemaModule());
|
||||
bind(SchemaVersion.class).to(SchemaVersion.C);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
KeyPairProvider createHostKey() {
|
||||
return getHostKeys();
|
||||
}
|
||||
|
||||
private static SimpleGeneratorHostKeyProvider keys;
|
||||
|
||||
private static synchronized KeyPairProvider getHostKeys() {
|
||||
if (keys == null) {
|
||||
keys = new SimpleGeneratorHostKeyProvider();
|
||||
keys.setAlgorithm("RSA");
|
||||
keys.loadKeys();
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
static class CreateDatabase implements LifecycleListener {
|
||||
private final InMemoryDatabase mem;
|
||||
|
||||
@Inject
|
||||
CreateDatabase(InMemoryDatabase mem) {
|
||||
this.mem = mem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
try {
|
||||
mem.create();
|
||||
} catch (OrmException e) {
|
||||
throw new OrmRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
mem.drop();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
// Copyright (C) 2013 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.acceptance;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({METHOD})
|
||||
@Retention(RUNTIME)
|
||||
public @interface UseLocalDisk {
|
||||
}
|
@@ -24,6 +24,7 @@ import com.google.gerrit.acceptance.RestResponse;
|
||||
import com.google.gerrit.acceptance.RestSession;
|
||||
import com.google.gerrit.acceptance.SshSession;
|
||||
import com.google.gerrit.acceptance.TestAccount;
|
||||
import com.google.gerrit.acceptance.UseLocalDisk;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.server.config.AllProjectsName;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
@@ -83,8 +84,8 @@ public class GarbageCollectionIT extends AbstractDaemonTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@UseLocalDisk
|
||||
public void testGcOneProject() throws JSchException, IOException {
|
||||
|
||||
assertEquals(HttpStatus.SC_OK, POST("/projects/" + allProjects.get() + "/gc"));
|
||||
gcAssert.assertHasPackFile(allProjects);
|
||||
gcAssert.assertHasNoPackFile(project1, project2);
|
||||
|
@@ -24,6 +24,7 @@ import com.google.gerrit.acceptance.AccountCreator;
|
||||
import com.google.gerrit.acceptance.GcAssert;
|
||||
import com.google.gerrit.acceptance.SshSession;
|
||||
import com.google.gerrit.acceptance.TestAccount;
|
||||
import com.google.gerrit.acceptance.UseLocalDisk;
|
||||
import com.google.gerrit.common.data.GarbageCollectionResult;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.server.config.AllProjectsName;
|
||||
@@ -83,6 +84,7 @@ public class GarbageCollectionIT extends AbstractDaemonTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@UseLocalDisk
|
||||
public void testGc() throws JSchException, IOException {
|
||||
String response =
|
||||
sshSession.exec("gerrit gc \"" + project1.get() + "\" \""
|
||||
@@ -94,6 +96,7 @@ public class GarbageCollectionIT extends AbstractDaemonTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@UseLocalDisk
|
||||
public void testGcAll() throws JSchException, IOException {
|
||||
String response = sshSession.exec("gerrit gc --all");
|
||||
assertFalse(sshSession.hasError());
|
||||
@@ -110,6 +113,7 @@ public class GarbageCollectionIT extends AbstractDaemonTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@UseLocalDisk
|
||||
public void testGcAlreadyScheduled() {
|
||||
gcQueue.addAll(Arrays.asList(project1));
|
||||
GarbageCollectionResult result = garbageCollectionFactory.create().run(
|
||||
|
Reference in New Issue
Block a user