Merge changes from topic 'Plugin-IT-tests'

* changes:
  Update cookbook-plugin revision
  Fix unmade plugin jar with buckd by means of disabling buckd temporarily
  Replace the hardcoded UNIT_TEST_GERRIT_SITE with a junit TemporaryFolder
  Add acceptance (IT) tests support for plugins
  Exclude bouncycastle key files to fix SecurityException upon plugin-api
This commit is contained in:
David Pursehouse 2015-09-09 02:27:12 +00:00 committed by Gerrit Code Review
commit 92cbd71bfe
7 changed files with 231 additions and 3 deletions

View File

@ -44,6 +44,7 @@ java_library(
'//lib/mina:sshd',
],
visibility = [
'//gerrit-plugin-api/...',
'//tools/eclipse:classpath',
'//gerrit-acceptance-tests/...',
],

View File

@ -76,6 +76,7 @@ import org.eclipse.jgit.transport.Transport;
import org.junit.AfterClass;
import org.junit.Rule;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
@ -193,6 +194,9 @@ public abstract class AbstractDaemonTest {
}
};
@Rule
public TemporaryFolder tempSiteDir = new TemporaryFolder();
@AfterClass
public static void stopCommonServer() throws Exception {
if (commonServer != null) {
@ -222,12 +226,14 @@ public abstract class AbstractDaemonTest {
return cfg.getBoolean("change", null, "submitWholeTopic", false);
}
private void beforeTest(Description description) throws Exception {
protected void beforeTest(Description description) throws Exception {
GerritServer.Description classDesc =
GerritServer.Description.forTestClass(description, configName);
GerritServer.Description methodDesc =
GerritServer.Description.forTestMethod(description, configName);
baseConfig.setString("gerrit", null, "tempSiteDir",
tempSiteDir.getRoot().getPath());
if (classDesc.equals(methodDesc)) {
if (commonServer == null) {
commonServer = GerritServer.start(classDesc, baseConfig);

View File

@ -62,7 +62,7 @@ class InMemoryTestingDatabaseModule extends LifecycleModule {
// TODO(dborowitz): Use jimfs.
bind(Path.class)
.annotatedWith(SitePath.class)
.toInstance(Paths.get("UNIT_TEST_GERRIT_SITE"));
.toInstance(Paths.get(cfg.getString("gerrit", null, "tempSiteDir")));
bind(GitRepositoryManager.class)
.toInstance(new InMemoryRepositoryManager());

View File

@ -0,0 +1,218 @@
// Copyright (C) 2015 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 com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.gerrit.server.config.SitePaths;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.junit.runner.Description;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ProcessBuilder.Redirect;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public abstract class PluginDaemonTest extends AbstractDaemonTest {
private static final String BUCKLC = "buck";
private static final String BUCKOUT = "buck-out";
private Path gen;
private Path testSite;
private Path pluginRoot;
private Path pluginsSitePath;
private Path pluginSubPath;
private Path pluginSource;
private String pluginName;
private boolean standalone;
@Override
protected void beforeTest(Description description) throws Exception {
locatePaths();
retrievePluginName();
buildPluginJar();
createTestSiteDirs();
copyJarToTestSite();
super.beforeTest(description);
}
protected void setPluginConfigString(String name, String value)
throws IOException, ConfigInvalidException {
SitePaths sitePath = new SitePaths(testSite);
FileBasedConfig cfg = getGerritConfigFile(sitePath);
cfg.load();
cfg.setString("plugin", pluginName, name, value);
cfg.save();
}
private FileBasedConfig getGerritConfigFile(SitePaths sitePath)
throws IOException {
FileBasedConfig cfg =
new FileBasedConfig(sitePath.gerrit_config.toFile(), FS.DETECTED);
if (!cfg.getFile().exists()) {
Path etc_path = Files.createDirectories(sitePath.etc_dir);
Files.createFile(etc_path.resolve("gerrit.config"));
}
return cfg;
}
private void locatePaths() {
URL pluginClassesUrl =
getClass().getProtectionDomain().getCodeSource().getLocation();
Path basePath = Paths.get(pluginClassesUrl.getPath()).getParent();
int idx = 0;
int buckOutIdx = 0;
int pluginsIdx = 0;
for (Path subPath : basePath) {
if (subPath.endsWith("plugins")) {
pluginsIdx = idx;
}
if (subPath.endsWith(BUCKOUT)) {
buckOutIdx = idx;
}
idx++;
}
standalone = checkStandalone(basePath);
pluginRoot = basePath.getRoot().resolve(basePath.subpath(0, buckOutIdx));
gen = pluginRoot.resolve(BUCKOUT).resolve("gen");
if (standalone) {
pluginSource = pluginRoot;
} else {
pluginSubPath = basePath.subpath(pluginsIdx, pluginsIdx + 2);
pluginSource = pluginRoot.resolve(pluginSubPath);
}
}
private boolean checkStandalone(Path basePath) {
String pathCharStringOrNone = "[a-zA-Z0-9._-]*?";
Pattern pattern = Pattern.compile(pathCharStringOrNone + "gerrit" +
pathCharStringOrNone);
Path partialPath = basePath;
for (int i = basePath.getNameCount(); i > 0; i--) {
int count = partialPath.getNameCount();
if (count > 1) {
String gerritDirCandidate =
partialPath.subpath(count - 2, count - 1).toString();
if (pattern.matcher(gerritDirCandidate).matches()) {
if (partialPath.endsWith(gerritDirCandidate + "/" + BUCKOUT)) {
return false;
}
}
}
partialPath = partialPath.getParent();
}
return true;
}
private void retrievePluginName() throws IOException {
Path buckFile = pluginSource.resolve("BUCK");
byte[] bytes = Files.readAllBytes(buckFile);
String buckContent =
new String(bytes, StandardCharsets.UTF_8).replaceAll("\\s+", "");
Matcher matcher =
Pattern.compile("gerrit_plugin\\(name='(.*?)'").matcher(buckContent);
if (matcher.find()) {
pluginName = matcher.group(1);
}
if (Strings.isNullOrEmpty(pluginName)) {
if (standalone) {
pluginName = pluginRoot.getFileName().toString();
} else {
pluginName = pluginSubPath.getFileName().toString();
}
}
}
private void buildPluginJar() throws IOException, InterruptedException {
Properties properties = loadBuckProperties();
String buck =
MoreObjects.firstNonNull(properties.getProperty(BUCKLC), BUCKLC);
String target;
if (standalone) {
target = "//:" + pluginName;
} else {
target = pluginSubPath.toString();
}
ProcessBuilder processBuilder =
new ProcessBuilder(buck, "build", target).directory(pluginRoot.toFile())
.redirectErrorStream(true);
// otherwise plugin jar creation fails:
processBuilder.environment().put("NO_BUCKD", "1");
Path forceJar = pluginSource.resolve("src/main/java/ForceJarIfMissing.java");
// if exists after cancelled test:
Files.deleteIfExists(forceJar);
Files.createFile(forceJar);
testSite = tempSiteDir.getRoot().toPath();
// otherwise process often hangs:
Path log = testSite.resolve("log");
processBuilder.redirectErrorStream(true);
processBuilder.redirectOutput(Redirect.appendTo(log.toFile()));
try {
processBuilder.start().waitFor();
} finally {
Files.delete(forceJar);
// otherwise jar not made next time if missing again:
processBuilder.start().waitFor();
}
}
private Properties loadBuckProperties() throws IOException {
Properties properties = new Properties();
Path propertiesPath = gen.resolve("tools").resolve("buck.properties");
if (Files.exists(propertiesPath)) {
try (InputStream in = Files.newInputStream(propertiesPath)) {
properties.load(in);
}
}
return properties;
}
private void createTestSiteDirs() throws IOException {
SitePaths sitePath = new SitePaths(testSite);
pluginsSitePath = Files.createDirectories(sitePath.plugins_dir);
Files.createDirectories(sitePath.tmp_dir);
}
private void copyJarToTestSite() throws IOException {
Path pluginOut;
if (standalone) {
pluginOut = gen;
} else {
pluginOut = gen.resolve(pluginSubPath);
}
Path jar = pluginOut.resolve(pluginName + ".jar");
Path dest = pluginsSitePath.resolve(jar.getFileName());
Files.copy(jar, dest, StandardCopyOption.REPLACE_EXISTING);
}
}

View File

@ -20,6 +20,7 @@ java_binary(
java_library(
name = 'lib',
exported_deps = PLUGIN_API + [
'//gerrit-acceptance-tests:lib',
'//gerrit-antlr:query_exception',
'//gerrit-antlr:query_parser',
'//gerrit-common:annotations',

View File

@ -9,6 +9,7 @@ maven_jar(
id = 'org.bouncycastle:bcprov-jdk15on:' + VERSION,
sha1 = '88a941faf9819d371e3174b5ed56a3f3f7d73269',
license = 'DO_NOT_DISTRIBUTE', #'bouncycastle'
exclude = ['META-INF/BCKEY.*'],
)
maven_jar(
@ -16,6 +17,7 @@ maven_jar(
id = 'org.bouncycastle:bcpg-jdk15on:' + VERSION,
sha1 = 'ff4665a4b5633ff6894209d5dd10b7e612291858',
license = 'DO_NOT_DISTRIBUTE', #'bouncycastle'
exclude = ['META-INF/BCKEY.*'],
deps = [':bcprov'],
)

@ -1 +1 @@
Subproject commit b9d3ca8a65030071e28be19296ba867ab424fbbf
Subproject commit ec6ed89c47ba7223f82d9cb512926a6c5081343e