| // 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; |
| } |
| } |
| } |