StandaloneSiteTest: Ignore user and system git config

Override SystemReader to return empty files for the user and system
config. This makes StandaloneNoteDbMigrationIT pass regardless of the
configuration of the system it's running on.

This has to happen in StandaloneSiteTest prior to site initialization,
since the SystemReader is queried at FileRepository creation time, and
Gerrit by design holds all created repos open in the RepositoryCache. If
we tried to override the SystemReader in a test, it would have no
effect, because the cached repos would already have the wrong config
files loaded.

Another complication is that GerritLauncher#mainImpl was creating a new
classloader for every invocation, meaning the SystemReader class used by
the wrapper code in StandaloneSiteTest was not the same class instance
seen by the tests. Fix this by explicitly passing a ClassLoader when
running.

Change-Id: I478f3f712bced530c87b8fac3422275ec93d3557
This commit is contained in:
Dave Borowitz 2018-03-20 10:41:35 -04:00
parent d2612783fc
commit d3ee31c0cf
2 changed files with 87 additions and 4 deletions

View File

@ -35,9 +35,13 @@ import com.google.gerrit.testutil.ConfigSuite;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Provider;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader;
import org.junit.Rule;
import org.junit.rules.RuleChain;
import org.junit.rules.TemporaryFolder;
@ -109,8 +113,12 @@ public abstract class StandaloneSiteTest {
return new Statement() {
@Override
public void evaluate() throws Throwable {
beforeTest(description);
base.evaluate();
try {
beforeTest(description);
base.evaluate();
} finally {
afterTest();
}
}
};
}
@ -122,13 +130,65 @@ public abstract class StandaloneSiteTest {
protected Account.Id adminId;
private GerritServer.Description serverDesc;
private SystemReader oldSystemReader;
private void beforeTest(Description description) throws Exception {
// SystemReader must be overridden before creating any repos, since they read the user/system
// configs at initialization time, and are then stored in the RepositoryCache forever.
oldSystemReader = setFakeSystemReader(tempSiteDir.getRoot());
serverDesc = GerritServer.Description.forTestMethod(description, configName);
sitePaths = new SitePaths(tempSiteDir.getRoot().toPath());
GerritServer.init(serverDesc, baseConfig, sitePaths.site_path);
}
private static SystemReader setFakeSystemReader(File tempDir) {
SystemReader oldSystemReader = SystemReader.getInstance();
SystemReader.setInstance(
new SystemReader() {
@Override
public String getHostname() {
return oldSystemReader.getHostname();
}
@Override
public String getenv(String variable) {
return oldSystemReader.getenv(variable);
}
@Override
public String getProperty(String key) {
return oldSystemReader.getProperty(key);
}
@Override
public FileBasedConfig openUserConfig(Config parent, FS fs) {
return new FileBasedConfig(parent, new File(tempDir, "user.config"), FS.detect());
}
@Override
public FileBasedConfig openSystemConfig(Config parent, FS fs) {
return new FileBasedConfig(parent, new File(tempDir, "system.config"), FS.detect());
}
@Override
public long getCurrentTime() {
return oldSystemReader.getCurrentTime();
}
@Override
public int getTimezone(long when) {
return oldSystemReader.getTimezone(when);
}
});
return oldSystemReader;
}
private void afterTest() throws Exception {
SystemReader.setInstance(oldSystemReader);
oldSystemReader = null;
}
protected ServerContext startServer() throws Exception {
return startServer(null);
}
@ -153,7 +213,10 @@ public abstract class StandaloneSiteTest {
}
protected static void runGerrit(String... args) throws Exception {
assertThat(GerritLauncher.mainImpl(args))
// Use invokeProgram with the current classloader, rather than mainImpl, which would create a
// new classloader. This is necessary so that static state, particularly the SystemReader, is
// shared with the test method.
assertThat(GerritLauncher.invokeProgram(StandaloneSiteTest.class.getClassLoader(), args))
.named("gerrit.war " + Arrays.stream(args).collect(joining(" ")))
.isEqualTo(0);
}

View File

@ -63,6 +63,17 @@ public final class GerritLauncher {
System.exit(mainImpl(argv));
}
/**
* Invokes a proram.
*
* <p>Creates a new classloader to load and run the program class. To reuse a classloader across
* calls (e.g. from tests), use {@link #invokeProgram(ClassLoader, String[])}.
*
* @param argv arguments, as would be passed to {@code gerrit.war}. The first argument is the
* program name.
* @return program return code.
* @throws Exception if any error occurs.
*/
public static int mainImpl(String[] argv) throws Exception {
if (argv.length == 0) {
File me;
@ -163,7 +174,16 @@ public final class GerritLauncher {
}
}
private static int invokeProgram(ClassLoader loader, String[] origArgv) throws Exception {
/**
* Invokes a proram in the provided {@code ClassLoader}.
*
* @param loader classloader to load program class from.
* @param origArgv arguments, as would be passed to {@code gerrit.war}. The first argument is the
* program name.
* @return program return code.
* @throws Exception if any error occurs.
*/
public static int invokeProgram(ClassLoader loader, String[] origArgv) throws Exception {
String name = origArgv[0];
final String[] argv = new String[origArgv.length - 1];
System.arraycopy(origArgv, 1, argv, 0, argv.length);