package net.raymanoz.migrate;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import net.raymanoz.config.Configuration;
import net.raymanoz.io.File;
import org.junit.Test;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ScriptListImplTest {
private final Configuration config = mock(Configuration.class);
private File mockFile(String fileName){
File mockFile = mock(File.class);
when(mockFile.getName()).thenReturn(fileName);
return mockFile;
}
private File[] mockFiles(String ... fileNames){
File[] result = new File[fileNames.length];
for (int idx = 0; idx < fileNames.length;idx++){
result[idx] = mockFile(fileNames[idx]);
}
return result;
}
@Test
public void canCreateScriptListFromFileList() {
File[] files = mockFiles("1_thing.sql","2_thingy.sql");
ScriptList list = new ScriptListImpl(files, 1, 1, config);
assertNotNull("list should not be null", list);
assertEquals("list should have 2 elements", 2, list.size());
}
@Test
public void invalidFilesShouldBeIgnored() {
File[] files = mockFiles("1_thing.sql", "dud.sql", "2_thingy.sql" );
ScriptList list = new ScriptListImpl(files, 1, 1, config);
assertEquals("list should have 2 elements", 2, list.size());
}
@Test
public void listShouldReturnInOrder() {
File[] files = mockFiles("2_thing.sql", "1_script.sql", "3_script.sql" );
ScriptList list = new ScriptListImpl(files, 1, 1, config);
assertEquals("first script should be 1", 1L, list.get(0).getPatch());
assertEquals("second script should be 2", 2L, list.get(1).getPatch());
assertEquals("thrid script should be 3", 3L, list.get(2).getPatch());
}
private void checkForProblemsInSciptListNumbers(String expectedMessage, long dbVersion, String ... fileNames){
File[] files = mockFiles(fileNames);
try {
new ScriptListImpl(files, 3, dbVersion, config);
assertEquals("ProblemInScriptListNumbers thrown", true, false);
}
catch (ProblemInScriptListNumbers e){
assertEquals(expectedMessage, e.getMessage());
}
}
public void listShouldOnlyContainSequentialScripts() {
checkForProblemsInSciptListNumbers(
"Missing script number 4 (jumps to 16) for db version 5",
5,
"1_thing.sql", "2_script.sql", "3_script.sql", "16_script.sql"
);
}
@Test
public void scriptListShouldOnlyStartAt1() {
checkForProblemsInSciptListNumbers(
"Scripts must start at 1, first script for db version 2 is 4",
2,
"004_doSomething.sql"
);
}
@Test
public void scriptListShouldNoAllowDuplicates() {
checkForProblemsInSciptListNumbers(
"Duplicate script number 2 found for db version 1",
1,
"001_doSomething.sql","002_doSomething.sql","002_doSomethingElse.sql"
);
}
@Test
public void nextNumberEmptyFilesListShouldGiveOne() {
File[] emptyList = new File[0];
assertEquals("Next script number should be 1", "1_script.sql", new ScriptListImpl(emptyList, 1, 1, config)
.nextScriptName("script"));
}
@Test
public void nextScriptShouldNotDoubleSqlFileExt() {
File[] emptyList = new File[0];
assertEquals("Next script number should be 1", "1_script.sql", new ScriptListImpl(emptyList, 1, 1, config)
.nextScriptName("script.sql"));
}
@Test(expected = IllegalArgumentException.class)
public void nullListShouldBeInvalid() {
new ScriptListImpl(null, 1, 1, config).nextScriptName("script");
}
@Test
public void perfectListOneElementShouldGiveNextNumber() {
File[] oneElementList = mockFiles("1_createATable.sql" );
assertEquals("Next script number should be 2", "2_script.sql", new ScriptListImpl(oneElementList, 1, 1, config)
.nextScriptName("script"));
}
@Test
public void perfectListManyElementsShouldGiveNextNumber() {
File[] twoElementList = mockFiles("1_createATable.sql", "2_createATable.sql" );
assertEquals("Next script number should be 3", "3_script.sql", new ScriptListImpl(twoElementList, 1, 1, config)
.nextScriptName("script"));
}
@Test
public void fileNameWithNoNumberShouldBeIgnored() {
File[] oneElementList = mockFiles("createATable.sql");
assertEquals("Next script number should be 1", "1_script.sql", new ScriptListImpl(oneElementList, 1, 1, config)
.nextScriptName("script"));
}
@Test
public void listOutOfOrderShouldGiveNextHighestNumber() {
File[] twoElementList = mockFiles("2_createATable.sql", "1_createATable.sql");
assertEquals("Next script number should be 3", "3_script.sql", new ScriptListImpl(twoElementList, 1, 1, config)
.nextScriptName("script"));
}
@Test(expected = IllegalArgumentException.class)
public void nullScriptActionShouldBeInvalid() {
new ScriptListImpl(new File[0], 1, 1, config).nextScriptName(null);
}
@Test
public void canIterateUsingForEach() {
File[] files = mockFiles("1_a.sql", "2_b.sql" );
ScriptList scripts = new ScriptListImpl(files, 1, 1, config);
long i = 1;
for (Script script : scripts) {
assertEquals("this script should be " + i, i, script.getPatch());
i++;
}
}
@Test
public void nextFileNameShouldHandleNumberOfDigits() {
File[] oneElementList = mockFiles("001_doSomething.sql");
assertEquals("Next script name incorrect", "002_fight.sql", new ScriptListImpl(oneElementList, 3, 1, config)
.nextScriptName("fight"));
}
@Test(expected = IllegalArgumentException.class)
public void scriptListShouldOnlyAcceptPositiveNumberOfDigits() {
File[] oneElementList = mockFiles("001_doSomething.sql");
new ScriptListImpl(oneElementList, 0, 1, config);
}
@Test
public void shouldReturnMaxScriptVersion() throws Exception {
File[] twoElementList = mockFiles("001_doSomething.sql", "002_doSomethingElse.sql");
ScriptList list = new ScriptListImpl(twoElementList, 3, 1, config);
assertThat(list.maxScriptVersion(), is(equalTo(2L)));
}
@Test
public void maxSchemaShouldReturnNoScriptWithVersionZeroIfScriptListIsEmpty() {
File[] emptyList = new File[] {};
ScriptList list = new ScriptListImpl(emptyList, 3, 1, config);
assertThat(list.maxScriptVersion(), is(equalTo(0L)));
}
}