Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Add Scheduler Acceptance Tests #186

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dataflow-rest-client</artifactId>
<version>1.2.1.BUILD-SNAPSHOT</version>
<version>1.7.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dataflow-core</artifactId>
<version>1.2.1.BUILD-SNAPSHOT</version>
<version>1.7.0.BUILD-SNAPSHOT</version>
</dependency>
</dependencies>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,17 @@
import org.springframework.cloud.dataflow.acceptance.test.util.TestConfigurationProperties;
import org.springframework.cloud.dataflow.rest.client.AppRegistryOperations;
import org.springframework.cloud.dataflow.rest.client.DataFlowTemplate;
import org.springframework.cloud.dataflow.rest.client.SchedulerOperations;
import org.springframework.cloud.dataflow.rest.client.TaskOperations;
import org.springframework.cloud.dataflow.rest.resource.ScheduleInfoResource;
import org.springframework.cloud.dataflow.rest.resource.TaskDefinitionResource;
import org.springframework.cloud.dataflow.rest.resource.TaskExecutionResource;
import org.springframework.hateoas.PagedResources;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Abstract base class that is used by task acceptance tests. This class contains commonly
* used utility methods for task acceptance tests as well as the ability to retrieve
Expand All @@ -58,6 +62,8 @@
@EnableConfigurationProperties(TestConfigurationProperties.class)
public abstract class AbstractTaskTests implements InitializingBean {

protected static final String DEFAULT_CRON_EXPRESSION_KEY = "spring.cloud.scheduler.cron.expression";

private static final Logger logger = LoggerFactory.getLogger(AbstractTaskTests.class);

private static boolean tasksRegistered = false;
Expand All @@ -69,6 +75,8 @@ public abstract class AbstractTaskTests implements InitializingBean {

protected TaskOperations taskOperations;

protected SchedulerOperations schedulerOperations;

protected AppRegistryOperations appRegistryOperations;

@Autowired
Expand Down Expand Up @@ -123,6 +131,18 @@ protected String taskLaunch(String definition,
return taskDefinitionName;
}

/**
* Creates a unique task definition name from a UUID.
*
* @param definition The definition to test.
* @return The name of the task associated with this launch.
*/
protected String taskCreate(String definition) {
String taskDefinitionName = "task-" + UUID.randomUUID().toString();
taskOperations.create(taskDefinitionName, definition);
return taskDefinitionName;
}

/**
* Launch an existing task definition.
*/
Expand Down Expand Up @@ -162,6 +182,7 @@ public void afterPropertiesSet() {
DataFlowTemplate dataFlowOperationsTemplate = new DataFlowTemplate(
new URI(configurationProperties.getServerUri()));
taskOperations = dataFlowOperationsTemplate.taskOperations();
schedulerOperations = dataFlowOperationsTemplate.schedulerOperations();
appRegistryOperations = dataFlowOperationsTemplate.appRegistryOperations();
}
catch (URISyntaxException uriException) {
Expand Down Expand Up @@ -226,6 +247,75 @@ protected List<TaskExecutionResource> getTaskExecutionResource(
return result;
}

/**
* Creates a unique schedule name from a UUID from an existing task definition.
*
* @param taskDefinitionName The definition to test.
* @param properties Map containing deployment properties for the task.
* @param arguments List containing the arguments used to execute the task.
* @return The name of the schedule.
*/
protected String schedule(String taskDefinitionName,
Map<String, String> properties, List<String> arguments) {
String scheduleName = "schedule-" + UUID.randomUUID().toString();
this.schedulerOperations.schedule(scheduleName, taskDefinitionName, properties, arguments);
return scheduleName;
}

/**
* Verifies that the scheduleName specified exists in the schedule list results.
* @param scheduleName the name of the schedule to search.
* @return true if found else false;
*/

protected boolean verifyScheduleExists(String scheduleName) {
boolean result = false;
for(ScheduleInfoResource resource : this.schedulerOperations.list()) {
if(resource.getScheduleName().equals(scheduleName)){
result = true;
break;
}
}
return result;
}

/**
* Asserts that the {@link ScheduleInfoResource} contains the expected data.
* @param scheduleInfoResource the {@link ScheduleInfoResource} that needs to be interrogated.
* @param scheduleName The expected name of the schedule.
* @param cronExpression The expected expression.
*/
protected void verifyScheduleIsValid(ScheduleInfoResource scheduleInfoResource, String scheduleName, String cronExpression) {
assertThat(scheduleInfoResource.getScheduleName()).isEqualTo(scheduleName);
assertThat(scheduleInfoResource.getScheduleProperties().containsKey(DEFAULT_CRON_EXPRESSION_KEY)).isTrue();
assertThat(scheduleInfoResource.getScheduleProperties().get(DEFAULT_CRON_EXPRESSION_KEY)).isEqualTo(cronExpression);
}

/**
* Retrieves a {@link PagedResources} of the existing schedules.
*/
protected PagedResources<ScheduleInfoResource> listSchedules() {
return this.schedulerOperations.list();
}

/**
* Retrieves a {@link PagedResources} of the existing {@link ScheduleInfoResource}s that are
* associated with the task definition name.
* @param taskDefinitionName The name of the task definition that the schedules should be associated.
*/
protected PagedResources<ScheduleInfoResource> listSchedules(String taskDefinitionName) {
return this.schedulerOperations.list(taskDefinitionName);
}

/**
* Deletes an existing schedule based on the schedule name.
*
* @param scheduleName the name of the schedule instance to be unscheduled.
*/
protected void unschedule(String scheduleName) {
this.schedulerOperations.unschedule(scheduleName);
}

public enum TaskTestTypes {
TIMESTAMP,
CORE
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright 2018 the original author or authors.
*
* 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 org.springframework.cloud.dataflow.acceptance.test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.junit.ClassRule;
import org.junit.Test;

import org.springframework.cloud.dataflow.acceptance.test.util.SchedulerRule;
import org.springframework.cloud.dataflow.rest.resource.ScheduleInfoResource;
import org.springframework.hateoas.PagedResources;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;

public class SchedulerTests extends AbstractTaskTests {

private final static String DEFAULT_SCDF_EXPRESSION_KEY = "scheduler.cron.expression";

private final static String DEFAULT_CRON_EXPRESSION = "56 20 ? * *";

@ClassRule
public static SchedulerRule cfAvailable = new SchedulerRule();

@Test
public void listTest() {
final int ENTRY_COUNT = 2;
Set<String> scheduleSet = new HashSet(2);
for(int i = 0; i < ENTRY_COUNT; i++) {
scheduleSet.add(createDefaultSchedule());
}
PagedResources<ScheduleInfoResource> pagedResources = listSchedules();
assertThat(pagedResources.getMetadata().getSize()).isEqualTo(ENTRY_COUNT);
Iterator<ScheduleInfoResource> iterator = pagedResources.getContent().iterator();
for(int i = 0; i < ENTRY_COUNT; i++) {
ScheduleInfoResource resource = iterator.next();
if(scheduleSet.contains(resource.getScheduleName())) {
assertThat(resource.getScheduleProperties().get(DEFAULT_CRON_EXPRESSION_KEY)).isEqualTo(DEFAULT_CRON_EXPRESSION);
} else {
fail(String.format("%s schedule is missing from result set of list."));
}
}
}

@Test
public void scheduleTest() {
assertThat(verifyScheduleExists(createDefaultSchedule())).isTrue();
}

@Test
public void deleteTest() {
String scheduleName = createDefaultSchedule();
assertThat(verifyScheduleExists(scheduleName)).isTrue();
unschedule(scheduleName);
assertThat(verifyScheduleExists(scheduleName)).isFalse();
}

@Test
public void filterByTaskDefNameTest() {
final int ENTRY_COUNT = 2;
String[] taskNames = new String[ENTRY_COUNT];
String[] scheduleNames = new String[ENTRY_COUNT];
for(int i = 0; i < ENTRY_COUNT; i++) {
taskNames[i] = taskCreate("timestamp");
scheduleNames[i] = createDefaultSchedule(taskNames[i]);
}
for(int i = 0; i < ENTRY_COUNT; i++) {
PagedResources<ScheduleInfoResource> pagedResources = listSchedules(taskNames[i]);
assertThat(pagedResources.getMetadata().getSize()).isEqualTo(1);
verifyScheduleIsValid(pagedResources.getContent().iterator().next(), scheduleNames[i], DEFAULT_CRON_EXPRESSION);
}
}

@Test
public void getScheduleTest() {
String scheduleName = createDefaultSchedule();
ScheduleInfoResource scheduleInfoResource = schedulerOperations.getSchedule(scheduleName);
verifyScheduleIsValid(scheduleInfoResource, scheduleName, DEFAULT_CRON_EXPRESSION);
}

private String createDefaultSchedule() {
return createDefaultSchedule(taskCreate("timestamp"));
}

private String createDefaultSchedule(String taskName) {
Map<String,String> taskProperties = new HashMap<>(1);
taskProperties.put(DEFAULT_SCDF_EXPRESSION_KEY, DEFAULT_CRON_EXPRESSION);
List<String> taskArgs = new ArrayList<>();
return schedule(taskName, taskProperties, taskArgs);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright 2018 the original author or authors.
*
* 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 org.springframework.cloud.dataflow.acceptance.test.util;

import java.net.URI;
import java.net.URISyntaxException;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.dataflow.rest.client.DataFlowTemplate;
import org.springframework.cloud.dataflow.rest.client.SchedulerOperations;
import org.springframework.cloud.scheduler.spi.junit.AbstractExternalResourceTestSupport;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;

/**
* Verifies that the Spring Cloud Data Flow Scheduler is available.
*
* @author Glenn Renfro
*/
public class SchedulerRule extends AbstractExternalResourceTestSupport<DataFlowTemplate> {

private ConfigurableApplicationContext context;

public SchedulerRule() {
super("SCHEDULER");
}

@Override
protected void cleanupResource() throws Exception {
context.close();
}

@Override
protected void obtainResource() throws Exception {
context = new SpringApplicationBuilder(Config.class).web(false).run();
resource = context.getBean(DataFlowTemplate.class);

SchedulerOperations schedulerOperations = resource.schedulerOperations();
Assert.notNull(schedulerOperations, "no SchedulerOperations bean is available. Skipping test.");
}

@Configuration
@EnableConfigurationProperties
public static class Config {

@Bean
@ConfigurationProperties
public TestConfigurationProperties cloudFoundryConnectionProperties() {
return new TestConfigurationProperties();
}

@Bean
public DataFlowTemplate dataFlowTemplate(TestConfigurationProperties configurationProperties) {
DataFlowTemplate dataFlowOperationsTemplate = null;
try {
dataFlowOperationsTemplate = new DataFlowTemplate(
new URI(configurationProperties.getServerUri()));
}
catch (URISyntaxException uriException) {
throw new IllegalStateException(uriException);
}
return dataFlowOperationsTemplate;
}

}
}