Merge branch 'stable-2.15' * stable-2.15: Update bazlets to latest stable-2.15 to use 2.15rc3 Change-Id: I1a026ec2be41f470164090139ffba41d0c8ac5c5
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 3629f3c..5591045 100644 --- a/WORKSPACE +++ b/WORKSPACE
@@ -3,24 +3,24 @@ load("//:bazlets.bzl", "load_bazlets") load_bazlets( - commit = "34d5ef186f73c80e61dcfa057ee400b2725164bf", + 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("");