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