SCT-6 Support RDBMS & Map Repositories

* `DefaultTaskConfigurer` returns only one `SimpleTaskRepository` all others have been removed
* `SimpleTaskRepository` can use `JdbcTaskExecutionDao` or a `MapTaskExecutionDao`
* Add `Jdbc` and Map` `TaskRepositoryFactoryBeans` to support the creation of the correct type of `SimpleTaskRepository`
* `TaskDatabaseInitializer` will initialize a database if a datasource is found and if they have not disabled it using the `spring.task.initialize.enable`
* Add tests
* Added Transaction Support
* Re-add the samples to `pom.xml`
* Samples pom skips install and deploy lifecycle targets.
This commit is contained in:
Glenn Renfro
2015-12-01 17:45:57 -05:00
committed by Gunnar Hillert
parent 96fab303ae
commit a9f882f24b
36 changed files with 1738 additions and 153 deletions

View File

@@ -22,10 +22,12 @@ import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.aop.framework.Advised;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.cloud.task.configuration.SimpleTaskConfiguration;
import org.springframework.cloud.task.repository.support.LoggerTaskRepository;
import org.springframework.cloud.task.repository.TaskRepository;
import org.springframework.cloud.task.repository.support.SimpleTaskRepository;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -35,16 +37,17 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
* @author Glenn Renfro
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SimpleTaskConfiguration.class)
@ContextConfiguration(classes = {SimpleTaskConfiguration.class, PropertyPlaceholderAutoConfiguration.class})
public class SimpleTaskConfigurationTests {
@Autowired
private TaskRepository taskRepository;
@Test
public void testRepository() {
public void testRepository() throws Exception {
assertNotNull("testRepository should not be null", taskRepository);
assertThat(taskRepository, instanceOf(LoggerTaskRepository.class));
TaskRepository clazz = (TaskRepository) ((Advised)taskRepository).getTargetSource().getTarget();
assertThat(clazz, instanceOf(SimpleTaskRepository.class));
}
}

View File

@@ -23,10 +23,11 @@ import org.aspectj.lang.JoinPoint;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.cloud.task.configuration.TaskHandler;
import org.springframework.cloud.task.repository.TaskExecution;
import org.springframework.cloud.task.util.LoggerTestUtils;
import org.springframework.cloud.task.util.TestDefaultConfiguration;
import org.springframework.cloud.task.util.TestVerifierUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -37,7 +38,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
* @author Glenn Renfro
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestDefaultConfiguration.class)
@ContextConfiguration(classes = {TestDefaultConfiguration.class, PropertyPlaceholderAutoConfiguration.class})
public class TaskHandlerDefaultTests {
@Autowired
@@ -49,9 +50,9 @@ public class TaskHandlerDefaultTests {
@Test
public void testTaskException() {
taskHandler.beforeCommandLineRunner(joinPoint);
final Appender mockAppender = LoggerTestUtils.getMockAppender();
final Appender mockAppender = TestVerifierUtils.getMockAppender();
taskHandler.logExceptionCommandLineRunner(joinPoint);
LoggerTestUtils.verifyLogEntryExists(mockAppender,
TestVerifierUtils.verifyLogEntryExists(mockAppender,
"Updating: TaskExecution{executionId='" +
taskHandler.getTaskExecution().getExecutionId());
TaskExecution taskExecution = taskHandler.getTaskExecution();
@@ -61,9 +62,9 @@ public class TaskHandlerDefaultTests {
@Test
public void testTaskCreate() {
final Appender mockAppender = LoggerTestUtils.getMockAppender();
final Appender mockAppender = TestVerifierUtils.getMockAppender();
taskHandler.beforeCommandLineRunner(joinPoint);
LoggerTestUtils.verifyLogEntryExists(mockAppender,
TestVerifierUtils.verifyLogEntryExists(mockAppender,
"Creating: TaskExecution{executionId='" +
taskHandler.getTaskExecution().getExecutionId());
assertEquals("Create should report that exit code is zero",
@@ -74,9 +75,9 @@ public class TaskHandlerDefaultTests {
@Test
public void testTaskUpdate() {
taskHandler.beforeCommandLineRunner(joinPoint);
final Appender mockAppender = LoggerTestUtils.getMockAppender();
final Appender mockAppender = TestVerifierUtils.getMockAppender();
taskHandler.afterReturnCommandLineRunner(joinPoint);
LoggerTestUtils.verifyLogEntryExists(mockAppender,
TestVerifierUtils.verifyLogEntryExists(mockAppender,
"Updating: TaskExecution{executionId='" +
taskHandler.getTaskExecution().getExecutionId());
assertEquals("Update should report that exit code is zero",

View File

@@ -0,0 +1,101 @@
/*
* Copyright 2015 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.task.repository.dao;
import javax.sql.DataSource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.cloud.task.annotation.EnableTask;
import org.springframework.cloud.task.repository.TaskExecution;
import org.springframework.cloud.task.util.TestDBUtils;
import org.springframework.cloud.task.util.TestVerifierUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.dao.DuplicateKeyException;
/**
* Executes unit tests on JdbcTaskExecutionDao.
*
* @author Glenn Renfro
*/
public class JdbcTaskExecutionDaoTests {
private DataSource dataSource;
private AnnotationConfigApplicationContext context;
@Before
public void setup() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(TestConfiguration.class,
EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
dataSource = this.context.getBean(DataSource.class);
}
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void saveTaskExecution() {
JdbcTaskExecutionDao dao = new JdbcTaskExecutionDao(dataSource);
TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
dao.saveTaskExecution(expectedTaskExecution);
TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
TestDBUtils.getTaskExecutionFromDB(dataSource, expectedTaskExecution.getExecutionId()));
}
@Test(expected = DuplicateKeyException.class)
public void duplicateSaveTaskExecution() {
JdbcTaskExecutionDao dao = new JdbcTaskExecutionDao(dataSource);
TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
dao.saveTaskExecution(expectedTaskExecution);
dao.saveTaskExecution(expectedTaskExecution);
}
@Test
public void updateTaskExecution() {
JdbcTaskExecutionDao dao = new JdbcTaskExecutionDao(dataSource);
TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
dao.saveTaskExecution(expectedTaskExecution);
dao.updateTaskExecution(expectedTaskExecution);
TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
TestDBUtils.getTaskExecutionFromDB(dataSource, expectedTaskExecution.getExecutionId()));
}
@Test(expected = IllegalStateException.class)
public void updateTaskExecutionWithNoCreate() {
JdbcTaskExecutionDao dao = new JdbcTaskExecutionDao(dataSource);
TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
dao.updateTaskExecution(expectedTaskExecution);
}
@EnableTask
protected static class TestConfiguration {
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2015 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.task.repository.dao;
import static org.junit.Assert.assertNotNull;
import java.util.Map;
import org.junit.Test;
import org.springframework.cloud.task.repository.TaskExecution;
import org.springframework.cloud.task.util.TestVerifierUtils;
/**
* Executes unit tests on MapTaskExecutionDaoTests.
* @author Glenn Renfro
*/
public class MapTaskExecutionDaoTests {
@Test
public void saveTaskExecution(){
MapTaskExecutionDao dao = new MapTaskExecutionDao();
TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
dao.saveTaskExecution(expectedTaskExecution);
Map<String, TaskExecution> taskExecutionMap = dao.getTaskExecutions();
assertNotNull("taskExecutionMap must not be null", taskExecutionMap);
TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
taskExecutionMap.get(expectedTaskExecution.getExecutionId()));
}
@Test
public void updateTaskExecution(){
MapTaskExecutionDao dao = new MapTaskExecutionDao();
TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
dao.saveTaskExecution(expectedTaskExecution);
dao.updateTaskExecution(expectedTaskExecution);
Map<String, TaskExecution> taskExecutionMap = dao.getTaskExecutions();
assertNotNull("taskExecutionMap must not be null", taskExecutionMap);
TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
taskExecutionMap.get(expectedTaskExecution.getExecutionId()));
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2015 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.task.repository.support;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.cloud.task.repository.support.DatabaseType.HSQL;
import static org.springframework.cloud.task.repository.support.DatabaseType.ORACLE;
import static org.springframework.cloud.task.repository.support.DatabaseType.POSTGRES;
import static org.springframework.cloud.task.repository.support.DatabaseType.fromProductName;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import javax.sql.DataSource;
import org.junit.Test;
/**
* Tests that the correct database names are selected from datasource metadata.
*
* @author Lucas Ward
* @author Will Schipp
* @author Glenn Renfro
*
*/
public class DatabaseTypeTests {
@Test
public void testFromProductName() {
assertEquals(HSQL, fromProductName("HSQL Database Engine"));
assertEquals(ORACLE, fromProductName("Oracle"));
assertEquals(POSTGRES, fromProductName("PostgreSQL"));
}
@Test(expected = IllegalArgumentException.class)
public void testInvalidProductName() {
fromProductName("bad product name");
}
@Test
public void testFromMetaDataForHsql() throws Exception {
DataSource ds = getMockDataSource("HSQL Database Engine");
assertEquals(HSQL, DatabaseType.fromMetaData(ds));
}
@Test
public void testFromMetaDataForOracle() throws Exception {
DataSource ds = getMockDataSource("Oracle");
assertEquals(ORACLE, DatabaseType.fromMetaData(ds));
}
@Test
public void testFromMetaDataForPostgres() throws Exception {
DataSource ds = getMockDataSource("PostgreSQL");
assertEquals(POSTGRES, DatabaseType.fromMetaData(ds));
}
public DataSource getMockDataSource(String databaseProductName) throws Exception {
DatabaseMetaData dmd = mock(DatabaseMetaData.class);
DataSource ds = mock(DataSource.class);
Connection con = mock(Connection.class);
when(ds.getConnection()).thenReturn(con);
when(con.getMetaData()).thenReturn(dmd);
when(dmd.getDatabaseProductName()).thenReturn(databaseProductName);
return ds;
}
public DataSource getMockDataSource(Exception e) throws Exception {
DataSource ds = mock(DataSource.class);
when(ds.getConnection()).thenReturn(null);
return ds;
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright 2015 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.task.repository.support;
import javax.sql.DataSource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.cloud.task.annotation.EnableTask;
import org.springframework.cloud.task.repository.TaskExecution;
import org.springframework.cloud.task.repository.TaskRepository;
import org.springframework.cloud.task.util.TaskExecutionCreator;
import org.springframework.cloud.task.util.TestDBUtils;
import org.springframework.cloud.task.util.TestVerifierUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Tests for the SimpleTaskRepository that uses JDBC as a datastore.
*
* @author Glenn Renfro.
*/
public class SimpleTaskRepositoryJdbcTests {
private TaskRepository taskRepository;
private DataSource dataSource;
private AnnotationConfigApplicationContext context;
@Before
public void setup() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(TestConfiguration.class,
EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
dataSource = this.context.getBean(DataSource.class);
JdbcTaskRepositoryFactoryBean factoryBean =
new JdbcTaskRepositoryFactoryBean(dataSource);
taskRepository = factoryBean.getObject();
}
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void testCreateTaskExecutionNoParam() {
TaskExecution expectedTaskExecution =
TaskExecutionCreator.createAndStoreTaskExecutionNoParams(taskRepository);
TaskExecution actualTaskExecution = TestDBUtils.getTaskExecutionFromDB(dataSource,
expectedTaskExecution.getExecutionId());
TestVerifierUtils.verifyTaskExecution(expectedTaskExecution, actualTaskExecution);
}
@Test
public void testCreateTaskExecutionWithParam() {
TaskExecution expectedTaskExecution =
TaskExecutionCreator.createAndStoreTaskExecutionWithParams(taskRepository);
TaskExecution actualTaskExecution = TestDBUtils.getTaskExecutionFromDB(
dataSource, expectedTaskExecution.getExecutionId());
TestVerifierUtils.verifyTaskExecution(expectedTaskExecution, actualTaskExecution);
}
@Test
public void testUpdateTaskExecution() {
TaskExecution expectedTaskExecution =
TaskExecutionCreator.createAndStoreTaskExecutionNoParams(taskRepository);
expectedTaskExecution = TaskExecutionCreator.updateTaskExecution(taskRepository,
expectedTaskExecution.getExecutionId());
TaskExecution actualTaskExecution = TestDBUtils.getTaskExecutionFromDB(
dataSource, expectedTaskExecution.getExecutionId());
TestVerifierUtils.verifyTaskExecution(expectedTaskExecution, actualTaskExecution);
}
@EnableTask
protected static class TestConfiguration {
}
}

View File

@@ -14,58 +14,50 @@
* limitations under the License.
*/
package org.springframework.cloud.task;
import java.util.UUID;
package org.springframework.cloud.task.repository.support;
import ch.qos.logback.core.Appender;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.task.repository.TaskExecution;
import org.springframework.cloud.task.repository.TaskRepository;
import org.springframework.cloud.task.util.LoggerTestUtils;
import org.springframework.cloud.task.util.TaskExecutionCreator;
import org.springframework.cloud.task.util.TestDefaultConfiguration;
import org.springframework.cloud.task.util.TestVerifierUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* Verifies that the LoggerRepository has correct prefixes written to logs.
* Verifies that the SimpleTaskRepository has correct prefixes written to logs.
* @author Glenn Renfro
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestDefaultConfiguration.class)
public class LoggerTaskRepositoryTests {
public class SimpleTaskRepositoryLoggerTests {
@Autowired
private TaskRepository taskRepository;
private TaskExecution taskExecution;
private String uuId;
@Before
public void setup(){
taskExecution = new TaskExecution();
uuId = UUID.randomUUID().toString();
taskExecution.setExecutionId(uuId);
}
@Test
public void testCreateTaskExecution() {
final Appender mockAppender = LoggerTestUtils.getMockAppender();
taskRepository.createTaskExecution(taskExecution);
LoggerTestUtils.verifyLogEntryExists(mockAppender,
"Creating: TaskExecution{executionId='" + uuId);
final Appender mockAppender = TestVerifierUtils.getMockAppender();
TaskExecution expectedTaskExecution =
TaskExecutionCreator.createAndStoreTaskExecutionNoParams(taskRepository);
TestVerifierUtils.verifyLogEntryExists(mockAppender,
"Creating: TaskExecution{executionId='" + expectedTaskExecution.getExecutionId());
}
@Test
public void testTaskUpdate() {
final Appender mockAppender = LoggerTestUtils.getMockAppender();
taskRepository.update(taskExecution);
LoggerTestUtils.verifyLogEntryExists(mockAppender,
"Updating: TaskExecution{executionId='" + uuId);
final Appender mockAppender = TestVerifierUtils.getMockAppender();
TaskExecution expectedTaskExecution =
TaskExecutionCreator.createAndStoreTaskExecutionNoParams(taskRepository);
TaskExecutionCreator.updateTaskExecution(taskRepository,
expectedTaskExecution.getExecutionId());
TestVerifierUtils.verifyLogEntryExists(mockAppender,
"Updating: TaskExecution{executionId='"
+ expectedTaskExecution.getExecutionId());
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright 2015 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.task.repository.support;
import static org.springframework.test.util.AssertionErrors.assertTrue;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cloud.task.repository.TaskExecution;
import org.springframework.cloud.task.repository.TaskRepository;
import org.springframework.cloud.task.repository.dao.MapTaskExecutionDao;
import org.springframework.cloud.task.util.TaskExecutionCreator;
import org.springframework.cloud.task.util.TestVerifierUtils;
/**
* Tests for the SimpleTaskRepository that uses Map as a datastore.
* @author Glenn Renfro.
*/
public class SimpleTaskRepositoryMapTests {
private TaskRepository taskRepository;
@Before
public void setUp() {
MapTaskRepositoryFactoryBean factoryBean =
new MapTaskRepositoryFactoryBean();
taskRepository = factoryBean.getObject();
}
@Test
public void testCreateTaskExecutionNoParam() {
TaskExecution expectedTaskExecution =
TaskExecutionCreator.createAndStoreTaskExecutionNoParams(taskRepository);
TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
getSingleTaskExecutionFromMapRepository(taskRepository,
expectedTaskExecution.getExecutionId()));
}
@Test
public void testCreateTaskExecutionWithParam() {
TaskExecution expectedTaskExecution =
TaskExecutionCreator.createAndStoreTaskExecutionWithParams(taskRepository);
TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
getSingleTaskExecutionFromMapRepository(taskRepository,
expectedTaskExecution.getExecutionId()));
}
@Test
public void testUpdateTaskExecution() {
TaskExecution expectedTaskExecution =
TaskExecutionCreator.createAndStoreTaskExecutionNoParams(taskRepository);
expectedTaskExecution = TaskExecutionCreator.updateTaskExecution(taskRepository,
expectedTaskExecution.getExecutionId());
TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
getSingleTaskExecutionFromMapRepository(taskRepository,
expectedTaskExecution.getExecutionId()));
}
private TaskExecution getSingleTaskExecutionFromMapRepository(
TaskRepository repository, String taskExecutionId){
Map<String, TaskExecution> taskMap = ((MapTaskExecutionDao)
((SimpleTaskRepository)taskRepository).getTaskExecutionDao()).getTaskExecutions();
assertTrue("taskExecutionId must be in MapTaskExecutionRepository",
taskMap.containsKey(taskExecutionId));
return taskMap.get(taskExecutionId);
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright 2015 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.task.repository.support;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import javax.sql.DataSource;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.cloud.task.annotation.EnableTask;
import org.springframework.cloud.task.configuration.TaskConfigurer;
import org.springframework.cloud.task.repository.TaskRepository;
import org.springframework.cloud.task.repository.dao.MapTaskExecutionDao;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* Verifies that task initialization occurs properly.
*
* @author Glenn Renfro
*/
public class TaskDatabaseInitializerTests {
private AnnotationConfigApplicationContext context;
@Rule
public ExpectedException expected = ExpectedException.none();
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void testDefaultContext() throws Exception {
this.context = new AnnotationConfigApplicationContext();
this.context.register( TestConfiguration.class,
EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertEquals(0, new JdbcTemplate(this.context.getBean(DataSource.class))
.queryForList("select * from TASK_EXECUTION").size());
}
// @Test
public void testNoDatabase() throws Exception {
SimpleTaskRepository repository = new SimpleTaskRepository(new MapTaskExecutionDao());
this.context.refresh();
assertThat(repository.getTaskExecutionDao(), instanceOf(MapTaskExecutionDao.class));
MapTaskExecutionDao dao = (MapTaskExecutionDao) repository.getTaskExecutionDao();
assertEquals(0, dao.getTaskExecutions().size());
}
@Test
public void testNoTaskConfiguration() throws Exception {
this.context = new AnnotationConfigApplicationContext();
this.context.register(EmptyConfiguration.class,
EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertEquals(0, this.context.getBeanNamesForType(SimpleTaskRepository.class).length);
}
@Test(expected = BeanCreationException.class)
public void testMultipleDataSourcesContext() throws Exception {
this.context = new AnnotationConfigApplicationContext();
this.context.register( TestConfiguration.class,
EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
DataSource dataSource = mock(DataSource.class);
context.getBeanFactory().registerSingleton("mockDataSource", dataSource);
this.context.refresh();
}
@EnableTask
protected static class TestConfiguration {
}
@EnableTask
protected static class TestCustomConfiguration implements TaskConfigurer {
@Override
public TaskRepository getTaskRepository() {
return new SimpleTaskRepository(new MapTaskExecutionDao());
}
}
@Configuration
protected static class EmptyConfiguration {
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2015 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.task.repository.support;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import javax.sql.DataSource;
import org.junit.Test;
import org.springframework.cloud.task.repository.TaskRepository;
import org.springframework.cloud.task.repository.dao.JdbcTaskExecutionDao;
import org.springframework.cloud.task.repository.dao.MapTaskExecutionDao;
/**
* Tests that the TaskRepositoryFactoryBeans produce the correct repositories.
*
* @author Glenn Renfro
*/
public class TaskRepositoryFactoryBeanTests {
@Test
public void testJdbcTaskRepositoryFactoryBean() {
DataSource dataSource = mock(DataSource.class);
JdbcTaskRepositoryFactoryBean factory = new JdbcTaskRepositoryFactoryBean(dataSource);
TaskRepository repository = factory.getObject();
assertThat(repository, instanceOf(SimpleTaskRepository.class));
assertThat(((SimpleTaskRepository) repository).getTaskExecutionDao(),
instanceOf(JdbcTaskExecutionDao.class));
}
@Test
public void testMapTaskRepositoryFactoryBean() {
MapTaskRepositoryFactoryBean factory = new MapTaskRepositoryFactoryBean();
TaskRepository repository = factory.getObject();
assertThat(repository, instanceOf(SimpleTaskRepository.class));
assertThat(((SimpleTaskRepository) repository).getTaskExecutionDao(),
instanceOf(MapTaskExecutionDao.class));
}
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright 2015 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.task.util;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.Appender;
import org.mockito.ArgumentMatcher;
import org.slf4j.LoggerFactory;
/**
* Offers utils to test the log results produced by the code being tested.
*
* @author Glenn Renfro
*/
public class LoggerTestUtils {
/**
* Creates a mock {@link Appender} to be added to the root logger.
* @return reference to the mock appender.
*/
public static Appender getMockAppender(){
ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
final Appender mockAppender = mock(Appender.class);
when(mockAppender.getName()).thenReturn("MOCK");
root.addAppender(mockAppender);
return mockAppender;
}
/**
* Verifies that the log sample is contained within the content that was written
* to the mock appender.
* @param mockAppender The appender that is associated with the test.
* @param logSample The string to search for in the log entry.
*/
public static void verifyLogEntryExists(Appender mockAppender, final String logSample){
verify(mockAppender).doAppend(argThat(new ArgumentMatcher() {
@Override
public boolean matches(final Object argument) {
return ((LoggingEvent)argument).getFormattedMessage().contains(logSample);
}
}));
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2015 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.task.util;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.springframework.cloud.task.repository.TaskExecution;
import org.springframework.cloud.task.repository.TaskRepository;
/**
* Offers ability to create TaskExecutions for the test suite.
*
* @author Glenn Renfro
*/
public class TaskExecutionCreator {
/**
* Creates a sample TaskExecution and stores it in the taskRepository.
*
* @param taskRepository the taskRepository where the taskExecution should be stored.
* @return the taskExecution created.
*/
public static TaskExecution createAndStoreTaskExecutionNoParams(TaskRepository taskRepository) {
TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
taskRepository.createTaskExecution(expectedTaskExecution);
return expectedTaskExecution;
}
/**
* Creates a sample TaskExecution and stores it in the taskRepository with params.
*
* @param taskRepository the taskRepository where the taskExecution should be stored.
* @return the taskExecution created.
*/
public static TaskExecution createAndStoreTaskExecutionWithParams(TaskRepository taskRepository) {
TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
List<String> params = new ArrayList<String>();
params.add(UUID.randomUUID().toString());
params.add(UUID.randomUUID().toString());
expectedTaskExecution.setParameters(params);
taskRepository.createTaskExecution(expectedTaskExecution);
return expectedTaskExecution;
}
/**
* Updates a sample TaskExecution in the taskRepository.
*
* @param taskRepository the taskRepository where the taskExecution should be updated.
* @return the taskExecution created.
*/
public static TaskExecution updateTaskExecution(TaskRepository taskRepository,
String taskExecutionId) {
TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
expectedTaskExecution.setExecutionId(taskExecutionId);
taskRepository.update(expectedTaskExecution);
return expectedTaskExecution;
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2015 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.task.util;
import static org.junit.Assert.assertEquals;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.cloud.task.repository.TaskExecution;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
/**
* Provides a suite of tools that allow tests the ability to retrieve results from a
* relational database.
*
* @author Glenn Renfro
*/
public class TestDBUtils {
/**
* Retrieves the TaskExecution from the datasource
*
* @param dataSource The datasource from which to retrieve the taskExecution
* @param taskExecutionId The id of the task to search .
* @return taskExecution
*/
public static TaskExecution getTaskExecutionFromDB(DataSource dataSource,
String taskExecutionId) {
String sql = "SELECT * FROM TASK_EXECUTION WHERE "
+ "TASK_EXECUTION_ID = '"
+ taskExecutionId + "'";
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
List<TaskExecution> rows = jdbcTemplate.query(sql, new RowMapper<TaskExecution>(){
@Override
public TaskExecution mapRow(ResultSet rs, int rownumber) throws SQLException {
TaskExecution taskExecution=new TaskExecution();
taskExecution.setExecutionId(rs.getString(1));
taskExecution.setStartTime(rs.getTimestamp("START_TIME"));
taskExecution.setEndTime(rs.getTimestamp("END_TIME"));
taskExecution.setExitCode(rs.getInt("EXIT_CODE"));
taskExecution.setExitMessage(rs.getString("EXIT_MESSAGE"));
taskExecution.setStatusCode(rs.getString("STATUS_CODE"));
taskExecution.setTaskName(rs.getString("TASK_NAME"));
return taskExecution;
}
});
assertEquals("only one row should be returned", 1, rows.size());
TaskExecution taskExecution = rows.get(0);
populateParamsToDB(dataSource, taskExecution);
return taskExecution;
}
private static void populateParamsToDB(DataSource dataSource, TaskExecution taskExecution) {
String sql = "SELECT * FROM TASK_EXECUTION_PARAMS WHERE TASK_EXECUTION_ID = '"
+ taskExecution.getExecutionId() + "'";
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql);
List<String> params = new ArrayList<>();
for (Map row : rows) {
params.add((String) row.get("TASK_PARAM"));
}
taskExecution.setParameters(params);
}
}

View File

@@ -18,8 +18,9 @@ package org.springframework.cloud.task.util;
import org.aspectj.lang.JoinPoint;
import org.springframework.cloud.task.configuration.TaskHandler;
import org.springframework.cloud.task.repository.support.LoggerTaskRepository;
import org.springframework.cloud.task.repository.TaskRepository;
import org.springframework.cloud.task.repository.dao.MapTaskExecutionDao;
import org.springframework.cloud.task.repository.support.SimpleTaskRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -33,7 +34,7 @@ public class TestDefaultConfiguration {
@Bean
public TaskRepository taskRepository(){
return new LoggerTaskRepository();
return new SimpleTaskRepository(new MapTaskExecutionDao());
}
@Bean

View File

@@ -0,0 +1,145 @@
/*
* Copyright 2015 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.task.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.Appender;
import org.mockito.ArgumentMatcher;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.task.repository.TaskExecution;
/**
* Offers utils to test the results produced by the code being tested.
*
* @author Glenn Renfro
*/
public class TestVerifierUtils {
/**
* Creates a mock {@link Appender} to be added to the root logger.
*
* @return reference to the mock appender.
*/
public static Appender getMockAppender() {
ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
final Appender mockAppender = mock(Appender.class);
when(mockAppender.getName()).thenReturn("MOCK");
root.addAppender(mockAppender);
return mockAppender;
}
/**
* Verifies that the log sample is contained within the content that was written
* to the mock appender.
*
* @param mockAppender The appender that is associated with the test.
* @param logSample The string to search for in the log entry.
*/
public static void verifyLogEntryExists(Appender mockAppender, final String logSample) {
verify(mockAppender).doAppend(argThat(new ArgumentMatcher() {
@Override
public boolean matches(final Object argument) {
return ((LoggingEvent) argument).getFormattedMessage().contains(logSample);
}
}));
}
/**
* Creates a fully populated TaskExecution (except params) for testing.
*
* @return
*/
public static TaskExecution createSampleTaskExecutionNoParam() {
Random randomGenerator = new Random();
int exitCode = randomGenerator.nextInt();
Date startTime = new Date();
Date endTime = new Date();
String executionId = UUID.randomUUID().toString();
String taskName = UUID.randomUUID().toString();
String exitMessage = UUID.randomUUID().toString();
String statusCode = UUID.randomUUID().toString().substring(0, 9);
return new TaskExecution(executionId, exitCode, taskName,
startTime, endTime, statusCode,
exitMessage, new ArrayList<String>());
}
/**
* Verifies that all the fields in between the expected and actual are the same;
*
* @param expectedTaskExecution The expected value for the task execution.
* @param actualTaskExecution The actual value for the task execution.
*/
public static void verifyTaskExecution(TaskExecution expectedTaskExecution,
TaskExecution actualTaskExecution) {
assertEquals("taskExecutionId must be equal", expectedTaskExecution.getExecutionId(),
actualTaskExecution.getExecutionId());
assertEquals("startTime must be equal",
expectedTaskExecution.getStartTime(),
actualTaskExecution.getStartTime());
assertEquals("endTime must be equal",
expectedTaskExecution.getEndTime(),
actualTaskExecution.getEndTime());
assertEquals("exitCode must be equal",
expectedTaskExecution.getExitCode(),
actualTaskExecution.getExitCode());
assertEquals("taskName must be equal",
expectedTaskExecution.getTaskName(),
actualTaskExecution.getTaskName());
assertEquals("exitMessage must be equal",
expectedTaskExecution.getExitMessage(),
actualTaskExecution.getExitMessage());
assertEquals("statusCode must be equal",
expectedTaskExecution.getStatusCode(),
actualTaskExecution.getStatusCode());
if (expectedTaskExecution.getParameters() != null) {
assertNotNull("parameters should not be null",
actualTaskExecution.getParameters());
assertEquals("parameters result set count should match expected count",
expectedTaskExecution.getParameters().size(),
actualTaskExecution.getParameters().size());
}
else {
assertNull("parameters should be null", actualTaskExecution.getParameters());
}
Set<String> params = new HashSet<String>();
for (String param : expectedTaskExecution.getParameters()) {
params.add(param);
}
for (String param : actualTaskExecution.getParameters()) {
assertTrue("param must exist in the repository", params.contains(param));
}
}
}