mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-09 18:48:51 -06:00
Add more constraints on table Repetitions
This commit is contained in:
@@ -19,6 +19,9 @@
|
||||
|
||||
package org.isoron.uhabits.core;
|
||||
|
||||
import android.support.annotation.*;
|
||||
|
||||
import org.apache.commons.io.*;
|
||||
import org.isoron.uhabits.core.commands.*;
|
||||
import org.isoron.uhabits.core.database.*;
|
||||
import org.isoron.uhabits.core.models.*;
|
||||
@@ -30,11 +33,13 @@ import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
import org.mockito.junit.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.validateMockitoUsage;
|
||||
import sun.reflect.generics.reflectiveObjects.*;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class BaseUnitTest
|
||||
@@ -53,6 +58,29 @@ public class BaseUnitTest
|
||||
|
||||
protected CommandRunner commandRunner;
|
||||
|
||||
protected DatabaseOpener databaseOpener = new DatabaseOpener()
|
||||
{
|
||||
@Override
|
||||
public Database open(@NonNull File file)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new JdbcDatabase(DriverManager.getConnection(
|
||||
String.format("jdbc:sqlite:%s", file.getAbsolutePath())));
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getProductionDatabaseFile()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
};
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
@@ -91,8 +119,9 @@ public class BaseUnitTest
|
||||
{
|
||||
Database db = new JdbcDatabase(
|
||||
DriverManager.getConnection("jdbc:sqlite::memory:"));
|
||||
db.execute("pragma user_version=8;");
|
||||
MigrationHelper helper = new MigrationHelper(db);
|
||||
helper.executeMigrations(8, 21);
|
||||
helper.migrateTo(21);
|
||||
return db;
|
||||
}
|
||||
catch (SQLException e)
|
||||
@@ -100,4 +129,33 @@ public class BaseUnitTest
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void copyAssetToFile(String assetPath, File dst)
|
||||
throws IOException
|
||||
{
|
||||
IOUtils.copy(openAsset(assetPath), new FileOutputStream(dst));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected InputStream openAsset(String assetPath) throws IOException
|
||||
{
|
||||
InputStream in = getClass().getResourceAsStream(assetPath);
|
||||
if (in != null) return in;
|
||||
|
||||
String basePath = "uhabits-core/src/test/resources/";
|
||||
File file = new File(basePath + assetPath);
|
||||
if (file.exists() && file.canRead()) in = new FileInputStream(file);
|
||||
if (in != null) return in;
|
||||
|
||||
throw new IllegalStateException("asset not found: " + assetPath);
|
||||
}
|
||||
|
||||
protected Database openDatabaseResource(String path) throws IOException
|
||||
{
|
||||
InputStream original = openAsset(path);
|
||||
File tmpDbFile = File.createTempFile("database", ".db");
|
||||
tmpDbFile.deleteOnExit();
|
||||
IOUtils.copy(original, new FileOutputStream(tmpDbFile));
|
||||
return databaseOpener.open(tmpDbFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.core.database.migrations;
|
||||
|
||||
import org.isoron.uhabits.core.*;
|
||||
import org.isoron.uhabits.core.database.*;
|
||||
import org.isoron.uhabits.core.models.*;
|
||||
import org.isoron.uhabits.core.models.sqlite.*;
|
||||
import org.isoron.uhabits.core.test.*;
|
||||
import org.junit.*;
|
||||
import org.junit.rules.*;
|
||||
|
||||
import static junit.framework.TestCase.*;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
public class Version22Test extends BaseUnitTest
|
||||
{
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
private Database db;
|
||||
|
||||
private MigrationHelper helper;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
db = openDatabaseResource("/databases/021.db");
|
||||
helper = new MigrationHelper(db);
|
||||
modelFactory = new SQLModelFactory(db);
|
||||
habitList = modelFactory.buildHabitList();
|
||||
fixtures = new HabitFixtures(modelFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeepValidReps() throws Exception
|
||||
{
|
||||
db.query("select count(*) from repetitions",
|
||||
(c) -> assertThat(c.getInt(0), equalTo(3)));
|
||||
|
||||
helper.migrateTo(22);
|
||||
|
||||
db.query("select count(*) from repetitions",
|
||||
(c) -> assertThat(c.getInt(0), equalTo(3)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveRepsWithInvalidId() throws Exception
|
||||
{
|
||||
db.execute("insert into Repetitions(habit, timestamp, value) " +
|
||||
"values (99999, 100, 2)");
|
||||
db.query("select count(*) from repetitions where habit = 99999",
|
||||
(c) -> assertThat(c.getInt(0), equalTo(1)));
|
||||
|
||||
helper.migrateTo(22);
|
||||
|
||||
db.query("select count(*) from repetitions where habit = 99999",
|
||||
(c) -> assertThat(c.getInt(0), equalTo(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisallowNewRepsWithInvalidRef() throws Exception
|
||||
{
|
||||
helper.migrateTo(22);
|
||||
exception.expectMessage(containsString("FOREIGNKEY"));
|
||||
db.execute("insert into Repetitions(habit, timestamp, value) " +
|
||||
"values (99999, 100, 2)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveRepetitionsWithNullTimestamp() throws Exception
|
||||
{
|
||||
db.execute("insert into repetitions(habit, value) values (0, 2)");
|
||||
db.query("select count(*) from repetitions where timestamp is null",
|
||||
(c) -> assertThat(c.getInt(0), equalTo(1)));
|
||||
|
||||
helper.migrateTo(22);
|
||||
|
||||
db.query("select count(*) from repetitions where timestamp is null",
|
||||
(c) -> assertThat(c.getInt(0), equalTo(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisallowNullTimestamp() throws Exception
|
||||
{
|
||||
helper.migrateTo(22);
|
||||
exception.expectMessage(containsString("SQLITE_CONSTRAINT_NOTNULL"));
|
||||
db.execute("insert into Repetitions(habit, value) " + "values (0, 2)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveRepetitionsWithNullHabit() throws Exception
|
||||
{
|
||||
db.execute("insert into repetitions(timestamp, value) values (0, 2)");
|
||||
db.query("select count(*) from repetitions where habit is null",
|
||||
(c) -> assertThat(c.getInt(0), equalTo(1)));
|
||||
|
||||
helper.migrateTo(22);
|
||||
|
||||
db.query("select count(*) from repetitions where habit is null",
|
||||
(c) -> assertThat(c.getInt(0), equalTo(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisallowNullHabit() throws Exception
|
||||
{
|
||||
helper.migrateTo(22);
|
||||
exception.expectMessage(containsString("SQLITE_CONSTRAINT_NOTNULL"));
|
||||
db.execute(
|
||||
"insert into Repetitions(timestamp, value) " + "values (5, 2)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveDuplicateRepetitions() throws Exception
|
||||
{
|
||||
db.execute("insert into repetitions(habit, timestamp, value)" +
|
||||
"values (0, 100, 2)");
|
||||
db.execute("insert into repetitions(habit, timestamp, value)" +
|
||||
"values (0, 100, 5)");
|
||||
db.execute("insert into repetitions(habit, timestamp, value)" +
|
||||
"values (0, 100, 10)");
|
||||
db.query(
|
||||
"select count(*) from repetitions where timestamp=100 and habit=0",
|
||||
(c) -> assertThat(c.getInt(0), equalTo(3)));
|
||||
|
||||
helper.migrateTo(22);
|
||||
|
||||
db.query(
|
||||
"select count(*) from repetitions where timestamp=100 and habit=0",
|
||||
(c) -> assertThat(c.getInt(0), equalTo(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisallowNewDuplicateTimestamps() throws Exception
|
||||
{
|
||||
helper.migrateTo(22);
|
||||
db.execute("insert into repetitions(habit, timestamp, value)" +
|
||||
"values (0, 100, 2)");
|
||||
exception.expectMessage(containsString("SQLITE_CONSTRAINT_UNIQUE"));
|
||||
db.execute("insert into repetitions(habit, timestamp, value)" +
|
||||
"values (0, 100, 5)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeepHabitsUnchanged() throws Exception
|
||||
{
|
||||
Habit original = fixtures.createLongHabit();
|
||||
Reminder reminder = new Reminder(8, 30, new WeekdayList(100));
|
||||
original.setReminder(reminder);
|
||||
habitList.update(original);
|
||||
|
||||
helper.migrateTo(22);
|
||||
|
||||
((SQLiteHabitList) habitList).reload();
|
||||
Habit modified = habitList.getById(original.getId());
|
||||
assertNotNull(modified);
|
||||
|
||||
assertThat(original.getData(), equalTo(modified.getData()));
|
||||
}
|
||||
}
|
||||
@@ -19,25 +19,18 @@
|
||||
|
||||
package org.isoron.uhabits.core.io;
|
||||
|
||||
import android.support.annotation.*;
|
||||
|
||||
import org.apache.commons.io.*;
|
||||
import org.isoron.uhabits.core.*;
|
||||
import org.isoron.uhabits.core.database.*;
|
||||
import org.isoron.uhabits.core.models.*;
|
||||
import org.isoron.uhabits.core.utils.*;
|
||||
import org.junit.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
|
||||
import sun.reflect.generics.reflectiveObjects.*;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.core.IsEqual.*;
|
||||
import static org.isoron.uhabits.core.models.Frequency.THREE_TIMES_PER_WEEK;
|
||||
import static org.isoron.uhabits.core.models.Frequency.*;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ImportTest extends BaseUnitTest
|
||||
@@ -67,6 +60,7 @@ public class ImportTest extends BaseUnitTest
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testLoopDB() throws IOException
|
||||
{
|
||||
importFromFile("loop.db");
|
||||
@@ -131,17 +125,6 @@ public class ImportTest extends BaseUnitTest
|
||||
return h.getRepetitions().containsTimestamp(date.getTimeInMillis());
|
||||
}
|
||||
|
||||
private void copyAssetToFile(String assetPath, File dst) throws IOException
|
||||
{
|
||||
InputStream in = getClass().getResourceAsStream(assetPath);
|
||||
if(in == null) {
|
||||
File file = new File("uhabits-core/src/test/resources/" + assetPath);
|
||||
if(file.exists()) in = new FileInputStream(file);
|
||||
}
|
||||
|
||||
IOUtils.copy(in, new FileOutputStream(dst));
|
||||
}
|
||||
|
||||
private void importFromFile(String assetFilename) throws IOException
|
||||
{
|
||||
File file = File.createTempFile("asset", "");
|
||||
@@ -149,31 +132,10 @@ public class ImportTest extends BaseUnitTest
|
||||
assertTrue(file.exists());
|
||||
assertTrue(file.canRead());
|
||||
|
||||
DatabaseOpener opener = new DatabaseOpener() {
|
||||
@Override
|
||||
public Database open(@NonNull File file)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new JdbcDatabase(DriverManager.getConnection(
|
||||
String.format("jdbc:sqlite:%s", file.getAbsolutePath())));
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getProductionDatabaseFile()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
};
|
||||
GenericImporter importer = new GenericImporter(habitList,
|
||||
new LoopDBImporter(habitList, opener),
|
||||
new RewireDBImporter(habitList, modelFactory, opener),
|
||||
new TickmateDBImporter(habitList, modelFactory, opener),
|
||||
new LoopDBImporter(habitList, databaseOpener),
|
||||
new RewireDBImporter(habitList, modelFactory, databaseOpener),
|
||||
new TickmateDBImporter(habitList, modelFactory, databaseOpener),
|
||||
new HabitBullCSVImporter(habitList, modelFactory));
|
||||
|
||||
assertTrue(importer.canHandle(file));
|
||||
|
||||
BIN
uhabits-core/src/test/resources/databases/021.db
Normal file
BIN
uhabits-core/src/test/resources/databases/021.db
Normal file
Binary file not shown.
Reference in New Issue
Block a user