Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'feature/JENKINS-37637-changesets-in-classpath' into dev…
…elop
  • Loading branch information
prospero238 committed Aug 23, 2016
2 parents 31e832c + 9e99086 commit f188624
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 6 deletions.
Expand Up @@ -14,6 +14,8 @@
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.DatabaseException;
import liquibase.exception.LiquibaseException;
import liquibase.resource.ClassLoaderResourceAccessor;
import liquibase.resource.CompositeResourceAccessor;
import liquibase.resource.ResourceAccessor;

import java.io.IOException;
Expand Down Expand Up @@ -79,6 +81,7 @@ public AbstractLiquibaseBuilder() {


}

protected static String getProperty(Properties configProperties, LiquibaseProperty property) {
return configProperties.getProperty(property.propertyName());
}
Expand Down Expand Up @@ -132,9 +135,14 @@ public Liquibase createLiquibase(AbstractBuild<?, ?> build,
Database database =
DatabaseFactory.getInstance().findCorrectDatabaseImplementation(jdbcConnection);

ResourceAccessor resourceAccessor = new FilePathAccessor(build);
ResourceAccessor filePathAccessor = new FilePathAccessor(build);
CompositeResourceAccessor compositeResourceAccessor =
new CompositeResourceAccessor(filePathAccessor,
new ClassLoaderResourceAccessor(Thread.currentThread().getContextClassLoader()),
new ClassLoaderResourceAccessor(ClassLoader.getSystemClassLoader())
);
liquibase = new Liquibase(configProperties.getProperty(LiquibaseProperty.CHANGELOG_FILE.propertyName()),
resourceAccessor, database);
compositeResourceAccessor, database);

} catch (LiquibaseException e) {
throw new RuntimeException("Error creating liquibase database.", e);
Expand Down
Expand Up @@ -15,6 +15,8 @@
import java.util.Set;

import org.apache.commons.io.filefilter.FileFileFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Sets;

Expand All @@ -24,6 +26,8 @@
public class FilePathAccessor implements ResourceAccessor {
private final AbstractBuild<?, ?> build;

private static final Logger LOG = LoggerFactory.getLogger(FilePathAccessor.class);

public FilePathAccessor(AbstractBuild<?, ?> build) {
this.build = build;
}
Expand All @@ -46,8 +50,16 @@ public InputStream getResourceAsStream(String s) throws IOException {
}

public Set<InputStream> getResourcesAsStream(String path) throws IOException {
Set<InputStream> streams = Sets.newHashSet();
streams.add(getResourceAsStream(path));
Set<InputStream> streams = null;
try {
InputStream resourceAsStream = getResourceAsStream(path);
if (resourceAsStream!=null) {
streams = Sets.newHashSet();
streams.add(resourceAsStream);
}
} catch (IOException e) {
LOG.info("Unable to load resources from path '" + path +"'", e);
}
return streams;
}

Expand Down Expand Up @@ -122,7 +134,11 @@ protected Set<String> list(FilePath workspace,
}
}

return result;
if (result.isEmpty()) {
return null;
} else {
return result;
}
}

public ClassLoader toClassLoader() {
Expand Down
@@ -0,0 +1,133 @@
package org.jenkinsci.plugins.liquibase.evaluator;

import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.Build;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
import hudson.tasks.Builder;
import liquibase.Contexts;
import liquibase.Liquibase;
import liquibase.changelog.ChangeSet;
import liquibase.changelog.DatabaseChangeLog;
import liquibase.exception.LiquibaseException;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

import org.apache.commons.lang3.RandomStringUtils;
import org.jenkinsci.plugins.liquibase.integration.LiquibaseTestUtil;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class AbstractLiquibaseBuilderTest {

private static final Logger LOG = LoggerFactory.getLogger(AbstractLiquibaseBuilderTest.class);

@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();

@Mock
Build build;

@Mock
BuildListener buildListener;

@Mock
Launcher launcher;

protected String dbUrl;

@Before
public void setup() throws IOException {
temporaryFolder.create();
File dbfiles = temporaryFolder.newFolder("dbfiles");
File dbFile = new File(dbfiles, "h2");
dbUrl = "jdbc:h2:file:" + dbFile.getAbsolutePath();
when(buildListener.getLogger()).thenReturn(System.out);
}

@Test
public void should_load_changeset_from_system_classpath() throws IOException, LiquibaseException {
AbstractLiquibaseBuilder liquibaseBuilder = new LiquibaseBuilderStub();

Properties configProperties = createLiquibaseProperties();
// this changelogFile is available only through this test class's classloader
configProperties.setProperty("changeLogFile", "example-changesets/single-changeset.xml");

Liquibase liquibase = liquibaseBuilder
.createLiquibase(build, buildListener, new ExecutedChangesetAction(build), configProperties, launcher);
liquibase.update(new Contexts());

assertThatOneChangesetExecuted(liquibase);
}

@Test
public void should_load_changeset_from_dynamic_classpath() throws IOException, LiquibaseException {
Properties liquibaseProperties = createLiquibaseProperties();
LiquibaseBuilderStub stub = new LiquibaseBuilderStub();

File changesets = temporaryFolder.newFolder("changesets");

String subDirectoryName = RandomStringUtils.randomAlphabetic(5);
File randomSubDir = new File(changesets, subDirectoryName);

LiquibaseTestUtil.createFileFromResource(randomSubDir, "/example-changesets/single-changeset.xml");

String changeLogResourcePath = subDirectoryName + "/single-changeset.xml";
liquibaseProperties.setProperty("changeLogFile", changeLogResourcePath);
stub.setClasspath(changesets.getAbsolutePath());

Liquibase liquibase =
stub.createLiquibase(build, buildListener, new ExecutedChangesetAction(build), liquibaseProperties,
launcher);
liquibase.update(new Contexts(""));

assertThatOneChangesetExecuted(liquibase);

}

private static void assertThatOneChangesetExecuted(Liquibase liquibase) throws LiquibaseException {
DatabaseChangeLog databaseChangeLog = liquibase.getDatabaseChangeLog();
List<ChangeSet> changeSets = databaseChangeLog.getChangeSets();
assertThat(changeSets, hasSize(1));
}

private Properties createLiquibaseProperties() throws IOException {
Properties configProperties = new Properties();
configProperties.load(getClass().getResourceAsStream("/example-changesets/unit-test.h2.liquibase.properties"));
configProperties.setProperty("url", dbUrl);
return configProperties;
}

private static class LiquibaseBuilderStub extends AbstractLiquibaseBuilder {
@Override
public void doPerform(AbstractBuild<?, ?> build,
BuildListener listener,
Liquibase liquibase,
Contexts contexts,
ExecutedChangesetAction executedChangesetAction)
throws InterruptedException, IOException, LiquibaseException {

}

@Override
public Descriptor<Builder> getDescriptor() {
return null;
}
}
}
Expand Up @@ -5,16 +5,20 @@

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnit44Runner;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.hamcrest.core.IsCollectionContaining.hasItem;
Expand All @@ -28,9 +32,15 @@ public class FilePathAccessorTest {

@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();

@Before

public void setup() throws IOException {
temporaryFolder.create();

}
@Test
public void should_list_files() throws IOException, InterruptedException {
temporaryFolder.create();
File childDir = temporaryFolder.newFolder(CHILD_DIR);
childDir.mkdirs();

Expand All @@ -50,4 +60,13 @@ public void should_list_files() throws IOException, InterruptedException {
assertThat(result, hasItem(childFilepath));
}

@Test
public void should_return_null_if_not_found() throws IOException {
FilePathAccessor accessor = new FilePathAccessor(build);

InputStream inputStream = accessor.getResourceAsStream("i_dont_exist");
assertThat(inputStream, is(nullValue()));

}

}
19 changes: 19 additions & 0 deletions src/test/resources/example-changesets/single-changeset.xml
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>

<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">

<changeSet author="keith" id="create-table">
<createTable
remarks="sample table"
tableName="shape">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
</createTable>
<comment>This is a simple create table</comment>
</changeSet>
</databaseChangeLog>

0 comments on commit f188624

Please sign in to comment.