blob: a1255d3d21fdb6afebf1ac960f22c61f9cad9453 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.shardingsphere.elasticjob.cloud.scheduler.restful;
import org.apache.shardingsphere.elasticjob.cloud.scheduler.config.job.CloudJobExecutionType;
import org.apache.shardingsphere.elasticjob.cloud.scheduler.fixture.TaskNode;
import org.apache.shardingsphere.elasticjob.cloud.scheduler.state.running.RunningService;
import org.apache.shardingsphere.elasticjob.cloud.context.ExecutionType;
import org.apache.shardingsphere.elasticjob.cloud.event.rdb.JobEventRdbSearch;
import org.apache.shardingsphere.elasticjob.cloud.event.type.JobExecutionEvent;
import org.apache.shardingsphere.elasticjob.cloud.scheduler.fixture.CloudAppJsonConstants;
import org.apache.shardingsphere.elasticjob.cloud.scheduler.fixture.CloudJsonConstants;
import org.apache.shardingsphere.elasticjob.cloud.scheduler.state.failover.FailoverTaskInfo;
import org.apache.shardingsphere.elasticjob.cloud.statistics.type.task.TaskResultStatistics;
import org.apache.shardingsphere.elasticjob.cloud.util.json.GsonFactory;
import org.apache.shardingsphere.elasticjob.cloud.context.TaskContext;
import org.apache.shardingsphere.elasticjob.cloud.event.type.JobStatusTraceEvent;
import org.apache.shardingsphere.elasticjob.cloud.statistics.type.job.JobExecutionTypeStatistics;
import org.apache.shardingsphere.elasticjob.cloud.statistics.type.job.JobTypeStatistics;
import com.google.common.collect.Lists;
import org.hamcrest.core.Is;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.unitils.util.ReflectionUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@RunWith(MockitoJUnitRunner.class)
public final class CloudJobRestfulApiTest extends AbstractCloudRestfulApiTest {
@Test
public void assertRegister() throws Exception {
Mockito.when(getRegCenter().get("/config/app/test_app")).thenReturn(CloudAppJsonConstants.getAppJson("test_app"));
Mockito.when(getRegCenter().isExisted("/config/job/test_job")).thenReturn(false);
Assert.assertThat(RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/register", "POST", CloudJsonConstants.getJobJson()), Is.is(204));
Mockito.verify(getRegCenter()).persist("/config/job/test_job", CloudJsonConstants.getJobJson());
RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/deregister", "DELETE", "test_job");
}
@Test
public void assertRegisterWithoutApp() throws Exception {
Mockito.when(getRegCenter().isExisted("/config/job/test_job")).thenReturn(false);
Assert.assertThat(RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/register", "POST", CloudJsonConstants.getJobJson()), Is.is(500));
}
@Test
public void assertRegisterWithExistedName() throws Exception {
Mockito.when(getRegCenter().get("/config/app/test_app")).thenReturn(CloudAppJsonConstants.getAppJson("test_app"));
Mockito.when(getRegCenter().isExisted("/config/test_job")).thenReturn(false);
Assert.assertThat(RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/register", "POST", CloudJsonConstants.getJobJson()), Is.is(204));
Mockito.when(getRegCenter().get("/config/job/test_job")).thenReturn(CloudJsonConstants.getJobJson());
Assert.assertThat(RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/register", "POST", CloudJsonConstants.getJobJson()), Is.is(500));
RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/deregister", "DELETE", "test_job");
}
@Test
public void assertRegisterWithBadRequest() throws Exception {
Mockito.when(getRegCenter().get("/config/app/test_app")).thenReturn(CloudAppJsonConstants.getAppJson("test_app"));
Assert.assertThat(RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/register", "POST", "\"{\"jobName\":\"wrong_job\"}"), Is.is(500));
}
@Test
public void assertUpdate() throws Exception {
Mockito.when(getRegCenter().isExisted("/config/job/test_job")).thenReturn(true);
Mockito.when(getRegCenter().get("/config/job/test_job")).thenReturn(CloudJsonConstants.getJobJson());
Assert.assertThat(RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/update", "PUT", CloudJsonConstants.getJobJson()), Is.is(204));
Mockito.verify(getRegCenter()).update("/config/job/test_job", CloudJsonConstants.getJobJson());
RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/deregister", "DELETE", "test_job");
}
@Test
public void assertDeregister() throws Exception {
Mockito.when(getRegCenter().isExisted("/config/job/test_job")).thenReturn(false);
Assert.assertThat(RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/deregister", "DELETE", "test_job"), Is.is(204));
Mockito.verify(getRegCenter(), Mockito.times(3)).get("/config/job/test_job");
}
@Test
public void assertTriggerWithDaemonJob() throws Exception {
Mockito.when(getRegCenter().get("/config/job/test_job")).thenReturn(CloudJsonConstants.getJobJson(CloudJobExecutionType.DAEMON));
Assert.assertThat(RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/trigger", "POST", "test_job"), Is.is(500));
}
@Test
public void assertTriggerWithTransientJob() throws Exception {
Mockito.when(getRegCenter().get("/config/job/test_job")).thenReturn(CloudJsonConstants.getJobJson());
Assert.assertThat(RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/trigger", "POST", "test_job"), Is.is(204));
}
@Test
public void assertDetail() throws Exception {
Mockito.when(getRegCenter().get("/config/job/test_job")).thenReturn(CloudJsonConstants.getJobJson());
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/jobs/test_job"), Is.is(CloudJsonConstants.getJobJson()));
Mockito.verify(getRegCenter()).get("/config/job/test_job");
}
@Test
public void assertDetailWithNotExistedJob() throws Exception {
Assert.assertThat(RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/jobs/notExistedJobName", "GET", ""), Is.is(404));
}
@Test
public void assertFindAllJobs() throws Exception {
Mockito.when(getRegCenter().isExisted("/config/job")).thenReturn(true);
Mockito.when(getRegCenter().getChildrenKeys("/config/job")).thenReturn(Lists.newArrayList("test_job"));
Mockito.when(getRegCenter().get("/config/job/test_job")).thenReturn(CloudJsonConstants.getJobJson());
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/jobs"), Is.is("[" + CloudJsonConstants.getJobJson() + "]"));
Mockito.verify(getRegCenter()).isExisted("/config/job");
Mockito.verify(getRegCenter()).getChildrenKeys("/config/job");
Mockito.verify(getRegCenter()).get("/config/job/test_job");
}
@Test
public void assertFindAllRunningTasks() throws Exception {
RunningService runningService = new RunningService(getRegCenter());
TaskContext actualTaskContext = TaskContext.from(TaskNode.builder().build().getTaskNodeValue());
Mockito.when(getRegCenter().get("/config/job/" + actualTaskContext.getMetaInfo().getJobName())).thenReturn(CloudJsonConstants.getJobJson());
runningService.add(actualTaskContext);
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/tasks/running"), Is.is(GsonFactory.getGson().toJson(Lists.newArrayList(actualTaskContext))));
}
@Test
public void assertFindAllReadyTasks() throws Exception {
Mockito.when(getRegCenter().isExisted("/state/ready")).thenReturn(true);
Mockito.when(getRegCenter().getChildrenKeys("/state/ready")).thenReturn(Lists.newArrayList("test_job"));
Mockito.when(getRegCenter().get("/state/ready/test_job")).thenReturn("1");
Map<String, String> expectedMap = new HashMap<>();
expectedMap.put("jobName", "test_job");
expectedMap.put("times", "1");
@SuppressWarnings("unchecked")
Collection<Map<String, String>> expectedResult = Lists.newArrayList(expectedMap);
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/tasks/ready"), Is.is(GsonFactory.getGson().toJson(expectedResult)));
Mockito.verify(getRegCenter()).isExisted("/state/ready");
Mockito.verify(getRegCenter()).getChildrenKeys("/state/ready");
Mockito.verify(getRegCenter()).get("/state/ready/test_job");
}
@Test
public void assertFindAllFailoverTasks() throws Exception {
Mockito.when(getRegCenter().isExisted("/state/failover")).thenReturn(true);
Mockito.when(getRegCenter().getChildrenKeys("/state/failover")).thenReturn(Lists.newArrayList("test_job"));
Mockito.when(getRegCenter().getChildrenKeys("/state/failover/test_job")).thenReturn(Lists.newArrayList("test_job@-@0"));
String originalTaskId = UUID.randomUUID().toString();
Mockito.when(getRegCenter().get("/state/failover/test_job/test_job@-@0")).thenReturn(originalTaskId);
FailoverTaskInfo expectedFailoverTask = new FailoverTaskInfo(TaskContext.MetaInfo.from("test_job@-@0"), originalTaskId);
Collection<FailoverTaskInfo> expectedResult = Lists.newArrayList(expectedFailoverTask);
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/tasks/failover"), Is.is(GsonFactory.getGson().toJson(expectedResult)));
Mockito.verify(getRegCenter()).isExisted("/state/failover");
Mockito.verify(getRegCenter()).getChildrenKeys("/state/failover");
Mockito.verify(getRegCenter()).getChildrenKeys("/state/failover/test_job");
Mockito.verify(getRegCenter()).get("/state/failover/test_job/test_job@-@0");
}
@Test
public void assertFindJobExecutionEventsWhenNotConfigRDB() throws Exception {
ReflectionUtils.setFieldValue(CloudJobRestfulApi.class, CloudJobRestfulApi.class.getDeclaredField("jobEventRdbSearch"), null);
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/events/executions"), Is.is(GsonFactory.getGson().toJson(new JobEventRdbSearch.Result<>(0,
Collections.<JobExecutionEvent>emptyList()))));
}
@Test
public void assertFindJobExecutionEvents() throws Exception {
ReflectionUtils.setFieldValue(CloudJobRestfulApi.class, CloudJobRestfulApi.class.getDeclaredField("jobEventRdbSearch"), getJobEventRdbSearch());
JobExecutionEvent jobExecutionEvent = new JobExecutionEvent("fake_task_id", "test_job", JobExecutionEvent.ExecutionSource.NORMAL_TRIGGER, 0);
Mockito.when(getJobEventRdbSearch().findJobExecutionEvents(Mockito.any(JobEventRdbSearch.Condition.class))).thenReturn(new JobEventRdbSearch.Result<>(0,
Lists.newArrayList(jobExecutionEvent)));
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/events/executions?" + buildFindJobEventsQueryParameter()),
Is.is(GsonFactory.getGson().toJson(new JobEventRdbSearch.Result<>(0, Lists.newArrayList(jobExecutionEvent)))));
Mockito.verify(getJobEventRdbSearch()).findJobExecutionEvents(Mockito.any(JobEventRdbSearch.Condition.class));
}
@Test
public void assertFindJobStatusTraceEventEventsWhenNotConfigRDB() throws Exception {
ReflectionUtils.setFieldValue(CloudJobRestfulApi.class, CloudJobRestfulApi.class.getDeclaredField("jobEventRdbSearch"), null);
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/events/statusTraces"), Is.is(GsonFactory.getGson().toJson(new JobEventRdbSearch.Result<>(0,
Collections.<JobExecutionEvent>emptyList()))));
}
@Test
public void assertFindJobStatusTraceEvent() throws Exception {
ReflectionUtils.setFieldValue(CloudJobRestfulApi.class, CloudJobRestfulApi.class.getDeclaredField("jobEventRdbSearch"), getJobEventRdbSearch());
JobStatusTraceEvent jobStatusTraceEvent = new JobStatusTraceEvent(
"test-job", "fake_task_id", "fake_slave_id", JobStatusTraceEvent.Source.LITE_EXECUTOR, ExecutionType.READY, "0", JobStatusTraceEvent.State.TASK_RUNNING, "message is empty.");
Mockito.when(getJobEventRdbSearch().findJobStatusTraceEvents(Mockito.any(JobEventRdbSearch.Condition.class))).thenReturn(new JobEventRdbSearch.Result<>(0,
Lists.newArrayList(jobStatusTraceEvent)));
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/events/statusTraces?" + buildFindJobEventsQueryParameter()),
Is.is(GsonFactory.getGson().toJson(new JobEventRdbSearch.Result<>(0, Lists.newArrayList(jobStatusTraceEvent)))));
Mockito.verify(getJobEventRdbSearch()).findJobStatusTraceEvents(Mockito.any(JobEventRdbSearch.Condition.class));
}
private String buildFindJobEventsQueryParameter() throws UnsupportedEncodingException {
return "per_page=10&page=1&sort=jobName&order=DESC&jobName=test_job"
+ "&startTime=" + URLEncoder.encode("2016-12-26 10:00:00", "UTF-8") + "&endTime=" + URLEncoder.encode("2016-12-26 10:00:00", "UTF-8");
}
@Test
public void assertGetTaskResultStatistics() throws Exception {
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/statistics/tasks/results"),
Is.is(GsonFactory.getGson().toJson(Collections.emptyList())));
}
@Test
public void assertGetTaskResultStatisticsWithSinceParameter() throws Exception {
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/statistics/tasks/results?since=last24hours"),
Is.is(GsonFactory.getGson().toJson(Collections.emptyList())));
}
@Test
public void assertGetTaskResultStatisticsWithPathParameter() throws Exception {
String[] parameters = {"online", "lastWeek", "lastHour", "lastMinute"};
for (String each : parameters) {
String result = RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/statistics/tasks/results/" + each);
TaskResultStatistics taskResultStatistics = GsonFactory.getGson().fromJson(result, TaskResultStatistics.class);
Assert.assertThat(taskResultStatistics.getSuccessCount(), Is.is(0));
Assert.assertThat(taskResultStatistics.getFailedCount(), Is.is(0));
}
}
@Test
public void assertGetTaskResultStatisticsWithErrorPathParameter() throws Exception {
String result = RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/statistics/tasks/results/errorPath");
TaskResultStatistics taskResultStatistics = GsonFactory.getGson().fromJson(result, TaskResultStatistics.class);
Assert.assertThat(taskResultStatistics.getSuccessCount(), Is.is(0));
Assert.assertThat(taskResultStatistics.getFailedCount(), Is.is(0));
}
@Test
public void assertGetJobTypeStatistics() throws Exception {
String result = RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/statistics/jobs/type");
JobTypeStatistics jobTypeStatistics = GsonFactory.getGson().fromJson(result, JobTypeStatistics.class);
Assert.assertThat(jobTypeStatistics.getSimpleJobCount(), Is.is(0));
Assert.assertThat(jobTypeStatistics.getDataflowJobCount(), Is.is(0));
Assert.assertThat(jobTypeStatistics.getScriptJobCount(), Is.is(0));
}
@Test
public void assertGetJobExecutionTypeStatistics() throws Exception {
String result = RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/statistics/jobs/executionType");
JobExecutionTypeStatistics jobExecutionTypeStatistics = GsonFactory.getGson().fromJson(result, JobExecutionTypeStatistics.class);
Assert.assertThat(jobExecutionTypeStatistics.getDaemonJobCount(), Is.is(0));
Assert.assertThat(jobExecutionTypeStatistics.getTransientJobCount(), Is.is(0));
}
@Test
public void assertFindTaskRunningStatistics() throws Exception {
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/statistics/tasks/running"),
Is.is(GsonFactory.getGson().toJson(Collections.emptyList())));
}
@Test
public void assertFindTaskRunningStatisticsWeekly() throws Exception {
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/statistics/tasks/running?since=lastWeek"),
Is.is(GsonFactory.getGson().toJson(Collections.emptyList())));
}
@Test
public void assertFindJobRunningStatistics() throws Exception {
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/statistics/jobs/running"),
Is.is(GsonFactory.getGson().toJson(Collections.emptyList())));
}
@Test
public void assertFindJobRunningStatisticsWeekly() throws Exception {
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/statistics/jobs/running?since=lastWeek"),
Is.is(GsonFactory.getGson().toJson(Collections.emptyList())));
}
@Test
public void assertFindJobRegisterStatisticsSinceOnline() throws Exception {
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/statistics/jobs/register"),
Is.is(GsonFactory.getGson().toJson(Collections.emptyList())));
}
@Test
public void assertIsDisabled() throws Exception {
Mockito.when(getRegCenter().isExisted("/state/disable/job/test_job")).thenReturn(true);
Assert.assertThat(RestfulTestsUtil.sentGetRequest("http://127.0.0.1:19000/api/job/test_job/disable"), Is.is("true"));
}
@Test
public void assertDisable() throws Exception {
Mockito.when(getRegCenter().isExisted("/config/job")).thenReturn(true);
Mockito.when(getRegCenter().getChildrenKeys("/config/job")).thenReturn(Lists.newArrayList("test_job"));
Mockito.when(getRegCenter().get("/config/app/test_app")).thenReturn(CloudAppJsonConstants.getAppJson("test_app"));
Mockito.when(getRegCenter().get("/config/job/test_job")).thenReturn(CloudJsonConstants.getJobJson());
Assert.assertThat(RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/test_job/disable", "POST"), Is.is(204));
Mockito.verify(getRegCenter()).persist("/state/disable/job/test_job", "test_job");
}
@Test
public void assertEnable() throws Exception {
Mockito.when(getRegCenter().isExisted("/config/job")).thenReturn(true);
Mockito.when(getRegCenter().getChildrenKeys("/config/job")).thenReturn(Lists.newArrayList("test_job"));
Mockito.when(getRegCenter().get("/config/app/test_app")).thenReturn(CloudAppJsonConstants.getAppJson("test_app"));
Mockito.when(getRegCenter().get("/config/job/test_job")).thenReturn(CloudJsonConstants.getJobJson());
Assert.assertThat(RestfulTestsUtil.sentRequest("http://127.0.0.1:19000/api/job/test_job/disable", "DELETE", "test_job"), Is.is(204));
Mockito.verify(getRegCenter()).remove("/state/disable/job/test_job");
}
}