/*
* Copyright 2012 Brian Thomas Matthews
*
* 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 com.btmatthews.maven.plugins.inmemdb.test;
import static org.junit.Assert.assertNotNull;
import static org.mockito.MockitoAnnotations.initMocks;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import com.btmatthews.maven.plugins.inmemdb.Source;
import com.btmatthews.maven.plugins.inmemdb.mojo.RunMojo;
import com.btmatthews.maven.plugins.inmemdb.mojo.Script;
import com.btmatthews.utils.monitor.Logger;
import com.btmatthews.utils.monitor.Monitor;
import org.apache.maven.plugin.Mojo;
import org.codehaus.plexus.util.ReflectionUtils;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.Mock;
/**
* Unit tests for the Mojo that implements the run goal.
*
* @author <a href="mailto:brian@btmatthews.com">Brian Matthews</a>
*/
public abstract class AbstractTestRunMojo {
/**
* Mock the logger.
*/
@Mock
private Logger logger;
/**
* The mojo being tested.
*/
private Mojo mojo;
/**
* Used to create temporary directories used by the unit tests.
*/
@Rule
public TemporaryFolder outputDirectory = new TemporaryFolder();
/**
* Concrete implementations should override this method to get the port number that the monitor controlling the
* server listens for commands on.
*
* @return The port number.
*/
protected abstract int getMonitorPort();
/**
* Concrete implementations should override this method to get the database server type.
*
* @return The database server type.
*/
protected abstract String getType();
/**
* Concrete implementations should override this method to get the driver class name.
*
* @return The driver class name.
*/
protected abstract String getDriverClassName();
/**
* Concrete implementations should override this method to get the database connection string.
*
* @return The database connection string.
*/
protected abstract String getConnectionString();
/**
* Get the name of the database table used for testing.
*
* @return The name of the database table.
*/
private String getTableName() {
return getType() + "_users";
}
/**
* Get the relative path of the database script used to create the database schema.
*
* @return The relative path of the script.
*/
private String getCreateScript() {
return "src/test/resources/create_" + getType() + "_database.sql";
}
/**
* Prepare for test execution by initialising the mock objects and test fixture.
*
* @throws Exception If there was an error configuring the test fixture.
*/
@Before
public void setUp() throws Exception {
initMocks(this);
Class.forName(getDriverClassName());
mojo = new RunMojo();
ReflectionUtils.setVariableValueInObject(mojo, "monitorPort", getMonitorPort());
ReflectionUtils.setVariableValueInObject(mojo, "monitorKey", "inmemdb");
ReflectionUtils.setVariableValueInObject(mojo, "type", getType());
ReflectionUtils.setVariableValueInObject(mojo, "database", "test");
final Script source = new Script();
source.setSourceFile(getCreateScript());
final List<Source> sources = new ArrayList<Source>();
sources.add(source);
ReflectionUtils.setVariableValueInObject(mojo, "sources", sources);
}
/**
* Verify that we can start the server.
*
* @throws Exception If there was an error.
*/
@Test
public void testRun() throws Exception {
ReflectionUtils.setVariableValueInObject(mojo, "daemon", Boolean.FALSE);
final Thread mojoThread = new Thread(new Runnable() {
public void run() {
try {
mojo.execute();
} catch (final Exception e) {
}
}
});
mojoThread.start();
try {
Thread.sleep(5000);
final Connection jdbcConnection = DriverManager.getConnection(getConnectionString());
final IDatabaseConnection connection = new DatabaseConnection(jdbcConnection);
IDataSet databaseDataSet = connection.createDataSet();
assertNotNull(databaseDataSet.getTable(getTableName()));
connection.close();
jdbcConnection.close();
} finally {
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
signalStop();
}
}, 5000L);
mojoThread.join(15000L);
}
}
/**
* Verify that we can start the server as a daemon.
*
* @throws Exception If there was an error.
*/
@Test
public void testRunDaemon() throws Exception {
ReflectionUtils.setVariableValueInObject(mojo, "daemon", Boolean.TRUE);
try {
mojo.execute();
Thread.sleep(5000L);
final Connection jdbcConnection = DriverManager.getConnection(getConnectionString());
final IDatabaseConnection connection = new DatabaseConnection(jdbcConnection);
IDataSet databaseDataSet = connection.createDataSet();
assertNotNull(databaseDataSet.getTable(getTableName()));
connection.close();
jdbcConnection.close();
} finally {
signalStop();
}
}
/**
* Send a stop signal to monitor controlling the server.
*/
private void signalStop() {
new Monitor("inmemdb", getMonitorPort()).sendCommand("stop", logger);
}
}