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

Commit b29d4c6

Browse files
committed
Add Scheduler Acceptance Tests
2 Notes: * Tests should skip on current AT's. Because scheduling is disabled. * Merge only after spring-attic/spring-cloud-dataflow#2342 has been merged. resolves #124
1 parent 057e838 commit b29d4c6

File tree

4 files changed

+289
-2
lines changed

4 files changed

+289
-2
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@
5151
<dependency>
5252
<groupId>org.springframework.cloud</groupId>
5353
<artifactId>spring-cloud-dataflow-rest-client</artifactId>
54-
<version>1.2.1.BUILD-SNAPSHOT</version>
54+
<version>1.6.1.BUILD-SNAPSHOT</version>
5555
</dependency>
5656
<dependency>
5757
<groupId>org.springframework.cloud</groupId>
5858
<artifactId>spring-cloud-dataflow-core</artifactId>
59-
<version>1.2.1.BUILD-SNAPSHOT</version>
59+
<version>1.6.1.BUILD-SNAPSHOT</version>
6060
</dependency>
6161
</dependencies>
6262

src/test/java/org/springframework/cloud/dataflow/acceptance/test/AbstractTaskTests.java

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,17 @@
3939
import org.springframework.cloud.dataflow.acceptance.test.util.TestConfigurationProperties;
4040
import org.springframework.cloud.dataflow.rest.client.AppRegistryOperations;
4141
import org.springframework.cloud.dataflow.rest.client.DataFlowTemplate;
42+
import org.springframework.cloud.dataflow.rest.client.SchedulerOperations;
4243
import org.springframework.cloud.dataflow.rest.client.TaskOperations;
44+
import org.springframework.cloud.dataflow.rest.resource.ScheduleInfoResource;
4345
import org.springframework.cloud.dataflow.rest.resource.TaskDefinitionResource;
4446
import org.springframework.cloud.dataflow.rest.resource.TaskExecutionResource;
4547
import org.springframework.hateoas.PagedResources;
4648
import org.springframework.test.context.junit4.SpringRunner;
4749
import org.springframework.web.client.RestTemplate;
4850

51+
import static org.assertj.core.api.Assertions.assertThat;
52+
4953
/**
5054
* Abstract base class that is used by task acceptance tests. This class contains commonly
5155
* used utility methods for task acceptance tests as well as the ability to retrieve
@@ -58,6 +62,8 @@
5862
@EnableConfigurationProperties(TestConfigurationProperties.class)
5963
public abstract class AbstractTaskTests implements InitializingBean {
6064

65+
protected static final String DEFAULT_CRON_EXPRESSION_KEY = "spring.cloud.scheduler.cron.expression";
66+
6167
private static final Logger logger = LoggerFactory.getLogger(AbstractTaskTests.class);
6268

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

7076
protected TaskOperations taskOperations;
7177

78+
protected SchedulerOperations schedulerOperations;
79+
7280
protected AppRegistryOperations appRegistryOperations;
7381

7482
@Autowired
@@ -123,6 +131,18 @@ protected String taskLaunch(String definition,
123131
return taskDefinitionName;
124132
}
125133

134+
/**
135+
* Creates a unique task definition name from a UUID.
136+
*
137+
* @param definition The definition to test.
138+
* @return The name of the task associated with this launch.
139+
*/
140+
protected String taskCreate(String definition) {
141+
String taskDefinitionName = "task-" + UUID.randomUUID().toString();
142+
taskOperations.create(taskDefinitionName, definition);
143+
return taskDefinitionName;
144+
}
145+
126146
/**
127147
* Launch an existing task definition.
128148
*/
@@ -162,6 +182,7 @@ public void afterPropertiesSet() {
162182
DataFlowTemplate dataFlowOperationsTemplate = new DataFlowTemplate(
163183
new URI(configurationProperties.getServerUri()));
164184
taskOperations = dataFlowOperationsTemplate.taskOperations();
185+
schedulerOperations = dataFlowOperationsTemplate.schedulerOperations();
165186
appRegistryOperations = dataFlowOperationsTemplate.appRegistryOperations();
166187
}
167188
catch (URISyntaxException uriException) {
@@ -226,6 +247,75 @@ protected List<TaskExecutionResource> getTaskExecutionResource(
226247
return result;
227248
}
228249

250+
/**
251+
* Creates a unique schedule name from a UUID from an existing task definition.
252+
*
253+
* @param taskDefinitionName The definition to test.
254+
* @param properties Map containing deployment properties for the task.
255+
* @param arguments List containing the arguments used to execute the task.
256+
* @return The name of the schedule.
257+
*/
258+
protected String schedule(String taskDefinitionName,
259+
Map<String, String> properties, List<String> arguments) {
260+
String scheduleName = "schedule-" + UUID.randomUUID().toString();
261+
this.schedulerOperations.schedule(scheduleName, taskDefinitionName, properties, arguments);
262+
return scheduleName;
263+
}
264+
265+
/**
266+
* Verifies that the scheduleName specified exists in the schedule list results.
267+
* @param scheduleName the name of the schedule to search.
268+
* @return true if found else false;
269+
*/
270+
271+
protected boolean verifyScheduleExists(String scheduleName) {
272+
boolean result = false;
273+
for(ScheduleInfoResource resource : this.schedulerOperations.list()) {
274+
if(resource.getScheduleName().equals(scheduleName)){
275+
result = true;
276+
break;
277+
}
278+
}
279+
return result;
280+
}
281+
282+
/**
283+
* Asserts that the {@link ScheduleInfoResource} contains the expected data.
284+
* @param scheduleInfoResource the {@link ScheduleInfoResource} that needs to be interrogated.
285+
* @param scheduleName The expected name of the schedule.
286+
* @param cronExpression The expected expression.
287+
*/
288+
protected void verifyScheduleIsValid(ScheduleInfoResource scheduleInfoResource, String scheduleName, String cronExpression) {
289+
assertThat(scheduleInfoResource.getScheduleName()).isEqualTo(scheduleName);
290+
assertThat(scheduleInfoResource.getScheduleProperties().containsKey(DEFAULT_CRON_EXPRESSION_KEY)).isTrue();
291+
assertThat(scheduleInfoResource.getScheduleProperties().get(DEFAULT_CRON_EXPRESSION_KEY)).isEqualTo(cronExpression);
292+
}
293+
294+
/**
295+
* Retrieves a {@link PagedResources} of the existing schedules.
296+
*/
297+
protected PagedResources<ScheduleInfoResource> listSchedules() {
298+
return this.schedulerOperations.list();
299+
}
300+
301+
/**
302+
* Retrieves a {@link PagedResources} of the existing {@link ScheduleInfoResource}s that are
303+
* associated with the task definition name.
304+
* @param taskDefinitionName The name of the task definition that the schedules should be associated.
305+
*/
306+
protected PagedResources<ScheduleInfoResource> listSchedules(String taskDefinitionName) {
307+
return this.schedulerOperations.list(taskDefinitionName);
308+
}
309+
310+
/**
311+
* Deletes an existing schedule based on the schedule name.
312+
*
313+
* @param scheduleName the name of the schedule instance to be unscheduled.
314+
*/
315+
protected void unschedule(String scheduleName) {
316+
this.schedulerOperations.unschedule(scheduleName);
317+
}
318+
229319
public enum TaskTestTypes {
230320
TIMESTAMP,
231321
CORE
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Copyright 2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.dataflow.acceptance.test;
18+
19+
import java.util.ArrayList;
20+
import java.util.HashMap;
21+
import java.util.HashSet;
22+
import java.util.Iterator;
23+
import java.util.List;
24+
import java.util.Map;
25+
import java.util.Set;
26+
27+
import org.junit.ClassRule;
28+
import org.junit.Test;
29+
30+
import org.springframework.cloud.dataflow.acceptance.test.util.SchedulerRule;
31+
import org.springframework.cloud.dataflow.rest.resource.ScheduleInfoResource;
32+
import org.springframework.hateoas.PagedResources;
33+
34+
import static org.assertj.core.api.Assertions.assertThat;
35+
import static org.assertj.core.api.Assertions.fail;
36+
37+
public class SchedulerTests extends AbstractTaskTests {
38+
39+
private final static String DEFAULT_SCDF_EXPRESSION_KEY = "scheduler.cron.expression";
40+
41+
private final static String DEFAULT_CRON_EXPRESSION = "56 20 ? * *";
42+
43+
@ClassRule
44+
public static SchedulerRule cfAvailable = new SchedulerRule();
45+
46+
@Test
47+
public void listTest() {
48+
final int ENTRY_COUNT = 2;
49+
Set<String> scheduleSet = new HashSet(2);
50+
for(int i = 0; i < ENTRY_COUNT; i++) {
51+
scheduleSet.add(createDefaultSchedule());
52+
}
53+
PagedResources<ScheduleInfoResource> pagedResources = listSchedules();
54+
assertThat(pagedResources.getMetadata().getSize()).isEqualTo(ENTRY_COUNT);
55+
Iterator<ScheduleInfoResource> iterator = pagedResources.getContent().iterator();
56+
for(int i = 0; i < ENTRY_COUNT; i++) {
57+
ScheduleInfoResource resource = iterator.next();
58+
if(scheduleSet.contains(resource.getScheduleName())) {
59+
assertThat(resource.getScheduleProperties().get(DEFAULT_CRON_EXPRESSION_KEY)).isEqualTo(DEFAULT_CRON_EXPRESSION);
60+
} else {
61+
fail(String.format("%s schedule is missing from result set of list."));
62+
}
63+
}
64+
}
65+
66+
@Test
67+
public void scheduleTest() {
68+
assertThat(verifyScheduleExists(createDefaultSchedule())).isTrue();
69+
}
70+
71+
@Test
72+
public void deleteTest() {
73+
String scheduleName = createDefaultSchedule();
74+
assertThat(verifyScheduleExists(scheduleName)).isTrue();
75+
unschedule(scheduleName);
76+
assertThat(verifyScheduleExists(scheduleName)).isFalse();
77+
}
78+
79+
@Test
80+
public void filterByTaskDefNameTest() {
81+
final int ENTRY_COUNT = 2;
82+
String[] taskNames = new String[ENTRY_COUNT];
83+
String[] scheduleNames = new String[ENTRY_COUNT];
84+
for(int i = 0; i < ENTRY_COUNT; i++) {
85+
taskNames[i] = taskCreate("timestamp");
86+
scheduleNames[i] = createDefaultSchedule(taskNames[i]);
87+
}
88+
for(int i = 0; i < ENTRY_COUNT; i++) {
89+
PagedResources<ScheduleInfoResource> pagedResources = listSchedules(taskNames[i]);
90+
assertThat(pagedResources.getMetadata().getSize()).isEqualTo(1);
91+
verifyScheduleIsValid(pagedResources.getContent().iterator().next(), scheduleNames[i], DEFAULT_CRON_EXPRESSION);
92+
}
93+
}
94+
95+
@Test
96+
public void getScheduleTest() {
97+
String scheduleName = createDefaultSchedule();
98+
ScheduleInfoResource scheduleInfoResource = schedulerOperations.getSchedule(scheduleName);
99+
verifyScheduleIsValid(scheduleInfoResource, scheduleName, DEFAULT_CRON_EXPRESSION);
100+
}
101+
102+
private String createDefaultSchedule() {
103+
return createDefaultSchedule(taskCreate("timestamp"));
104+
}
105+
106+
private String createDefaultSchedule(String taskName) {
107+
Map<String,String> taskProperties = new HashMap<>(1);
108+
taskProperties.put(DEFAULT_SCDF_EXPRESSION_KEY, DEFAULT_CRON_EXPRESSION);
109+
List<String> taskArgs = new ArrayList<>();
110+
return schedule(taskName, taskProperties, taskArgs);
111+
}
112+
113+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright 2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.dataflow.acceptance.test.util;
18+
19+
import java.net.URI;
20+
import java.net.URISyntaxException;
21+
22+
import org.springframework.boot.builder.SpringApplicationBuilder;
23+
import org.springframework.boot.context.properties.ConfigurationProperties;
24+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
25+
import org.springframework.cloud.dataflow.rest.client.DataFlowTemplate;
26+
import org.springframework.cloud.dataflow.rest.client.SchedulerOperations;
27+
import org.springframework.cloud.scheduler.spi.junit.AbstractExternalResourceTestSupport;
28+
import org.springframework.context.ConfigurableApplicationContext;
29+
import org.springframework.context.annotation.Bean;
30+
import org.springframework.context.annotation.Configuration;
31+
import org.springframework.util.Assert;
32+
33+
/**
34+
* Verifies that the Spring Cloud Data Flow Scheduler is available.
35+
*
36+
* @author Glenn Renfro
37+
*/
38+
public class SchedulerRule extends AbstractExternalResourceTestSupport<DataFlowTemplate> {
39+
40+
private ConfigurableApplicationContext context;
41+
42+
public SchedulerRule() {
43+
super("SCHEDULER");
44+
}
45+
46+
@Override
47+
protected void cleanupResource() throws Exception {
48+
context.close();
49+
}
50+
51+
@Override
52+
protected void obtainResource() throws Exception {
53+
context = new SpringApplicationBuilder(Config.class).web(false).run();
54+
resource = context.getBean(DataFlowTemplate.class);
55+
56+
SchedulerOperations schedulerOperations = resource.schedulerOperations();
57+
Assert.notNull(schedulerOperations, "no SchedulerOperations bean is available. Skipping test.");
58+
}
59+
60+
@Configuration
61+
@EnableConfigurationProperties
62+
public static class Config {
63+
64+
@Bean
65+
@ConfigurationProperties
66+
public TestConfigurationProperties cloudFoundryConnectionProperties() {
67+
return new TestConfigurationProperties();
68+
}
69+
70+
@Bean
71+
public DataFlowTemplate dataFlowTemplate(TestConfigurationProperties configurationProperties) {
72+
DataFlowTemplate dataFlowOperationsTemplate = null;
73+
try {
74+
dataFlowOperationsTemplate = new DataFlowTemplate(
75+
new URI(configurationProperties.getServerUri()));
76+
}
77+
catch (URISyntaxException uriException) {
78+
throw new IllegalStateException(uriException);
79+
}
80+
return dataFlowOperationsTemplate;
81+
}
82+
83+
}
84+
}

0 commit comments

Comments
 (0)