/*
* 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.jenkins.plugins.externalresource.dispatcher.utils.resourcemanagers;
//CS IGNORE LineLength FOR NEXT 35 LINES. REASON: imports.
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.fail;
import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.when;
import com.sonyericsson.jenkins.plugins.externalresource.dispatcher.MockUtils;
import com.sonyericsson.jenkins.plugins.externalresource.dispatcher.utils.JsonRpcUtil;
import hudson.model.Computer;
import hudson.model.Hudson;
import hudson.model.Node;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import net.sf.json.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.googlecode.jsonrpc4j.JsonRpcHttpClient;
import com.sonyericsson.jenkins.plugins.externalresource.dispatcher.data.StashResult;
import com.sonyericsson.jenkins.plugins.externalresource.dispatcher.data.ExternalResource;
import com.sonyericsson.jenkins.plugins.externalresource.dispatcher.data.StashResult.Status;
import com.sonyericsson.jenkins.plugins.externalresource.dispatcher.utils.resourcemanagers.ResourceMonitorExternalResourceManager.RpcResult;
/**
* The unit test for the external resource manager.
*
* @author Zhang Leimeng
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ JsonRpcUtil.class, Node.class, Hudson.class })
public class ExternalResourceManagerTest {
/**
* the method name of reserve.
*/
private static final String RESERVE_METHOD = "ResourceMonitor.Resources.Reserve";
/**
* the method of lock.
*/
private static final String LOCK_METHOD = "ResourceMonitor.Resources.Lock";
/**
* the method of release.
*/
private static final String RELEASE_METHOD = "ResourceMonitor.Resources.Release";
/**
* test reserve method.
*/
@Test
public void testReserve() {
Hudson mockHudson = MockUtils.mockHudson();
when(mockHudson.getRootUrl()).thenReturn("jenkins");
// the external resource we mocked.
String externalResourceId = "id_1";
String externalResourceName = "id_1";
ExternalResource er = new ExternalResource(externalResourceName, externalResourceId);
// mocked nodename, the host name used inside the monitor.
String nodeName = "slave1";
// the result we expected.
String reserveKey = "348304849303";
int code = 0;
String message = "the device is reserved";
RpcResult result = new RpcResult();
long now = new Date().getTime();
String isoTime = "China Beijing";
result.setCode(code);
result.setKey(reserveKey);
result.setMessage(message);
result.setStatus(Status.OK);
result.setIsotime(isoTime);
result.setTime(now);
int time = (int)Math.random();
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("resource", externalResourceId);
paramMap.put("timeout", time);
JSONObject clientInfo = new JSONObject();
clientInfo.put("id", "jenkins");
clientInfo.put("url", "me");
paramMap.put("clientInfo", clientInfo);
// mock for reserve.
mockForOperation(result, new Object[]{paramMap}, nodeName, RESERVE_METHOD);
// mock a node which has hostname.
Node n = mockNode(nodeName);
ExternalResourceManager rpcCallERM = new ResourceMonitorExternalResourceManager();
StashResult sRes = rpcCallERM.reserve(n, er, time, "me");
assertFalse(er.isAvailable());
assertEquals(code, sRes.getErrorCode());
assertEquals(message, sRes.getMessage());
assertEquals(reserveKey, sRes.getKey());
assertEquals(Status.OK , sRes.getStatus());
assertTrue(sRes.isOk());
assertEquals(isoTime, sRes.getLease().getSlaveIsoTime());
assertNotNull(sRes.getLease().getServerTime());
}
/**
* test lock method.
*/
@Test
public void testLock() {
Hudson mockHudson = MockUtils.mockHudson();
when(mockHudson.getRootUrl()).thenReturn("jenkins");
// the external resource we mocked.
String externalResourceId = "id_1";
String externalResourceName = "id_1";
ExternalResource er = new ExternalResource(externalResourceName, externalResourceId);
// mocked nodename, the host name used inside the monitor.
String nodeName = "slave1";
// the result we expected.
String reserveKey = "3483048493039334";
int code = 0;
String message = "the device is locked";
RpcResult result = new RpcResult();
result.setCode(code);
result.setKey(reserveKey);
result.setMessage(message);
result.setStatus(Status.OK);
Map<String, Object> paramMap = mockParamMap(externalResourceId, reserveKey);
// mock for reserve.
mockForOperation(result, new Object[]{paramMap}, nodeName, LOCK_METHOD);
// mock a node which has hostname.
Node n = mockNode(nodeName);
ExternalResourceManager rpcCallERM = new ResourceMonitorExternalResourceManager();
StashResult sRes = rpcCallERM.lock(n, er, reserveKey, "me");
assertFalse(er.isAvailable());
assertEquals(code, sRes.getErrorCode());
assertEquals(message, sRes.getMessage());
assertEquals(Status.OK, sRes.getStatus());
assertTrue(sRes.isOk());
assertEquals(reserveKey, sRes.getKey());
}
/**
* Creates a parameter map to be used when mocking the rpc methods.
*
* @param externalResourceId the id
* @param reserveKey the key
* @return the parameters in a map.
*/
private Map<String, Object> mockParamMap(String externalResourceId, String reserveKey) {
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("resource", externalResourceId);
paramMap.put("key", reserveKey);
JSONObject clientInfo = new JSONObject();
clientInfo.put("id", "jenkins");
clientInfo.put("url", "me");
paramMap.put("clientInfo", clientInfo);
return paramMap;
}
/**
* test release method.
*/
@Test
public void testRelease() {
Hudson mockHudson = MockUtils.mockHudson();
when(mockHudson.getRootUrl()).thenReturn("jenkins");
// the external resource we mocked.
String externalResourceId = "id_1";
String externalResourceName = "id_1";
ExternalResource er = new ExternalResource(externalResourceName, externalResourceId);
// mocked nodename, the host name used inside the monitor.
String nodeName = "slave1";
// the result we expected.
String reserveKey = "3483048493039334";
int code = 0;
String message = "the device is released";
RpcResult result = new RpcResult();
result.setCode(code);
result.setKey(reserveKey);
result.setMessage(message);
result.setStatus(Status.OK);
String key = "mockreservekey";
Map<String, Object> paramMap = mockParamMap(externalResourceId, key);
// mock for reserve.
mockForOperation(result, new Object[] { paramMap }, nodeName, RELEASE_METHOD);
// mock a node which has hostname.
Node n = mockNode(nodeName);
ExternalResourceManager rpcCallERM = new ResourceMonitorExternalResourceManager();
StashResult sRes = rpcCallERM.release(n, er, key, "me");
assertTrue(er.isAvailable());
assertEquals(code, sRes.getErrorCode());
assertEquals(Status.OK, sRes.getStatus());
assertEquals(message, sRes.getMessage());
assertTrue(sRes.isOk());
assertEquals(reserveKey, sRes.getKey());
}
/**
* mock job for the reserve method.
* @param expectedOutput the expected {@link RpcResult}
* @param expectedInput the expected input as Object[].
* @param nodeName the expected node name.
* @param methodName the method name of the rpc call
*/
private void mockForOperation(RpcResult expectedOutput, Object[] expectedInput, String nodeName, String methodName) {
JsonRpcHttpClient mockRpcClient = PowerMockito.mock(JsonRpcHttpClient.class);
try {
when(mockRpcClient.invoke(methodName, expectedInput,
ResourceMonitorExternalResourceManager.RpcResult.class)).thenReturn(
expectedOutput);
} catch (Throwable e) {
e.printStackTrace();
fail();
}
mockJsonRpcUtil(mockRpcClient, nodeName);
}
/**
* mock the static JsonRpcUtil class to let the test work.
* @param expectedClient the expected {@link JsonRpcHttpClient}.
* @param nodeName the expected nodeName.
*/
private void mockJsonRpcUtil(JsonRpcHttpClient expectedClient, String nodeName) {
PowerMockito.mockStatic(JsonRpcUtil.class);
when(JsonRpcUtil.createJsonRpcClient(MessageFormat.format("http://{0}:{1}/", nodeName, "8080"))).thenReturn(
expectedClient);
ObjectMapper om = JsonRpcUtil.customizeObjectMapper();
when(JsonRpcUtil.customizeObjectMapper()).thenReturn(om);
when(JsonRpcUtil.createJsonRpcClient(MessageFormat.format("http://{0}:{1}/", nodeName, "8080"), om))
.thenReturn(expectedClient);
}
/**
* mock a node which will return the expected node name.
* @param nodeName the expected nodeName.
* @return the {@link Node} which will return the nodeName.
*/
private Node mockNode(String nodeName) {
Computer com = PowerMockito.mock(Computer.class);
try {
when(com.getHostName()).thenReturn(nodeName);
} catch (IOException e) {
e.printStackTrace();
fail();
} catch (InterruptedException e) {
e.printStackTrace();
fail();
}
Node n = PowerMockito.mock(Node.class);
PowerMockito.doReturn(com).when(n).toComputer();
return n;
}
}