package net.raymanoz.migrate;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import org.mockito.InOrder;
import java.io.IOException;
import java.io.InputStream;
import net.raymanoz.config.Configuration;
import net.raymanoz.config.ConfigurationImpl;
import net.raymanoz.io.File;
import net.raymanoz.util.FileUtilImpl;
import net.raymanoz.util.Properties;
import net.raymanoz.util.StreamUtil;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
public class ScriptCreatorImplTest {
final Properties mockProperties = mock(Properties.class);;
final ScriptCreatorAssembler mockScriptCreatorAssembler = mock(ScriptCreatorAssembler.class);
final File mockTemplateFile = mock(File.class);
final File mockNewScript = mock(File.class);
final File mockScriptDir = mock(File.class);
final ScriptList scriptList = mock(ScriptList.class);
final StreamUtil mockStreamUtil = mock(StreamUtil.class);
private Configuration createMockConfiguration() {
Configuration mockConfiguration = mock(ConfigurationImpl.class);
when(mockConfiguration.getNumberOfDigits()).thenReturn(1);
when(mockConfiguration.getLatestScriptDirectory()).thenReturn(mockScriptDir);
when(mockConfiguration.getTemplateFile()).thenReturn(mockTemplateFile);
return mockConfiguration;
}
final Configuration mockConfiguration = createMockConfiguration();
final FileUtilImpl mockFileUtil = mock(FileUtilImpl.class);
final ScriptCreator creator = new ScriptCreatorImpl(mockScriptCreatorAssembler, mockConfiguration, mockProperties, mockStreamUtil);
private void setupScriptDir(Long dbVersion, int noDigits, File ... scripts){
when(mockConfiguration.getNumberOfDigits()).thenReturn(noDigits);
when(mockScriptDir.listFiles()).thenReturn(scripts);
when(mockScriptDir.getDBVersion()).thenReturn(dbVersion);
when(mockScriptCreatorAssembler.newScriptList(scripts, noDigits, dbVersion)).thenReturn(scriptList);
when(mockScriptCreatorAssembler.newFileUtil()).thenReturn(mockFileUtil);
when(mockScriptCreatorAssembler.newFile(mockScriptDir, scriptList.nextScriptName("createScript"))).thenReturn(mockTemplateFile);
}
private void setupScriptInfo(boolean templateExists, String actionName, String nextScriptName){
when(mockTemplateFile.exists(false)).thenReturn(templateExists);
when(scriptList.nextScriptName(actionName)).thenReturn(nextScriptName);
when(mockScriptCreatorAssembler.newFile(mockScriptDir, nextScriptName)).thenReturn(mockNewScript);
}
@Test
public void newScriptWithTemplate() throws IOException {
final int noDigits = 7;
final Long dbVersion = 4L;
final String actionName = "An Action";
final String scriptName = "A Script";
setupScriptDir(dbVersion, noDigits);
setupScriptInfo(true, actionName, scriptName);
creator.newScript(actionName);
verify(mockProperties).setProperty(ScriptCreatorImpl.UMIGRATE_SCRIPT_NAME_PROPERTY, scriptName);
verify(mockFileUtil).copyFile(mockTemplateFile, mockNewScript, mockProperties, "");
verify(mockFileUtil, never()).copyFile(mockTemplateFile, mockNewScript, mockProperties);
verify(mockScriptCreatorAssembler).newFile(mockScriptDir, scriptName);
verify(mockNewScript, never()).createNewFile();
verify(mockScriptCreatorAssembler).newScriptList(any(File[].class), eq(noDigits), eq(dbVersion));
}
@Test
public void newScriptWithTemplateAndPrefix() throws IOException {
final int noDigits = 7;
final Long dbVersion = 4L;
final String actionName = "An Action";
final String scriptName = "A Script";
final String scriptPrefix = "A Prefix";
setupScriptDir(dbVersion, noDigits);
setupScriptInfo(true, actionName, scriptName);
creator.newScript(actionName, scriptPrefix);
verify(mockProperties).setProperty(ScriptCreatorImpl.UMIGRATE_SCRIPT_NAME_PROPERTY, scriptName);
verify(mockFileUtil).copyFile(mockTemplateFile, mockNewScript, mockProperties, scriptPrefix);
verify(mockFileUtil, never()).copyFile(mockTemplateFile, mockNewScript, mockProperties);
verify(mockScriptCreatorAssembler).newFile(mockScriptDir, scriptName);
verify(mockNewScript, never()).createNewFile();
verify(mockScriptCreatorAssembler).newScriptList(any(File[].class), eq(noDigits), eq(dbVersion));
}
@Test
public void ifTemplateFileDoesNotExistShouldCreateEmptyNewScript() throws IOException {
final int noDigits = 4;
final Long dbVersion = 5L;
final String actionName = "An Action";
final String scriptName = "A Script";
setupScriptDir(dbVersion, noDigits);
setupScriptInfo(false, actionName, scriptName);
creator.newScript(actionName);
verify(mockProperties, never()).setProperty(ScriptCreatorImpl.UMIGRATE_SCRIPT_NAME_PROPERTY, scriptName);
verify(mockFileUtil, never()).copyFile(mockTemplateFile, mockNewScript, mockProperties, "");
verify(mockFileUtil, never()).copyFile(mockTemplateFile, mockNewScript, mockProperties);
verify(mockScriptCreatorAssembler).newFile(mockScriptDir, scriptName);
verify(mockNewScript).createNewFile();
verify(mockScriptCreatorAssembler).newScriptList(any(File[].class), eq(noDigits), eq(dbVersion));
}
@Test(expected=RuntimeException.class)
public void ifIOExceptionThrownShouldBeChainedAsRuntimeException() throws IOException {
final int noDigits = 3;
final Long dbVersion = 9L;
final String actionName = "An Action";
final String scriptName = "A Script";
setupScriptDir(dbVersion, noDigits);
setupScriptInfo(false, actionName, scriptName);
when(mockNewScript.createNewFile()).thenThrow(new IOException());
creator.newScript(actionName);
}
@Test
public void validateTemplateHandlesNoTemplate() throws IOException {
when(mockConfiguration.getTemplateFile()).thenReturn(mockTemplateFile);
when(mockTemplateFile.exists(false)).thenReturn(false);
assertFalse(creator.validateTemplate());
InOrder inOrder = inOrder(mockConfiguration, mockTemplateFile);
inOrder.verify(mockConfiguration).getTemplateFile();
inOrder.verify(mockTemplateFile).exists(false);
verify(mockScriptCreatorAssembler, never()).newFileUtil();
verify(mockStreamUtil, never()).newFileInputStream(any(File.class));
verify(mockFileUtil, never()).loadStreamIntoString(any(InputStream.class));
}
private void chkValidateTemplateTemplateExists(String templateAsStr, Boolean expected){
when(mockConfiguration.getTemplateFile()).thenReturn(mockTemplateFile);
when(mockTemplateFile.exists(false)).thenReturn(true);
when(mockScriptCreatorAssembler.newFileUtil()).thenReturn(mockFileUtil);
final InputStream mockStream = mock(InputStream.class);
when(mockStreamUtil.newFileInputStream(mockTemplateFile)).thenReturn(mockStream);
when(mockFileUtil.loadStreamIntoString(mockStream)).thenReturn(templateAsStr);
assertEquals(expected, creator.validateTemplate());
InOrder inOrder = inOrder(mockConfiguration, mockTemplateFile,mockConfiguration,mockScriptCreatorAssembler,mockStreamUtil,mockFileUtil);
inOrder.verify(mockConfiguration).getTemplateFile();
inOrder.verify(mockTemplateFile).exists(false);
inOrder.verify(mockStreamUtil).newFileInputStream(mockTemplateFile);
inOrder.verify(mockScriptCreatorAssembler).newFileUtil();
inOrder.verify(mockFileUtil).loadStreamIntoString(mockStream);
}
@Test
public void validateTemplateWhenNoSqlProperty() throws IOException {
chkValidateTemplateTemplateExists("A Template without \r\n any Sql parameter", false);
}
@Test
public void validateTemplateWhenWithSqlProperty() throws IOException {
chkValidateTemplateTemplateExists("A Template with \r\n${sql}\r\n a Sql parameter", true);
}
@Test
public void validateLatestScriptDirShouldCheckScriptDirAndNotCatchException() throws IOException {
final Long dbVersion = 102L;
final int numberOfDigits = 6;
final String errorMessage ="The is an Error Message";
setupScriptDir(dbVersion, numberOfDigits);
when(mockScriptCreatorAssembler.newScriptList(new File[0], numberOfDigits, dbVersion)).thenThrow(new ProblemInScriptListNumbers(errorMessage));
try {
creator.validateLatestScriptDir();
assertTrue("Should have thrown ProblemInScriptListNumbers", false);
}
catch (ProblemInScriptListNumbers e){
assertEquals(errorMessage, e.getMessage());
}
verify(mockConfiguration).getLatestScriptDirectory();
verify(mockScriptDir).listFiles();
verify(mockScriptCreatorAssembler).newScriptList(new File[0], numberOfDigits, dbVersion);
}
@Test
public void validateLatestScriptDirIfNoError() throws IOException {
final Long dbVersion = 102L;
final int numberOfDigits = 6;
setupScriptDir(dbVersion, numberOfDigits);
creator.validateLatestScriptDir();
verify(mockConfiguration).getLatestScriptDirectory();
verify(mockScriptDir).listFiles();
verify(mockScriptCreatorAssembler).newScriptList(new File[0], numberOfDigits, dbVersion);
}
}