Merge branch 'stable-2.15'
* stable-2.15:
Update bazlets to the latest on stable-2.14 to use 2.14.7 release API
Properly escape the subject
PropertyExtractor: Add null check for event.submitter
Change-Id: I135d0ec0589279663c4aee458c3aa7d310b76dda
diff --git a/.gitignore b/.gitignore
index dc4fc0a..cabf34f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,5 @@
.project
/.settings
/bazel-*
+.DS_Store
+/eclipse-out
diff --git a/WORKSPACE b/WORKSPACE
index c8cbd68..5591045 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,24 +3,24 @@
load("//:bazlets.bzl", "load_bazlets")
load_bazlets(
- commit = "cbddbc2b9571b1d692fb823ba8791ccd60b52421",
+ commit = "42bffc66c0e92753133e4cea2debe65abc359c4d",
# local_path = "/home/<user>/projects/bazlets",
)
# Snapshot Plugin API
-#load(
-# "@com_googlesource_gerrit_bazlets//:gerrit_api_maven_local.bzl",
-# "gerrit_api_maven_local",
-#)
-
-# Release Plugin API
load(
- "@com_googlesource_gerrit_bazlets//:gerrit_api.bzl",
- "gerrit_api",
+ "@com_googlesource_gerrit_bazlets//:gerrit_api_maven_local.bzl",
+ "gerrit_api_maven_local",
)
+# Release Plugin API
+#load(
+# "@com_googlesource_gerrit_bazlets//:gerrit_api.bzl",
+# "gerrit_api",
+#)
+
# Load release Plugin API
-gerrit_api()
+#gerrit_api()
# Load snapshot Plugin API
-# gerrit_api_maven_local()
+gerrit_api_maven_local()
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/ItsHookModule.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/ItsHookModule.java
index 91b26a0..691a037 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/ItsHookModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/ItsHookModule.java
@@ -14,14 +14,17 @@
package com.googlesource.gerrit.plugins.its.base;
-import com.google.gerrit.common.EventListener;
import com.google.gerrit.extensions.annotations.Exports;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.ProjectConfigEntry;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.events.EventListener;
import com.google.gerrit.server.git.validators.CommitValidationListener;
+import com.google.inject.Inject;
+import com.google.inject.Provides;
import com.googlesource.gerrit.plugins.its.base.its.ItsConfig;
import com.googlesource.gerrit.plugins.its.base.its.ItsHookEnabledConfigEntry;
import com.googlesource.gerrit.plugins.its.base.validation.ItsValidateComment;
@@ -33,11 +36,14 @@
import com.googlesource.gerrit.plugins.its.base.workflow.action.AddComment;
import com.googlesource.gerrit.plugins.its.base.workflow.action.AddSoyComment;
import com.googlesource.gerrit.plugins.its.base.workflow.action.AddStandardComment;
-import com.googlesource.gerrit.plugins.its.base.workflow.action.AddVelocityComment;
import com.googlesource.gerrit.plugins.its.base.workflow.action.LogEvent;
+import java.nio.file.Path;
public class ItsHookModule extends FactoryModule {
+ /** Folder where rules configuration files are located */
+ private static final String ITS_FOLDER = "its";
+
private final String pluginName;
private final PluginConfigFactory pluginCfgFactory;
@@ -61,7 +67,13 @@
factory(AddComment.Factory.class);
factory(AddSoyComment.Factory.class);
factory(AddStandardComment.Factory.class);
- factory(AddVelocityComment.Factory.class);
factory(LogEvent.Factory.class);
}
+
+ @Provides
+ @ItsPath
+ @Inject
+ Path itsPath(SitePaths sitePaths) {
+ return sitePaths.etc_dir.normalize().resolve(ITS_FOLDER);
+ }
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/ItsPath.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/ItsPath.java
new file mode 100644
index 0000000..dfd5119
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/ItsPath.java
@@ -0,0 +1,24 @@
+// Copyright (C) 2018 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.googlesource.gerrit.plugins.its.base;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+import java.lang.annotation.Retention;
+
+@Retention(RUNTIME)
+@BindingAnnotation
+public @interface ItsPath {}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/its/InitIts.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/its/InitIts.java
index 1cd2b74..9fb2b3d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/its/InitIts.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/its/InitIts.java
@@ -21,7 +21,10 @@
import com.google.gerrit.pgm.init.api.ConsoleUI;
import com.google.gerrit.pgm.init.api.InitStep;
import com.google.gerrit.pgm.init.api.Section;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.inject.Inject;
import java.io.IOException;
+import java.nio.file.Path;
import java.util.EnumSet;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
@@ -41,6 +44,8 @@
ENFORCED
}
+ @Inject private SitePaths sitePaths;
+
private final String pluginName;
private final String itsDisplayName;
protected final ConsoleUI ui;
@@ -61,7 +66,18 @@
}
@Override
- public void run() throws IOException, ConfigInvalidException {}
+ public void run() throws IOException, ConfigInvalidException {
+ Path deprecatedRules = sitePaths.etc_dir.normalize().resolve("its").resolve("action.config");
+ if (deprecatedRules.toFile().exists()) {
+ ui.error(
+ "Deprecated rules file '%s' (No trailing 's' in 'action') will not be read. "
+ + "Please migrate to 'etc/its/actions.config' (Trailing 's' in 'actions') and retry "
+ + "the init step.\n",
+ deprecatedRules);
+ throw new ConfigInvalidException(
+ "Deprecated configuration file found: " + deprecatedRules.toRealPath());
+ }
+ }
@Override
public void postRun() throws IOException, ConfigInvalidException {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/its/InvalidTransitionException.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/its/InvalidTransitionException.java
index 78c6ec5..949031b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/its/InvalidTransitionException.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/its/InvalidTransitionException.java
@@ -14,9 +14,7 @@
package com.googlesource.gerrit.plugins.its.base.its;
-import java.io.IOException;
-
-public class InvalidTransitionException extends IOException {
+public class InvalidTransitionException extends Exception {
private static final long serialVersionUID = 1L;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/its/ItsConfig.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/its/ItsConfig.java
index 99fe80c..de22f9c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/its/ItsConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/its/ItsConfig.java
@@ -28,8 +28,8 @@
import com.google.gerrit.server.events.ChangeMergedEvent;
import com.google.gerrit.server.events.ChangeRestoredEvent;
import com.google.gerrit.server.events.CommentAddedEvent;
-import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.events.PatchSetCreatedEvent;
+import com.google.gerrit.server.events.RefEvent;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectCache;
@@ -76,29 +76,17 @@
// Plugin enablement --------------------------------------------------------
- public boolean isEnabled(Event event) {
- if (event instanceof PatchSetCreatedEvent) {
- PatchSetCreatedEvent e = (PatchSetCreatedEvent) event;
- return isEnabled(e.getProjectNameKey(), e.getRefName());
- } else if (event instanceof CommentAddedEvent) {
- CommentAddedEvent e = (CommentAddedEvent) event;
- return isEnabled(e.getProjectNameKey(), e.getRefName());
- } else if (event instanceof ChangeMergedEvent) {
- ChangeMergedEvent e = (ChangeMergedEvent) event;
- return isEnabled(e.getProjectNameKey(), e.getRefName());
- } else if (event instanceof ChangeAbandonedEvent) {
- ChangeAbandonedEvent e = (ChangeAbandonedEvent) event;
- return isEnabled(e.getProjectNameKey(), e.getRefName());
- } else if (event instanceof ChangeRestoredEvent) {
- ChangeRestoredEvent e = (ChangeRestoredEvent) event;
- return isEnabled(e.getProjectNameKey(), e.getRefName());
- } else if (event instanceof RefUpdatedEvent) {
- RefUpdatedEvent e = (RefUpdatedEvent) event;
- return isEnabled(e.getProjectNameKey(), e.getRefName());
- } else {
- log.debug("Event {} not recognised and ignored", event);
- return false;
+ public boolean isEnabled(RefEvent event) {
+ if (event instanceof PatchSetCreatedEvent
+ || event instanceof CommentAddedEvent
+ || event instanceof ChangeMergedEvent
+ || event instanceof ChangeAbandonedEvent
+ || event instanceof ChangeRestoredEvent
+ || event instanceof RefUpdatedEvent) {
+ return isEnabled(event.getProjectNameKey(), event.getRefName());
}
+ log.debug("Event {} not recognised and ignored", event);
+ return false;
}
public boolean isEnabled(Project.NameKey projectNK, String refName) {
@@ -110,17 +98,8 @@
projectNK.get());
return false;
}
-
- if (isEnforcedByAnyParentProject(refName, projectState)) {
- return true;
- }
-
- return !"false"
- .equals(
- pluginCfgFactory
- .getFromProjectConfigWithInheritance(projectState, pluginName)
- .getString("enabled", "false"))
- && isEnabledForBranch(projectState, refName);
+ return isEnforcedByAnyParentProject(refName, projectState)
+ || (isEnabledForProject(projectState) && isEnabledForBranch(projectState, refName));
}
private boolean isEnforcedByAnyParentProject(String refName, ProjectState projectState) {
@@ -134,6 +113,14 @@
return false;
}
+ private boolean isEnabledForProject(ProjectState projectState) {
+ return !"false"
+ .equals(
+ pluginCfgFactory
+ .getFromProjectConfigWithInheritance(projectState, pluginName)
+ .getString("enabled", "false"));
+ }
+
private boolean isEnabledForBranch(ProjectState project, String refName) {
String[] refPatterns =
pluginCfgFactory
@@ -215,6 +202,17 @@
}
/**
+ * Pattern to skip the mandatory check for an issue. Can be used to explicitly bypass the
+ * mandatory issue pattern check for some commits.
+ *
+ * <p>When no pattern is specified, it will return a pattern which never matches.
+ */
+ public Optional<Pattern> getDummyIssuePattern() {
+ return Optional.ofNullable(getPluginConfigString("dummyIssuePattern"))
+ .map(Pattern::compile);
+ }
+
+ /**
* Gets how necessary it is to associate commits with issues
*
* @return policy on how necessary association with issues is
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/util/IssueExtractor.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/util/IssueExtractor.java
index 5c344f1..fd37249 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/util/IssueExtractor.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/util/IssueExtractor.java
@@ -1,5 +1,7 @@
package com.googlesource.gerrit.plugins.its.base.util;
+import static java.util.Arrays.copyOfRange;
+
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@@ -17,7 +19,6 @@
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -156,13 +157,11 @@
if (footerStart == -1) {
// No footer could be found. So all lines after the first one (that's
// the subject) is the body.
- //body = String[] templateParameters =
- // Arrays.copyOfRange(allParameters, 1, allParameters.length);
if (lines.length > 0) {
- body = StringUtils.join(lines, "\n", 1, lines.length);
+ body = String.join("\n", copyOfRange(lines, 1, lines.length));
}
} else {
- body = StringUtils.join(lines, "\n", 1, footerStart - 1);
+ body = String.join("\n", copyOfRange(lines, 1, footerStart - 1));
StringBuilder footerBuilder = new StringBuilder();
for (int lineIdx = footerStart; lineIdx < footerEnd; lineIdx++) {
@@ -182,7 +181,7 @@
}
footerBuilder.append(line);
}
- footer = StringUtils.join(lines, "\n", footerStart, footerEnd);
+ footer = String.join("\n", copyOfRange(lines, footerStart, footerEnd));
}
if (body != null) {
addIssuesOccurrence(body, "body", ret);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/util/PropertyExtractor.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/util/PropertyExtractor.java
index b04bcb0..6cc93da 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/util/PropertyExtractor.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/util/PropertyExtractor.java
@@ -27,9 +27,9 @@
import com.google.gerrit.server.events.ChangeMergedEvent;
import com.google.gerrit.server.events.ChangeRestoredEvent;
import com.google.gerrit.server.events.CommentAddedEvent;
-import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.events.PatchSetCreatedEvent;
import com.google.gerrit.server.events.PatchSetEvent;
+import com.google.gerrit.server.events.RefEvent;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.its.base.workflow.Property;
@@ -169,7 +169,7 @@
* @param event The event to extract property sets from.
* @return sets of property sets extracted from the event.
*/
- public Set<Set<Property>> extractFrom(Event event) {
+ public Set<Set<Property>> extractFrom(RefEvent event) {
Map<String, Set<String>> associations = null;
Set<Set<Property>> ret = Sets.newHashSet();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/validation/ItsValidateComment.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/validation/ItsValidateComment.java
index 969eeb0..d45d0a6 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/validation/ItsValidateComment.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/validation/ItsValidateComment.java
@@ -92,7 +92,10 @@
ret.add(commitValidationFailure(synopsis, details));
}
- } else {
+ } else if (!itsConfig
+ .getDummyIssuePattern()
+ .map(p -> p.matcher(commitMessage).find())
+ .orElse(false)) {
synopsis = "Missing issue-id in commit message";
StringBuilder sb = new StringBuilder();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionController.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionController.java
index b1c0982..844ac91 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionController.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionController.java
@@ -14,8 +14,9 @@
package com.googlesource.gerrit.plugins.its.base.workflow;
-import com.google.gerrit.common.EventListener;
import com.google.gerrit.server.events.Event;
+import com.google.gerrit.server.events.EventListener;
+import com.google.gerrit.server.events.RefEvent;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.its.base.its.ItsConfig;
import com.googlesource.gerrit.plugins.its.base.util.PropertyExtractor;
@@ -48,11 +49,16 @@
@Override
public void onEvent(Event event) {
- if (!itsConfig.isEnabled(event)) {
- return;
+ if (event instanceof RefEvent) {
+ RefEvent refEvent = (RefEvent) event;
+ if (itsConfig.isEnabled(refEvent)) {
+ handleEvent(refEvent);
+ }
}
+ }
- Set<Set<Property>> propertiesCollections = propertyExtractor.extractFrom(event);
+ private void handleEvent(RefEvent refEvent) {
+ Set<Set<Property>> propertiesCollections = propertyExtractor.extractFrom(refEvent);
for (Set<Property> properties : propertiesCollections) {
Collection<ActionRequest> actions = ruleBase.actionRequestsFor(properties);
if (!actions.isEmpty()) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutor.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutor.java
index 0e31b93..fdf1e8e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutor.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutor.java
@@ -20,7 +20,6 @@
import com.googlesource.gerrit.plugins.its.base.workflow.action.AddComment;
import com.googlesource.gerrit.plugins.its.base.workflow.action.AddSoyComment;
import com.googlesource.gerrit.plugins.its.base.workflow.action.AddStandardComment;
-import com.googlesource.gerrit.plugins.its.base.workflow.action.AddVelocityComment;
import com.googlesource.gerrit.plugins.its.base.workflow.action.LogEvent;
import java.io.IOException;
import java.util.Set;
@@ -34,7 +33,6 @@
private final ItsFacade its;
private final AddComment.Factory addCommentFactory;
private final AddStandardComment.Factory addStandardCommentFactory;
- private final AddVelocityComment.Factory addVelocityCommentFactory;
private final AddSoyComment.Factory addSoyCommentFactory;
private final LogEvent.Factory logEventFactory;
@@ -43,33 +41,33 @@
ItsFacade its,
AddComment.Factory addCommentFactory,
AddStandardComment.Factory addStandardCommentFactory,
- AddVelocityComment.Factory addVelocityCommentFactory,
AddSoyComment.Factory addSoyCommentFactory,
LogEvent.Factory logEventFactory) {
this.its = its;
this.addCommentFactory = addCommentFactory;
this.addStandardCommentFactory = addStandardCommentFactory;
- this.addVelocityCommentFactory = addVelocityCommentFactory;
this.addSoyCommentFactory = addSoyCommentFactory;
this.logEventFactory = logEventFactory;
}
+ private Action getAction(String actionName) {
+ switch (actionName) {
+ case "add-comment":
+ return addCommentFactory.create();
+ case "add-standard-comment":
+ return addStandardCommentFactory.create();
+ case "add-soy-comment":
+ return addSoyCommentFactory.create();
+ case "log-event":
+ return logEventFactory.create();
+ default:
+ return null;
+ }
+ }
+
public void execute(String issue, ActionRequest actionRequest, Set<Property> properties) {
try {
- String name = actionRequest.getName();
- Action action = null;
- if ("add-comment".equals(name)) {
- action = addCommentFactory.create();
- } else if ("add-standard-comment".equals(name)) {
- action = addStandardCommentFactory.create();
- } else if ("add-velocity-comment".equals(name)) {
- action = addVelocityCommentFactory.create();
- } else if ("add-soy-comment".equals(name)) {
- action = addSoyCommentFactory.create();
- } else if ("log-event".equals(name)) {
- action = logEventFactory.create();
- }
-
+ Action action = getAction(actionRequest.getName());
if (action == null) {
its.performAction(issue, actionRequest.getUnparsed());
} else {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionRequest.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionRequest.java
index dec671e..964c01d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionRequest.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionRequest.java
@@ -49,11 +49,7 @@
* @return The name of the requested action, if a name has been given. "" otherwise.
*/
public String getName() {
- String ret = "";
- if (chopped.length > 0) {
- ret = chopped[0];
- }
- return ret;
+ return getParameter(0);
}
/**
@@ -63,11 +59,7 @@
* @return The name of the requested parameter, if the requested parameter exists. "" otherwise.
*/
public String getParameter(int i) {
- String ret = "";
- if (chopped.length > i) {
- ret = chopped[i];
- }
- return ret;
+ return chopped.length > i ? chopped[i] : "";
}
/**
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/RuleBase.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/RuleBase.java
index 41dc9fa..8dd0016 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/RuleBase.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/RuleBase.java
@@ -16,8 +16,8 @@
import com.google.common.collect.Lists;
import com.google.gerrit.extensions.annotations.PluginName;
-import com.google.gerrit.server.config.SitePath;
import com.google.inject.Inject;
+import com.googlesource.gerrit.plugins.its.base.ItsPath;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
@@ -28,16 +28,12 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/** Collection and matcher agains {@link Rule}s. */
+/** Collection and matcher against {@link Rule}s. */
public class RuleBase {
private static final Logger log = LoggerFactory.getLogger(RuleBase.class);
- /** File beginning (relative to site) to load rules from */
- private static final String ITS_CONFIG_FILE_START =
- "etc" + File.separatorChar + "its" + File.separator + "actions";
-
- /** File end to load rules from */
- private static final String ITS_CONFIG_FILE_END = ".config";
+ /** Rules configuration filename pattern */
+ private static final String CONFIG_FILE_NAME = "actions%s.config";
/** The section for rules within rulebases */
private static final String RULE_SECTION = "rule";
@@ -45,7 +41,7 @@
/** The key for actions within rulebases */
private static final String ACTION_KEY = "action";
- private final Path sitePath;
+ private final Path itsPath;
private final Rule.Factory ruleFactory;
private final Condition.Factory conditionFactory;
private final ActionRequest.Factory actionRequestFactory;
@@ -59,12 +55,12 @@
@Inject
public RuleBase(
- @SitePath Path sitePath,
+ @ItsPath Path itsPath,
Rule.Factory ruleFactory,
Condition.Factory conditionFactory,
ActionRequest.Factory actionRequestFactory,
@PluginName String pluginName) {
- this.sitePath = sitePath;
+ this.itsPath = itsPath;
this.ruleFactory = ruleFactory;
this.conditionFactory = conditionFactory;
this.actionRequestFactory = actionRequestFactory;
@@ -73,7 +69,7 @@
}
/**
- * Adds rules from a file to the the RuleBase.
+ * Adds rules from a file to the RuleBase.
*
* <p>If the given file does not exist, it is silently ignored
*
@@ -116,49 +112,20 @@
private void reloadRules() {
rules = Lists.newArrayList();
- // Add rules from file with typo in filename
- //
- // While the documentation called for "actions.config" (Trailing "s" in
- // "actions"), the code previously only loaded "action.config" (No
- // trailing "s" in "action"). To give users time to gracefully migrate to
- // "actions.config" (with trailing "s", we (for now) load files from both
- // locations, but consider "actions.config" (with trailing "s" the
- // canonical place.
- File faultyNameRuleFile =
- new File(
- sitePath.toFile(),
- "etc" + File.separatorChar + "its" + File.separator + "action.config");
- if (faultyNameRuleFile.exists()) {
- log.warn(
- "Loading rules from deprecated 'etc/its/action.config' (No "
- + "trailing 's' in 'action'). Please migrate to "
- + "'etc/its/actions.config' (Trailing 's' in 'actions').");
- addRulesFromFile(faultyNameRuleFile);
- }
-
// Add global rules
- File globalRuleFile = new File(sitePath.toFile(), ITS_CONFIG_FILE_START + ITS_CONFIG_FILE_END);
+ File globalRuleFile = itsPath.resolve(String.format(CONFIG_FILE_NAME, "")).toFile();
addRulesFromFile(globalRuleFile);
// Add its-specific rules
File itsSpecificRuleFile =
- new File(sitePath.toFile(), ITS_CONFIG_FILE_START + "-" + pluginName + ITS_CONFIG_FILE_END);
+ itsPath.resolve(String.format(CONFIG_FILE_NAME, "-" + pluginName)).toFile();
addRulesFromFile(itsSpecificRuleFile);
if (!globalRuleFile.exists() && !itsSpecificRuleFile.exists()) {
- try {
- log.warn(
- "Neither global rule file "
- + globalRuleFile.getCanonicalPath()
- + " nor Its specific rule file"
- + itsSpecificRuleFile.getCanonicalPath()
- + " exist. Please configure "
- + "rules.");
- } catch (IOException e) {
- log.warn(
- "Neither global rule file nor Its specific rule files exist. "
- + "Please configure rules.");
- }
+ log.warn(
+ "Neither global rule file {} nor Its specific rule file {} exist. Please configure rules.",
+ globalRuleFile,
+ itsSpecificRuleFile);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddComment.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddComment.java
index 16855d3..51f976c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddComment.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddComment.java
@@ -21,7 +21,6 @@
import com.googlesource.gerrit.plugins.its.base.workflow.Property;
import java.io.IOException;
import java.util.Set;
-import org.apache.commons.lang.StringUtils;
/**
* Adds a fixed comment to an issue.
@@ -43,8 +42,7 @@
@Override
public void execute(String issue, ActionRequest actionRequest, Set<Property> properties)
throws IOException {
- String[] parameters = actionRequest.getParameters();
- String comment = StringUtils.join(parameters, " ");
+ String comment = String.join(" ", actionRequest.getParameters());
if (!Strings.isNullOrEmpty(comment)) {
its.addComment(issue, comment);
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddSoyComment.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddSoyComment.java
index bbad6e9..0ddefd5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddSoyComment.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddSoyComment.java
@@ -16,16 +16,15 @@
import com.google.common.base.Strings;
import com.google.common.io.CharStreams;
-import com.google.gerrit.server.config.SitePath;
import com.google.inject.Inject;
import com.google.inject.ProvisionException;
import com.google.template.soy.SoyFileSet;
import com.google.template.soy.data.SanitizedContent;
import com.google.template.soy.tofu.SoyTofu;
+import com.googlesource.gerrit.plugins.its.base.ItsPath;
import com.googlesource.gerrit.plugins.its.base.its.ItsFacade;
import com.googlesource.gerrit.plugins.its.base.workflow.ActionRequest;
import com.googlesource.gerrit.plugins.its.base.workflow.Property;
-import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
@@ -48,17 +47,13 @@
AddSoyComment create();
}
- /** Directory (relative to site) to search templates in */
- private static final String ITS_TEMPLATE_DIR =
- "etc" + File.separator + "its" + File.separator + "templates";
-
private final ItsFacade its;
- private final Path sitePath;
+ private final Path templateDir;
protected HashMap<String, Object> soyContext;
@Inject
- public AddSoyComment(@SitePath Path sitePath, ItsFacade its) {
- this.sitePath = sitePath;
+ public AddSoyComment(@ItsPath Path itsPath, ItsFacade its) {
+ this.templateDir = itsPath.resolve("templates");
this.its = its;
}
@@ -82,7 +77,6 @@
String template,
SanitizedContent.ContentKind kind,
Set<Property> properties) {
- Path templateDir = sitePath.resolve(ITS_TEMPLATE_DIR);
Path templatePath = templateDir.resolve(template + ".soy");
String content;
@@ -115,17 +109,18 @@
@Override
public void execute(String issue, ActionRequest actionRequest, Set<Property> properties)
throws IOException {
- SoyFileSet.Builder builder = SoyFileSet.builder();
- String template = null;
- String templateName = actionRequest.getParameter(1);
- if (templateName.isEmpty()) {
- log.error("No template name given in {}", actionRequest);
- } else {
- template = templateName;
- }
- if (!Strings.isNullOrEmpty(template)) {
- String comment = soyTextTemplate(builder, template, properties);
+ String comment = buildComment(actionRequest, properties);
+ if (!Strings.isNullOrEmpty(comment)) {
its.addComment(issue, comment);
}
}
+
+ private String buildComment(ActionRequest actionRequest, Set<Property> properties) {
+ String template = actionRequest.getParameter(1);
+ if (!template.isEmpty()) {
+ return soyTextTemplate(SoyFileSet.builder(), template, properties);
+ }
+ log.error("No template name given in {}", actionRequest);
+ return "";
+ }
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddStandardComment.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddStandardComment.java
index eb8c4a6..4777d4b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddStandardComment.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddStandardComment.java
@@ -41,16 +41,6 @@
this.its = its;
}
- private String formatPerson(String prefix, Map<String, String> map) {
- String ret = Strings.nullToEmpty(map.get(prefix + "-name"));
- ret = Strings.nullToEmpty(map.get(prefix + "Name"));
- if (ret.isEmpty()) {
- ret = Strings.nullToEmpty(map.get(prefix + "-username"));
- ret = Strings.nullToEmpty(map.get(prefix + "Username"));
- }
- return ret;
- }
-
private String getCommentChangeEvent(String action, String prefix, Map<String, String> map) {
String ret = "";
String changeNumber = getValueFromMap(map, "", "change-number", "changeNumber");
@@ -87,26 +77,16 @@
return "";
}
- private String getCommentChangeAbandoned(Map<String, String> map) {
- return getCommentChangeEvent("abandoned", "abandoner", map);
- }
-
- private String getCommentChangeMerged(Map<String, String> map) {
- return getCommentChangeEvent("merged", "submitter", map);
- }
-
- private String getCommentChangeRestored(Map<String, String> map) {
- return getCommentChangeEvent("restored", "restorer", map);
- }
-
- private String getCommentPatchSetCreated(Map<String, String> map) {
- return getCommentChangeEvent("had a related patch set uploaded", "uploader", map);
- }
-
@Override
public void execute(String issue, ActionRequest actionRequest, Set<Property> properties)
throws IOException {
- String comment = "";
+ String comment = buildComment(properties);
+ if (!Strings.isNullOrEmpty(comment)) {
+ its.addComment(issue, comment);
+ }
+ }
+
+ private String buildComment(Set<Property> properties) {
Map<String, String> map = Maps.newHashMap();
for (Property property : properties) {
String current = property.getValue();
@@ -119,18 +99,17 @@
map.put(key, old + current);
}
}
- String eventType = map.get("event-type");
- if ("change-abandoned".equals(eventType)) {
- comment = getCommentChangeAbandoned(map);
- } else if ("change-merged".equals(eventType)) {
- comment = getCommentChangeMerged(map);
- } else if ("change-restored".equals(eventType)) {
- comment = getCommentChangeRestored(map);
- } else if ("patchset-created".equals(eventType)) {
- comment = getCommentPatchSetCreated(map);
- }
- if (!Strings.isNullOrEmpty(comment)) {
- its.addComment(issue, comment);
+ switch (map.get("event-type")) {
+ case "change-abandoned":
+ return getCommentChangeEvent("abandoned", "abandoner", map);
+ case "change-merged":
+ return getCommentChangeEvent("merged", "submitter", map);
+ case "change-restored":
+ return getCommentChangeEvent("restored", "restorer", map);
+ case "patchset-created":
+ return getCommentChangeEvent("had a related patch set uploaded", "uploader", map);
+ default:
+ return "";
}
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddVelocityComment.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddVelocityComment.java
deleted file mode 100644
index 13a6655..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddVelocityComment.java
+++ /dev/null
@@ -1,150 +0,0 @@
-// 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.googlesource.gerrit.plugins.its.base.workflow.action;
-
-import com.google.common.base.Strings;
-import com.google.gerrit.server.config.SitePath;
-import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.its.base.its.ItsFacade;
-import com.googlesource.gerrit.plugins.its.base.workflow.ActionRequest;
-import com.googlesource.gerrit.plugins.its.base.workflow.Property;
-import java.io.File;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.Set;
-import org.apache.commons.lang.StringUtils;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.runtime.RuntimeInstance;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Adds a short predefined comments to an issue.
- *
- * <p>Comments are added for merging, abandoning, restoring of changes and adding of patch sets.
- */
-public class AddVelocityComment implements Action {
- private static final Logger log = LoggerFactory.getLogger(AddVelocityComment.class);
-
- public interface Factory {
- AddVelocityComment create();
- }
-
- /** Directory (relative to site) to search templates in */
- private static final String ITS_TEMPLATE_DIR =
- "etc" + File.separator + "its" + File.separator + "templates";
-
- private final ItsFacade its;
- private final Path sitePath;
- private final RuntimeInstance velocityRuntime;
-
- @Inject
- public AddVelocityComment(
- RuntimeInstance velocityRuntime, @SitePath Path sitePath, ItsFacade its) {
- this.velocityRuntime = velocityRuntime;
- this.sitePath = sitePath;
- this.its = its;
- }
-
- private VelocityContext getVelocityContext(Set<Property> properties) {
- VelocityContext velocityContext = new VelocityContext();
- for (Property property : properties) {
- String key = property.getKey();
- if (!Strings.isNullOrEmpty(key)) {
- String value = property.getValue();
- if (!Strings.isNullOrEmpty(value)) {
- velocityContext.put(key, value);
- }
- }
- }
-
- velocityContext.put("its", new VelocityAdapterItsFacade(its));
-
- return velocityContext;
- }
-
- private String velocify(String template, Set<Property> properties) {
- VelocityContext context = getVelocityContext(properties);
- StringWriter w = new StringWriter();
- velocityRuntime.evaluate(context, w, "ItsComment", template);
- return w.toString();
- }
-
- @Override
- public void execute(String issue, ActionRequest actionRequest, Set<Property> properties)
- throws IOException {
- String template = null;
- String templateName = actionRequest.getParameter(1);
- if ("inline".equals(templateName)) {
- String[] allParameters = actionRequest.getParameters();
- String[] templateParameters = Arrays.copyOfRange(allParameters, 1, allParameters.length);
- template = StringUtils.join(templateParameters, " ");
- } else {
- if (templateName.isEmpty()) {
- log.error("No template name given in {}", actionRequest);
- } else {
- Path templateDir = sitePath.resolve(ITS_TEMPLATE_DIR);
- Path templatePath = templateDir.resolve(templateName + ".vm");
- if (Files.isReadable(templatePath)) {
- template = new String(Files.readAllBytes(templatePath));
- } else {
- log.error("Cannot read template {}", templatePath);
- }
- }
- }
- if (!Strings.isNullOrEmpty(template)) {
- String comment = velocify(template, properties);
- its.addComment(issue, comment);
- }
- }
-
- /** Adapter for ItsFacade to be used through Velocity */
- // Although we'd prefer to keep this class private, Velocity will only pick
- // it up, if it is public.
- public class VelocityAdapterItsFacade {
-
- private final ItsFacade facade;
-
- private VelocityAdapterItsFacade(ItsFacade facade) {
- this.facade = facade;
- }
-
- /**
- * Format a link to a URL in the used Its' syntax.
- *
- * @param url URL to link to
- * @param caption Text used to represent the link
- * @return Link to the given URL in the used Its' syntax.
- */
- public String formatLink(String url, String caption) {
- return facade.createLinkForWebui(url, caption);
- }
-
- /**
- * Format a link to an URL.
- *
- * <p>The provided URL is used as caption for the formatted link.
- *
- * @param url URL to link to
- * @return Link to the given URL in the used Its' syntax.
- */
- public String formatLink(String url) {
- return facade.createLinkForWebui(url, url);
- }
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/LogEvent.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/LogEvent.java
index 3a46202..4abff71 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/LogEvent.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/action/LogEvent.java
@@ -34,7 +34,18 @@
ERROR,
WARN,
INFO,
- DEBUG
+ DEBUG;
+
+ static Level fromString(String s) {
+ if (s != null) {
+ for (Level level : Level.values()) {
+ if (s.toUpperCase().equals(level.toString())) {
+ return level;
+ }
+ }
+ }
+ return INFO;
+ }
}
public interface Factory {
@@ -67,21 +78,7 @@
@Override
public void execute(String issue, ActionRequest actionRequest, Set<Property> properties)
throws IOException {
- String levelParameter = actionRequest.getParameter(1);
- if (levelParameter != null) {
- levelParameter = levelParameter.toLowerCase();
- }
- Level level = Level.INFO;
- if ("error".equals(levelParameter)) {
- level = Level.ERROR;
- } else if ("warn".equals(levelParameter)) {
- level = Level.WARN;
- } else if ("info".equals(levelParameter)) {
- level = Level.INFO;
- } else if ("debug".equals(levelParameter)) {
- level = Level.DEBUG;
- }
-
+ Level level = Level.fromString(actionRequest.getParameter(1));
for (Property property : properties) {
logProperty(level, property);
}
diff --git a/src/main/resources/Documentation/config-common.md b/src/main/resources/Documentation/config-common.md
index d53b0c6..9532510 100644
--- a/src/main/resources/Documentation/config-common.md
+++ b/src/main/resources/Documentation/config-common.md
@@ -42,8 +42,8 @@
values are supported (default is `OPTIONAL`):
MANDATORY
-: One or more issue-ids are required in the git commit message, otherwise
- the git push will be rejected.
+: One or more issue-ids are required in the git commit message. The git push will
+ be rejected otherwise.
SUGGESTED
: Whenever the git commit message does not contain one or more issue-ids,
@@ -185,6 +185,12 @@
the `@PLUGIN@.commentlink` comment link, and the default is `0`, if there
are no such groups.
+<a name="common-config-dummyIssuePattern">`@PLUGIN@.dummyIssuePattern`
+: Pattern which can be specified to match a dummy issue.
+
+ This setting is useful to bypass the MANDATORY check for commits matching
+ a specific pattern.
+
[Back to @PLUGIN@ documentation index][index]
[index]: index.html
diff --git a/src/main/resources/Documentation/config-rulebase-common.md b/src/main/resources/Documentation/config-rulebase-common.md
index 16f2de5..2409a63 100644
--- a/src/main/resources/Documentation/config-rulebase-common.md
+++ b/src/main/resources/Documentation/config-rulebase-common.md
@@ -175,50 +175,50 @@
values are:
`somewhere`
-: issue id occurs somewhere in the commit message of the change/the
- most recent patch set.
+: issue id occurs somewhere in the commit message of the change/the
+ most recent patch set.
`subject`
-: issue id occurs in the first line of the commit message of the
- change/the most recent patch set.
+: issue id occurs in the first line of the commit message of the
+ change/the most recent patch set.
`body`
-: issue id occurs after the subject but before the footer of the
- commit message of the change/the most recent patch set.
+: issue id occurs after the subject but before the footer of the
+ commit message of the change/the most recent patch set.
`footer`
-: issue id occurs in the last paragraph after the subject of the
- commit message of the change/the most recent patch set
+: issue id occurs in the last paragraph after the subject of the
+ commit message of the change/the most recent patch set
`footer-<Key>`
-: issue id occurs in the footer of the commit message of the
- change/the most recent patch set, and is in a line with a key
- (part before the colon).
+: issue id occurs in the footer of the commit message of the
+ change/the most recent patch set, and is in a line with a key
+ (part before the colon).
- So for example, if the footer would contain a line
+ So for example, if the footer would contain a line
- ```
+ ```
Fixes-Issue: issue 4711
```
- then a property `association` with value `footer-Fixes-Issue`
- would get added to the event for issue “4711”.
+ then a property `association` with value `footer-Fixes-Issue`
+ would get added to the event for issue “4711”.
`added@<Association-Value>`
-: (only for events that allow to determine the patch set number.
- So for example, this `association` property is not set for
- RevUpdatedEvents)
+: (only for events that allow to determine the patch set number.
+ So for example, this `association` property is not set for
+ RevUpdatedEvents)
- issue id occurs at `<Association-Value>` in the most recent
- patch set of the change, and either the event is for patch set
- 1 or the issue id does not occur at `<Association-Value>` in
- the previous patch set.
+ issue id occurs at `<Association-Value>` in the most recent
+ patch set of the change, and either the event is for patch set
+ 1 or the issue id does not occur at `<Association-Value>` in
+ the previous patch set.
- So for example if issue “4711” occurs in the subject of patch
- set 3 (the most recent patch set) of a change, but not in
- patch set 2. When adding a comment to this change, the event
- for issue “4711” would get a property 'association' with value
- `added@subject`.
+ So for example if issue “4711” occurs in the subject of patch
+ set 3 (the most recent patch set) of a change, but not in
+ patch set 2. When adding a comment to this change, the event
+ for issue “4711” would get a property 'association' with value
+ `added@subject`.
[event-properties-ChangeAbandonedEvent]: #event-properties-ChangeAbandonedEvent
### <a name="event-properties-ChangeAbandonedEvent">ChangeAbandonedEvent</a>
@@ -482,10 +482,7 @@
[`add-standard-comment`][action-add-standard-comment]
: adds a predefined standard comment for certain events
-[`add-velocity-comment`][action-add-velocity-comment]
-: adds a rendered Velocity template as issue comment
-
-[`add-soy-comment`][action-add-velocity-comment]
+[`add-soy-comment`][action-add-soy-comment]
: adds a rendered Closure Template (soy) template as issue comment
[`log-event`][action-log-event]
@@ -523,67 +520,6 @@
(abandoner, merger, ...), the change's subject, a reason (if one has
been given), and a link to the change.
-[action-add-velocity-comment]: #action-add-velocity-comment
-### <a name="action-add-velocity-comment">Action: add-velocity-comment</a>
-
-The `add-velocity-comment` action renders a Velocity template for the
-event and adds the output as comment to any associated issue.
-
-So for example
-
-```
- action = add-velocity-comment TemplateName
-```
-
-would render the template `etc/its/templates/TemplateName.vm` add the
-output as comment to associated issues.
-
-If 'TemplateName' is `inline`, the Velocity template to render is not
-loaded from a file, but the template is built by joining the remaining
-parameters. So for example
-
-```
- action = add-velocity-comment inline Sample template using $subject property.
-```
-
-would render “Sample template using $subject property.” as Velocity
-template.
-
-If 'TemplateName' is not `inline`, further parameters get ignored.
-
-Any [property][event-properties] of the event may be used from
-templates. So for example `$subject` in the above example refers to
-the event's subject property, and `$changeNumber` would refer to the
-change's number.
-
-Additionally, the context's `its` property provides an object that
-allows to format links using the its' syntax:
-
-`formatLink( url )`
-: Formats a link to a url.
-
- So for example upon adding a comment to a change, the
- following rule formats a link to the change:
-
- ```
-[rule "formatLinkSampleRule"]
- event-type = comment-added
- action = add-velocity-comment inline Comment for change $change-number added. See ${its.formatLink($changeUrl)}
-```
-
-`formatLink( url, caption )`
-: Formats a link to a url using 'caption' to represent the url.
-
- So for example upon adding a comment to a change, the following rule
- formats a link to the change using the change number as link
- capition:
-
- ```
-[rule "formatLinkSampleRule"]
- event-type = comment-added
- action = add-velocity-comment inline Comment for change ${its.formatLink($changeUrl, $changeNumber)} added.
-```
-
[action-add-soy-comment]: #action-add-soy-comment
### <a name="action-add-soy-comment">Action: add-soy-comment</a>
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/base/its/ItsConfigTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/base/its/ItsConfigTest.java
index 6561d00..9664542 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/its/base/its/ItsConfigTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/base/its/ItsConfigTest.java
@@ -28,8 +28,8 @@
import com.google.gerrit.server.events.ChangeMergedEvent;
import com.google.gerrit.server.events.ChangeRestoredEvent;
import com.google.gerrit.server.events.CommentAddedEvent;
-import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.events.PatchSetCreatedEvent;
+import com.google.gerrit.server.events.RefEvent;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
@@ -469,7 +469,7 @@
}
public void BROKEN_testIsEnabledUnknownEvent() {
- Event event = new Event("foo") {};
+ RefEvent event = createMock(RefEvent.class);
ItsConfig itsConfig = createItsConfig();
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/base/util/PropertyExtractorTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/base/util/PropertyExtractorTest.java
index 981eeae..7255f43 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/its/base/util/PropertyExtractorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/base/util/PropertyExtractorTest.java
@@ -22,6 +22,7 @@
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project.NameKey;
import com.google.gerrit.server.data.AccountAttribute;
import com.google.gerrit.server.data.ApprovalAttribute;
import com.google.gerrit.server.data.ChangeAttribute;
@@ -31,8 +32,8 @@
import com.google.gerrit.server.events.ChangeMergedEvent;
import com.google.gerrit.server.events.ChangeRestoredEvent;
import com.google.gerrit.server.events.CommentAddedEvent;
-import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.events.PatchSetCreatedEvent;
+import com.google.gerrit.server.events.RefEvent;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.inject.Guice;
import com.google.inject.Injector;
@@ -330,7 +331,7 @@
}
private void eventHelper(
- Event event, String className, String type, Set<Property> common, boolean withRevision) {
+ RefEvent event, String className, String type, Set<Property> common, boolean withRevision) {
PropertyExtractor propertyExtractor = injector.getInstance(PropertyExtractor.class);
Property propertyItsName = createMock(Property.class);
@@ -421,9 +422,19 @@
}
}
- private class DummyEvent extends Event {
+ private class DummyEvent extends RefEvent {
public DummyEvent() {
super(null);
}
+
+ @Override
+ public String getRefName() {
+ return null;
+ }
+
+ @Override
+ public NameKey getProjectNameKey() {
+ return null;
+ }
}
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/base/validation/ItsValidateCommentTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/base/validation/ItsValidateCommentTest.java
index 5573878..14744c4 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/its/base/validation/ItsValidateCommentTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/base/validation/ItsValidateCommentTest.java
@@ -30,6 +30,7 @@
import com.googlesource.gerrit.plugins.its.base.util.IssueExtractor;
import java.io.IOException;
import java.util.List;
+import java.util.Optional;
import java.util.regex.Pattern;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.ReceiveCommand;
@@ -75,6 +76,7 @@
expect(itsConfig.getItsAssociationPolicy())
.andReturn(ItsAssociationPolicy.SUGGESTED)
.atLeastOnce();
+ expect(itsConfig.getDummyIssuePattern()).andReturn(Optional.empty()).atLeastOnce();
expect(commit.getFullMessage()).andReturn("TestMessage").atLeastOnce();
expect(commit.getId()).andReturn(commit).anyTimes();
expect(commit.getName()).andReturn("TestCommit").anyTimes();
@@ -99,6 +101,7 @@
expect(itsConfig.getItsAssociationPolicy())
.andReturn(ItsAssociationPolicy.MANDATORY)
.atLeastOnce();
+ expect(itsConfig.getDummyIssuePattern()).andReturn(Optional.empty()).atLeastOnce();
expect(commit.getFullMessage()).andReturn("TestMessage").atLeastOnce();
expect(commit.getId()).andReturn(commit).anyTimes();
expect(commit.getName()).andReturn("TestCommit").anyTimes();
@@ -116,6 +119,31 @@
}
}
+ public void testOnlySkipMatching() throws CommitValidationException {
+ List<CommitValidationMessage> ret;
+ ItsValidateComment ivc = injector.getInstance(ItsValidateComment.class);
+ ReceiveCommand command = createMock(ReceiveCommand.class);
+ RevCommit commit = createMock(RevCommit.class);
+ CommitReceivedEvent event = newCommitReceivedEvent(command, project, null, commit, null);
+
+ expect(itsConfig.getItsAssociationPolicy())
+ .andReturn(ItsAssociationPolicy.MANDATORY)
+ .atLeastOnce();
+ expect(itsConfig.getDummyIssuePattern())
+ .andReturn(Optional.of(Pattern.compile("SKIP")))
+ .atLeastOnce();
+ expect(commit.getFullMessage()).andReturn("TestMessage SKIP").atLeastOnce();
+ expect(commit.getId()).andReturn(commit).anyTimes();
+ expect(commit.getName()).andReturn("TestCommit").anyTimes();
+ expect(issueExtractor.getIssueIds("TestMessage SKIP")).andReturn(new String[] {}).atLeastOnce();
+
+ replayMocks();
+
+ ret = ivc.onCommitReceived(event);
+
+ assertEmptyList(ret);
+ }
+
public void testSuggestedMatchingSingleExisting() throws CommitValidationException, IOException {
List<CommitValidationMessage> ret;
ItsValidateComment ivc = injector.getInstance(ItsValidateComment.class);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionControllerTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionControllerTest.java
index d2926f9..7c85f7f 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionControllerTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionControllerTest.java
@@ -20,7 +20,7 @@
import com.google.common.collect.Sets;
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.server.events.ChangeEvent;
-import com.google.gerrit.server.events.Event;
+import com.google.gerrit.server.events.RefEvent;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.googlesource.gerrit.plugins.its.base.its.ItsConfig;
@@ -173,7 +173,7 @@
}
private void setupCommonMocks() {
- expect(itsConfig.isEnabled(anyObject(Event.class))).andReturn(true).anyTimes();
+ expect(itsConfig.isEnabled(anyObject(RefEvent.class))).andReturn(true).anyTimes();
}
@Override
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutorTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutorTest.java
index f2b6a55..4dbc779 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/ActionExecutorTest.java
@@ -25,7 +25,6 @@
import com.googlesource.gerrit.plugins.its.base.workflow.action.AddComment;
import com.googlesource.gerrit.plugins.its.base.workflow.action.AddSoyComment;
import com.googlesource.gerrit.plugins.its.base.workflow.action.AddStandardComment;
-import com.googlesource.gerrit.plugins.its.base.workflow.action.AddVelocityComment;
import com.googlesource.gerrit.plugins.its.base.workflow.action.LogEvent;
import java.io.IOException;
import java.util.Collections;
@@ -37,7 +36,6 @@
private ItsFacade its;
private AddComment.Factory addCommentFactory;
private AddStandardComment.Factory addStandardCommentFactory;
- private AddVelocityComment.Factory addVelocityCommentFactory;
private AddSoyComment.Factory addSoyCommentFactory;
private LogEvent.Factory logEventFactory;
@@ -176,23 +174,6 @@
actionExecutor.execute("4711", actionRequest, properties);
}
- public void testAddVelocityCommentDelegation() throws IOException {
- ActionRequest actionRequest = createMock(ActionRequest.class);
- expect(actionRequest.getName()).andReturn("add-velocity-comment");
-
- Set<Property> properties = Collections.emptySet();
-
- AddVelocityComment addVelocityComment = createMock(AddVelocityComment.class);
- expect(addVelocityCommentFactory.create()).andReturn(addVelocityComment);
-
- addVelocityComment.execute("4711", actionRequest, properties);
-
- replayMocks();
-
- ActionExecutor actionExecutor = createActionExecutor();
- actionExecutor.execute("4711", actionRequest, properties);
- }
-
public void testLogEventDelegation() throws IOException {
ActionRequest actionRequest = createMock(ActionRequest.class);
expect(actionRequest.getName()).andReturn("log-event");
@@ -235,9 +216,6 @@
addStandardCommentFactory = createMock(AddStandardComment.Factory.class);
bind(AddStandardComment.Factory.class).toInstance(addStandardCommentFactory);
- addVelocityCommentFactory = createMock(AddVelocityComment.Factory.class);
- bind(AddVelocityComment.Factory.class).toInstance(addVelocityCommentFactory);
-
logEventFactory = createMock(LogEvent.Factory.class);
bind(LogEvent.Factory.class).toInstance(logEventFactory);
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/RuleBaseTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/RuleBaseTest.java
index 80e12fb..2ba4d4a 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/RuleBaseTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/RuleBaseTest.java
@@ -18,13 +18,10 @@
import com.google.common.collect.Lists;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.config.FactoryModule;
-import com.google.gerrit.server.config.SitePath;
import com.google.inject.Guice;
import com.google.inject.Injector;
+import com.googlesource.gerrit.plugins.its.base.ItsPath;
import com.googlesource.gerrit.plugins.its.base.testutil.LoggingMockingTestCase;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -38,7 +35,7 @@
public class RuleBaseTest extends LoggingMockingTestCase {
private Injector injector;
- private Path sitePath;
+ private Path itsPath;
private Rule.Factory ruleFactory;
private Condition.Factory conditionFactory;
private ActionRequest.Factory actionRequestFactory;
@@ -46,9 +43,14 @@
private boolean cleanupSitePath;
private enum RuleBaseKind {
- GLOBAL,
- ITS,
- FAULTY
+ GLOBAL("actions"),
+ ITS("actions-ItsTestName");
+
+ String fileName;
+
+ RuleBaseKind(String fileName) {
+ this.fileName = fileName + ".config";
+ }
}
public void testWarnNonExistingRuleBase() {
@@ -221,41 +223,6 @@
assertEquals("Matched actionRequests do not match", expected, actual);
}
- public void testWarnExistingFaultyNameRuleBaseFile() throws IOException {
- injectRuleBase("", RuleBaseKind.FAULTY);
-
- replayMocks();
-
- createRuleBase();
-
- assertLogMessageContains("Please migrate"); // Migration warning for old name
- assertLogMessageContains("Neither global"); // For rule file at at usual places
- }
-
- public void testSimpleFaultyNameRuleBase() throws IOException {
- injectRuleBase(
- "[rule \"rule1\"]\n" + "\tconditionA = value1\n" + "\taction = action1",
- RuleBaseKind.FAULTY);
-
- Rule rule1 = createMock(Rule.class);
- expect(ruleFactory.create("rule1")).andReturn(rule1);
-
- Condition condition1 = createMock(Condition.class);
- expect(conditionFactory.create("conditionA", "value1")).andReturn(condition1);
- rule1.addCondition(condition1);
-
- ActionRequest actionRequest1 = createMock(ActionRequest.class);
- expect(actionRequestFactory.create("action1")).andReturn(actionRequest1);
- rule1.addActionRequest(actionRequest1);
-
- replayMocks();
-
- createRuleBase();
-
- assertLogMessageContains("Please migrate"); // Migration warning for old name
- assertLogMessageContains("Neither global"); // For rule file at at usual places
- }
-
public void testSimpleItsRuleBase() throws IOException {
injectRuleBase(
"[rule \"rule1\"]\n" + "\tconditionA = value1\n" + "\taction = action1", RuleBaseKind.ITS);
@@ -277,25 +244,12 @@
}
public void testAllRuleBaseFilesAreLoaded() throws IOException {
- injectRuleBase("[rule \"rule1\"]\n" + "\taction = action1", RuleBaseKind.FAULTY);
-
injectRuleBase("[rule \"rule2\"]\n" + "\taction = action2", RuleBaseKind.GLOBAL);
injectRuleBase("[rule \"rule3\"]\n" + "\taction = action3", RuleBaseKind.ITS);
Collection<Property> properties = Collections.emptySet();
- Rule rule1 = createMock(Rule.class);
- expect(ruleFactory.create("rule1")).andReturn(rule1);
-
- ActionRequest actionRequest1 = createMock(ActionRequest.class);
- expect(actionRequestFactory.create("action1")).andReturn(actionRequest1);
- rule1.addActionRequest(actionRequest1);
-
- List<ActionRequest> rule1Match = Lists.newArrayListWithCapacity(1);
- rule1Match.add(actionRequest1);
- expect(rule1.actionRequestsFor(properties)).andReturn(rule1Match);
-
Rule rule2 = createMock(Rule.class);
expect(ruleFactory.create("rule2")).andReturn(rule2);
@@ -325,13 +279,10 @@
Collection<ActionRequest> actual = ruleBase.actionRequestsFor(properties);
List<ActionRequest> expected = Lists.newArrayListWithCapacity(3);
- expected.add(actionRequest1);
expected.add(actionRequest2);
expected.add(actionRequest3);
assertEquals("Matched actionRequests do not match", expected, actual);
-
- assertLogMessageContains("Please migrate"); // Migration warning for old name
}
private RuleBase createRuleBase() {
@@ -343,35 +294,9 @@
}
private void injectRuleBase(String rules, RuleBaseKind ruleBaseKind) throws IOException {
- String baseName = "";
- switch (ruleBaseKind) {
- case GLOBAL:
- baseName = "actions";
- break;
- case ITS:
- baseName = "actions-ItsTestName";
- break;
- case FAULTY:
- baseName = "action";
- break;
- default:
- fail("Unknown ruleBaseKind");
- }
- File ruleBaseFile =
- new File(
- sitePath.toFile(),
- "etc" + File.separatorChar + "its" + File.separator + baseName + ".config");
-
- File ruleBaseParentFile = ruleBaseFile.getParentFile();
- if (!ruleBaseParentFile.exists()) {
- assertTrue(
- "Failed to create parent (" + ruleBaseParentFile + ") for " + "rule base",
- ruleBaseParentFile.mkdirs());
- }
- try (FileWriter unbufferedWriter = new FileWriter(ruleBaseFile);
- BufferedWriter writer = new BufferedWriter(unbufferedWriter)) {
- writer.write(rules);
- }
+ Path ruleBaseFile = itsPath.resolve(ruleBaseKind.fileName);
+ Files.createDirectories(ruleBaseFile.getParent());
+ Files.write(ruleBaseFile, rules.getBytes());
}
@Override
@@ -384,8 +309,8 @@
@Override
public void tearDown() throws Exception {
if (cleanupSitePath) {
- if (Files.exists(sitePath)) {
- FileUtils.delete(sitePath.toFile(), FileUtils.RECURSIVE);
+ if (Files.exists(itsPath)) {
+ FileUtils.delete(itsPath.toFile(), FileUtils.RECURSIVE);
}
}
super.tearDown();
@@ -401,11 +326,11 @@
bind(String.class).annotatedWith(PluginName.class).toInstance("ItsTestName");
- sitePath = randomTargetPath();
- assertFalse("sitePath already (" + sitePath + ") already exists", Files.exists(sitePath));
+ itsPath = randomTargetPath().resolve("etc").resolve("its");
+ assertFalse("itsPath (" + itsPath + ") already exists", Files.exists(itsPath));
cleanupSitePath = true;
- bind(Path.class).annotatedWith(SitePath.class).toInstance(sitePath);
+ bind(Path.class).annotatedWith(ItsPath.class).toInstance(itsPath);
ruleFactory = createMock(Rule.Factory.class);
bind(Rule.Factory.class).toInstance(ruleFactory);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddCommentTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddCommentTest.java
index 3039b12..d16bab2 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddCommentTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddCommentTest.java
@@ -21,7 +21,6 @@
import com.googlesource.gerrit.plugins.its.base.its.ItsFacade;
import com.googlesource.gerrit.plugins.its.base.testutil.LoggingMockingTestCase;
import com.googlesource.gerrit.plugins.its.base.workflow.ActionRequest;
-import com.googlesource.gerrit.plugins.its.base.workflow.Property;
import java.io.IOException;
import java.util.HashSet;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddVelocityCommentTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddVelocityCommentTest.java
deleted file mode 100644
index 61042a4..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/action/AddVelocityCommentTest.java
+++ /dev/null
@@ -1,450 +0,0 @@
-// 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.googlesource.gerrit.plugins.its.base.workflow.action;
-
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.capture;
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-
-import com.google.common.collect.Sets;
-import com.google.gerrit.extensions.config.FactoryModule;
-import com.google.gerrit.server.config.SitePath;
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-import com.googlesource.gerrit.plugins.its.base.its.ItsFacade;
-import com.googlesource.gerrit.plugins.its.base.testutil.LoggingMockingTestCase;
-import com.googlesource.gerrit.plugins.its.base.workflow.ActionRequest;
-import com.googlesource.gerrit.plugins.its.base.workflow.Property;
-import com.googlesource.gerrit.plugins.its.base.workflow.action.AddVelocityComment.VelocityAdapterItsFacade;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.Writer;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.runtime.RuntimeInstance;
-import org.easymock.Capture;
-import org.easymock.EasyMock;
-import org.easymock.IAnswer;
-import org.eclipse.jgit.util.FileUtils;
-
-public class AddVelocityCommentTest extends LoggingMockingTestCase {
- private Injector injector;
-
- private Path sitePath;
- private ItsFacade its;
- private RuntimeInstance velocityRuntime;
-
- private boolean cleanupSitePath;
-
- public void testWarnNoTemplateNameGiven() throws IOException {
- ActionRequest actionRequest = createMock(ActionRequest.class);
- expect(actionRequest.getParameter(1)).andReturn("");
- replayMocks();
-
- AddVelocityComment addVelocityComment = createAddVelocityComment();
- addVelocityComment.execute("4711", actionRequest, new HashSet<>());
-
- assertLogMessageContains("No template name");
- }
-
- public void testInlinePlain() throws IOException {
- ActionRequest actionRequest = createMock(ActionRequest.class);
- expect(actionRequest.getParameter(1)).andReturn("inline");
- expect(actionRequest.getParameters()).andReturn(new String[] {"inline", "Simple-text"});
-
- IAnswer<Boolean> answer = new VelocityWriterFiller("Simple-text");
- expect(
- velocityRuntime.evaluate(
- (VelocityContext) anyObject(),
- (Writer) anyObject(),
- (String) anyObject(),
- eq("Simple-text")))
- .andAnswer(answer);
-
- its.addComment("4711", "Simple-text");
-
- replayMocks();
-
- AddVelocityComment addVelocityComment = createAddVelocityComment();
- addVelocityComment.execute("4711", actionRequest, new HashSet<>());
- }
-
- public void testInlineWithMultipleParameters() throws IOException {
- ActionRequest actionRequest = createMock(ActionRequest.class);
- expect(actionRequest.getParameter(1)).andReturn("inline");
- expect(actionRequest.getParameters()).andReturn(new String[] {"inline", "Param2", "Param3"});
-
- Set<Property> properties = Sets.newHashSet();
-
- IAnswer<Boolean> answer = new VelocityWriterFiller("Param2 Param3");
- expect(
- velocityRuntime.evaluate(
- (VelocityContext) anyObject(),
- (Writer) anyObject(),
- (String) anyObject(),
- eq("Param2 Param3")))
- .andAnswer(answer);
-
- its.addComment("4711", "Param2 Param3");
-
- replayMocks();
-
- AddVelocityComment addVelocityComment = createAddVelocityComment();
- addVelocityComment.execute("4711", actionRequest, properties);
- }
-
- public void testInlineWithSingleProperty() throws IOException {
- ActionRequest actionRequest = createMock(ActionRequest.class);
- expect(actionRequest.getParameter(1)).andReturn("inline");
- expect(actionRequest.getParameters()).andReturn(new String[] {"inline", "${subject}"});
-
- Set<Property> properties = Sets.newHashSet();
-
- Property propertySubject = createMock(Property.class);
- expect(propertySubject.getKey()).andReturn("subject").anyTimes();
- expect(propertySubject.getValue()).andReturn("Rosebud").anyTimes();
- properties.add(propertySubject);
-
- IAnswer<Boolean> answer = new VelocityWriterFiller("Rosebud");
- Capture<VelocityContext> contextCapture = createCapture();
- expect(
- velocityRuntime.evaluate(
- capture(contextCapture),
- (Writer) anyObject(),
- (String) anyObject(),
- eq("${subject}")))
- .andAnswer(answer);
-
- its.addComment("4711", "Rosebud");
-
- replayMocks();
-
- AddVelocityComment addVelocityComment = createAddVelocityComment();
- addVelocityComment.execute("4711", actionRequest, properties);
-
- VelocityContext context = contextCapture.getValue();
- assertEquals("Subject property of context did not match", "Rosebud", context.get("subject"));
- }
-
- public void testInlineWithUnusedProperty() throws IOException {
- ActionRequest actionRequest = createMock(ActionRequest.class);
- expect(actionRequest.getParameter(1)).andReturn("inline");
- expect(actionRequest.getParameters()).andReturn(new String[] {"inline", "Test"});
-
- Set<Property> properties = Sets.newHashSet();
-
- Property propertySubject = createMock(Property.class);
- expect(propertySubject.getKey()).andReturn("subject").anyTimes();
- expect(propertySubject.getValue()).andReturn("Rosebud").anyTimes();
- properties.add(propertySubject);
-
- IAnswer<Boolean> answer = new VelocityWriterFiller("Test");
- expect(
- velocityRuntime.evaluate(
- (VelocityContext) anyObject(),
- (Writer) anyObject(),
- (String) anyObject(),
- eq("Test")))
- .andAnswer(answer);
-
- its.addComment("4711", "Test");
-
- replayMocks();
-
- AddVelocityComment addVelocityComment = createAddVelocityComment();
- addVelocityComment.execute("4711", actionRequest, properties);
- }
-
- public void testInlineWithMultipleProperties() throws IOException {
- ActionRequest actionRequest = createMock(ActionRequest.class);
- expect(actionRequest.getParameter(1)).andReturn("inline");
- expect(actionRequest.getParameters())
- .andReturn(new String[] {"inline", "${subject}", "${reason}", "${subject}"});
-
- Set<Property> properties = Sets.newHashSet();
-
- Property propertySubject = createMock(Property.class);
- expect(propertySubject.getKey()).andReturn("subject").anyTimes();
- expect(propertySubject.getValue()).andReturn("Rosebud").anyTimes();
- properties.add(propertySubject);
-
- Property propertyReason = createMock(Property.class);
- expect(propertyReason.getKey()).andReturn("reason").anyTimes();
- expect(propertyReason.getValue()).andReturn("Life").anyTimes();
- properties.add(propertyReason);
-
- IAnswer<Boolean> answer = new VelocityWriterFiller("Rosebud Life Rosebud");
- Capture<VelocityContext> contextCapture = createCapture();
- expect(
- velocityRuntime.evaluate(
- capture(contextCapture),
- (Writer) anyObject(),
- (String) anyObject(),
- eq("${subject} ${reason} ${subject}")))
- .andAnswer(answer);
-
- its.addComment("4711", "Rosebud Life Rosebud");
-
- replayMocks();
-
- AddVelocityComment addVelocityComment = createAddVelocityComment();
- addVelocityComment.execute("4711", actionRequest, properties);
-
- VelocityContext context = contextCapture.getValue();
- assertEquals("Subject property of context did not match", "Rosebud", context.get("subject"));
- assertEquals("Reason property of context did not match", "Life", context.get("reason"));
- }
-
- public void testItsWrapperFormatLink1Parameter()
- throws IOException, SecurityException, IllegalArgumentException {
- ActionRequest actionRequest = createMock(ActionRequest.class);
- expect(actionRequest.getParameter(1)).andReturn("inline");
- expect(actionRequest.getParameters()).andReturn(new String[] {"inline", "Simple-Text"});
-
- IAnswer<Boolean> answer = new VelocityWriterFiller("Simple-Text");
- Capture<VelocityContext> contextCapture = createCapture();
- expect(
- velocityRuntime.evaluate(
- capture(contextCapture),
- (Writer) anyObject(),
- (String) anyObject(),
- eq("Simple-Text")))
- .andAnswer(answer);
-
- its.addComment("4711", "Simple-Text");
-
- expect(its.createLinkForWebui("http://www.example.org/", "http://www.example.org/"))
- .andReturn("Formatted Link");
-
- replayMocks();
-
- AddVelocityComment addVelocityComment = createAddVelocityComment();
- addVelocityComment.execute("4711", actionRequest, new HashSet<>());
-
- VelocityContext context = contextCapture.getValue();
- Object itsAdapterObj = context.get("its");
- assertNotNull("its property is null", itsAdapterObj);
- assertTrue(
- "Its is not a VelocityAdapterItsFacade instance",
- itsAdapterObj instanceof VelocityAdapterItsFacade);
- VelocityAdapterItsFacade itsAdapter = (VelocityAdapterItsFacade) itsAdapterObj;
- String formattedLink = itsAdapter.formatLink("http://www.example.org/");
- assertEquals("Result of formatLink does not match", "Formatted Link", formattedLink);
- }
-
- public void testItsWrapperFormatLink2Parameters()
- throws IOException, SecurityException, IllegalArgumentException {
- ActionRequest actionRequest = createMock(ActionRequest.class);
- expect(actionRequest.getParameter(1)).andReturn("inline");
- expect(actionRequest.getParameters()).andReturn(new String[] {"inline", "Simple-Text"});
-
- IAnswer<Boolean> answer = new VelocityWriterFiller("Simple-Text");
- Capture<VelocityContext> contextCapture = createCapture();
- expect(
- velocityRuntime.evaluate(
- capture(contextCapture),
- (Writer) anyObject(),
- (String) anyObject(),
- eq("Simple-Text")))
- .andAnswer(answer);
-
- its.addComment("4711", "Simple-Text");
-
- expect(its.createLinkForWebui("http://www.example.org/", "Caption"))
- .andReturn("Formatted Link");
-
- replayMocks();
-
- AddVelocityComment addVelocityComment = createAddVelocityComment();
- addVelocityComment.execute("4711", actionRequest, new HashSet<>());
-
- VelocityContext context = contextCapture.getValue();
- Object itsAdapterObj = context.get("its");
- assertNotNull("its property is null", itsAdapterObj);
- assertTrue(
- "Its is not a VelocityAdapterItsFacade instance",
- itsAdapterObj instanceof VelocityAdapterItsFacade);
- VelocityAdapterItsFacade itsAdapter = (VelocityAdapterItsFacade) itsAdapterObj;
- String formattedLink = itsAdapter.formatLink("http://www.example.org/", "Caption");
- assertEquals("Result of formatLink does not match", "Formatted Link", formattedLink);
- }
-
- public void testWarnTemplateNotFound() throws IOException {
- ActionRequest actionRequest = createMock(ActionRequest.class);
- expect(actionRequest.getParameter(1)).andReturn("non-existing-template");
-
- replayMocks();
-
- AddVelocityComment addVelocityComment = createAddVelocityComment();
- addVelocityComment.execute("4711", actionRequest, new HashSet<>());
-
- assertLogMessageContains("non-existing-template");
- }
-
- public void testTemplateSimple() throws IOException {
- ActionRequest actionRequest = createMock(ActionRequest.class);
- expect(actionRequest.getParameter(1)).andReturn("test-template");
-
- injectTestTemplate("Simple Test Template");
-
- IAnswer<Boolean> answer = new VelocityWriterFiller("Simple Test Template");
- expect(
- velocityRuntime.evaluate(
- (VelocityContext) anyObject(),
- (Writer) anyObject(),
- (String) anyObject(),
- eq("Simple Test Template")))
- .andAnswer(answer);
-
- its.addComment("4711", "Simple Test Template");
-
- replayMocks();
-
- AddVelocityComment addVelocityComment = createAddVelocityComment();
- addVelocityComment.execute("4711", actionRequest, new HashSet<>());
- }
-
- public void testTemplateMultipleParametersAndProperties() throws IOException {
- ActionRequest actionRequest = createMock(ActionRequest.class);
- expect(actionRequest.getParameter(1)).andReturn("test-template");
-
- Set<Property> properties = Sets.newHashSet();
-
- Property propertySubject = createMock(Property.class);
- expect(propertySubject.getKey()).andReturn("subject").anyTimes();
- expect(propertySubject.getValue()).andReturn("Rosebud").anyTimes();
- properties.add(propertySubject);
-
- Property propertyReason = createMock(Property.class);
- expect(propertyReason.getKey()).andReturn("reason").anyTimes();
- expect(propertyReason.getValue()).andReturn("Life").anyTimes();
- properties.add(propertyReason);
-
- injectTestTemplate(
- "Test Template with subject: ${subject}.\n" + "${reason} is the reason for ${subject}.");
-
- IAnswer<Boolean> answer =
- new VelocityWriterFiller(
- "Test Template with subject: Rosebud.\n" + "Life is the reason for Rosebud.");
- Capture<VelocityContext> contextCapture = createCapture();
- expect(
- velocityRuntime.evaluate(
- capture(contextCapture),
- (Writer) anyObject(),
- (String) anyObject(),
- eq(
- "Test Template with subject: ${subject}.\n"
- + "${reason} is the reason for ${subject}.")))
- .andAnswer(answer);
-
- its.addComment(
- "4711", "Test Template with subject: Rosebud.\n" + "Life is the reason for Rosebud.");
-
- replayMocks();
-
- AddVelocityComment addVelocityComment = createAddVelocityComment();
- addVelocityComment.execute("4711", actionRequest, properties);
-
- VelocityContext context = contextCapture.getValue();
- assertEquals("Subject property of context did not match", "Rosebud", context.get("subject"));
- assertEquals("Reason property of context did not match", "Life", context.get("reason"));
- }
-
- private AddVelocityComment createAddVelocityComment() {
- return injector.getInstance(AddVelocityComment.class);
- }
-
- private void injectTestTemplate(String template) throws IOException {
- File templateParentFile =
- new File(
- sitePath.toFile(), "etc" + File.separatorChar + "its" + File.separator + "templates");
- assertTrue(
- "Failed to create parent (" + templateParentFile + ") for " + "rule base",
- templateParentFile.mkdirs());
- File templateFile = new File(templateParentFile, "test-template.vm");
-
- try (FileWriter unbufferedWriter = new FileWriter(templateFile);
- BufferedWriter writer = new BufferedWriter(unbufferedWriter)) {
- writer.write(template);
- }
- }
-
- @Override
- public void setUp() throws Exception {
- super.setUp();
- cleanupSitePath = false;
- injector = Guice.createInjector(new TestModule());
- }
-
- @Override
- public void tearDown() throws Exception {
- if (cleanupSitePath) {
- if (Files.exists(sitePath)) {
- FileUtils.delete(sitePath.toFile(), FileUtils.RECURSIVE);
- }
- }
- super.tearDown();
- }
-
- private Path randomTargetPath() {
- return Paths.get("target", "random-name-" + UUID.randomUUID().toString());
- }
-
- private class TestModule extends FactoryModule {
- @Override
- protected void configure() {
- sitePath = randomTargetPath();
- assertFalse("sitePath already (" + sitePath + ") already exists", Files.exists(sitePath));
- cleanupSitePath = true;
-
- bind(Path.class).annotatedWith(SitePath.class).toInstance(sitePath);
-
- its = createMock(ItsFacade.class);
- bind(ItsFacade.class).toInstance(its);
-
- velocityRuntime = createMock(RuntimeInstance.class);
- bind(RuntimeInstance.class).toInstance(velocityRuntime);
- }
- }
-
- private class VelocityWriterFiller implements IAnswer<Boolean> {
- private final String fill;
- private final boolean returnValue;
-
- private VelocityWriterFiller(String fill, boolean returnValue) {
- this.fill = fill;
- this.returnValue = returnValue;
- }
-
- private VelocityWriterFiller(String fill) {
- this(fill, true);
- }
-
- @Override
- public Boolean answer() throws Throwable {
- Object[] arguments = EasyMock.getCurrentArguments();
- Writer writer = (Writer) arguments[1];
- writer.write(fill);
- return returnValue;
- }
- }
-}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/action/LogEventTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/action/LogEventTest.java
index 99fa2c3..54b9942 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/action/LogEventTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/base/workflow/action/LogEventTest.java
@@ -30,6 +30,16 @@
public class LogEventTest extends LoggingMockingTestCase {
private Injector injector;
+ public void testNull() throws IOException {
+ ActionRequest actionRequest = createMock(ActionRequest.class);
+ expect(actionRequest.getParameter(1)).andReturn(null);
+
+ replayMocks();
+
+ LogEvent logEvent = createLogEvent();
+ logEvent.execute("4711", actionRequest, new HashSet<>());
+ }
+
public void testEmpty() throws IOException {
ActionRequest actionRequest = createMock(ActionRequest.class);
expect(actionRequest.getParameter(1)).andReturn("");