Add action for short predefined comments
AddStandardComments allows to add short Its comments for merging,
abandoning, restoring of changes and adding of patch sets.
Change-Id: Id0c699ce353e3ff92b4de178cf9fd4ec2e5936a5
diff --git a/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/ItsHookModule.java b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/ItsHookModule.java
index 0fcf032..9e18eef 100644
--- a/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/ItsHookModule.java
+++ b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/ItsHookModule.java
@@ -29,6 +29,7 @@
import com.googlesource.gerrit.plugins.hooks.workflow.ActionController;
import com.googlesource.gerrit.plugins.hooks.workflow.Property;
import com.googlesource.gerrit.plugins.hooks.workflow.Rule;
+import com.googlesource.gerrit.plugins.hooks.workflow.action.AddStandardComment;
public class ItsHookModule extends FactoryModule {
@@ -57,5 +58,6 @@
factory(Property.Factory.class);
factory(Condition.Factory.class);
factory(Rule.Factory.class);
+ factory(AddStandardComment.Factory.class);
}
}
diff --git a/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionController.java b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionController.java
index e5c4728..16657fb 100644
--- a/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionController.java
+++ b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionController.java
@@ -52,7 +52,7 @@
for (Property property : properties) {
if ("issue".equals(property.getKey())) {
String issue = property.getValue();
- actionExecutor.execute(issue, actions);
+ actionExecutor.execute(issue, actions, properties);
}
}
}
diff --git a/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutor.java b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutor.java
index 029ef8d..4e99423 100644
--- a/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutor.java
+++ b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutor.java
@@ -15,12 +15,15 @@
package com.googlesource.gerrit.plugins.hooks.workflow;
import java.io.IOException;
+import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.hooks.its.ItsFacade;
+import com.googlesource.gerrit.plugins.hooks.workflow.action.Action;
+import com.googlesource.gerrit.plugins.hooks.workflow.action.AddStandardComment;
/**
* Executes an {@link ActionRequest}
@@ -30,23 +33,38 @@
ActionExecutor.class);
private final ItsFacade its;
+ private final AddStandardComment.Factory addStandardCommentFactory;
@Inject
- public ActionExecutor(ItsFacade its) {
+ public ActionExecutor(ItsFacade its,
+ AddStandardComment.Factory addStandardCommentFactory) {
this.its = its;
+ this.addStandardCommentFactory = addStandardCommentFactory;
}
- public void execute(String issue, ActionRequest actionRequest) {
+ public void execute(String issue, ActionRequest actionRequest,
+ Set<Property> properties) {
try {
- its.performAction(issue, actionRequest.getUnparsed());
+ String name = actionRequest.getName();
+ Action action = null;
+ if ("add-standard-comment".equals(name)) {
+ action = addStandardCommentFactory.create();
+ }
+
+ if (action == null) {
+ its.performAction(issue, actionRequest.getUnparsed());
+ } else {
+ action.execute(issue, actionRequest, properties);
+ }
} catch (IOException e) {
log.error("Error while executing action " + actionRequest, e);
}
}
- public void execute(String issue, Iterable<ActionRequest> actions) {
+ public void execute(String issue, Iterable<ActionRequest> actions,
+ Set<Property> properties) {
for (ActionRequest actionRequest : actions) {
- execute(issue, actionRequest);
+ execute(issue, actionRequest, properties);
}
}
}
diff --git a/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequest.java b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequest.java
index 89e4bde..cb3e5f3 100644
--- a/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequest.java
+++ b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequest.java
@@ -27,6 +27,7 @@
*/
public class ActionRequest {
private final String unparsed;
+ private final String[] chopped;
public interface Factory {
ActionRequest create(String specification);
@@ -39,6 +40,21 @@
} else {
this.unparsed = specification;
}
+ this.chopped = unparsed.split(" ");
+ }
+
+ /**
+ * Gets the name of the requested action.
+ *
+ * @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;
}
/**
diff --git a/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/Action.java b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/Action.java
new file mode 100644
index 0000000..7e0595c
--- /dev/null
+++ b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/Action.java
@@ -0,0 +1,37 @@
+// 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.hooks.workflow.action;
+
+import java.io.IOException;
+import java.util.Set;
+
+import com.googlesource.gerrit.plugins.hooks.workflow.ActionRequest;
+import com.googlesource.gerrit.plugins.hooks.workflow.Property;
+
+/**
+ * Interface for actions on an issue tracking system
+ */
+public interface Action {
+
+ /**
+ * Execute this action.
+ *
+ * @param issue The issue to execute on.
+ * @param actionRequest The request to execute.
+ * @param properties The properties for the execution.
+ */
+ public void execute(String issue, ActionRequest actionRequest,
+ Set<Property> properties) throws IOException;
+}
diff --git a/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddStandardComment.java b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddStandardComment.java
new file mode 100644
index 0000000..8cdeef7
--- /dev/null
+++ b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddStandardComment.java
@@ -0,0 +1,129 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.hooks.workflow.action;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Maps;
+import com.google.inject.Inject;
+import com.googlesource.gerrit.plugins.hooks.its.ItsFacade;
+import com.googlesource.gerrit.plugins.hooks.workflow.ActionRequest;
+import com.googlesource.gerrit.plugins.hooks.workflow.Property;
+
+/**
+ * Adds a short predefined comments to an issue.
+ *
+ * Comments are added for merging, abandoning, restoring of changes and adding
+ * of patch sets.
+ */
+public class AddStandardComment implements Action {
+ public interface Factory {
+ AddStandardComment create();
+ }
+
+ private final ItsFacade its;
+
+ @Inject
+ public AddStandardComment(ItsFacade its) {
+ this.its = its;
+ }
+
+ private String formatPerson(String prefix, Map<String, String> map) {
+ String ret = Strings.nullToEmpty(map.get(prefix + "-name"));
+ if (ret.isEmpty()) {
+ ret = Strings.nullToEmpty(map.get(prefix + "-username"));
+ }
+ return ret;
+ }
+
+ private String getCommentChangeEvent(String Action, String prefix,
+ Map<String, String> map) {
+ String ret = "";
+ String changeNumber = Strings.nullToEmpty(map.get("change-number"));
+ if (!changeNumber.isEmpty()) {
+ changeNumber += " ";
+ }
+ ret += "Change " + changeNumber + Action;
+ String submitter = formatPerson(prefix, map);
+ if (!submitter.isEmpty()) {
+ ret += " by " + submitter;
+ }
+ String subject = Strings.nullToEmpty(map.get("subject"));
+ if (!subject.isEmpty()) {
+ ret += ":\n" + subject;
+ }
+ String reason = Strings.nullToEmpty(map.get("reason"));
+ if (!reason.isEmpty()) {
+ ret += "\n\nReason:\n" + reason;
+ }
+ String url = Strings.nullToEmpty(map.get("change-url"));
+ if (!url.isEmpty()) {
+ ret += "\n\n" + its.createLinkForWebui(url, url);
+ }
+ return ret;
+ }
+
+ 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 = "";
+ Map<String, String> map = Maps.newHashMap();
+ for (Property property : properties) {
+ String current = property.getValue();
+ if (!Strings.isNullOrEmpty(current))
+ {
+ String key = property.getKey();
+ String old = Strings.nullToEmpty(map.get(key));
+ if (!old.isEmpty()) {
+ old += ", ";
+ }
+ 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);
+ }
+ }
+}
diff --git a/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionControllerTest.java b/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionControllerTest.java
index 926fe8b..d6c9c2d 100644
--- a/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionControllerTest.java
+++ b/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionControllerTest.java
@@ -116,7 +116,7 @@
expect(ruleBase.actionRequestsFor(propertySet)).andReturn(actionRequests)
.once();
- actionExecutor.execute("testIssue", actionRequests);
+ actionExecutor.execute("testIssue", actionRequests, propertySet);
replayMocks();
@@ -167,9 +167,9 @@
expect(ruleBase.actionRequestsFor(propertySet2)).andReturn(actionRequests2)
.once();
- actionExecutor.execute("testIssue", actionRequests1);
- actionExecutor.execute("testIssue", actionRequests2);
- actionExecutor.execute("testIssue2", actionRequests2);
+ actionExecutor.execute("testIssue", actionRequests1, propertySet1);
+ actionExecutor.execute("testIssue", actionRequests2, propertySet2);
+ actionExecutor.execute("testIssue2", actionRequests2, propertySet2);
replayMocks();
diff --git a/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutorTest.java b/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutorTest.java
index 5a93b4c..a243812 100644
--- a/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutorTest.java
+++ b/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionExecutorTest.java
@@ -17,6 +17,8 @@
import static org.easymock.EasyMock.expectLastCall;
import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
import com.google.common.collect.Sets;
import com.google.gerrit.server.config.FactoryModule;
@@ -24,46 +26,58 @@
import com.google.inject.Injector;
import com.googlesource.gerrit.plugins.hooks.its.ItsFacade;
import com.googlesource.gerrit.plugins.hooks.testutil.LoggingMockingTestCase;
+import com.googlesource.gerrit.plugins.hooks.workflow.action.AddStandardComment;
public class ActionExecutorTest extends LoggingMockingTestCase {
private Injector injector;
private ItsFacade its;
+ private AddStandardComment.Factory addStandardCommentFactory;
public void testExecuteItem() throws IOException {
ActionRequest actionRequest = createMock(ActionRequest.class);
+ expect(actionRequest.getName()).andReturn("unparsed");
expect(actionRequest.getUnparsed()).andReturn("unparsed action 1");
+ Set<Property> properties = Collections.emptySet();
+
its.performAction("4711", "unparsed action 1");
replayMocks();
ActionExecutor actionExecutor = createActionExecutor();
- actionExecutor.execute("4711", actionRequest);
+ actionExecutor.execute("4711", actionRequest, properties);
}
public void testExecuteItemException() throws IOException {
ActionRequest actionRequest = createMock(ActionRequest.class);
+ expect(actionRequest.getName()).andReturn("unparsed");
expect(actionRequest.getUnparsed()).andReturn("unparsed action 1");
+ Set<Property> properties = Collections.emptySet();
+
its.performAction("4711", "unparsed action 1");
expectLastCall().andThrow(new IOException("injected exception 1"));
replayMocks();
ActionExecutor actionExecutor = createActionExecutor();
- actionExecutor.execute("4711", actionRequest);
+ actionExecutor.execute("4711", actionRequest, properties);
assertLogThrowableMessageContains("injected exception 1");
}
public void testExecuteIterable() throws IOException {
ActionRequest actionRequest1 = createMock(ActionRequest.class);
+ expect(actionRequest1.getName()).andReturn("unparsed");
expect(actionRequest1.getUnparsed()).andReturn("unparsed action 1");
ActionRequest actionRequest2 = createMock(ActionRequest.class);
+ expect(actionRequest2.getName()).andReturn("unparsed");
expect(actionRequest2.getUnparsed()).andReturn("unparsed action 2");
+ Set<Property> properties = Collections.emptySet();
+
its.performAction("4711", "unparsed action 1");
its.performAction("4711", "unparsed action 2");
@@ -71,19 +85,24 @@
ActionExecutor actionExecutor = createActionExecutor();
actionExecutor.execute("4711", Sets.newHashSet(
- actionRequest1, actionRequest2));
+ actionRequest1, actionRequest2), properties);
}
public void testExecuteIterableExceptions() throws IOException {
ActionRequest actionRequest1 = createMock(ActionRequest.class);
+ expect(actionRequest1.getName()).andReturn("unparsed");
expect(actionRequest1.getUnparsed()).andReturn("unparsed action 1");
ActionRequest actionRequest2 = createMock(ActionRequest.class);
+ expect(actionRequest2.getName()).andReturn("unparsed");
expect(actionRequest2.getUnparsed()).andReturn("unparsed action 2");
ActionRequest actionRequest3 = createMock(ActionRequest.class);
+ expect(actionRequest3.getName()).andReturn("unparsed");
expect(actionRequest3.getUnparsed()).andReturn("unparsed action 3");
+ Set<Property> properties = Collections.emptySet();
+
its.performAction("4711", "unparsed action 1");
expectLastCall().andThrow(new IOException("injected exception 1"));
its.performAction("4711", "unparsed action 2");
@@ -94,7 +113,7 @@
ActionExecutor actionExecutor = createActionExecutor();
actionExecutor.execute("4711", Sets.newHashSet(
- actionRequest1, actionRequest2, actionRequest3));
+ actionRequest1, actionRequest2, actionRequest3), properties);
assertLogThrowableMessageContains("injected exception 1");
assertLogThrowableMessageContains("injected exception 3");
@@ -114,6 +133,10 @@
protected void configure() {
its = createMock(ItsFacade.class);
bind(ItsFacade.class).toInstance(its);
+
+ addStandardCommentFactory = createMock(AddStandardComment.Factory.class);
+ bind(AddStandardComment.Factory.class).toInstance(
+ addStandardCommentFactory);
}
}
}
\ No newline at end of file
diff --git a/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequestTest.java b/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequestTest.java
index 2445b98..415a4ec 100644
--- a/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequestTest.java
+++ b/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionRequestTest.java
@@ -55,6 +55,38 @@
actionRequest.getUnparsed());
}
+ public void testNameParameterless() throws IOException {
+ replayMocks();
+
+ ActionRequest actionRequest = createActionRequest("action");
+ assertEquals("Unparsed string does not match", "action",
+ actionRequest.getName());
+ }
+
+ public void testNameSingleParameter() throws IOException {
+ replayMocks();
+
+ ActionRequest actionRequest = createActionRequest("action param");
+ assertEquals("Unparsed string does not match", "action",
+ actionRequest.getName());
+ }
+
+ public void testNameMultipleParameters() throws IOException {
+ replayMocks();
+
+ ActionRequest actionRequest = createActionRequest("action param1 param2");
+ assertEquals("Unparsed string does not match", "action",
+ actionRequest.getName());
+ }
+
+ public void testNameNull() throws IOException {
+ replayMocks();
+
+ ActionRequest actionRequest = createActionRequest(null);
+ assertEquals("Unparsed string does not match", "",
+ actionRequest.getName());
+ }
+
private ActionRequest createActionRequest(String specification) {
ActionRequest.Factory factory = injector.getInstance(
ActionRequest.Factory.class);
diff --git a/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddStandardCommentTest.java b/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddStandardCommentTest.java
new file mode 100644
index 0000000..6b40093
--- /dev/null
+++ b/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/action/AddStandardCommentTest.java
@@ -0,0 +1,318 @@
+// 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.hooks.workflow.action;
+
+import static org.easymock.EasyMock.expect;
+
+import java.io.IOException;
+import java.util.Set;
+
+
+import com.google.common.collect.Sets;
+import com.google.gerrit.server.config.FactoryModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.googlesource.gerrit.plugins.hooks.its.ItsFacade;
+import com.googlesource.gerrit.plugins.hooks.testutil.LoggingMockingTestCase;
+import com.googlesource.gerrit.plugins.hooks.workflow.ActionRequest;
+import com.googlesource.gerrit.plugins.hooks.workflow.Property;
+
+public class AddStandardCommentTest extends LoggingMockingTestCase {
+ private Injector injector;
+
+ private ItsFacade its;
+
+ public void testChangeMergedPlain() throws IOException {
+ ActionRequest actionRequest = createMock(ActionRequest.class);
+
+ Set<Property> properties = Sets.newHashSet();
+
+ Property propertyEventType = createMock(Property.class);
+ expect(propertyEventType.getKey()).andReturn("event-type").anyTimes();
+ expect(propertyEventType.getValue()).andReturn("change-merged").anyTimes();
+ properties.add(propertyEventType);
+
+ its.addComment("42", "Change merged");
+ replayMocks();
+
+ Action action = injector.getInstance(AddStandardComment.class);
+ action.execute("42", actionRequest, properties);
+ }
+
+ public void testChangeMergedFull() throws IOException {
+ ActionRequest actionRequest = createMock(ActionRequest.class);
+
+ Set<Property> properties = Sets.newHashSet();
+
+ Property propertyEventType = createMock(Property.class);
+ expect(propertyEventType.getKey()).andReturn("event-type").anyTimes();
+ expect(propertyEventType.getValue()).andReturn("change-merged").anyTimes();
+ properties.add(propertyEventType);
+
+ Property propertySubject = createMock(Property.class);
+ expect(propertySubject.getKey()).andReturn("subject").anyTimes();
+ expect(propertySubject.getValue()).andReturn("Test-Change-Subject").anyTimes();
+ properties.add(propertySubject);
+
+ Property propertyChangeNumber = createMock(Property.class);
+ expect(propertyChangeNumber.getKey()).andReturn("change-number")
+ .anyTimes();
+ expect(propertyChangeNumber.getValue()).andReturn("4711").anyTimes();
+ properties.add(propertyChangeNumber);
+
+ Property propertySubmitterName = createMock(Property.class);
+ expect(propertySubmitterName.getKey()).andReturn("submitter-name")
+ .anyTimes();
+ expect(propertySubmitterName.getValue()).andReturn("John Doe").anyTimes();
+ properties.add(propertySubmitterName);
+
+ Property propertyChangeUrl= createMock(Property.class);
+ expect(propertyChangeUrl.getKey()).andReturn("change-url").anyTimes();
+ expect(propertyChangeUrl.getValue()).andReturn("http://example.org/change")
+ .anyTimes();
+ properties.add(propertyChangeUrl);
+
+ expect(its.createLinkForWebui("http://example.org/change",
+ "http://example.org/change")).andReturn("HtTp://ExAmPlE.OrG/ChAnGe");
+
+ its.addComment("176", "Change 4711 merged by John Doe:\n" +
+ "Test-Change-Subject\n" +
+ "\n" +
+ "HtTp://ExAmPlE.OrG/ChAnGe");
+ replayMocks();
+
+ Action action = injector.getInstance(AddStandardComment.class);
+ action.execute("176", actionRequest, properties);
+ }
+
+ public void testChangeAbandonedPlain() throws IOException {
+ ActionRequest actionRequest = createMock(ActionRequest.class);
+
+ Set<Property> properties = Sets.newHashSet();
+
+ Property propertyEventType = createMock(Property.class);
+ expect(propertyEventType.getKey()).andReturn("event-type").anyTimes();
+ expect(propertyEventType.getValue()).andReturn("change-abandoned").anyTimes();
+ properties.add(propertyEventType);
+
+ its.addComment("42", "Change abandoned");
+ replayMocks();
+
+ Action action = injector.getInstance(AddStandardComment.class);
+ action.execute("42", actionRequest, properties);
+ }
+
+ public void testChangeAbandonedFull() throws IOException {
+ ActionRequest actionRequest = createMock(ActionRequest.class);
+
+ Set<Property> properties = Sets.newHashSet();
+
+ Property propertyEventType = createMock(Property.class);
+ expect(propertyEventType.getKey()).andReturn("event-type").anyTimes();
+ expect(propertyEventType.getValue()).andReturn("change-abandoned").anyTimes();
+ properties.add(propertyEventType);
+
+ Property propertyReason = createMock(Property.class);
+ expect(propertyReason.getKey()).andReturn("reason").anyTimes();
+ expect(propertyReason.getValue()).andReturn("Test-Reason").anyTimes();
+ properties.add(propertyReason);
+
+ Property propertySubject = createMock(Property.class);
+ expect(propertySubject.getKey()).andReturn("subject").anyTimes();
+ expect(propertySubject.getValue()).andReturn("Test-Change-Subject").anyTimes();
+ properties.add(propertySubject);
+
+ Property propertyChangeNumber = createMock(Property.class);
+ expect(propertyChangeNumber.getKey()).andReturn("change-number")
+ .anyTimes();
+ expect(propertyChangeNumber.getValue()).andReturn("4711").anyTimes();
+ properties.add(propertyChangeNumber);
+
+ Property propertySubmitterName = createMock(Property.class);
+ expect(propertySubmitterName.getKey()).andReturn("abandoner-name")
+ .anyTimes();
+ expect(propertySubmitterName.getValue()).andReturn("John Doe").anyTimes();
+ properties.add(propertySubmitterName);
+
+ Property propertyChangeUrl= createMock(Property.class);
+ expect(propertyChangeUrl.getKey()).andReturn("change-url").anyTimes();
+ expect(propertyChangeUrl.getValue()).andReturn("http://example.org/change")
+ .anyTimes();
+ properties.add(propertyChangeUrl);
+
+ expect(its.createLinkForWebui("http://example.org/change",
+ "http://example.org/change")).andReturn("HtTp://ExAmPlE.OrG/ChAnGe");
+
+ its.addComment("176", "Change 4711 abandoned by John Doe:\n" +
+ "Test-Change-Subject\n" +
+ "\n" +
+ "Reason:\n" +
+ "Test-Reason\n" +
+ "\n" +
+ "HtTp://ExAmPlE.OrG/ChAnGe");
+ replayMocks();
+
+ Action action = injector.getInstance(AddStandardComment.class);
+ action.execute("176", actionRequest, properties);
+ }
+
+ public void testChangeRestoredPlain() throws IOException {
+ ActionRequest actionRequest = createMock(ActionRequest.class);
+
+ Set<Property> properties = Sets.newHashSet();
+
+ Property propertyEventType = createMock(Property.class);
+ expect(propertyEventType.getKey()).andReturn("event-type").anyTimes();
+ expect(propertyEventType.getValue()).andReturn("change-restored").anyTimes();
+ properties.add(propertyEventType);
+
+ its.addComment("42", "Change restored");
+ replayMocks();
+
+ Action action = injector.getInstance(AddStandardComment.class);
+ action.execute("42", actionRequest, properties);
+ }
+
+ public void testChangeRestoredFull() throws IOException {
+ ActionRequest actionRequest = createMock(ActionRequest.class);
+
+ Set<Property> properties = Sets.newHashSet();
+
+ Property propertyEventType = createMock(Property.class);
+ expect(propertyEventType.getKey()).andReturn("event-type").anyTimes();
+ expect(propertyEventType.getValue()).andReturn("change-restored").anyTimes();
+ properties.add(propertyEventType);
+
+ Property propertyReason = createMock(Property.class);
+ expect(propertyReason.getKey()).andReturn("reason").anyTimes();
+ expect(propertyReason.getValue()).andReturn("Test-Reason").anyTimes();
+ properties.add(propertyReason);
+
+ Property propertySubject = createMock(Property.class);
+ expect(propertySubject.getKey()).andReturn("subject").anyTimes();
+ expect(propertySubject.getValue()).andReturn("Test-Change-Subject").anyTimes();
+ properties.add(propertySubject);
+
+ Property propertyChangeNumber = createMock(Property.class);
+ expect(propertyChangeNumber.getKey()).andReturn("change-number")
+ .anyTimes();
+ expect(propertyChangeNumber.getValue()).andReturn("4711").anyTimes();
+ properties.add(propertyChangeNumber);
+
+ Property propertySubmitterName = createMock(Property.class);
+ expect(propertySubmitterName.getKey()).andReturn("restorer-name")
+ .anyTimes();
+ expect(propertySubmitterName.getValue()).andReturn("John Doe").anyTimes();
+ properties.add(propertySubmitterName);
+
+ Property propertyChangeUrl= createMock(Property.class);
+ expect(propertyChangeUrl.getKey()).andReturn("change-url").anyTimes();
+ expect(propertyChangeUrl.getValue()).andReturn("http://example.org/change")
+ .anyTimes();
+ properties.add(propertyChangeUrl);
+
+ expect(its.createLinkForWebui("http://example.org/change",
+ "http://example.org/change")).andReturn("HtTp://ExAmPlE.OrG/ChAnGe");
+
+ its.addComment("176", "Change 4711 restored by John Doe:\n" +
+ "Test-Change-Subject\n" +
+ "\n" +
+ "Reason:\n" +
+ "Test-Reason\n" +
+ "\n" +
+ "HtTp://ExAmPlE.OrG/ChAnGe");
+ replayMocks();
+
+ Action action = injector.getInstance(AddStandardComment.class);
+ action.execute("176", actionRequest, properties);
+ }
+
+ public void testPatchSetCreatedPlain() throws IOException {
+ ActionRequest actionRequest = createMock(ActionRequest.class);
+
+ Set<Property> properties = Sets.newHashSet();
+
+ Property propertyEventType = createMock(Property.class);
+ expect(propertyEventType.getKey()).andReturn("event-type").anyTimes();
+ expect(propertyEventType.getValue()).andReturn("patchset-created").anyTimes();
+ properties.add(propertyEventType);
+
+ its.addComment("42", "Change had a related patch set uploaded");
+ replayMocks();
+
+ Action action = injector.getInstance(AddStandardComment.class);
+ action.execute("42", actionRequest, properties);
+ }
+
+ public void testPatchSetCreatedFull() throws IOException {
+ ActionRequest actionRequest = createMock(ActionRequest.class);
+
+ Set<Property> properties = Sets.newHashSet();
+
+ Property propertyEventType = createMock(Property.class);
+ expect(propertyEventType.getKey()).andReturn("event-type").anyTimes();
+ expect(propertyEventType.getValue()).andReturn("patchset-created").anyTimes();
+ properties.add(propertyEventType);
+
+ Property propertySubject = createMock(Property.class);
+ expect(propertySubject.getKey()).andReturn("subject").anyTimes();
+ expect(propertySubject.getValue()).andReturn("Test-Change-Subject").anyTimes();
+ properties.add(propertySubject);
+
+ Property propertyChangeNumber = createMock(Property.class);
+ expect(propertyChangeNumber.getKey()).andReturn("change-number")
+ .anyTimes();
+ expect(propertyChangeNumber.getValue()).andReturn("4711").anyTimes();
+ properties.add(propertyChangeNumber);
+
+ Property propertySubmitterName = createMock(Property.class);
+ expect(propertySubmitterName.getKey()).andReturn("uploader-name")
+ .anyTimes();
+ expect(propertySubmitterName.getValue()).andReturn("John Doe").anyTimes();
+ properties.add(propertySubmitterName);
+
+ Property propertyChangeUrl= createMock(Property.class);
+ expect(propertyChangeUrl.getKey()).andReturn("change-url").anyTimes();
+ expect(propertyChangeUrl.getValue()).andReturn("http://example.org/change")
+ .anyTimes();
+ properties.add(propertyChangeUrl);
+
+ expect(its.createLinkForWebui("http://example.org/change",
+ "http://example.org/change")).andReturn("HtTp://ExAmPlE.OrG/ChAnGe");
+
+ its.addComment("176", "Change 4711 had a related patch set uploaded by " +
+ "John Doe:\n" +
+ "Test-Change-Subject\n" +
+ "\n" +
+ "HtTp://ExAmPlE.OrG/ChAnGe");
+ replayMocks();
+
+ Action action = injector.getInstance(AddStandardComment.class);
+ action.execute("176", actionRequest, properties);
+ }
+
+ public void setUp() throws Exception {
+ super.setUp();
+
+ injector = Guice.createInjector(new TestModule());
+ }
+
+ private class TestModule extends FactoryModule {
+ @Override
+ protected void configure() {
+ its = createMock(ItsFacade.class);
+ bind(ItsFacade.class).toInstance(its);
+ }
+ }
+}
\ No newline at end of file