#792 Force migration of SQLite when necessary (#1371)

- Detect if a migration is necessary
- Create a backup
- Perform the migration
This commit is contained in:
ljacqu
2017-10-22 09:16:48 +02:00
committed by GitHub
parent c37c0ce436
commit d6e2369f36
12 changed files with 234 additions and 260 deletions
@@ -78,7 +78,7 @@ public class SQLiteIntegrationTest extends AbstractDataSourceIntegrationTest {
Statement st = con.createStatement();
// table is absent
st.execute("DROP TABLE authme");
SQLite sqLite = new SQLite(settings, con);
SQLite sqLite = new SQLite(settings, null, con);
// when
sqLite.setup();
@@ -100,7 +100,7 @@ public class SQLiteIntegrationTest extends AbstractDataSourceIntegrationTest {
+ "username varchar(255) unique, "
+ "password varchar(255) not null, "
+ "primary key (id));");
SQLite sqLite = new SQLite(settings, con);
SQLite sqLite = new SQLite(settings, null, con);
// when
sqLite.setup();
@@ -114,7 +114,7 @@ public class SQLiteIntegrationTest extends AbstractDataSourceIntegrationTest {
@Override
protected DataSource getDataSource(String saltColumn) {
when(settings.getProperty(DatabaseSettings.MYSQL_COL_SALT)).thenReturn(saltColumn);
return new SQLite(settings, con);
return new SQLite(settings, null, con);
}
private static <T> void set(Property<T> property, T value) {
@@ -16,7 +16,7 @@ public class SQLiteResourceClosingTest extends AbstractSqlDataSourceResourceClos
@Override
protected DataSource createDataSource(Settings settings, Connection connection) throws Exception {
return new SQLite(settings, connection);
return new SQLite(settings, null, connection);
}
}
@@ -1,13 +1,10 @@
package fr.xephi.authme.command.executable.authme.debug;
package fr.xephi.authme.datasource;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
import fr.xephi.authme.ReflectionTestUtils;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.SQLite;
import fr.xephi.authme.settings.Settings;
import org.bukkit.command.CommandSender;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -18,25 +15,24 @@ import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData;
import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation;
import static fr.xephi.authme.datasource.SqlDataSourceTestUtil.createSqliteAndInitialize;
import static fr.xephi.authme.datasource.SqlDataSourceTestUtil.createSqlite;
import static org.hamcrest.Matchers.arrayContaining;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
/**
* Integration test for {@link SqliteMigrater}. Uses a real SQLite database.
* Integration test for {@link SqLiteMigrater}. Uses a real SQLite database.
*/
public class SqliteMigraterIntegrationTest {
public class SqLiteMigraterIntegrationTest {
private static final String CONFIRMATION_CODE = "ABCD";
private SqliteMigrater sqliteMigrater;
private File dataFolder;
private SQLite sqLite;
@Rule
@@ -50,26 +46,20 @@ public class SqliteMigraterIntegrationTest {
TestHelper.returnDefaultsForAllProperties(settings);
File sqliteDbFile = TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "datasource/sqlite.april2016.db");
File tempFile = temporaryFolder.newFile();
dataFolder = temporaryFolder.newFolder();
File tempFile = new File(dataFolder, "authme.db");
Files.copy(sqliteDbFile, tempFile);
Connection con = DriverManager.getConnection("jdbc:sqlite:" + tempFile.getPath());
sqLite = createSqliteAndInitialize(settings, con);
sqLite = createSqlite(settings, dataFolder, con);
sqliteMigrater = new SqliteMigrater();
ReflectionTestUtils.setField(sqliteMigrater, "dataSource", sqLite);
ReflectionTestUtils.setField(sqliteMigrater, "settings", settings);
ReflectionTestUtils.setField(sqliteMigrater, "confirmationCode", CONFIRMATION_CODE);
sqliteMigrater.setSqLiteField();
}
@Test
public void shouldRun() throws ClassNotFoundException, SQLException {
// given
CommandSender sender = mock(CommandSender.class);
// when
sqliteMigrater.execute(sender, Collections.singletonList(CONFIRMATION_CODE));
// given / when
sqLite.setup();
sqLite.migrateIfNeeded();
// then
List<PlayerAuth> auths = sqLite.getAllAuths();
@@ -99,6 +89,12 @@ public class SqliteMigraterIntegrationTest {
assertThat(auth6, hasAuthBasicData("mysql6", "MySql6", "user6@example.com", "44.45.67.188"));
assertThat(auth6, hasAuthLocation(28.5, 53.43, -147.23, "world6", 0, 0));
assertThat(auth6.getLastLogin(), equalTo(1472992686300L));
// Check that backup was made
File backupsFolder = new File(dataFolder, "backups");
assertThat(backupsFolder.exists(), equalTo(true));
assertThat(backupsFolder.isDirectory(), equalTo(true));
assertThat(backupsFolder.list(), arrayContaining(containsString("authme")));
}
private static PlayerAuth getByNameOrFail(String name, List<PlayerAuth> auths) {
@@ -5,6 +5,7 @@ import fr.xephi.authme.datasource.mysqlextensions.MySqlExtension;
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtensionsFactory;
import fr.xephi.authme.settings.Settings;
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
@@ -26,27 +27,23 @@ public final class SqlDataSourceTestUtil {
return new MySQL(settings, hikariDataSource, extensionsFactory);
}
public static SQLite createSqlite(Settings settings, Connection connection) {
return new SQLite(settings, connection) {
public static SQLite createSqlite(Settings settings, File dataFolder, Connection connection) {
return new SQLite(settings, dataFolder, connection) {
// Override reload() so it doesn't run SQLite#connect, since we're given a specific Connection to use
@Override
public void reload() {
try {
this.setup();
this.migrateIfNeeded();
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}
@Override
protected void connect() {
// noop
}
};
}
public static SQLite createSqliteAndInitialize(Settings settings, Connection connection) {
SQLite sqLite = createSqlite(settings, connection);
try {
sqLite.setup();
} catch (SQLException e) {
throw new IllegalStateException(e);
}
return sqLite;
}
}