summaryrefslogtreecommitdiff
path: root/storage/database
diff options
context:
space:
mode:
Diffstat (limited to 'storage/database')
-rw-r--r--storage/database/build.gradle3
-rw-r--r--storage/database/src/main/java/de/danoeh/antennapod/storage/database/FeedItemDuplicateGuesser.java8
-rw-r--r--storage/database/src/test/java/de/danoeh/antennapod/storage/database/FeedItemPermutorsTest.java231
-rw-r--r--storage/database/src/test/java/de/danoeh/antennapod/storage/database/mapper/FeedCursorMapperTest.java100
4 files changed, 338 insertions, 4 deletions
diff --git a/storage/database/build.gradle b/storage/database/build.gradle
index 63f9eeaec..a78afbf79 100644
--- a/storage/database/build.gradle
+++ b/storage/database/build.gradle
@@ -28,6 +28,9 @@ dependencies {
implementation "commons-io:commons-io:$commonsioVersion"
implementation "org.greenrobot:eventbus:$eventbusVersion"
implementation "com.google.guava:guava:31.0.1-android"
+ implementation "org.apache.commons:commons-lang3:$commonslangVersion"
testImplementation "junit:junit:$junitVersion"
+ testImplementation "androidx.test:core:$testCoreVersion"
+ testImplementation "org.robolectric:robolectric:$robolectricVersion"
}
diff --git a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/FeedItemDuplicateGuesser.java b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/FeedItemDuplicateGuesser.java
index bbaedb519..19a2bd5f1 100644
--- a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/FeedItemDuplicateGuesser.java
+++ b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/FeedItemDuplicateGuesser.java
@@ -1,11 +1,11 @@
package de.danoeh.antennapod.storage.database;
-import android.text.TextUtils;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
import java.text.DateFormat;
import java.util.Locale;
+import org.apache.commons.lang3.StringUtils;
/**
* Publishers sometimes mess up their feed by adding episodes twice or by changing the ID of existing episodes.
@@ -32,7 +32,7 @@ public class FeedItemDuplicateGuesser {
}
public static boolean sameAndNotEmpty(String string1, String string2) {
- if (TextUtils.isEmpty(string1) || TextUtils.isEmpty(string2)) {
+ if (StringUtils.isEmpty(string1) || StringUtils.isEmpty(string2)) {
return false;
}
return string1.equals(string2);
@@ -45,7 +45,7 @@ public class FeedItemDuplicateGuesser {
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US); // MM/DD/YY
String dateOriginal = dateFormat.format(item2.getPubDate());
String dateNew = dateFormat.format(item1.getPubDate());
- return TextUtils.equals(dateOriginal, dateNew); // Same date; time is ignored.
+ return StringUtils.equals(dateOriginal, dateNew); // Same date; time is ignored.
}
private static boolean durationsLookSimilar(FeedMedia media1, FeedMedia media2) {
@@ -62,7 +62,7 @@ public class FeedItemDuplicateGuesser {
mimeType1 = mimeType1.substring(0, mimeType1.indexOf("/"));
mimeType2 = mimeType2.substring(0, mimeType2.indexOf("/"));
}
- return TextUtils.equals(mimeType1, mimeType2);
+ return StringUtils.equals(mimeType1, mimeType2);
}
private static boolean titlesLookSimilar(FeedItem item1, FeedItem item2) {
diff --git a/storage/database/src/test/java/de/danoeh/antennapod/storage/database/FeedItemPermutorsTest.java b/storage/database/src/test/java/de/danoeh/antennapod/storage/database/FeedItemPermutorsTest.java
new file mode 100644
index 000000000..9e0f106fd
--- /dev/null
+++ b/storage/database/src/test/java/de/danoeh/antennapod/storage/database/FeedItemPermutorsTest.java
@@ -0,0 +1,231 @@
+package de.danoeh.antennapod.storage.database;
+
+import de.danoeh.antennapod.model.feed.SortOrder;
+import de.danoeh.antennapod.storage.database.FeedItemPermutors;
+import de.danoeh.antennapod.storage.database.Permutor;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+import de.danoeh.antennapod.model.feed.Feed;
+import de.danoeh.antennapod.model.feed.FeedItem;
+import de.danoeh.antennapod.model.feed.FeedMedia;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test class for FeedItemPermutors.
+ */
+public class FeedItemPermutorsTest {
+
+ @Test
+ public void testEnsureNonNullPermutors() {
+ for (SortOrder sortOrder : SortOrder.values()) {
+ assertNotNull("The permutor for SortOrder " + sortOrder + " is unexpectedly null",
+ FeedItemPermutors.getPermutor(sortOrder));
+ }
+ }
+
+ @Test
+ public void testPermutorForRule_EPISODE_TITLE_ASC() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.EPISODE_TITLE_A_Z);
+
+ List<FeedItem> itemList = getTestList();
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 1, 2, 3)); // after sorting
+ }
+
+ @Test
+ public void testPermutorForRule_EPISODE_TITLE_ASC_NullTitle() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.EPISODE_TITLE_A_Z);
+
+ List<FeedItem> itemList = getTestList();
+ itemList.get(2) // itemId 2
+ .setTitle(null);
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 2, 1, 3)); // after sorting
+ }
+
+
+ @Test
+ public void testPermutorForRule_EPISODE_TITLE_DESC() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.EPISODE_TITLE_Z_A);
+
+ List<FeedItem> itemList = getTestList();
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 3, 2, 1)); // after sorting
+ }
+
+ @Test
+ public void testPermutorForRule_DATE_ASC() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.DATE_OLD_NEW);
+
+ List<FeedItem> itemList = getTestList();
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 1, 2, 3)); // after sorting
+ }
+
+ @Test
+ public void testPermutorForRule_DATE_ASC_NulPubDatel() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.DATE_OLD_NEW);
+
+ List<FeedItem> itemList = getTestList();
+ itemList.get(2) // itemId 2
+ .setPubDate(null);
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 2, 1, 3)); // after sorting
+ }
+
+ @Test
+ public void testPermutorForRule_DATE_DESC() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.DATE_NEW_OLD);
+
+ List<FeedItem> itemList = getTestList();
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 3, 2, 1)); // after sorting
+ }
+
+ @Test
+ public void testPermutorForRule_DURATION_ASC() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.DURATION_SHORT_LONG);
+
+ List<FeedItem> itemList = getTestList();
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 1, 2, 3)); // after sorting
+ }
+
+ @Test
+ public void testPermutorForRule_DURATION_DESC() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.DURATION_LONG_SHORT);
+
+ List<FeedItem> itemList = getTestList();
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 3, 2, 1)); // after sorting
+ }
+
+ @Test
+ public void testPermutorForRule_size_asc() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.SIZE_SMALL_LARGE);
+
+ List<FeedItem> itemList = getTestList();
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 1, 2, 3)); // after sorting
+ }
+
+ @Test
+ public void testPermutorForRule_size_desc() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.SIZE_LARGE_SMALL);
+
+ List<FeedItem> itemList = getTestList();
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 3, 2, 1)); // after sorting
+ }
+
+ @Test
+ public void testPermutorForRule_DURATION_DESC_NullMedia() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.DURATION_LONG_SHORT);
+
+ List<FeedItem> itemList = getTestList();
+ itemList.get(1) // itemId 3
+ .setMedia(null);
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 2, 1, 3)); // after sorting
+ }
+
+ @Test
+ public void testPermutorForRule_FEED_TITLE_ASC() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.FEED_TITLE_A_Z);
+
+ List<FeedItem> itemList = getTestList();
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 1, 2, 3)); // after sorting
+ }
+
+ @Test
+ public void testPermutorForRule_FEED_TITLE_DESC() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.FEED_TITLE_Z_A);
+
+ List<FeedItem> itemList = getTestList();
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 3, 2, 1)); // after sorting
+ }
+
+ @Test
+ public void testPermutorForRule_FEED_TITLE_DESC_NullTitle() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.FEED_TITLE_Z_A);
+
+ List<FeedItem> itemList = getTestList();
+ itemList.get(1) // itemId 3
+ .getFeed().setTitle(null);
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 2, 1, 3)); // after sorting
+ }
+
+ /**
+ * Generates a list with test data.
+ */
+ private List<FeedItem> getTestList() {
+ List<FeedItem> itemList = new ArrayList<>();
+
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2019, 0, 1); // January 1st
+ Feed feed1 = new Feed(null, null, "Feed title 1");
+ FeedItem feedItem1 = new FeedItem(1, "Title 1", null, null, calendar.getTime(), 0, feed1);
+ FeedMedia feedMedia1 = new FeedMedia(0, feedItem1, 1000, 0, 100, null, null, null, true, null, 0, 0);
+ feedItem1.setMedia(feedMedia1);
+ itemList.add(feedItem1);
+
+ calendar.set(2019, 2, 1); // March 1st
+ Feed feed2 = new Feed(null, null, "Feed title 3");
+ FeedItem feedItem2 = new FeedItem(3, "Title 3", null, null, calendar.getTime(), 0, feed2);
+ FeedMedia feedMedia2 = new FeedMedia(0, feedItem2, 3000, 0, 300, null, null, null, true, null, 0, 0);
+ feedItem2.setMedia(feedMedia2);
+ itemList.add(feedItem2);
+
+ calendar.set(2019, 1, 1); // February 1st
+ Feed feed3 = new Feed(null, null, "Feed title 2");
+ FeedItem feedItem3 = new FeedItem(2, "Title 2", null, null, calendar.getTime(), 0, feed3);
+ FeedMedia feedMedia3 = new FeedMedia(0, feedItem3, 2000, 0, 200, null, null, null, true, null, 0, 0);
+ feedItem3.setMedia(feedMedia3);
+ itemList.add(feedItem3);
+
+ return itemList;
+ }
+
+ /**
+ * Checks if both lists have the same size and the same ID order.
+ *
+ * @param itemList Item list.
+ * @param ids List of IDs.
+ * @return <code>true</code> if both lists have the same size and the same ID order.
+ */
+ private boolean checkIdOrder(List<FeedItem> itemList, long... ids) {
+ if (itemList.size() != ids.length) {
+ return false;
+ }
+
+ for (int i = 0; i < ids.length; i++) {
+ if (itemList.get(i).getId() != ids[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/storage/database/src/test/java/de/danoeh/antennapod/storage/database/mapper/FeedCursorMapperTest.java b/storage/database/src/test/java/de/danoeh/antennapod/storage/database/mapper/FeedCursorMapperTest.java
new file mode 100644
index 000000000..5e7a4843e
--- /dev/null
+++ b/storage/database/src/test/java/de/danoeh/antennapod/storage/database/mapper/FeedCursorMapperTest.java
@@ -0,0 +1,100 @@
+package de.danoeh.antennapod.storage.database.mapper;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import de.danoeh.antennapod.model.feed.Feed;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(RobolectricTestRunner.class)
+public class FeedCursorMapperTest {
+ private PodDBAdapter adapter;
+
+ @Before
+ public void setUp() {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+
+ PodDBAdapter.init(context);
+ adapter = PodDBAdapter.getInstance();
+
+ writeFeedToDatabase();
+ }
+
+ @After
+ public void tearDown() {
+ PodDBAdapter.tearDownTests();
+ }
+
+ @SuppressWarnings("ConstantConditions")
+ @Test
+ public void testFromCursor() {
+ try (Cursor cursor = adapter.getAllFeedsCursor()) {
+ cursor.moveToNext();
+ Feed feed = FeedCursorMapper.convert(cursor);
+ assertTrue(feed.getId() >= 0);
+ assertEquals("feed custom title", feed.getTitle());
+ assertEquals("feed custom title", feed.getCustomTitle());
+ assertEquals("feed link", feed.getLink());
+ assertEquals("feed description", feed.getDescription());
+ assertEquals("feed payment link", feed.getPaymentLinks().get(0).url);
+ assertEquals("feed author", feed.getAuthor());
+ assertEquals("feed language", feed.getLanguage());
+ assertEquals("feed image url", feed.getImageUrl());
+ assertEquals("feed file url", feed.getLocalFileUrl());
+ assertEquals("feed download url", feed.getDownloadUrl());
+ assertEquals(42, feed.getLastRefreshAttempt());
+ assertEquals("feed last update", feed.getLastModified());
+ assertEquals("feed type", feed.getType());
+ assertEquals("feed identifier", feed.getFeedIdentifier());
+ assertTrue(feed.isPaged());
+ assertEquals("feed next page link", feed.getNextPageLink());
+ assertTrue(feed.getItemFilter().showUnplayed);
+ assertEquals(1, feed.getSortOrder().code);
+ assertTrue(feed.hasLastUpdateFailed());
+ }
+ }
+
+ /**
+ * Insert test data to the database.
+ * Uses raw database insert instead of adapter.setCompleteFeed() to avoid testing the Feed class
+ * against itself.
+ */
+ private void writeFeedToDatabase() {
+ ContentValues values = new ContentValues();
+ values.put(PodDBAdapter.KEY_TITLE, "feed title");
+ values.put(PodDBAdapter.KEY_CUSTOM_TITLE, "feed custom title");
+ values.put(PodDBAdapter.KEY_LINK, "feed link");
+ values.put(PodDBAdapter.KEY_DESCRIPTION, "feed description");
+ values.put(PodDBAdapter.KEY_PAYMENT_LINK, "feed payment link");
+ values.put(PodDBAdapter.KEY_AUTHOR, "feed author");
+ values.put(PodDBAdapter.KEY_LANGUAGE, "feed language");
+ values.put(PodDBAdapter.KEY_IMAGE_URL, "feed image url");
+
+ values.put(PodDBAdapter.KEY_FILE_URL, "feed file url");
+ values.put(PodDBAdapter.KEY_DOWNLOAD_URL, "feed download url");
+ values.put(PodDBAdapter.KEY_LAST_REFRESH_ATTEMPT, 42);
+ values.put(PodDBAdapter.KEY_LASTUPDATE, "feed last update");
+ values.put(PodDBAdapter.KEY_TYPE, "feed type");
+ values.put(PodDBAdapter.KEY_FEED_IDENTIFIER, "feed identifier");
+
+ values.put(PodDBAdapter.KEY_IS_PAGED, true);
+ values.put(PodDBAdapter.KEY_NEXT_PAGE_LINK, "feed next page link");
+ values.put(PodDBAdapter.KEY_HIDE, "unplayed");
+ values.put(PodDBAdapter.KEY_SORT_ORDER, "1");
+ values.put(PodDBAdapter.KEY_LAST_UPDATE_FAILED, true);
+
+ adapter.insertTestData(PodDBAdapter.TABLE_NAME_FEEDS, values);
+ }
+}