/*
* The MIT License
*
* Copyright 2011 Sony Ericsson Mobile Communications. All rights reserved.
* Copyright 2012 Sony Mobile Communications AB. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.sonyericsson.hudson.plugins.metadata.cli;
import com.sonyericsson.hudson.plugins.metadata.MockUtils;
import com.sonyericsson.hudson.plugins.metadata.model.MetadataContainer;
import com.sonyericsson.hudson.plugins.metadata.model.MetadataJobProperty;
import com.sonyericsson.hudson.plugins.metadata.model.values.MetadataValue;
import com.sonyericsson.hudson.plugins.metadata.model.values.StringMetadataValue;
import com.sonyericsson.hudson.plugins.metadata.model.values.TreeNodeMetadataValue;
import com.sonyericsson.hudson.plugins.metadata.model.values.TreeStructureUtil;
import com.sonyericsson.hudson.plugins.metadata.util.ExtensionUtils;
import hudson.model.Hudson;
import hudson.model.Queue;
import hudson.security.ACL;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.mockito.internal.stubbing.answers.DoesNothing;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import javax.servlet.ServletOutputStream;
import java.util.Collections;
import static com.sonyericsson.hudson.plugins.metadata.cli.CliResponse.CONTENT_TYPE;
import static junit.framework.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.contains;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* Tests for {@link HttpCliRootAction}.
*
* @author Robert Sandell <robert.sandell@sonyericsson.com>
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({CliUtils.class, Hudson.class, ACL.class, Queue.class, ExtensionUtils.class })
public class HttpCliRootActionTest {
private MetadataContainer<MetadataValue> container;
private StaplerRequest request;
private StaplerResponse response;
private ServletOutputStream out;
private HttpCliRootAction action;
private final String job = "testJob1";
private String printed;
private ACL acl;
private Queue queue;
/**
* Do some mocking for all tests.
*
* @throws Exception if so and fail.
*/
@Before
public void prepareSomeStuff() throws Exception {
Hudson hudson = MockUtils.mockHudson();
MockUtils.mockMetadataValueDescriptors(hudson);
container = mock(MetadataContainer.class);
acl = PowerMockito.mock(ACL.class);
when(container.getACL()).thenReturn(acl);
PowerMockito.mockStatic(Queue.class);
queue = PowerMockito.mock(Queue.class);
PowerMockito.when(Queue.getInstance()).thenReturn(queue);
PowerMockito.mockStatic(CliUtils.class);
request = mock(StaplerRequest.class);
response = mock(StaplerResponse.class);
out = mock(ServletOutputStream.class);
when(response.getOutputStream()).thenReturn(out);
action = new HttpCliRootAction();
printed = null;
}
/**
* Happy tests for {@link HttpCliRootAction#doUpdate(org.kohsuke.stapler.StaplerRequest,
* org.kohsuke.stapler.StaplerResponse)}.
*
* @throws Exception if so.
*/
@Test
public void testDoUpdate() throws Exception {
String value = (new StringMetadataValue("owner", "bobby")).toJson().toString();
boolean exposed = true;
JSONObject expectedJson = new JSONObject();
expectedJson.put("type", "ok");
expectedJson.put("errorCode", 0);
expectedJson.put("message", "OK");
when(request.getParameter(eq("job"))).thenReturn(job);
when(request.getParameter(eq("data"))).thenReturn(value);
PowerMockito.when(CliUtils.getContainer(null, job, null, true)).thenReturn(container);
action.doUpdate(request, response);
verify(response).setContentType(eq(CONTENT_TYPE));
verify(out).print(eq(expectedJson.toString()));
}
/**
* Happy tests for {@link HttpCliRootAction#doUpdate(org.kohsuke.stapler.StaplerRequest,
* org.kohsuke.stapler.StaplerResponse)}.
*
* @throws Exception if so.
*/
@Test
public void testDoUpdateWithReplace() throws Exception {
StringMetadataValue value = new StringMetadataValue("owner", "bobby");
String replace = (new StringMetadataValue("owner", "Tomas")).toJson().toString();
JSONObject expectedJson = new JSONObject();
expectedJson.put("type", "ok");
expectedJson.put("errorCode", 0);
expectedJson.put("message", "OK");
when(request.getParameter(eq("job"))).thenReturn(job);
when(request.getParameter(eq("data"))).thenReturn(replace);
when(request.getParameter(eq("replace"))).thenReturn("true");
PowerMockito.when(CliUtils.getContainer(null, job, null, true)).thenReturn(container);
when(container.getChild(eq("owner"))).thenReturn(value);
action.doUpdate(request, response);
verify(response).setContentType(eq(CONTENT_TYPE));
verify(out).print(eq(expectedJson.toString()));
verify(container).setChild(anyInt(), any(MetadataValue.class));
}
/**
* Double update test for {@link HttpCliRootAction#doUpdate(org.kohsuke.stapler.StaplerRequest,
* org.kohsuke.stapler.StaplerResponse)}.
* With a tree structure.
*
* @throws Exception if so.
*/
@Test
public void testDoUpdateTreeWithReplace() throws Exception {
TreeNodeMetadataValue path = TreeStructureUtil.createPath("Bobby", "description", "owner", "name");
TreeStructureUtil.addValue(path, "Admin", "What is the owner", "type");
MetadataJobProperty myContainer = spy(new MetadataJobProperty());
when(myContainer.getACL()).thenReturn(acl);
myContainer.addChild(path);
String replace = TreeStructureUtil.createPath("Tomas", "description", "owner", "name").toJson().toString();
JSONObject expectedJson = new JSONObject();
expectedJson.put("type", "ok");
expectedJson.put("errorCode", 0);
expectedJson.put("message", "OK");
when(request.getParameter(eq("job"))).thenReturn(job);
when(request.getParameter(eq("data"))).thenReturn(replace);
when(request.getParameter(eq("replace"))).thenReturn("true");
PowerMockito.when(CliUtils.getContainer(null, job, null, true)).thenReturn(myContainer);
action.doUpdate(request, response);
verify(response, atLeastOnce()).setContentType(eq(CONTENT_TYPE));
verify(out).print(eq(expectedJson.toString()));
assertEquals(1, myContainer.getChildren().size());
assertEquals(2, ((TreeNodeMetadataValue)myContainer.getChild("owner")).getChildren().size());
assertEquals("Tomas", TreeStructureUtil.getPath(myContainer, "owner", "name").getValue());
}
/**
* Happy tests for {@link HttpCliRootAction#doGet(org.kohsuke.stapler.StaplerRequest,
* org.kohsuke.stapler.StaplerResponse)} .
*
* @throws Exception if so.
*/
@Test
public void testDoGet() throws Exception {
StringMetadataValue metadataValue = new StringMetadataValue("owner", "bobby");
TreeNodeMetadataValue node = new TreeNodeMetadataValue("container",
Collections.<MetadataValue>singletonList(metadataValue));
JSONObject jsonObject = node.toJson();
when(request.getParameter(eq("job"))).thenReturn(job);
PowerMockito.when(CliUtils.getContainer(null, job, null, false)).thenReturn(container);
when(container.toJson()).thenReturn(jsonObject);
action.doGet(request, response);
verify(response).setContentType(eq(CONTENT_TYPE));
verify(out).print(eq(jsonObject.toString()));
}
/**
* Tests for {@link HttpCliRootAction#doGet(org.kohsuke.stapler.StaplerRequest,
* org.kohsuke.stapler.StaplerResponse)} . When no parameters has been defined.
*
* @throws Exception if so.
*/
@Test
public void testDoGetNothing() throws Exception {
String message = "You must provide either a job or a node.";
PowerMockito.when(CliUtils.getContainer(null, null, null, false))
.thenThrow(new CmdLineException(null, message));
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printed = (String)invocation.getArguments()[0];
return new DoesNothing().answer(invocation);
}
}).when(out).print(any(String.class));
action.doGet(request, response);
verify(response).setContentType(eq(CONTENT_TYPE));
verify(out).print(contains(message));
JSONObject obj = (JSONObject)JSONSerializer.toJSON(printed);
assertEquals("error", obj.getString("type"));
assertEquals(CliUtils.Status.ERR_BAD_CMD.code(), obj.getInt("errorCode"));
assertEquals(CliUtils.Status.ERR_BAD_CMD.name(), obj.getString("errorName"));
}
/**
* Tests for {@link HttpCliRootAction#doGet(org.kohsuke.stapler.StaplerRequest,
* org.kohsuke.stapler.StaplerResponse)} . When a non existing job has been defined.
*
* @throws Exception if so.
*/
@Test
public void testDoGetNoJob() throws Exception {
when(request.getParameter(eq("job"))).thenReturn(job);
PowerMockito.when(CliUtils.getContainer(null, job, null, false))
.thenThrow(new CliUtils.NoItemException("No job."));
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printed = (String)invocation.getArguments()[0];
return new DoesNothing().answer(invocation);
}
}).when(out).print(any(String.class));
action.doGet(request, response);
verify(response).setContentType(eq(CONTENT_TYPE));
JSONObject obj = (JSONObject)JSONSerializer.toJSON(printed);
assertEquals("error", obj.getString("type"));
assertEquals(CliUtils.Status.ERR_NO_ITEM.code(), obj.getInt("errorCode"));
assertEquals(CliUtils.Status.ERR_NO_ITEM.name(), obj.getString("errorName"));
}
/**
* Tests for {@link HttpCliRootAction#doGet(org.kohsuke.stapler.StaplerRequest,
* org.kohsuke.stapler.StaplerResponse)} . When a job with no metadata has been defined.
*
* @throws Exception if so.
*/
@Test
public void testDoGetNoJobMetadata() throws Exception {
when(request.getParameter(eq("job"))).thenReturn(job);
PowerMockito.when(CliUtils.getContainer(null, job, null, false))
.thenThrow(new CliUtils.NoMetadataException("No metadata."));
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printed = (String)invocation.getArguments()[0];
return new DoesNothing().answer(invocation);
}
}).when(out).print(any(String.class));
action.doGet(request, response);
verify(response).setContentType(eq(CONTENT_TYPE));
JSONObject obj = (JSONObject)JSONSerializer.toJSON(printed);
assertEquals("error", obj.getString("type"));
assertEquals(CliUtils.Status.ERR_NO_METADATA.code(), obj.getInt("errorCode"));
assertEquals(CliUtils.Status.ERR_NO_METADATA.name(), obj.getString("errorName"));
}
}