package azkaban.execapp.event;
import static azkaban.jobcallback.JobCallbackConstants.CONTEXT_EXECUTION_ID_TOKEN;
import static azkaban.jobcallback.JobCallbackConstants.CONTEXT_FLOW_TOKEN;
import static azkaban.jobcallback.JobCallbackConstants.HTTP_GET;
import static azkaban.jobcallback.JobCallbackConstants.HTTP_POST;
import static azkaban.jobcallback.JobCallbackConstants.CONTEXT_JOB_STATUS_TOKEN;
import static azkaban.jobcallback.JobCallbackConstants.CONTEXT_JOB_TOKEN;
import static azkaban.jobcallback.JobCallbackConstants.CONTEXT_PROJECT_TOKEN;
import static azkaban.jobcallback.JobCallbackConstants.CONTEXT_SERVER_TOKEN;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.http.Header;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import azkaban.jobcallback.JobCallbackConstants;
import azkaban.jobcallback.JobCallbackStatusEnum;
import azkaban.utils.Props;
public class JobCallbackUtilTest {
private static Map<String, String> contextInfo;
private static final String SERVER_NAME = "localhost:9999";
private static final String PROJECT_NAME = "PROJECTX";
private static final String FLOW_NAME = "FLOWX";
private static final String JOB_NAME = "JOBX";
private static final String EXECUTION_ID = "1234";
private static final String JOB_STATUS_NAME = JobCallbackStatusEnum.STARTED
.name();
@BeforeClass
public static void setup() {
contextInfo = new HashMap<String, String>();
contextInfo.put(CONTEXT_SERVER_TOKEN, SERVER_NAME);
contextInfo.put(CONTEXT_PROJECT_TOKEN, PROJECT_NAME);
contextInfo.put(CONTEXT_FLOW_TOKEN, FLOW_NAME);
contextInfo.put(CONTEXT_EXECUTION_ID_TOKEN, EXECUTION_ID);
contextInfo.put(CONTEXT_JOB_TOKEN, JOB_NAME);
contextInfo.put(CONTEXT_JOB_STATUS_TOKEN, JOB_STATUS_NAME);
}
@Test
public void noCallbackPropertiesTest() {
Props props = new Props();
props.put("abc", "def");
Assert.assertFalse(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.STARTED));
Assert.assertFalse(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.COMPLETED));
Assert.assertFalse(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.FAILURE));
Assert.assertFalse(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.SUCCESS));
}
@Test
public void hasCallbackPropertiesTest() {
Props props = new Props();
for (JobCallbackStatusEnum jobStatus : JobCallbackStatusEnum.values()) {
props.put(
"job.notification." + jobStatus.name().toLowerCase() + ".1.url",
"def");
}
System.out.println(props);
Assert.assertTrue(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.STARTED));
Assert.assertTrue(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.COMPLETED));
Assert.assertTrue(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.FAILURE));
Assert.assertTrue(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.SUCCESS));
}
@Test
public void multipleStatusWithNoJobCallbackTest() {
Props props = new Props();
props.put("abc", "def");
Assert.assertFalse(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.STARTED, JobCallbackStatusEnum.COMPLETED,
JobCallbackStatusEnum.FAILURE, JobCallbackStatusEnum.SUCCESS));
}
@Test
public void multipleStatusesWithJobCallbackTest() {
Props props = new Props();
props.put("job.notification."
+ JobCallbackStatusEnum.STARTED.name().toLowerCase() + ".1.url", "def");
Assert.assertTrue(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.STARTED, JobCallbackStatusEnum.COMPLETED,
JobCallbackStatusEnum.FAILURE, JobCallbackStatusEnum.SUCCESS));
props = new Props();
props.put("job.notification."
+ JobCallbackStatusEnum.COMPLETED.name().toLowerCase() + ".1.url",
"def");
Assert.assertTrue(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.STARTED, JobCallbackStatusEnum.COMPLETED,
JobCallbackStatusEnum.FAILURE, JobCallbackStatusEnum.SUCCESS));
props = new Props();
props.put("job.notification."
+ JobCallbackStatusEnum.FAILURE.name().toLowerCase() + ".1.url", "def");
Assert.assertTrue(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.STARTED, JobCallbackStatusEnum.COMPLETED,
JobCallbackStatusEnum.FAILURE, JobCallbackStatusEnum.SUCCESS));
props = new Props();
props.put("job.notification."
+ JobCallbackStatusEnum.SUCCESS.name().toLowerCase() + ".1.url", "def");
Assert.assertTrue(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.STARTED, JobCallbackStatusEnum.COMPLETED,
JobCallbackStatusEnum.FAILURE, JobCallbackStatusEnum.SUCCESS));
}
@Test
public void hasCallbackPropertiesWithGapTest() {
Props props = new Props();
for (JobCallbackStatusEnum jobStatus : JobCallbackStatusEnum.values()) {
props.put(
"job.notification." + jobStatus.name().toLowerCase() + ".2.url",
"def");
}
System.out.println(props);
Assert.assertFalse(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.STARTED));
Assert.assertFalse(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.COMPLETED));
Assert.assertFalse(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.FAILURE));
Assert.assertFalse(JobCallbackUtil.isThereJobCallbackProperty(props,
JobCallbackStatusEnum.SUCCESS));
}
@Test
public void noTokenTest() {
String urlWithNoToken = "http://www.linkedin.com";
String result =
JobCallbackUtil.replaceTokens(urlWithNoToken, contextInfo, true);
Assert.assertEquals(urlWithNoToken, result);
}
@Test
public void oneTokenTest() {
String urlWithOneToken =
"http://www.linkedin.com?project=" + CONTEXT_PROJECT_TOKEN + "&another=yes";
String result =
JobCallbackUtil.replaceTokens(urlWithOneToken, contextInfo, true);
Assert.assertEquals("http://www.linkedin.com?project=" + PROJECT_NAME
+ "&another=yes", result);
}
@Test
public void twoTokensTest() {
String urlWithOneToken =
"http://www.linkedin.com?project=" + CONTEXT_PROJECT_TOKEN + "&flow="
+ CONTEXT_FLOW_TOKEN;
String result =
JobCallbackUtil.replaceTokens(urlWithOneToken, contextInfo, true);
Assert.assertEquals("http://www.linkedin.com?project=" + PROJECT_NAME
+ "&flow=" + FLOW_NAME, result);
}
@Test
public void allTokensTest() {
String urlWithOneToken =
"http://www.linkedin.com?server=" + SERVER_NAME + "&project="
+ CONTEXT_PROJECT_TOKEN + "&flow=" + CONTEXT_FLOW_TOKEN + "&executionId="
+ CONTEXT_EXECUTION_ID_TOKEN + "&job=" + CONTEXT_JOB_TOKEN + "&status="
+ CONTEXT_JOB_STATUS_TOKEN;
String result =
JobCallbackUtil.replaceTokens(urlWithOneToken, contextInfo, true);
String expectedResult =
"http://www.linkedin.com?server=" + SERVER_NAME + "&project="
+ PROJECT_NAME + "&flow=" + FLOW_NAME + "&executionId="
+ EXECUTION_ID + "&job=" + JOB_NAME + "&status=" + JOB_STATUS_NAME;
Assert.assertEquals(expectedResult, result);
}
@Test
public void tokenWithEncoding() throws Exception {
String jobNameWithSpaces = "my job";
String encodedJobName = URLEncoder.encode(jobNameWithSpaces, "UTF-8");
Map<String, String> customContextInfo = new HashMap<String, String>();
customContextInfo = new HashMap<String, String>();
customContextInfo.put(CONTEXT_SERVER_TOKEN, SERVER_NAME);
customContextInfo.put(CONTEXT_PROJECT_TOKEN, PROJECT_NAME);
customContextInfo.put(CONTEXT_FLOW_TOKEN, FLOW_NAME);
customContextInfo.put(CONTEXT_EXECUTION_ID_TOKEN, EXECUTION_ID);
customContextInfo.put(CONTEXT_JOB_TOKEN, jobNameWithSpaces);
customContextInfo.put(CONTEXT_JOB_STATUS_TOKEN, JOB_STATUS_NAME);
String urlWithOneToken =
"http://www.linkedin.com?job=" + CONTEXT_JOB_TOKEN + "&flow=" + CONTEXT_FLOW_TOKEN;
String result =
JobCallbackUtil.replaceTokens(urlWithOneToken, customContextInfo, true);
Assert.assertEquals("http://www.linkedin.com?job=" + encodedJobName
+ "&flow=" + FLOW_NAME, result);
}
@Test
public void parseJobCallbackOneGetTest() {
Props props = new Props();
String url = "http://lva1-rpt07.corp.linkedin.com";
props.put("job.notification."
+ JobCallbackStatusEnum.STARTED.name().toLowerCase() + ".1.url", url);
List<HttpRequestBase> result =
JobCallbackUtil.parseJobCallbackProperties(props,
JobCallbackStatusEnum.STARTED, contextInfo, 3);
Assert.assertEquals(1, result.size());
Assert.assertEquals(HTTP_GET, result.get(0).getMethod());
Assert.assertEquals(url, result.get(0).getURI().toString());
}
@Test
public void parseJobCallbackWithInvalidURLTest() {
Props props = new Props();
String url = "linkedin.com";
props.put("job.notification."
+ JobCallbackStatusEnum.STARTED.name().toLowerCase() + ".1.url", url);
List<HttpRequestBase> result =
JobCallbackUtil.parseJobCallbackProperties(props,
JobCallbackStatusEnum.STARTED, contextInfo, 3);
Assert.assertEquals(1, result.size());
Assert.assertEquals(HTTP_GET, result.get(0).getMethod());
Assert.assertEquals(url, result.get(0).getURI().toString());
}
@Test
public void parseJobCallbackTwoGetsTest() {
Props props = new Props();
String[] urls =
{ "http://lva1-rpt07.corp.linkedin.com",
"http://lva1-rpt06.corp.linkedin.com" };
props.put("job.notification."
+ JobCallbackStatusEnum.STARTED.name().toLowerCase() + ".1.url",
urls[0]);
props.put("job.notification."
+ JobCallbackStatusEnum.STARTED.name().toLowerCase() + ".2.url",
urls[1]);
List<HttpRequestBase> result =
JobCallbackUtil.parseJobCallbackProperties(props,
JobCallbackStatusEnum.STARTED, contextInfo, 3);
Assert.assertEquals(2, result.size());
for (int i = 0; i < urls.length; i++) {
Assert.assertEquals(HTTP_GET, result.get(i).getMethod());
Assert.assertEquals(urls[i], result.get(i).getURI().toString());
}
}
@Test
public void parseJobCallbackWithGapTest() {
Props props = new Props();
String[] urls =
{ "http://lva1-rpt07.corp.linkedin.com",
"http://lva1-rpt06.corp.linkedin.com" };
props.put("job.notification."
+ JobCallbackStatusEnum.STARTED.name().toLowerCase() + ".1.url",
urls[0]);
props.put("job.notification."
+ JobCallbackStatusEnum.STARTED.name().toLowerCase() + ".3.url",
urls[1]);
List<HttpRequestBase> result =
JobCallbackUtil.parseJobCallbackProperties(props,
JobCallbackStatusEnum.STARTED, contextInfo, 3);
Assert.assertEquals(1, result.size());
Assert.assertEquals(HTTP_GET, result.get(0).getMethod());
Assert.assertEquals(urls[0], result.get(0).getURI().toString());
}
@Test
public void parseJobCallbackWithPostTest() {
Props props = new Props();
String url = "http://lva1-rpt07.corp.linkedin.com";
String bodyText = "{name:\"you\"}";
props.put("job.notification."
+ JobCallbackStatusEnum.STARTED.name().toLowerCase() + ".1.url", url);
props.put("job.notification."
+ JobCallbackStatusEnum.STARTED.name().toLowerCase() + ".1.method",
HTTP_POST);
props.put("job.notification."
+ JobCallbackStatusEnum.STARTED.name().toLowerCase() + ".1.body",
bodyText);
List<HttpRequestBase> result =
JobCallbackUtil.parseJobCallbackProperties(props,
JobCallbackStatusEnum.STARTED, contextInfo, 3);
Assert.assertEquals(1, result.size());
HttpPost httpPost = (HttpPost) result.get(0);
Assert.assertEquals(url, httpPost.getURI().toString());
Assert.assertEquals(HTTP_POST, httpPost.getMethod());
Assert.assertEquals(bodyText.length(), httpPost.getEntity()
.getContentLength());
}
@Test
public void noHeaderElementTest() {
Header[] headerArr =
JobCallbackUtil.parseHttpHeaders("this is an amazing day");
Assert.assertNotNull(headerArr);
Assert.assertEquals(0, headerArr.length);
}
@Test
public void oneHeaderElementTest() {
String name = "Content-type";
String value = "application/json";
String headers =
name + JobCallbackConstants.HEADER_NAME_VALUE_DELIMITER + value;
Header[] headerArr = JobCallbackUtil.parseHttpHeaders(headers);
Assert.assertNotNull(headerArr);
Assert.assertEquals(1, headerArr.length);
Assert.assertEquals(name, headerArr[0].getName());
Assert.assertEquals(value, headerArr[0].getValue());
String headersWithExtraDelimiter =
name + JobCallbackConstants.HEADER_NAME_VALUE_DELIMITER + value
+ JobCallbackConstants.HEADER_ELEMENT_DELIMITER;
headerArr = JobCallbackUtil.parseHttpHeaders(headersWithExtraDelimiter);
Assert.assertNotNull(headerArr);
Assert.assertEquals(1, headerArr.length);
Assert.assertEquals(name, headerArr[0].getName());
Assert.assertEquals(value, headerArr[0].getValue());
}
@Test
public void multipleHeaderElementTest() {
String name1 = "Content-type";
String value1 = "application/json";
String name2 = "Accept";
String value2 = "application/xml";
String name3 = "User-Agent";
String value3 =
"Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0";
String headers = makeHeaderElement(name1, value1);
headers += JobCallbackConstants.HEADER_ELEMENT_DELIMITER;
headers += makeHeaderElement(name2, value2);
headers += JobCallbackConstants.HEADER_ELEMENT_DELIMITER;
headers += makeHeaderElement(name3, value3);
System.out.println("headers: " + headers);
Header[] headerArr = JobCallbackUtil.parseHttpHeaders(headers);
Assert.assertNotNull(headerArr);
Assert.assertEquals(3, headerArr.length);
Assert.assertEquals(name1, headerArr[0].getName());
Assert.assertEquals(value1, headerArr[0].getValue());
Assert.assertEquals(name2, headerArr[1].getName());
Assert.assertEquals(value2, headerArr[1].getValue());
Assert.assertEquals(name3, headerArr[2].getName());
Assert.assertEquals(value3, headerArr[2].getValue());
}
@Test
public void partialHeaderElementTest() {
String name1 = "Content-type";
String value1 = "application/json";
String name2 = "Accept";
String value2 = "";
String name3 = "User-Agent";
String value3 =
"Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0";
String headers = makeHeaderElement(name1, value1);
headers += JobCallbackConstants.HEADER_ELEMENT_DELIMITER;
headers += makeHeaderElement(name2, value2);
headers += JobCallbackConstants.HEADER_ELEMENT_DELIMITER;
headers += makeHeaderElement(name3, value3);
System.out.println("headers: " + headers);
Header[] headerArr = JobCallbackUtil.parseHttpHeaders(headers);
Assert.assertNotNull(headerArr);
Assert.assertEquals(3, headerArr.length);
Assert.assertEquals(name1, headerArr[0].getName());
Assert.assertEquals(value1, headerArr[0].getValue());
Assert.assertEquals(name2, headerArr[1].getName());
Assert.assertEquals(value2, headerArr[1].getValue());
Assert.assertEquals(name3, headerArr[2].getName());
Assert.assertEquals(value3, headerArr[2].getValue());
}
private String makeHeaderElement(String name, String value) {
return name + JobCallbackConstants.HEADER_NAME_VALUE_DELIMITER + value;
}
}