diff --git a/app/src/androidTest/java/org/schabi/newpipe/error/ErrorInfoTest.java b/app/src/androidTest/java/org/schabi/newpipe/error/ErrorInfoTest.java deleted file mode 100644 index 891824a55..000000000 --- a/app/src/androidTest/java/org/schabi/newpipe/error/ErrorInfoTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.schabi.newpipe.error; - -import android.os.Parcel; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.LargeTest; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.schabi.newpipe.R; -import org.schabi.newpipe.extractor.ServiceList; -import org.schabi.newpipe.extractor.exceptions.ParsingException; - -import java.util.Arrays; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * Instrumented tests for {@link ErrorInfo}. - */ -@RunWith(AndroidJUnit4.class) -@LargeTest -public class ErrorInfoTest { - - @Test - public void errorInfoTestParcelable() { - final ErrorInfo info = new ErrorInfo(new ParsingException("Hello"), - UserAction.USER_REPORT, "request", ServiceList.YouTube.getServiceId()); - // Obtain a Parcel object and write the parcelable object to it: - final Parcel parcel = Parcel.obtain(); - info.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - final ErrorInfo infoFromParcel = (ErrorInfo) ErrorInfo.CREATOR.createFromParcel(parcel); - - assertTrue(Arrays.toString(infoFromParcel.getStackTraces()) - .contains(ErrorInfoTest.class.getSimpleName())); - assertEquals(UserAction.USER_REPORT, infoFromParcel.getUserAction()); - assertEquals(ServiceList.YouTube.getServiceInfo().getName(), - infoFromParcel.getServiceName()); - assertEquals("request", infoFromParcel.getRequest()); - assertEquals(R.string.parsing_error, infoFromParcel.getMessageStringId()); - - parcel.recycle(); - } -} diff --git a/app/src/androidTest/java/org/schabi/newpipe/error/ErrorInfoTest.kt b/app/src/androidTest/java/org/schabi/newpipe/error/ErrorInfoTest.kt new file mode 100644 index 000000000..3c9431658 --- /dev/null +++ b/app/src/androidTest/java/org/schabi/newpipe/error/ErrorInfoTest.kt @@ -0,0 +1,36 @@ +package org.schabi.newpipe.error + +import android.os.Parcel +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.LargeTest +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith +import org.schabi.newpipe.R +import org.schabi.newpipe.extractor.ServiceList +import org.schabi.newpipe.extractor.exceptions.ParsingException + +/** + * Instrumented tests for [ErrorInfo]. + */ +@RunWith(AndroidJUnit4::class) +@LargeTest +class ErrorInfoTest { + @Test + fun errorInfoTestParcelable() { + val info = ErrorInfo(ParsingException("Hello"), + UserAction.USER_REPORT, "request", ServiceList.YouTube.serviceId) + // Obtain a Parcel object and write the parcelable object to it: + val parcel = Parcel.obtain() + info.writeToParcel(parcel, 0) + parcel.setDataPosition(0) + val infoFromParcel = ErrorInfo.CREATOR.createFromParcel(parcel) as ErrorInfo + Assert.assertTrue(infoFromParcel.stackTraces.contentToString().contains(ErrorInfoTest::class.java.getSimpleName())) + Assert.assertEquals(UserAction.USER_REPORT, infoFromParcel.userAction) + Assert.assertEquals(ServiceList.YouTube.serviceInfo.name, + infoFromParcel.serviceName) + Assert.assertEquals("request", infoFromParcel.request) + Assert.assertEquals(R.string.parsing_error.toLong(), infoFromParcel.messageStringId.toLong()) + parcel.recycle() + } +} diff --git a/app/src/androidTest/java/org/schabi/newpipe/local/subscription/SubscriptionManagerTest.java b/app/src/androidTest/java/org/schabi/newpipe/local/subscription/SubscriptionManagerTest.java deleted file mode 100644 index 213b679f0..000000000 --- a/app/src/androidTest/java/org/schabi/newpipe/local/subscription/SubscriptionManagerTest.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.schabi.newpipe.local.subscription; - -import static org.junit.Assert.assertEquals; - -import androidx.test.core.app.ApplicationProvider; - -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.schabi.newpipe.database.AppDatabase; -import org.schabi.newpipe.database.feed.model.FeedGroupEntity; -import org.schabi.newpipe.database.subscription.SubscriptionEntity; -import org.schabi.newpipe.extractor.channel.ChannelInfo; -import org.schabi.newpipe.extractor.exceptions.ExtractionException; -import org.schabi.newpipe.testUtil.TestDatabase; -import org.schabi.newpipe.testUtil.TrampolineSchedulerRule; - -import java.io.IOException; -import java.util.List; - -public class SubscriptionManagerTest { - private AppDatabase database; - private SubscriptionManager manager; - - @Rule - public TrampolineSchedulerRule trampolineScheduler = new TrampolineSchedulerRule(); - - - private SubscriptionEntity getAssertOneSubscriptionEntity() { - final List entities = manager - .getSubscriptions(FeedGroupEntity.GROUP_ALL_ID, "", false) - .blockingFirst(); - assertEquals(1, entities.size()); - return entities.get(0); - } - - - @Before - public void setup() { - database = TestDatabase.Companion.createReplacingNewPipeDatabase(); - manager = new SubscriptionManager(ApplicationProvider.getApplicationContext()); - } - - @After - public void cleanUp() { - database.close(); - } - - @Test - public void testInsert() throws ExtractionException, IOException { - final ChannelInfo info = ChannelInfo.getInfo("https://www.youtube.com/c/3blue1brown"); - final SubscriptionEntity subscription = SubscriptionEntity.from(info); - - manager.insertSubscription(subscription); - final SubscriptionEntity readSubscription = getAssertOneSubscriptionEntity(); - - // the uid has changed, since the uid is chosen upon inserting, but the rest should match - assertEquals(subscription.getServiceId(), readSubscription.getServiceId()); - assertEquals(subscription.getUrl(), readSubscription.getUrl()); - assertEquals(subscription.getName(), readSubscription.getName()); - assertEquals(subscription.getAvatarUrl(), readSubscription.getAvatarUrl()); - assertEquals(subscription.getSubscriberCount(), readSubscription.getSubscriberCount()); - assertEquals(subscription.getDescription(), readSubscription.getDescription()); - } - - @Test - public void testUpdateNotificationMode() throws ExtractionException, IOException { - final ChannelInfo info = ChannelInfo.getInfo("https://www.youtube.com/c/veritasium"); - final SubscriptionEntity subscription = SubscriptionEntity.from(info); - subscription.setNotificationMode(0); - - manager.insertSubscription(subscription); - manager.updateNotificationMode(subscription.getServiceId(), subscription.getUrl(), 1) - .blockingAwait(); - final SubscriptionEntity anotherSubscription = getAssertOneSubscriptionEntity(); - - assertEquals(0, subscription.getNotificationMode()); - assertEquals(subscription.getUrl(), anotherSubscription.getUrl()); - assertEquals(1, anotherSubscription.getNotificationMode()); - } -} diff --git a/app/src/androidTest/java/org/schabi/newpipe/local/subscription/SubscriptionManagerTest.kt b/app/src/androidTest/java/org/schabi/newpipe/local/subscription/SubscriptionManagerTest.kt new file mode 100644 index 000000000..dcae5c9f3 --- /dev/null +++ b/app/src/androidTest/java/org/schabi/newpipe/local/subscription/SubscriptionManagerTest.kt @@ -0,0 +1,76 @@ +package org.schabi.newpipe.local.subscription + +import androidx.test.core.app.ApplicationProvider +import org.junit.After +import org.junit.Assert +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.schabi.newpipe.database.AppDatabase +import org.schabi.newpipe.database.feed.model.FeedGroupEntity +import org.schabi.newpipe.database.subscription.SubscriptionEntity +import org.schabi.newpipe.database.subscription.SubscriptionEntity.Companion.from +import org.schabi.newpipe.extractor.channel.ChannelInfo +import org.schabi.newpipe.extractor.exceptions.ExtractionException +import org.schabi.newpipe.testUtil.TestDatabase.Companion.createReplacingNewPipeDatabase +import org.schabi.newpipe.testUtil.TrampolineSchedulerRule +import java.io.IOException + +class SubscriptionManagerTest { + private var database: AppDatabase? = null + private var manager: SubscriptionManager? = null + + @Rule + var trampolineScheduler = TrampolineSchedulerRule() + private val assertOneSubscriptionEntity: SubscriptionEntity + private get() { + val entities = manager + .getSubscriptions(FeedGroupEntity.GROUP_ALL_ID, "", false) + .blockingFirst() + Assert.assertEquals(1, entities.size.toLong()) + return entities[0] + } + + @Before + fun setup() { + database = createReplacingNewPipeDatabase() + manager = SubscriptionManager(ApplicationProvider.getApplicationContext()) + } + + @After + fun cleanUp() { + database!!.close() + } + + @Test + @Throws(ExtractionException::class, IOException::class) + fun testInsert() { + val info = ChannelInfo.getInfo("https://www.youtube.com/c/3blue1brown") + val subscription = from(info) + manager!!.insertSubscription(subscription) + val readSubscription = assertOneSubscriptionEntity + + // the uid has changed, since the uid is chosen upon inserting, but the rest should match + Assert.assertEquals(subscription.getServiceId().toLong(), readSubscription.getServiceId().toLong()) + Assert.assertEquals(subscription.getUrl(), readSubscription.getUrl()) + Assert.assertEquals(subscription.getName(), readSubscription.getName()) + Assert.assertEquals(subscription.getAvatarUrl(), readSubscription.getAvatarUrl()) + Assert.assertEquals(subscription.getSubscriberCount(), readSubscription.getSubscriberCount()) + Assert.assertEquals(subscription.getDescription(), readSubscription.getDescription()) + } + + @Test + @Throws(ExtractionException::class, IOException::class) + fun testUpdateNotificationMode() { + val info = ChannelInfo.getInfo("https://www.youtube.com/c/veritasium") + val subscription = from(info) + subscription.setNotificationMode(0) + manager!!.insertSubscription(subscription) + manager!!.updateNotificationMode(subscription.getServiceId(), subscription.getUrl()!!, 1) + .blockingAwait() + val anotherSubscription = assertOneSubscriptionEntity + Assert.assertEquals(0, subscription.getNotificationMode().toLong()) + Assert.assertEquals(subscription.getUrl(), anotherSubscription.getUrl()) + Assert.assertEquals(1, anotherSubscription.getNotificationMode().toLong()) + } +} diff --git a/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVDLeakCanary.java b/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVDLeakCanary.java deleted file mode 100644 index a2d65f6f4..000000000 --- a/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVDLeakCanary.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.schabi.newpipe.settings; - -import android.content.Intent; - -import leakcanary.LeakCanary; - -/** - * Build variant dependent (BVD) leak canary API implementation for the debug settings fragment. - * This class is loaded via reflection by - * {@link DebugSettingsFragment.DebugSettingsBVDLeakCanaryAPI}. - */ -@SuppressWarnings("unused") // Class is used but loaded via reflection -public class DebugSettingsBVDLeakCanary - implements DebugSettingsFragment.DebugSettingsBVDLeakCanaryAPI { - - @Override - public Intent getNewLeakDisplayActivityIntent() { - return LeakCanary.INSTANCE.newLeakDisplayActivityIntent(); - } -} diff --git a/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVDLeakCanary.kt b/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVDLeakCanary.kt new file mode 100644 index 000000000..2e3f36c33 --- /dev/null +++ b/app/src/debug/java/org/schabi/newpipe/settings/DebugSettingsBVDLeakCanary.kt @@ -0,0 +1,18 @@ +package org.schabi.newpipe.settings + +import android.content.Intent +import leakcanary.LeakCanary.newLeakDisplayActivityIntent +import org.schabi.newpipe.settings.DebugSettingsFragment.DebugSettingsBVDLeakCanaryAPI + +/** + * Build variant dependent (BVD) leak canary API implementation for the debug settings fragment. + * This class is loaded via reflection by + * [DebugSettingsFragment.DebugSettingsBVDLeakCanaryAPI]. + */ +@Suppress("unused") // Class is used but loaded via reflection + +class DebugSettingsBVDLeakCanary : DebugSettingsBVDLeakCanaryAPI { + override fun getNewLeakDisplayActivityIntent(): Intent? { + return newLeakDisplayActivityIntent() + } +} diff --git a/app/src/test/java/org/schabi/newpipe/database/playlist/PlaylistLocalItemTest.java b/app/src/test/java/org/schabi/newpipe/database/playlist/PlaylistLocalItemTest.java deleted file mode 100644 index 847c54aa8..000000000 --- a/app/src/test/java/org/schabi/newpipe/database/playlist/PlaylistLocalItemTest.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.schabi.newpipe.database.playlist; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity; -import org.schabi.newpipe.local.bookmark.MergedPlaylistManager; - -import java.util.ArrayList; -import java.util.List; - -public class PlaylistLocalItemTest { - @Test - public void emptyPlaylists() { - final List localPlaylists = new ArrayList<>(); - final List remotePlaylists = new ArrayList<>(); - final List mergedPlaylists = - MergedPlaylistManager.merge(localPlaylists, remotePlaylists); - - assertEquals(0, mergedPlaylists.size()); - } - - @Test - public void onlyLocalPlaylists() { - final List localPlaylists = new ArrayList<>(); - final List remotePlaylists = new ArrayList<>(); - localPlaylists.add(new PlaylistMetadataEntry(1, "name1", "", false, -1, 0, 1)); - localPlaylists.add(new PlaylistMetadataEntry(2, "name2", "", false, -1, 1, 1)); - localPlaylists.add(new PlaylistMetadataEntry(3, "name3", "", false, -1, 3, 1)); - final List mergedPlaylists = - MergedPlaylistManager.merge(localPlaylists, remotePlaylists); - - assertEquals(3, mergedPlaylists.size()); - assertEquals(0, mergedPlaylists.get(0).getDisplayIndex()); - assertEquals(1, mergedPlaylists.get(1).getDisplayIndex()); - assertEquals(3, mergedPlaylists.get(2).getDisplayIndex()); - } - - @Test - public void onlyRemotePlaylists() { - final List localPlaylists = new ArrayList<>(); - final List remotePlaylists = new ArrayList<>(); - remotePlaylists.add(new PlaylistRemoteEntity( - 1, "name1", "url1", "", "", 1, 1L)); - remotePlaylists.add(new PlaylistRemoteEntity( - 2, "name2", "url2", "", "", 2, 1L)); - remotePlaylists.add(new PlaylistRemoteEntity( - 3, "name3", "url3", "", "", 4, 1L)); - final List mergedPlaylists = - MergedPlaylistManager.merge(localPlaylists, remotePlaylists); - - assertEquals(3, mergedPlaylists.size()); - assertEquals(1, mergedPlaylists.get(0).getDisplayIndex()); - assertEquals(2, mergedPlaylists.get(1).getDisplayIndex()); - assertEquals(4, mergedPlaylists.get(2).getDisplayIndex()); - } - - @Test - public void sameIndexWithDifferentName() { - final List localPlaylists = new ArrayList<>(); - final List remotePlaylists = new ArrayList<>(); - localPlaylists.add(new PlaylistMetadataEntry(1, "name1", "", false, -1, 0, 1)); - localPlaylists.add(new PlaylistMetadataEntry(2, "name2", "", false, -1, 1, 1)); - remotePlaylists.add(new PlaylistRemoteEntity( - 1, "name3", "url1", "", "", 0, 1L)); - remotePlaylists.add(new PlaylistRemoteEntity( - 2, "name4", "url2", "", "", 1, 1L)); - final List mergedPlaylists = - MergedPlaylistManager.merge(localPlaylists, remotePlaylists); - - assertEquals(4, mergedPlaylists.size()); - assertTrue(mergedPlaylists.get(0) instanceof PlaylistMetadataEntry); - assertEquals("name1", ((PlaylistMetadataEntry) mergedPlaylists.get(0)).name); - assertTrue(mergedPlaylists.get(1) instanceof PlaylistRemoteEntity); - assertEquals("name3", ((PlaylistRemoteEntity) mergedPlaylists.get(1)).getName()); - assertTrue(mergedPlaylists.get(2) instanceof PlaylistMetadataEntry); - assertEquals("name2", ((PlaylistMetadataEntry) mergedPlaylists.get(2)).name); - assertTrue(mergedPlaylists.get(3) instanceof PlaylistRemoteEntity); - assertEquals("name4", ((PlaylistRemoteEntity) mergedPlaylists.get(3)).getName()); - } - - @Test - public void sameNameWithDifferentIndex() { - final List localPlaylists = new ArrayList<>(); - final List remotePlaylists = new ArrayList<>(); - localPlaylists.add(new PlaylistMetadataEntry(1, "name1", "", false, -1, 1, 1)); - localPlaylists.add(new PlaylistMetadataEntry(2, "name2", "", false, -1, 3, 1)); - remotePlaylists.add(new PlaylistRemoteEntity( - 1, "name1", "url1", "", "", 0, 1L)); - remotePlaylists.add(new PlaylistRemoteEntity( - 2, "name2", "url2", "", "", 2, 1L)); - final List mergedPlaylists = - MergedPlaylistManager.merge(localPlaylists, remotePlaylists); - - assertEquals(4, mergedPlaylists.size()); - assertTrue(mergedPlaylists.get(0) instanceof PlaylistRemoteEntity); - assertEquals("name1", ((PlaylistRemoteEntity) mergedPlaylists.get(0)).getName()); - assertTrue(mergedPlaylists.get(1) instanceof PlaylistMetadataEntry); - assertEquals("name1", ((PlaylistMetadataEntry) mergedPlaylists.get(1)).name); - assertTrue(mergedPlaylists.get(2) instanceof PlaylistRemoteEntity); - assertEquals("name2", ((PlaylistRemoteEntity) mergedPlaylists.get(2)).getName()); - assertTrue(mergedPlaylists.get(3) instanceof PlaylistMetadataEntry); - assertEquals("name2", ((PlaylistMetadataEntry) mergedPlaylists.get(3)).name); - } -} diff --git a/app/src/test/java/org/schabi/newpipe/database/playlist/PlaylistLocalItemTest.kt b/app/src/test/java/org/schabi/newpipe/database/playlist/PlaylistLocalItemTest.kt new file mode 100644 index 000000000..7aebed345 --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/database/playlist/PlaylistLocalItemTest.kt @@ -0,0 +1,91 @@ +package org.schabi.newpipe.database.playlist + +import org.junit.Assert +import org.junit.Test +import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity +import org.schabi.newpipe.local.bookmark.MergedPlaylistManager.merge + +class PlaylistLocalItemTest { + @Test + fun emptyPlaylists() { + val localPlaylists: List = ArrayList() + val remotePlaylists: List = ArrayList() + val mergedPlaylists = merge(localPlaylists, remotePlaylists) + Assert.assertEquals(0, mergedPlaylists.size.toLong()) + } + + @Test + fun onlyLocalPlaylists() { + val localPlaylists: MutableList = ArrayList() + val remotePlaylists: List = ArrayList() + localPlaylists.add(PlaylistMetadataEntry(1, "name1", "", false, -1, 0, 1)) + localPlaylists.add(PlaylistMetadataEntry(2, "name2", "", false, -1, 1, 1)) + localPlaylists.add(PlaylistMetadataEntry(3, "name3", "", false, -1, 3, 1)) + val mergedPlaylists = merge(localPlaylists, remotePlaylists) + Assert.assertEquals(3, mergedPlaylists.size.toLong()) + Assert.assertEquals(0, mergedPlaylists[0].getDisplayIndex()) + Assert.assertEquals(1, mergedPlaylists[1].getDisplayIndex()) + Assert.assertEquals(3, mergedPlaylists[2].getDisplayIndex()) + } + + @Test + fun onlyRemotePlaylists() { + val localPlaylists: List = ArrayList() + val remotePlaylists: MutableList = ArrayList() + remotePlaylists.add(PlaylistRemoteEntity( + 1, "name1", "url1", "", "", 1, 1L)) + remotePlaylists.add(PlaylistRemoteEntity( + 2, "name2", "url2", "", "", 2, 1L)) + remotePlaylists.add(PlaylistRemoteEntity( + 3, "name3", "url3", "", "", 4, 1L)) + val mergedPlaylists = merge(localPlaylists, remotePlaylists) + Assert.assertEquals(3, mergedPlaylists.size.toLong()) + Assert.assertEquals(1, mergedPlaylists[0].getDisplayIndex()) + Assert.assertEquals(2, mergedPlaylists[1].getDisplayIndex()) + Assert.assertEquals(4, mergedPlaylists[2].getDisplayIndex()) + } + + @Test + fun sameIndexWithDifferentName() { + val localPlaylists: MutableList = ArrayList() + val remotePlaylists: MutableList = ArrayList() + localPlaylists.add(PlaylistMetadataEntry(1, "name1", "", false, -1, 0, 1)) + localPlaylists.add(PlaylistMetadataEntry(2, "name2", "", false, -1, 1, 1)) + remotePlaylists.add(PlaylistRemoteEntity( + 1, "name3", "url1", "", "", 0, 1L)) + remotePlaylists.add(PlaylistRemoteEntity( + 2, "name4", "url2", "", "", 1, 1L)) + val mergedPlaylists = merge(localPlaylists, remotePlaylists) + Assert.assertEquals(4, mergedPlaylists.size.toLong()) + Assert.assertTrue(mergedPlaylists[0] is PlaylistMetadataEntry) + Assert.assertEquals("name1", (mergedPlaylists[0] as PlaylistMetadataEntry).name) + Assert.assertTrue(mergedPlaylists[1] is PlaylistRemoteEntity) + Assert.assertEquals("name3", (mergedPlaylists[1] as PlaylistRemoteEntity).getName()) + Assert.assertTrue(mergedPlaylists[2] is PlaylistMetadataEntry) + Assert.assertEquals("name2", (mergedPlaylists[2] as PlaylistMetadataEntry).name) + Assert.assertTrue(mergedPlaylists[3] is PlaylistRemoteEntity) + Assert.assertEquals("name4", (mergedPlaylists[3] as PlaylistRemoteEntity).getName()) + } + + @Test + fun sameNameWithDifferentIndex() { + val localPlaylists: MutableList = ArrayList() + val remotePlaylists: MutableList = ArrayList() + localPlaylists.add(PlaylistMetadataEntry(1, "name1", "", false, -1, 1, 1)) + localPlaylists.add(PlaylistMetadataEntry(2, "name2", "", false, -1, 3, 1)) + remotePlaylists.add(PlaylistRemoteEntity( + 1, "name1", "url1", "", "", 0, 1L)) + remotePlaylists.add(PlaylistRemoteEntity( + 2, "name2", "url2", "", "", 2, 1L)) + val mergedPlaylists = merge(localPlaylists, remotePlaylists) + Assert.assertEquals(4, mergedPlaylists.size.toLong()) + Assert.assertTrue(mergedPlaylists[0] is PlaylistRemoteEntity) + Assert.assertEquals("name1", (mergedPlaylists[0] as PlaylistRemoteEntity).getName()) + Assert.assertTrue(mergedPlaylists[1] is PlaylistMetadataEntry) + Assert.assertEquals("name1", (mergedPlaylists[1] as PlaylistMetadataEntry).name) + Assert.assertTrue(mergedPlaylists[2] is PlaylistRemoteEntity) + Assert.assertEquals("name2", (mergedPlaylists[2] as PlaylistRemoteEntity).getName()) + Assert.assertTrue(mergedPlaylists[3] is PlaylistMetadataEntry) + Assert.assertEquals("name2", (mergedPlaylists[3] as PlaylistMetadataEntry).name) + } +} diff --git a/app/src/test/java/org/schabi/newpipe/error/ErrorActivityTest.java b/app/src/test/java/org/schabi/newpipe/error/ErrorActivityTest.java deleted file mode 100644 index f77c7b268..000000000 --- a/app/src/test/java/org/schabi/newpipe/error/ErrorActivityTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.schabi.newpipe.error; - -import android.app.Activity; - -import org.junit.Test; -import org.schabi.newpipe.MainActivity; -import org.schabi.newpipe.RouterActivity; -import org.schabi.newpipe.fragments.detail.VideoDetailFragment; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -/** - * Unit tests for {@link ErrorActivity}. - */ -public class ErrorActivityTest { - @Test - public void getReturnActivity() { - Class returnActivity; - returnActivity = ErrorActivity.getReturnActivity(MainActivity.class); - assertEquals(MainActivity.class, returnActivity); - - returnActivity = ErrorActivity.getReturnActivity(RouterActivity.class); - assertEquals(RouterActivity.class, returnActivity); - - returnActivity = ErrorActivity.getReturnActivity(null); - assertNull(returnActivity); - - returnActivity = ErrorActivity.getReturnActivity(Integer.class); - assertEquals(MainActivity.class, returnActivity); - - returnActivity = ErrorActivity.getReturnActivity(VideoDetailFragment.class); - assertEquals(MainActivity.class, returnActivity); - } -} diff --git a/app/src/test/java/org/schabi/newpipe/error/ErrorActivityTest.kt b/app/src/test/java/org/schabi/newpipe/error/ErrorActivityTest.kt new file mode 100644 index 000000000..d6a9cd80f --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/error/ErrorActivityTest.kt @@ -0,0 +1,30 @@ +package org.schabi.newpipe.error + +import android.app.Activity +import org.junit.Assert +import org.junit.Test +import org.schabi.newpipe.MainActivity +import org.schabi.newpipe.RouterActivity +import org.schabi.newpipe.error.ErrorActivity.Companion.getReturnActivity +import org.schabi.newpipe.fragments.detail.VideoDetailFragment + +/** + * Unit tests for [ErrorActivity]. + */ +class ErrorActivityTest { + @get:Test + val returnActivity: Unit + get() { + var returnActivity: Class? + returnActivity = getReturnActivity(MainActivity::class.java) + Assert.assertEquals(MainActivity::class.java, returnActivity) + returnActivity = getReturnActivity(RouterActivity::class.java) + Assert.assertEquals(RouterActivity::class.java, returnActivity) + returnActivity = getReturnActivity(null) + Assert.assertNull(returnActivity) + returnActivity = getReturnActivity(Int::class.java) + Assert.assertEquals(MainActivity::class.java, returnActivity) + returnActivity = getReturnActivity(VideoDetailFragment::class.java) + Assert.assertEquals(MainActivity::class.java, returnActivity) + } +} diff --git a/app/src/test/java/org/schabi/newpipe/local/subscription/services/ImportExportJsonHelperTest.java b/app/src/test/java/org/schabi/newpipe/local/subscription/services/ImportExportJsonHelperTest.java deleted file mode 100644 index 4f0f125ec..000000000 --- a/app/src/test/java/org/schabi/newpipe/local/subscription/services/ImportExportJsonHelperTest.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.schabi.newpipe.local.subscription.services; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import org.junit.Test; -import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; -import org.schabi.newpipe.extractor.subscription.SubscriptionItem; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.List; - -/** - * @see ImportExportJsonHelper - */ -public class ImportExportJsonHelperTest { - @Test - public void testEmptySource() throws Exception { - final String emptySource = - "{\"app_version\":\"0.11.6\",\"app_version_int\": 47,\"subscriptions\":[]}"; - - final List items = ImportExportJsonHelper.readFrom( - new ByteArrayInputStream(emptySource.getBytes(StandardCharsets.UTF_8)), null); - assertTrue(items.isEmpty()); - } - - @Test - public void testInvalidSource() { - final List invalidList = Arrays.asList( - "{}", - "", - null, - "gibberish"); - - for (final String invalidContent : invalidList) { - try { - if (invalidContent != null) { - final byte[] bytes = invalidContent.getBytes(StandardCharsets.UTF_8); - ImportExportJsonHelper.readFrom((new ByteArrayInputStream(bytes)), null); - } else { - ImportExportJsonHelper.readFrom(null, null); - } - - fail("didn't throw exception"); - } catch (final Exception e) { - final boolean isExpectedException = - e instanceof SubscriptionExtractor.InvalidSourceException; - assertTrue("\"" + e.getClass().getSimpleName() - + "\" is not the expected exception", isExpectedException); - } - } - } - - @Test - public void ultimateTest() throws Exception { - // Read from file - final List itemsFromFile = readFromFile(); - - // Test writing to an output - final String jsonOut = testWriteTo(itemsFromFile); - - // Read again - final List itemsSecondRead = readFromWriteTo(jsonOut); - - // Check if both lists have the exact same items - if (itemsFromFile.size() != itemsSecondRead.size()) { - fail("The list of items were different from each other"); - } - - for (int i = 0; i < itemsFromFile.size(); i++) { - final SubscriptionItem item1 = itemsFromFile.get(i); - final SubscriptionItem item2 = itemsSecondRead.get(i); - - final boolean equals = item1.getServiceId() == item2.getServiceId() - && item1.getUrl().equals(item2.getUrl()) - && item1.getName().equals(item2.getName()); - - if (!equals) { - fail("The list of items were different from each other"); - } - } - } - - private List readFromFile() throws Exception { - final InputStream inputStream = getClass().getClassLoader().getResourceAsStream( - "import_export_test.json"); - final List itemsFromFile = ImportExportJsonHelper.readFrom( - inputStream, null); - - if (itemsFromFile.isEmpty()) { - fail("ImportExportJsonHelper.readFrom(input) returned a null or empty list"); - } - - return itemsFromFile; - } - - private String testWriteTo(final List itemsFromFile) throws Exception { - final ByteArrayOutputStream out = new ByteArrayOutputStream(); - ImportExportJsonHelper.writeTo(itemsFromFile, out, null); - final String jsonOut = out.toString("UTF-8"); - - if (jsonOut.isEmpty()) { - fail("JSON returned by writeTo was empty"); - } - - return jsonOut; - } - - private List readFromWriteTo(final String jsonOut) throws Exception { - final ByteArrayInputStream inputStream = new ByteArrayInputStream( - jsonOut.getBytes(StandardCharsets.UTF_8)); - final List secondReadItems = ImportExportJsonHelper.readFrom( - inputStream, null); - - if (secondReadItems.isEmpty()) { - fail("second call to readFrom returned an empty list"); - } - - return secondReadItems; - } -} diff --git a/app/src/test/java/org/schabi/newpipe/local/subscription/services/ImportExportJsonHelperTest.kt b/app/src/test/java/org/schabi/newpipe/local/subscription/services/ImportExportJsonHelperTest.kt new file mode 100644 index 000000000..209309c4c --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/local/subscription/services/ImportExportJsonHelperTest.kt @@ -0,0 +1,110 @@ +package org.schabi.newpipe.local.subscription.services + +import org.junit.Assert +import org.junit.Test +import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor.InvalidSourceException +import org.schabi.newpipe.extractor.subscription.SubscriptionItem +import org.schabi.newpipe.local.subscription.services.ImportExportJsonHelper.readFrom +import org.schabi.newpipe.local.subscription.services.ImportExportJsonHelper.writeTo +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.nio.charset.StandardCharsets + +/** + * @see ImportExportJsonHelper + */ +class ImportExportJsonHelperTest { + @Test + @Throws(Exception::class) + fun testEmptySource() { + val emptySource = "{\"app_version\":\"0.11.6\",\"app_version_int\": 47,\"subscriptions\":[]}" + val items = readFrom( + ByteArrayInputStream(emptySource.toByteArray(StandardCharsets.UTF_8)), null) + Assert.assertTrue(items.isEmpty()) + } + + @Test + fun testInvalidSource() { + val invalidList: List = mutableListOf( + "{}", + "", + null, + "gibberish") + for (invalidContent in invalidList) { + try { + if (invalidContent != null) { + val bytes = invalidContent.toByteArray(StandardCharsets.UTF_8) + readFrom(ByteArrayInputStream(bytes), null) + } else { + readFrom(null, null) + } + Assert.fail("didn't throw exception") + } catch (e: Exception) { + val isExpectedException = e is InvalidSourceException + Assert.assertTrue("\"" + e.javaClass.getSimpleName() + + "\" is not the expected exception", isExpectedException) + } + } + } + + @Test + @Throws(Exception::class) + fun ultimateTest() { + // Read from file + val itemsFromFile = readFromFile() + + // Test writing to an output + val jsonOut = testWriteTo(itemsFromFile) + + // Read again + val itemsSecondRead = readFromWriteTo(jsonOut) + + // Check if both lists have the exact same items + if (itemsFromFile.size != itemsSecondRead.size) { + Assert.fail("The list of items were different from each other") + } + for (i in itemsFromFile.indices) { + val item1 = itemsFromFile[i] + val item2 = itemsSecondRead[i] + val equals = item1!!.serviceId == item2.serviceId && item1.url == item2.url && item1.name == item2.name + if (!equals) { + Assert.fail("The list of items were different from each other") + } + } + } + + @Throws(Exception::class) + private fun readFromFile(): List { + val inputStream = javaClass.getClassLoader().getResourceAsStream( + "import_export_test.json") + val itemsFromFile: List = readFrom( + inputStream, null) + if (itemsFromFile.isEmpty()) { + Assert.fail("ImportExportJsonHelper.readFrom(input) returned a null or empty list") + } + return itemsFromFile + } + + @Throws(Exception::class) + private fun testWriteTo(itemsFromFile: List): String { + val out = ByteArrayOutputStream() + writeTo(itemsFromFile, out, null) + val jsonOut = out.toString("UTF-8") + if (jsonOut.isEmpty()) { + Assert.fail("JSON returned by writeTo was empty") + } + return jsonOut + } + + @Throws(Exception::class) + private fun readFromWriteTo(jsonOut: String): List { + val inputStream = ByteArrayInputStream( + jsonOut.toByteArray(StandardCharsets.UTF_8)) + val secondReadItems = readFrom( + inputStream, null) + if (secondReadItems.isEmpty()) { + Assert.fail("second call to readFrom returned an empty list") + } + return secondReadItems + } +} diff --git a/app/src/test/java/org/schabi/newpipe/player/playqueue/PlayQueueItemTest.java b/app/src/test/java/org/schabi/newpipe/player/playqueue/PlayQueueItemTest.java deleted file mode 100644 index d10d33f7e..000000000 --- a/app/src/test/java/org/schabi/newpipe/player/playqueue/PlayQueueItemTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.schabi.newpipe.player.playqueue; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -public class PlayQueueItemTest { - - public static final String URL = "MY_URL"; - - @Test - public void equalsMustNotBeOverloaded() { - final PlayQueueItem a = PlayQueueTest.makeItemWithUrl(URL); - final PlayQueueItem b = PlayQueueTest.makeItemWithUrl(URL); - assertEquals(a, a); - assertNotEquals(a, b); // they should compare different even if they have the same data - } -} diff --git a/app/src/test/java/org/schabi/newpipe/player/playqueue/PlayQueueItemTest.kt b/app/src/test/java/org/schabi/newpipe/player/playqueue/PlayQueueItemTest.kt new file mode 100644 index 000000000..c8635cc34 --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/player/playqueue/PlayQueueItemTest.kt @@ -0,0 +1,18 @@ +package org.schabi.newpipe.player.playqueue + +import org.junit.Assert +import org.junit.Test + +class PlayQueueItemTest { + @Test + fun equalsMustNotBeOverloaded() { + val a = PlayQueueTest.makeItemWithUrl(URL) + val b = PlayQueueTest.makeItemWithUrl(URL) + Assert.assertEquals(a, a) + Assert.assertNotEquals(a, b) // they should compare different even if they have the same data + } + + companion object { + const val URL = "MY_URL" + } +} diff --git a/app/src/test/java/org/schabi/newpipe/player/playqueue/PlayQueueTest.java b/app/src/test/java/org/schabi/newpipe/player/playqueue/PlayQueueTest.java deleted file mode 100644 index 15562729b..000000000 --- a/app/src/test/java/org/schabi/newpipe/player/playqueue/PlayQueueTest.java +++ /dev/null @@ -1,202 +0,0 @@ -package org.schabi.newpipe.player.playqueue; - -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.stream.StreamType; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; - -@SuppressWarnings("checkstyle:HideUtilityClassConstructor") -public class PlayQueueTest { - static PlayQueue makePlayQueue(final int index, final List streams) { - // I tried using Mockito, but it didn't work for some reason - return new PlayQueue(index, streams) { - @Override - public boolean isComplete() { - throw new UnsupportedOperationException(); - } - - @Override - public void fetch() { - throw new UnsupportedOperationException(); - } - }; - } - - static PlayQueueItem makeItemWithUrl(final String url) { - final StreamInfoItem infoItem = new StreamInfoItem( - 0, url, "", StreamType.VIDEO_STREAM - ); - return new PlayQueueItem(infoItem); - } - - public static class SetIndexTests { - private static final int SIZE = 5; - private PlayQueue nonEmptyQueue; - private PlayQueue emptyQueue; - - @Before - public void setup() { - final List streams = new ArrayList<>(5); - for (int i = 0; i < 5; ++i) { - streams.add(makeItemWithUrl("URL_" + i)); - } - nonEmptyQueue = spy(makePlayQueue(0, streams)); - emptyQueue = spy(makePlayQueue(0, new ArrayList<>())); - } - - @Test - public void negative() { - nonEmptyQueue.setIndex(-5); - assertEquals(0, nonEmptyQueue.getIndex()); - - emptyQueue.setIndex(-5); - assertEquals(0, nonEmptyQueue.getIndex()); - } - - @Test - public void inBounds() { - nonEmptyQueue.setIndex(2); - assertEquals(2, nonEmptyQueue.getIndex()); - - // emptyQueue not tested because 0 isn't technically inBounds - } - - @Test - public void outOfBoundIsComplete() { - doReturn(true).when(nonEmptyQueue).isComplete; - nonEmptyQueue.setIndex(7); - assertEquals(2, nonEmptyQueue.getIndex()); - - doReturn(true).when(emptyQueue).isComplete; - emptyQueue.setIndex(2); - assertEquals(0, emptyQueue.getIndex()); - } - - @Test - public void outOfBoundsNotComplete() { - doReturn(false).when(nonEmptyQueue).isComplete; - nonEmptyQueue.setIndex(7); - assertEquals(SIZE - 1, nonEmptyQueue.getIndex()); - - doReturn(false).when(emptyQueue).isComplete; - emptyQueue.setIndex(2); - assertEquals(0, emptyQueue.getIndex()); - } - - @Test - public void indexZero() { - nonEmptyQueue.setIndex(0); - assertEquals(0, nonEmptyQueue.getIndex()); - - doReturn(true).when(emptyQueue).isComplete; - emptyQueue.setIndex(0); - assertEquals(0, emptyQueue.getIndex()); - - doReturn(false).when(emptyQueue).isComplete; - emptyQueue.setIndex(0); - assertEquals(0, emptyQueue.getIndex()); - } - - @Test - public void addToHistory() { - nonEmptyQueue.setIndex(0); - assertFalse(nonEmptyQueue.previous()); - - nonEmptyQueue.setIndex(3); - assertTrue(nonEmptyQueue.previous()); - assertEquals("URL_0", Objects.requireNonNull(nonEmptyQueue.getItem()).url); - } - } - - public static class GetItemTests { - private static List streams; - private PlayQueue queue; - - @BeforeClass - public static void init() { - streams = new ArrayList<>(Collections.nCopies(5, makeItemWithUrl("OTHER_URL"))); - streams.set(3, makeItemWithUrl("TARGET_URL")); - } - - @Before - public void setup() { - queue = makePlayQueue(0, streams); - } - - @Test - public void inBounds() { - assertEquals("TARGET_URL", Objects.requireNonNull(queue.getItem(3)).url); - assertEquals("OTHER_URL", Objects.requireNonNull(queue.getItem(1)).url); - } - - @Test - public void outOfBounds() { - assertNull(queue.getItem(-1)); - assertNull(queue.getItem(5)); - } - - @Test - public void itemsAreNotCloned() { - final PlayQueueItem item = makeItemWithUrl("A url"); - final PlayQueue playQueue = makePlayQueue(0, List.of(item)); - - // make sure that items are not cloned when added to the queue - assertSame(playQueue.getItem(), item); - } - } - - public static class EqualsTests { - private final PlayQueueItem item1 = makeItemWithUrl("URL_1"); - private final PlayQueueItem item2 = makeItemWithUrl("URL_2"); - - @Test - public void sameStreams() { - final List streams = Collections.nCopies(5, item1); - final PlayQueue queue1 = makePlayQueue(0, streams); - final PlayQueue queue2 = makePlayQueue(0, streams); - assertTrue(queue1.equalStreams(queue2)); - assertTrue(queue1.equalStreamsAndIndex(queue2)); - } - - @Test - public void sameStreamsDifferentIndex() { - final List streams = Collections.nCopies(5, item1); - final PlayQueue queue1 = makePlayQueue(1, streams); - final PlayQueue queue2 = makePlayQueue(4, streams); - assertTrue(queue1.equalStreams(queue2)); - assertFalse(queue1.equalStreamsAndIndex(queue2)); - } - - @Test - public void sameSizeDifferentItems() { - final List streams1 = Collections.nCopies(5, item1); - final List streams2 = Collections.nCopies(5, item2); - final PlayQueue queue1 = makePlayQueue(0, streams1); - final PlayQueue queue2 = makePlayQueue(0, streams2); - assertFalse(queue1.equalStreams(queue2)); - } - - @Test - public void differentSizeStreams() { - final List streams1 = Collections.nCopies(5, item1); - final List streams2 = Collections.nCopies(6, item2); - final PlayQueue queue1 = makePlayQueue(0, streams1); - final PlayQueue queue2 = makePlayQueue(0, streams2); - assertFalse(queue1.equalStreams(queue2)); - } - } -} diff --git a/app/src/test/java/org/schabi/newpipe/player/playqueue/PlayQueueTest.kt b/app/src/test/java/org/schabi/newpipe/player/playqueue/PlayQueueTest.kt new file mode 100644 index 000000000..9a331206a --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/player/playqueue/PlayQueueTest.kt @@ -0,0 +1,187 @@ +package org.schabi.newpipe.player.playqueue + +import org.junit.Assert +import org.junit.Before +import org.junit.BeforeClass +import org.junit.Test +import org.mockito.Mockito +import org.schabi.newpipe.extractor.stream.StreamInfoItem +import org.schabi.newpipe.extractor.stream.StreamType +import java.util.Collections +import java.util.Objects + +object PlayQueueTest { + fun makePlayQueue(index: Int, streams: List?): PlayQueue { + // I tried using Mockito, but it didn't work for some reason + return object : PlayQueue(index, streams) { + override val isComplete: Boolean + get() { + throw UnsupportedOperationException() + } + + override fun fetch() { + throw UnsupportedOperationException() + } + } + } + + fun makeItemWithUrl(url: String?): PlayQueueItem { + val infoItem = StreamInfoItem( + 0, url, "", StreamType.VIDEO_STREAM + ) + return PlayQueueItem(infoItem) + } + + class SetIndexTests { + private var nonEmptyQueue: PlayQueue? = null + private var emptyQueue: PlayQueue? = null + @Before + fun setup() { + val streams: MutableList = ArrayList(5) + for (i in 0..4) { + streams.add(makeItemWithUrl("URL_$i")) + } + nonEmptyQueue = Mockito.spy(makePlayQueue(0, streams)) + emptyQueue = Mockito.spy(makePlayQueue(0, ArrayList())) + } + + @Test + fun negative() { + nonEmptyQueue!!.index = -5 + Assert.assertEquals(0, nonEmptyQueue!!.index.toLong()) + emptyQueue!!.index = -5 + Assert.assertEquals(0, nonEmptyQueue!!.index.toLong()) + } + + @Test + fun inBounds() { + nonEmptyQueue!!.index = 2 + Assert.assertEquals(2, nonEmptyQueue!!.index.toLong()) + + // emptyQueue not tested because 0 isn't technically inBounds + } + + @Test + fun outOfBoundIsComplete() { + Mockito.doReturn(true).`when`(nonEmptyQueue).isComplete + nonEmptyQueue!!.index = 7 + Assert.assertEquals(2, nonEmptyQueue!!.index.toLong()) + Mockito.doReturn(true).`when`(emptyQueue).isComplete + emptyQueue!!.index = 2 + Assert.assertEquals(0, emptyQueue!!.index.toLong()) + } + + @Test + fun outOfBoundsNotComplete() { + Mockito.doReturn(false).`when`(nonEmptyQueue).isComplete + nonEmptyQueue!!.index = 7 + Assert.assertEquals((SIZE - 1).toLong(), nonEmptyQueue!!.index.toLong()) + Mockito.doReturn(false).`when`(emptyQueue).isComplete + emptyQueue!!.index = 2 + Assert.assertEquals(0, emptyQueue!!.index.toLong()) + } + + @Test + fun indexZero() { + nonEmptyQueue!!.index = 0 + Assert.assertEquals(0, nonEmptyQueue!!.index.toLong()) + Mockito.doReturn(true).`when`(emptyQueue).isComplete + emptyQueue!!.index = 0 + Assert.assertEquals(0, emptyQueue!!.index.toLong()) + Mockito.doReturn(false).`when`(emptyQueue).isComplete + emptyQueue!!.index = 0 + Assert.assertEquals(0, emptyQueue!!.index.toLong()) + } + + @Test + fun addToHistory() { + nonEmptyQueue!!.index = 0 + Assert.assertFalse(nonEmptyQueue!!.previous()) + nonEmptyQueue!!.index = 3 + Assert.assertTrue(nonEmptyQueue!!.previous()) + Assert.assertEquals("URL_0", Objects.requireNonNull(nonEmptyQueue!!.item).url) + } + + companion object { + private const val SIZE = 5 + } + } + + class GetItemTests { + private var queue: PlayQueue? = null + @Before + fun setup() { + queue = makePlayQueue(0, streams) + } + + @Test + fun inBounds() { + Assert.assertEquals("TARGET_URL", Objects.requireNonNull(queue!!.getItem(3)).url) + Assert.assertEquals("OTHER_URL", Objects.requireNonNull(queue!!.getItem(1)).url) + } + + @Test + fun outOfBounds() { + Assert.assertNull(queue!!.getItem(-1)) + Assert.assertNull(queue!!.getItem(5)) + } + + @Test + fun itemsAreNotCloned() { + val item = makeItemWithUrl("A url") + val playQueue = makePlayQueue(0, java.util.List.of(item)) + + // make sure that items are not cloned when added to the queue + Assert.assertSame(playQueue.item, item) + } + + companion object { + private var streams: MutableList? = null + @BeforeClass + fun init() { + streams = ArrayList(Collections.nCopies(5, makeItemWithUrl("OTHER_URL"))) + streams.set(3, makeItemWithUrl("TARGET_URL")) + } + } + } + + class EqualsTests { + private val item1 = makeItemWithUrl("URL_1") + private val item2 = makeItemWithUrl("URL_2") + @Test + fun sameStreams() { + val streams = Collections.nCopies(5, item1) + val queue1 = makePlayQueue(0, streams) + val queue2 = makePlayQueue(0, streams) + Assert.assertTrue(queue1.equalStreams(queue2)) + Assert.assertTrue(queue1.equalStreamsAndIndex(queue2)) + } + + @Test + fun sameStreamsDifferentIndex() { + val streams = Collections.nCopies(5, item1) + val queue1 = makePlayQueue(1, streams) + val queue2 = makePlayQueue(4, streams) + Assert.assertTrue(queue1.equalStreams(queue2)) + Assert.assertFalse(queue1.equalStreamsAndIndex(queue2)) + } + + @Test + fun sameSizeDifferentItems() { + val streams1 = Collections.nCopies(5, item1) + val streams2 = Collections.nCopies(5, item2) + val queue1 = makePlayQueue(0, streams1) + val queue2 = makePlayQueue(0, streams2) + Assert.assertFalse(queue1.equalStreams(queue2)) + } + + @Test + fun differentSizeStreams() { + val streams1 = Collections.nCopies(5, item1) + val streams2 = Collections.nCopies(6, item2) + val queue1 = makePlayQueue(0, streams1) + val queue2 = makePlayQueue(0, streams2) + Assert.assertFalse(queue1.equalStreams(queue2)) + } + } +} diff --git a/app/src/test/java/org/schabi/newpipe/settings/tabs/TabTest.java b/app/src/test/java/org/schabi/newpipe/settings/tabs/TabTest.java deleted file mode 100644 index 23fdc0152..000000000 --- a/app/src/test/java/org/schabi/newpipe/settings/tabs/TabTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.schabi.newpipe.settings.tabs; - -import org.junit.Test; - -import java.util.HashSet; -import java.util.Set; - -import static org.junit.Assert.assertTrue; - -public class TabTest { - @Test - public void checkIdDuplication() { - final Set usedIds = new HashSet<>(); - - for (final Tab.Type type : Tab.Type.values()) { - final boolean added = usedIds.add(type.getTabId()); - assertTrue("Id was already used: " + type.getTabId(), added); - } - } -} diff --git a/app/src/test/java/org/schabi/newpipe/settings/tabs/TabTest.kt b/app/src/test/java/org/schabi/newpipe/settings/tabs/TabTest.kt new file mode 100644 index 000000000..07515b3a4 --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/settings/tabs/TabTest.kt @@ -0,0 +1,22 @@ +package org.schabi.newpipe.settings.tabs + +import org.junit.Assert +import org.junit.Test +import org.schabi.newpipe.settings.tabs.Tab.BlankTab.getTabId +import org.schabi.newpipe.settings.tabs.Tab.ChannelTab.getTabId +import org.schabi.newpipe.settings.tabs.Tab.DefaultKioskTab.getTabId +import org.schabi.newpipe.settings.tabs.Tab.KioskTab.getTabId +import org.schabi.newpipe.settings.tabs.Tab.SubscriptionsTab.getTabId +import org.schabi.newpipe.settings.tabs.Tab.Type.getTabId +import org.schabi.newpipe.settings.tabs.Tab.getTabId + +class TabTest { + @Test + fun checkIdDuplication() { + val usedIds: MutableSet = HashSet() + for (type in Tab.Type.org.schabi.newpipe.settings.tabs.Tab.Type.entries.toTypedArray()) { + val added = usedIds.add(type.getTabId()) + Assert.assertTrue("Id was already used: " + type.getTabId(), added) + } + } +} diff --git a/app/src/test/java/org/schabi/newpipe/settings/tabs/TabsJsonHelperTest.java b/app/src/test/java/org/schabi/newpipe/settings/tabs/TabsJsonHelperTest.java deleted file mode 100644 index bddb130fe..000000000 --- a/app/src/test/java/org/schabi/newpipe/settings/tabs/TabsJsonHelperTest.java +++ /dev/null @@ -1,134 +0,0 @@ -package org.schabi.newpipe.settings.tabs; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static java.util.Objects.requireNonNull; - -import com.grack.nanojson.JsonArray; -import com.grack.nanojson.JsonObject; -import com.grack.nanojson.JsonParser; -import com.grack.nanojson.JsonParserException; - -import org.junit.Test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public class TabsJsonHelperTest { - private static final String JSON_TABS_ARRAY_KEY = "tabs"; - private static final String JSON_TAB_ID_KEY = "tab_id"; - - @Test - public void testEmptyAndNullRead() throws TabsJsonHelper.InvalidJsonException { - final List defaultTabs = TabsJsonHelper.getDefaultTabs(); - - final String emptyTabsJson = "{\"" + JSON_TABS_ARRAY_KEY + "\":[]}"; - List items = TabsJsonHelper.getTabsFromJson(emptyTabsJson); - assertEquals(items, defaultTabs); - - final String nullSource = null; - items = TabsJsonHelper.getTabsFromJson(nullSource); - assertEquals(items, defaultTabs); - } - - @Test - public void testInvalidIdRead() throws TabsJsonHelper.InvalidJsonException { - final int blankTabId = Tab.Type.BLANK.getTabId(); - final String emptyTabsJson = "{\"" + JSON_TABS_ARRAY_KEY + "\":[" - + "{\"" + JSON_TAB_ID_KEY + "\":" + blankTabId + "}," - + "{\"" + JSON_TAB_ID_KEY + "\":" + 12345678 + "}" + "]}"; - final List items = TabsJsonHelper.getTabsFromJson(emptyTabsJson); - - assertEquals("Should ignore the tab with invalid id", 1, items.size()); - assertEquals(blankTabId, items.get(0).getTabId()); - } - - @Test - public void testInvalidRead() { - final List invalidList = Arrays.asList( - "{\"notTabsArray\":[]}", - "{invalidJSON]}", - "{}" - ); - - for (final String invalidContent : invalidList) { - try { - TabsJsonHelper.getTabsFromJson(invalidContent); - - fail("didn't throw exception"); - } catch (final Exception e) { - final boolean isExpectedException = - e instanceof TabsJsonHelper.InvalidJsonException; - assertTrue("\"" + e.getClass().getSimpleName() - + "\" is not the expected exception", isExpectedException); - } - } - } - - @Test - public void testEmptyAndNullSave() throws JsonParserException { - final List emptyList = Collections.emptyList(); - String returnedJson = TabsJsonHelper.getJsonToSave(emptyList); - assertTrue(isTabsArrayEmpty(returnedJson)); - - final List nullList = null; - returnedJson = TabsJsonHelper.getJsonToSave(nullList); - assertTrue(isTabsArrayEmpty(returnedJson)); - } - - private boolean isTabsArrayEmpty(final String returnedJson) throws JsonParserException { - final JsonObject jsonObject = JsonParser.object().from(returnedJson); - assertTrue(jsonObject.containsKey(JSON_TABS_ARRAY_KEY)); - return jsonObject.getArray(JSON_TABS_ARRAY_KEY).isEmpty(); - } - - @Test - public void testSaveAndReading() throws JsonParserException { - // Saving - final Tab.BlankTab blankTab = new Tab.BlankTab(); - final Tab.DefaultKioskTab defaultKioskTab = new Tab.DefaultKioskTab(); - final Tab.SubscriptionsTab subscriptionsTab = new Tab.SubscriptionsTab(); - final Tab.ChannelTab channelTab = new Tab.ChannelTab( - 666, "https://example.org", "testName"); - final Tab.KioskTab kioskTab = new Tab.KioskTab(123, "trending_key"); - - final List tabs = Arrays.asList( - blankTab, defaultKioskTab, subscriptionsTab, channelTab, kioskTab); - final String returnedJson = TabsJsonHelper.getJsonToSave(tabs); - - // Reading - final JsonObject jsonObject = JsonParser.object().from(returnedJson); - assertTrue(jsonObject.containsKey(JSON_TABS_ARRAY_KEY)); - final JsonArray tabsFromArray = jsonObject.getArray(JSON_TABS_ARRAY_KEY); - - assertEquals(tabs.size(), tabsFromArray.size()); - - final Tab.BlankTab blankTabFromReturnedJson = requireNonNull((Tab.BlankTab) Tab.from( - (JsonObject) tabsFromArray.get(0))); - assertEquals(blankTab.getTabId(), blankTabFromReturnedJson.getTabId()); - - final Tab.DefaultKioskTab defaultKioskTabFromReturnedJson = requireNonNull( - (Tab.DefaultKioskTab) Tab.from((JsonObject) tabsFromArray.get(1))); - assertEquals(defaultKioskTab.getTabId(), defaultKioskTabFromReturnedJson.getTabId()); - - final Tab.SubscriptionsTab subscriptionsTabFromReturnedJson = requireNonNull( - (Tab.SubscriptionsTab) Tab.from((JsonObject) tabsFromArray.get(2))); - assertEquals(subscriptionsTab.getTabId(), subscriptionsTabFromReturnedJson.getTabId()); - - final Tab.ChannelTab channelTabFromReturnedJson = requireNonNull((Tab.ChannelTab) Tab.from( - (JsonObject) tabsFromArray.get(3))); - assertEquals(channelTab.getTabId(), channelTabFromReturnedJson.getTabId()); - assertEquals(channelTab.getChannelServiceId(), - channelTabFromReturnedJson.getChannelServiceId()); - assertEquals(channelTab.getChannelUrl(), channelTabFromReturnedJson.getChannelUrl()); - assertEquals(channelTab.getChannelName(), channelTabFromReturnedJson.getChannelName()); - - final Tab.KioskTab kioskTabFromReturnedJson = requireNonNull((Tab.KioskTab) Tab.from( - (JsonObject) tabsFromArray.get(4))); - assertEquals(kioskTab.getTabId(), kioskTabFromReturnedJson.getTabId()); - assertEquals(kioskTab.getKioskServiceId(), kioskTabFromReturnedJson.getKioskServiceId()); - assertEquals(kioskTab.getKioskId(), kioskTabFromReturnedJson.getKioskId()); - } -} diff --git a/app/src/test/java/org/schabi/newpipe/settings/tabs/TabsJsonHelperTest.kt b/app/src/test/java/org/schabi/newpipe/settings/tabs/TabsJsonHelperTest.kt new file mode 100644 index 000000000..8a42218e4 --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/settings/tabs/TabsJsonHelperTest.kt @@ -0,0 +1,129 @@ +package org.schabi.newpipe.settings.tabs + +import com.grack.nanojson.JsonObject +import com.grack.nanojson.JsonParser +import com.grack.nanojson.JsonParserException +import org.junit.Assert +import org.junit.Test +import org.schabi.newpipe.settings.tabs.Tab.BlankTab +import org.schabi.newpipe.settings.tabs.Tab.ChannelTab +import org.schabi.newpipe.settings.tabs.Tab.Companion.from +import org.schabi.newpipe.settings.tabs.Tab.DefaultKioskTab +import org.schabi.newpipe.settings.tabs.Tab.KioskTab +import org.schabi.newpipe.settings.tabs.Tab.SubscriptionsTab +import org.schabi.newpipe.settings.tabs.TabsJsonHelper.InvalidJsonException +import org.schabi.newpipe.settings.tabs.TabsJsonHelper.getDefaultTabs +import org.schabi.newpipe.settings.tabs.TabsJsonHelper.getJsonToSave +import org.schabi.newpipe.settings.tabs.TabsJsonHelper.getTabsFromJson +import java.util.Arrays +import java.util.Objects + +class TabsJsonHelperTest { + @Test + @Throws(InvalidJsonException::class) + fun testEmptyAndNullRead() { + val defaultTabs = getDefaultTabs() + val emptyTabsJson = "{\"" + JSON_TABS_ARRAY_KEY + "\":[]}" + var items = getTabsFromJson(emptyTabsJson) + Assert.assertEquals(items, defaultTabs) + val nullSource: String? = null + items = getTabsFromJson(nullSource) + Assert.assertEquals(items, defaultTabs) + } + + @Test + @Throws(InvalidJsonException::class) + fun testInvalidIdRead() { + val blankTabId = Tab.Type.BLANK.getTabId() + val emptyTabsJson = ("{\"" + JSON_TABS_ARRAY_KEY + "\":[" + + "{\"" + JSON_TAB_ID_KEY + "\":" + blankTabId + "}," + + "{\"" + JSON_TAB_ID_KEY + "\":" + 12345678 + "}" + "]}") + val items = getTabsFromJson(emptyTabsJson) + Assert.assertEquals("Should ignore the tab with invalid id", 1, items.size.toLong()) + Assert.assertEquals(blankTabId.toLong(), items[0]!!.getTabId().toLong()) + } + + @Test + fun testInvalidRead() { + val invalidList: List = mutableListOf( + "{\"notTabsArray\":[]}", + "{invalidJSON]}", + "{}" + ) + for (invalidContent in invalidList) { + try { + getTabsFromJson(invalidContent) + Assert.fail("didn't throw exception") + } catch (e: Exception) { + val isExpectedException = e is InvalidJsonException + Assert.assertTrue("\"" + e.javaClass.getSimpleName() + + "\" is not the expected exception", isExpectedException) + } + } + } + + @Test + @Throws(JsonParserException::class) + fun testEmptyAndNullSave() { + val emptyList: List = emptyList() + var returnedJson = getJsonToSave(emptyList) + Assert.assertTrue(isTabsArrayEmpty(returnedJson)) + val nullList: List? = null + returnedJson = getJsonToSave(nullList) + Assert.assertTrue(isTabsArrayEmpty(returnedJson)) + } + + @Throws(JsonParserException::class) + private fun isTabsArrayEmpty(returnedJson: String): Boolean { + val jsonObject = JsonParser.`object`().from(returnedJson) + Assert.assertTrue(jsonObject.containsKey(JSON_TABS_ARRAY_KEY)) + return jsonObject.getArray(JSON_TABS_ARRAY_KEY).isEmpty() + } + + @Test + @Throws(JsonParserException::class) + fun testSaveAndReading() { + // Saving + val blankTab = BlankTab() + val defaultKioskTab = DefaultKioskTab() + val subscriptionsTab = SubscriptionsTab() + val channelTab = ChannelTab( + 666, "https://example.org", "testName") + val kioskTab = KioskTab(123, "trending_key") + val tabs = Arrays.asList( + blankTab, defaultKioskTab, subscriptionsTab, channelTab, kioskTab) + val returnedJson = getJsonToSave(tabs) + + // Reading + val jsonObject = JsonParser.`object`().from(returnedJson) + Assert.assertTrue(jsonObject.containsKey(JSON_TABS_ARRAY_KEY)) + val tabsFromArray = jsonObject.getArray(JSON_TABS_ARRAY_KEY) + Assert.assertEquals(tabs.size.toLong(), tabsFromArray.size.toLong()) + val blankTabFromReturnedJson = Objects.requireNonNull(from( + (tabsFromArray[0] as JsonObject)) as BlankTab?) + Assert.assertEquals(blankTab.getTabId().toLong(), blankTabFromReturnedJson.getTabId().toLong()) + val defaultKioskTabFromReturnedJson = Objects.requireNonNull( + from((tabsFromArray[1] as JsonObject)) as DefaultKioskTab?) + Assert.assertEquals(defaultKioskTab.getTabId().toLong(), defaultKioskTabFromReturnedJson.getTabId().toLong()) + val subscriptionsTabFromReturnedJson = Objects.requireNonNull( + from((tabsFromArray[2] as JsonObject)) as SubscriptionsTab?) + Assert.assertEquals(subscriptionsTab.getTabId().toLong(), subscriptionsTabFromReturnedJson.getTabId().toLong()) + val channelTabFromReturnedJson = Objects.requireNonNull(from( + (tabsFromArray[3] as JsonObject)) as ChannelTab?) + Assert.assertEquals(channelTab.getTabId().toLong(), channelTabFromReturnedJson.getTabId().toLong()) + Assert.assertEquals(channelTab.getChannelServiceId().toLong(), + channelTabFromReturnedJson.getChannelServiceId().toLong()) + Assert.assertEquals(channelTab.getChannelUrl(), channelTabFromReturnedJson.getChannelUrl()) + Assert.assertEquals(channelTab.getChannelName(), channelTabFromReturnedJson.getChannelName()) + val kioskTabFromReturnedJson = Objects.requireNonNull(from( + (tabsFromArray[4] as JsonObject)) as KioskTab?) + Assert.assertEquals(kioskTab.getTabId().toLong(), kioskTabFromReturnedJson.getTabId().toLong()) + Assert.assertEquals(kioskTab.getKioskServiceId().toLong(), kioskTabFromReturnedJson.getKioskServiceId().toLong()) + Assert.assertEquals(kioskTab.getKioskId(), kioskTabFromReturnedJson.getKioskId()) + } + + companion object { + private const val JSON_TABS_ARRAY_KEY = "tabs" + private const val JSON_TAB_ID_KEY = "tab_id" + } +} diff --git a/app/src/test/java/org/schabi/newpipe/util/ListHelperTest.java b/app/src/test/java/org/schabi/newpipe/util/ListHelperTest.java deleted file mode 100644 index c7c36eadc..000000000 --- a/app/src/test/java/org/schabi/newpipe/util/ListHelperTest.java +++ /dev/null @@ -1,482 +0,0 @@ -package org.schabi.newpipe.util; - -import org.junit.Test; -import org.schabi.newpipe.extractor.MediaFormat; -import org.schabi.newpipe.extractor.stream.AudioStream; -import org.schabi.newpipe.extractor.stream.AudioTrackType; -import org.schabi.newpipe.extractor.stream.VideoStream; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Locale; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -public class ListHelperTest { - private static final String BEST_RESOLUTION_KEY = "best_resolution"; - private static final List AUDIO_STREAMS_TEST_LIST = List.of( - generateAudioStream("m4a-128-1", MediaFormat.M4A, 128), - generateAudioStream("webma-192", MediaFormat.WEBMA, 192), - generateAudioStream("mp3-64", MediaFormat.MP3, 64), - generateAudioStream("webma-192", MediaFormat.WEBMA, 192), - generateAudioStream("m4a-128-2", MediaFormat.M4A, 128), - generateAudioStream("mp3-128", MediaFormat.MP3, 128), - generateAudioStream("webma-64", MediaFormat.WEBMA, 64), - generateAudioStream("m4a-320", MediaFormat.M4A, 320), - generateAudioStream("mp3-192", MediaFormat.MP3, 192), - generateAudioStream("webma-320", MediaFormat.WEBMA, 320)); - - private static final List AUDIO_TRACKS_TEST_LIST = List.of( - generateAudioTrack("en.or", "en.or", Locale.ENGLISH, AudioTrackType.ORIGINAL), - generateAudioTrack("en.du", "en.du", Locale.ENGLISH, AudioTrackType.DUBBED), - generateAudioTrack("en.ds", "en.ds", Locale.ENGLISH, AudioTrackType.DESCRIPTIVE), - generateAudioTrack("unknown", null, null, null), - generateAudioTrack("de.du", "de.du", Locale.GERMAN, AudioTrackType.DUBBED), - generateAudioTrack("de.ds", "de.ds", Locale.GERMAN, AudioTrackType.DESCRIPTIVE) - ); - - private static final List VIDEO_STREAMS_TEST_LIST = List.of( - generateVideoStream("mpeg_4-720", MediaFormat.MPEG_4, "720p", false), - generateVideoStream("v3gpp-240", MediaFormat.v3GPP, "240p", false), - generateVideoStream("webm-480", MediaFormat.WEBM, "480p", false), - generateVideoStream("v3gpp-144", MediaFormat.v3GPP, "144p", false), - generateVideoStream("mpeg_4-360", MediaFormat.MPEG_4, "360p", false), - generateVideoStream("webm-360", MediaFormat.WEBM, "360p", false)); - - private static final List VIDEO_ONLY_STREAMS_TEST_LIST = List.of( - generateVideoStream("mpeg_4-720-1", MediaFormat.MPEG_4, "720p", true), - generateVideoStream("mpeg_4-720-2", MediaFormat.MPEG_4, "720p", true), - generateVideoStream("mpeg_4-2160", MediaFormat.MPEG_4, "2160p", true), - generateVideoStream("mpeg_4-1440_60", MediaFormat.MPEG_4, "1440p60", true), - generateVideoStream("webm-720_60", MediaFormat.WEBM, "720p60", true), - generateVideoStream("mpeg_4-2160_60", MediaFormat.MPEG_4, "2160p60", true), - generateVideoStream("mpeg_4-720_60", MediaFormat.MPEG_4, "720p60", true), - generateVideoStream("mpeg_4-1080", MediaFormat.MPEG_4, "1080p", true), - generateVideoStream("mpeg_4-1080_60", MediaFormat.MPEG_4, "1080p60", true)); - - @Test - public void getSortedStreamVideosListTest() { - List result = ListHelper.getSortedStreamVideosList(MediaFormat.MPEG_4, true, - VIDEO_STREAMS_TEST_LIST, VIDEO_ONLY_STREAMS_TEST_LIST, true, false); - - List expected = List.of("144p", "240p", "360p", "480p", "720p", "720p60", - "1080p", "1080p60", "1440p60", "2160p", "2160p60"); - - assertEquals(expected.size(), result.size()); - for (int i = 0; i < result.size(); i++) { - assertEquals(result.get(i).getResolution(), expected.get(i)); - assertEquals(expected.get(i), result.get(i).getResolution()); - } - - //////////////////// - // Reverse Order // - ////////////////// - - result = ListHelper.getSortedStreamVideosList(MediaFormat.MPEG_4, true, - VIDEO_STREAMS_TEST_LIST, VIDEO_ONLY_STREAMS_TEST_LIST, false, false); - expected = List.of("2160p60", "2160p", "1440p60", "1080p60", "1080p", "720p60", - "720p", "480p", "360p", "240p", "144p"); - assertEquals(expected.size(), result.size()); - for (int i = 0; i < result.size(); i++) { - assertEquals(expected.get(i), result.get(i).getResolution()); - } - } - - @Test - public void getSortedStreamVideosListWithPreferVideoOnlyStreamsTest() { - List result = ListHelper.getSortedStreamVideosList(MediaFormat.MPEG_4, true, - null, VIDEO_ONLY_STREAMS_TEST_LIST, true, true); - - List expected = - List.of("720p", "720p60", "1080p", "1080p60", "1440p60", "2160p", "2160p60"); - - assertEquals(expected.size(), result.size()); - for (int i = 0; i < result.size(); i++) { - assertEquals(expected.get(i), result.get(i).getResolution()); - assertTrue(result.get(i).isVideoOnly()); - } - - ////////////////////////////////////////////////////////// - // No video only streams -> should return mixed streams // - ////////////////////////////////////////////////////////// - - result = ListHelper.getSortedStreamVideosList(MediaFormat.MPEG_4, true, - VIDEO_STREAMS_TEST_LIST, null, false, true); - expected = List.of("720p", "480p", "360p", "240p", "144p"); - assertEquals(expected.size(), result.size()); - for (int i = 0; i < result.size(); i++) { - assertEquals(expected.get(i), result.get(i).getResolution()); - assertFalse(result.get(i).isVideoOnly()); - } - - ///////////////////////////////////////////////////////////////// - // Both types of streams -> should return correct one streams // - ///////////////////////////////////////////////////////////////// - - result = ListHelper.getSortedStreamVideosList(MediaFormat.MPEG_4, true, - VIDEO_STREAMS_TEST_LIST, VIDEO_ONLY_STREAMS_TEST_LIST, true, true); - expected = List.of("144p", "240p", "360p", "480p", "720p", "720p60", - "1080p", "1080p60", "1440p60", "2160p", "2160p60"); - final List expectedVideoOnly = - List.of("720p", "720p60", "1080p", "1080p60", "1440p60", "2160p", "2160p60"); - - assertEquals(expected.size(), result.size()); - for (int i = 0; i < result.size(); i++) { - assertEquals(expected.get(i), result.get(i).getResolution()); - assertEquals(expectedVideoOnly.contains(result.get(i).getResolution()), - result.get(i).isVideoOnly()); - } - } - - @Test - public void getSortedStreamVideosExceptHighResolutionsTest() { - //////////////////////////////////// - // Don't show Higher resolutions // - ////////////////////////////////// - - final List result = ListHelper.getSortedStreamVideosList(MediaFormat.MPEG_4, - false, VIDEO_STREAMS_TEST_LIST, VIDEO_ONLY_STREAMS_TEST_LIST, false, false); - final List expected = List.of( - "1080p60", "1080p", "720p60", "720p", "480p", "360p", "240p", "144p"); - assertEquals(expected.size(), result.size()); - for (int i = 0; i < result.size(); i++) { - assertEquals(expected.get(i), result.get(i).getResolution()); - } - } - - @Test - public void getDefaultResolutionTest() { - final List testList = new ArrayList<>(List.of( - generateVideoStream("mpeg_4-720", MediaFormat.MPEG_4, "720p", false), - generateVideoStream("v3gpp-240", MediaFormat.v3GPP, "240p", false), - generateVideoStream("webm-480", MediaFormat.WEBM, "480p", false), - generateVideoStream("webm-240", MediaFormat.WEBM, "240p", false), - generateVideoStream("mpeg_4-240", MediaFormat.MPEG_4, "240p", false), - generateVideoStream("webm-144", MediaFormat.WEBM, "144p", false), - generateVideoStream("mpeg_4-360", MediaFormat.MPEG_4, "360p", false), - generateVideoStream("webm-360", MediaFormat.WEBM, "360p", false))); - VideoStream result = testList.get(ListHelper.getDefaultResolutionIndex( - "720p", BEST_RESOLUTION_KEY, MediaFormat.MPEG_4, testList)); - assertEquals("720p", result.getResolution()); - assertEquals(MediaFormat.MPEG_4, result.getFormat()); - - // Have resolution and the format - result = testList.get(ListHelper.getDefaultResolutionIndex( - "480p", BEST_RESOLUTION_KEY, MediaFormat.WEBM, testList)); - assertEquals("480p", result.getResolution()); - assertEquals(MediaFormat.WEBM, result.getFormat()); - - // Have resolution but not the format - result = testList.get(ListHelper.getDefaultResolutionIndex( - "480p", BEST_RESOLUTION_KEY, MediaFormat.MPEG_4, testList)); - assertEquals("480p", result.getResolution()); - assertEquals(MediaFormat.WEBM, result.getFormat()); - - // Have resolution and the format - result = testList.get(ListHelper.getDefaultResolutionIndex( - "240p", BEST_RESOLUTION_KEY, MediaFormat.WEBM, testList)); - assertEquals("240p", result.getResolution()); - assertEquals(MediaFormat.WEBM, result.getFormat()); - - // The best resolution - result = testList.get(ListHelper.getDefaultResolutionIndex( - BEST_RESOLUTION_KEY, BEST_RESOLUTION_KEY, MediaFormat.WEBM, testList)); - assertEquals("720p", result.getResolution()); - assertEquals(MediaFormat.MPEG_4, result.getFormat()); - - // Doesn't have the 60fps variant and format - result = testList.get(ListHelper.getDefaultResolutionIndex( - "720p60", BEST_RESOLUTION_KEY, MediaFormat.WEBM, testList)); - assertEquals("720p", result.getResolution()); - assertEquals(MediaFormat.MPEG_4, result.getFormat()); - - // Doesn't have the 60fps variant - result = testList.get(ListHelper.getDefaultResolutionIndex( - "480p60", BEST_RESOLUTION_KEY, MediaFormat.WEBM, testList)); - assertEquals("480p", result.getResolution()); - assertEquals(MediaFormat.WEBM, result.getFormat()); - - // Doesn't have the resolution, will return the best one - result = testList.get(ListHelper.getDefaultResolutionIndex( - "2160p60", BEST_RESOLUTION_KEY, MediaFormat.WEBM, testList)); - assertEquals("720p", result.getResolution()); - assertEquals(MediaFormat.MPEG_4, result.getFormat()); - } - - @Test - public void getHighestQualityAudioFormatTest() { - Comparator cmp = ListHelper.getAudioFormatComparator(MediaFormat.M4A, false); - AudioStream stream = AUDIO_STREAMS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - AUDIO_STREAMS_TEST_LIST, cmp)); - assertEquals(320, stream.getAverageBitrate()); - assertEquals(MediaFormat.M4A, stream.getFormat()); - - cmp = ListHelper.getAudioFormatComparator(MediaFormat.WEBMA, false); - stream = AUDIO_STREAMS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - AUDIO_STREAMS_TEST_LIST, cmp)); - assertEquals(320, stream.getAverageBitrate()); - assertEquals(MediaFormat.WEBMA, stream.getFormat()); - - cmp = ListHelper.getAudioFormatComparator(MediaFormat.MP3, false); - stream = AUDIO_STREAMS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - AUDIO_STREAMS_TEST_LIST, cmp)); - assertEquals(192, stream.getAverageBitrate()); - assertEquals(MediaFormat.MP3, stream.getFormat()); - } - - @Test - public void getHighestQualityAudioFormatPreferredAbsent() { - final Comparator cmp = - ListHelper.getAudioFormatComparator(MediaFormat.MP3, false); - - ////////////////////////////////////////// - // Doesn't contain the preferred format // - //////////////////////////////////////// - - List testList = List.of( - generateAudioStream("m4a-128", MediaFormat.M4A, 128), - generateAudioStream("webma-192", MediaFormat.WEBMA, 192)); - // List doesn't contains this format - // It should fallback to the highest bitrate audio no matter what format it is - AudioStream stream = testList.get(ListHelper.getAudioIndexByHighestRank(testList, cmp)); - assertEquals(192, stream.getAverageBitrate()); - assertEquals(MediaFormat.WEBMA, stream.getFormat()); - - //////////////////////////////////////////////////////// - // Multiple not-preferred-formats and equal bitrates // - ////////////////////////////////////////////////////// - - testList = new ArrayList<>(List.of( - generateAudioStream("webma-192-1", MediaFormat.WEBMA, 192), - generateAudioStream("m4a-192-1", MediaFormat.M4A, 192), - generateAudioStream("webma-192-2", MediaFormat.WEBMA, 192), - generateAudioStream("m4a-192-2", MediaFormat.M4A, 192), - generateAudioStream("webma-192-3", MediaFormat.WEBMA, 192), - generateAudioStream("m4a-192-3", MediaFormat.M4A, 192), - generateAudioStream("webma-192-4", MediaFormat.WEBMA, 192))); - // List doesn't contains this format, it should fallback to the highest bitrate audio and - // the highest quality format. - stream = - testList.get(ListHelper.getAudioIndexByHighestRank(testList, cmp)); - assertEquals(192, stream.getAverageBitrate()); - assertEquals(MediaFormat.M4A, stream.getFormat()); - - // Adding a new format and bitrate. Adding another stream will have no impact since - // it's not a preferred format. - testList.add(generateAudioStream("webma-192-5", MediaFormat.WEBMA, 192)); - stream = - testList.get(ListHelper.getAudioIndexByHighestRank(testList, cmp)); - assertEquals(192, stream.getAverageBitrate()); - assertEquals(MediaFormat.M4A, stream.getFormat()); - } - - @Test - public void getHighestQualityAudioNull() { - final Comparator cmp = ListHelper.getAudioFormatComparator(null, false); - assertEquals(-1, ListHelper.getAudioIndexByHighestRank(null, cmp)); - assertEquals(-1, ListHelper.getAudioIndexByHighestRank(new ArrayList<>(), cmp)); - } - - @Test - public void getLowestQualityAudioFormatTest() { - Comparator cmp = ListHelper.getAudioFormatComparator(MediaFormat.M4A, true); - AudioStream stream = AUDIO_STREAMS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - AUDIO_STREAMS_TEST_LIST, cmp)); - assertEquals(128, stream.getAverageBitrate()); - assertEquals(MediaFormat.M4A, stream.getFormat()); - - cmp = ListHelper.getAudioFormatComparator(MediaFormat.WEBMA, true); - stream = AUDIO_STREAMS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - AUDIO_STREAMS_TEST_LIST, cmp)); - assertEquals(64, stream.getAverageBitrate()); - assertEquals(MediaFormat.WEBMA, stream.getFormat()); - - cmp = ListHelper.getAudioFormatComparator(MediaFormat.MP3, true); - stream = AUDIO_STREAMS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - AUDIO_STREAMS_TEST_LIST, cmp)); - assertEquals(64, stream.getAverageBitrate()); - assertEquals(MediaFormat.MP3, stream.getFormat()); - } - - @Test - public void getLowestQualityAudioFormatPreferredAbsent() { - Comparator cmp = ListHelper.getAudioFormatComparator(MediaFormat.MP3, true); - - ////////////////////////////////////////// - // Doesn't contain the preferred format // - //////////////////////////////////////// - - List testList = new ArrayList<>(List.of( - generateAudioStream("m4a-128", MediaFormat.M4A, 128), - generateAudioStream("webma-192-1", MediaFormat.WEBMA, 192))); - // List doesn't contains this format - // It should fallback to the most compact audio no matter what format it is. - AudioStream stream = testList.get(ListHelper.getAudioIndexByHighestRank(testList, cmp)); - assertEquals(128, stream.getAverageBitrate()); - assertEquals(MediaFormat.M4A, stream.getFormat()); - - // WEBMA is more compact than M4A - testList.add(generateAudioStream("webma-192-2", MediaFormat.WEBMA, 128)); - stream = testList.get(ListHelper.getAudioIndexByHighestRank(testList, cmp)); - assertEquals(128, stream.getAverageBitrate()); - assertEquals(MediaFormat.WEBMA, stream.getFormat()); - - //////////////////////////////////////////////////////// - // Multiple not-preferred-formats and equal bitrates // - ////////////////////////////////////////////////////// - - testList = new ArrayList<>(List.of( - generateAudioStream("webma-192-1", MediaFormat.WEBMA, 192), - generateAudioStream("m4a-192-1", MediaFormat.M4A, 192), - generateAudioStream("webma-256", MediaFormat.WEBMA, 256), - generateAudioStream("m4a-192-2", MediaFormat.M4A, 192), - generateAudioStream("webma-192-2", MediaFormat.WEBMA, 192), - generateAudioStream("m4a-192-3", MediaFormat.M4A, 192))); - // List doesn't contain this format - // It should fallback to the most compact audio no matter what format it is. - stream = testList.get( - ListHelper.getAudioIndexByHighestRank(testList, cmp)); - assertEquals(192, stream.getAverageBitrate()); - assertEquals(MediaFormat.WEBMA, stream.getFormat()); - - // Should be same as above - cmp = ListHelper.getAudioFormatComparator(null, true); - stream = testList.get( - ListHelper.getAudioIndexByHighestRank(testList, cmp)); - assertEquals(192, stream.getAverageBitrate()); - assertEquals(MediaFormat.WEBMA, stream.getFormat()); - } - - @Test - public void getLowestQualityAudioNull() { - final Comparator cmp = ListHelper.getAudioFormatComparator(null, false); - assertEquals(-1, ListHelper.getAudioIndexByHighestRank(null, cmp)); - assertEquals(-1, ListHelper.getAudioIndexByHighestRank(new ArrayList<>(), cmp)); - } - - @Test - public void getAudioTrack() { - // English language - Comparator cmp = - ListHelper.getAudioTrackComparator(Locale.ENGLISH, false, false); - AudioStream stream = AUDIO_TRACKS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - AUDIO_TRACKS_TEST_LIST, cmp)); - assertEquals("en.or", stream.getId()); - - // German language - cmp = ListHelper.getAudioTrackComparator(Locale.GERMAN, false, false); - stream = AUDIO_TRACKS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - AUDIO_TRACKS_TEST_LIST, cmp)); - assertEquals("de.du", stream.getId()); - - // German language, but prefer original - cmp = ListHelper.getAudioTrackComparator(Locale.GERMAN, true, false); - stream = AUDIO_TRACKS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - AUDIO_TRACKS_TEST_LIST, cmp)); - assertEquals("en.or", stream.getId()); - - // Prefer descriptive audio - cmp = ListHelper.getAudioTrackComparator(Locale.ENGLISH, false, true); - stream = AUDIO_TRACKS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - AUDIO_TRACKS_TEST_LIST, cmp)); - assertEquals("en.ds", stream.getId()); - - // Japanese language, fall back to original - cmp = ListHelper.getAudioTrackComparator(Locale.JAPANESE, true, false); - stream = AUDIO_TRACKS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - AUDIO_TRACKS_TEST_LIST, cmp)); - assertEquals("en.or", stream.getId()); - } - - @Test - public void getVideoDefaultStreamIndexCombinations() { - final List testList = List.of( - generateVideoStream("mpeg_4-1080", MediaFormat.MPEG_4, "1080p", false), - generateVideoStream("mpeg_4-720_60", MediaFormat.MPEG_4, "720p60", false), - generateVideoStream("mpeg_4-720", MediaFormat.MPEG_4, "720p", false), - generateVideoStream("webm-480", MediaFormat.WEBM, "480p", false), - generateVideoStream("mpeg_4-360", MediaFormat.MPEG_4, "360p", false), - generateVideoStream("webm-360", MediaFormat.WEBM, "360p", false), - generateVideoStream("v3gpp-240_60", MediaFormat.v3GPP, "240p60", false), - generateVideoStream("webm-144", MediaFormat.WEBM, "144p", false)); - - // exact matches - assertEquals(1, ListHelper.getVideoStreamIndex("720p60", MediaFormat.MPEG_4, testList)); - assertEquals(2, ListHelper.getVideoStreamIndex("720p", MediaFormat.MPEG_4, testList)); - - // match but not refresh - assertEquals(0, ListHelper.getVideoStreamIndex("1080p60", MediaFormat.MPEG_4, testList)); - assertEquals(6, ListHelper.getVideoStreamIndex("240p", MediaFormat.v3GPP, testList)); - - // match but not format - assertEquals(1, ListHelper.getVideoStreamIndex("720p60", MediaFormat.WEBM, testList)); - assertEquals(2, ListHelper.getVideoStreamIndex("720p", MediaFormat.WEBM, testList)); - assertEquals(1, ListHelper.getVideoStreamIndex("720p60", null, testList)); - assertEquals(2, ListHelper.getVideoStreamIndex("720p", null, testList)); - - // match but not format and not refresh - assertEquals(0, ListHelper.getVideoStreamIndex("1080p60", MediaFormat.WEBM, testList)); - assertEquals(6, ListHelper.getVideoStreamIndex("240p", MediaFormat.WEBM, testList)); - assertEquals(0, ListHelper.getVideoStreamIndex("1080p60", null, testList)); - assertEquals(6, ListHelper.getVideoStreamIndex("240p", null, testList)); - - // match closest lower resolution - assertEquals(7, ListHelper.getVideoStreamIndex("200p", MediaFormat.WEBM, testList)); - assertEquals(7, ListHelper.getVideoStreamIndex("200p60", MediaFormat.WEBM, testList)); - assertEquals(7, ListHelper.getVideoStreamIndex("200p", MediaFormat.MPEG_4, testList)); - assertEquals(7, ListHelper.getVideoStreamIndex("200p60", MediaFormat.MPEG_4, testList)); - assertEquals(7, ListHelper.getVideoStreamIndex("200p", null, testList)); - assertEquals(7, ListHelper.getVideoStreamIndex("200p60", null, testList)); - - // Can't find a match - assertEquals(-1, ListHelper.getVideoStreamIndex("100p", null, testList)); - } - - @NonNull - private static AudioStream generateAudioStream(@NonNull final String id, - @Nullable final MediaFormat mediaFormat, - final int averageBitrate) { - return new AudioStream.Builder() - .setId(id) - .setContent("", true) - .setMediaFormat(mediaFormat) - .setAverageBitrate(averageBitrate) - .build(); - } - - private static AudioStream generateAudioTrack( - @NonNull final String id, - @Nullable final String trackId, - @Nullable final Locale locale, - @Nullable final AudioTrackType trackType) { - return new AudioStream.Builder() - .setId(id) - .setContent("", true) - .setMediaFormat(MediaFormat.M4A) - .setAverageBitrate(128) - .setAudioTrackId(trackId) - .setAudioLocale(locale) - .setAudioTrackType(trackType) - .build(); - } - - @NonNull - private static VideoStream generateVideoStream(@NonNull final String id, - @Nullable final MediaFormat mediaFormat, - @NonNull final String resolution, - final boolean isVideoOnly) { - return new VideoStream.Builder() - .setId(id) - .setContent("", true) - .setIsVideoOnly(isVideoOnly) - .setResolution(resolution) - .setMediaFormat(mediaFormat) - .build(); - } -} diff --git a/app/src/test/java/org/schabi/newpipe/util/ListHelperTest.kt b/app/src/test/java/org/schabi/newpipe/util/ListHelperTest.kt new file mode 100644 index 000000000..0ced5b847 --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/util/ListHelperTest.kt @@ -0,0 +1,462 @@ +package org.schabi.newpipe.util + +import org.junit.Assert +import org.junit.Test +import org.schabi.newpipe.extractor.MediaFormat +import org.schabi.newpipe.extractor.stream.AudioStream +import org.schabi.newpipe.extractor.stream.AudioTrackType +import org.schabi.newpipe.extractor.stream.VideoStream +import org.schabi.newpipe.util.ListHelper.getAudioFormatComparator +import org.schabi.newpipe.util.ListHelper.getAudioIndexByHighestRank +import org.schabi.newpipe.util.ListHelper.getAudioTrackComparator +import org.schabi.newpipe.util.ListHelper.getDefaultResolutionIndex +import org.schabi.newpipe.util.ListHelper.getSortedStreamVideosList +import org.schabi.newpipe.util.ListHelper.getVideoStreamIndex +import java.util.Locale + +class ListHelperTest { + @get:Test + val sortedStreamVideosListTest: Unit + get() { + var result = getSortedStreamVideosList(MediaFormat.MPEG_4, true, + VIDEO_STREAMS_TEST_LIST, VIDEO_ONLY_STREAMS_TEST_LIST, true, false) + var expected: List = listOf("144p", "240p", "360p", "480p", "720p", "720p60", + "1080p", "1080p60", "1440p60", "2160p", "2160p60") + Assert.assertEquals(expected.size.toLong(), result.size.toLong()) + for (i in result.indices) { + Assert.assertEquals(result[i]!!.getResolution(), expected[i]) + Assert.assertEquals(expected[i], result[i]!!.getResolution()) + } + + //////////////////// + // Reverse Order // + ////////////////// + result = getSortedStreamVideosList(MediaFormat.MPEG_4, true, + VIDEO_STREAMS_TEST_LIST, VIDEO_ONLY_STREAMS_TEST_LIST, false, false) + expected = listOf("2160p60", "2160p", "1440p60", "1080p60", "1080p", "720p60", + "720p", "480p", "360p", "240p", "144p") + Assert.assertEquals(expected.size.toLong(), result.size.toLong()) + for (i in result.indices) { + Assert.assertEquals(expected[i], result[i]!!.getResolution()) + } + } + + @get:Test + val sortedStreamVideosListWithPreferVideoOnlyStreamsTest: Unit + get() { + var result = getSortedStreamVideosList(MediaFormat.MPEG_4, true, + null, VIDEO_ONLY_STREAMS_TEST_LIST, true, true) + var expected: List = listOf("720p", "720p60", "1080p", "1080p60", "1440p60", "2160p", "2160p60") + Assert.assertEquals(expected.size.toLong(), result.size.toLong()) + for (i in result.indices) { + Assert.assertEquals(expected[i], result[i]!!.getResolution()) + Assert.assertTrue(result[i]!!.isVideoOnly()) + } + + ////////////////////////////////////////////////////////// + // No video only streams -> should return mixed streams // + ////////////////////////////////////////////////////////// + result = getSortedStreamVideosList(MediaFormat.MPEG_4, true, + VIDEO_STREAMS_TEST_LIST, null, false, true) + expected = listOf("720p", "480p", "360p", "240p", "144p") + Assert.assertEquals(expected.size.toLong(), result.size.toLong()) + for (i in result.indices) { + Assert.assertEquals(expected[i], result[i]!!.getResolution()) + Assert.assertFalse(result[i]!!.isVideoOnly()) + } + + ///////////////////////////////////////////////////////////////// + // Both types of streams -> should return correct one streams // + ///////////////////////////////////////////////////////////////// + result = getSortedStreamVideosList(MediaFormat.MPEG_4, true, + VIDEO_STREAMS_TEST_LIST, VIDEO_ONLY_STREAMS_TEST_LIST, true, true) + expected = listOf("144p", "240p", "360p", "480p", "720p", "720p60", + "1080p", "1080p60", "1440p60", "2160p", "2160p60") + val expectedVideoOnly = listOf("720p", "720p60", "1080p", "1080p60", "1440p60", "2160p", "2160p60") + Assert.assertEquals(expected.size.toLong(), result.size.toLong()) + for (i in result.indices) { + Assert.assertEquals(expected[i], result[i]!!.getResolution()) + Assert.assertEquals(expectedVideoOnly.contains(result[i]!!.getResolution()), + result[i]!!.isVideoOnly()) + } + } + + @get:Test + val sortedStreamVideosExceptHighResolutionsTest: Unit + get() { + //////////////////////////////////// + // Don't show Higher resolutions // + ////////////////////////////////// + val result = getSortedStreamVideosList(MediaFormat.MPEG_4, + false, VIDEO_STREAMS_TEST_LIST, VIDEO_ONLY_STREAMS_TEST_LIST, false, false) + val expected = listOf( + "1080p60", "1080p", "720p60", "720p", "480p", "360p", "240p", "144p") + Assert.assertEquals(expected.size.toLong(), result.size.toLong()) + for (i in result.indices) { + Assert.assertEquals(expected[i], result[i]!!.getResolution()) + } + } + + @get:Test + val defaultResolutionTest: Unit + get() { + val testList: List = ArrayList(java.util.List.of( + generateVideoStream("mpeg_4-720", MediaFormat.MPEG_4, "720p", false), + generateVideoStream("v3gpp-240", MediaFormat.v3GPP, "240p", false), + generateVideoStream("webm-480", MediaFormat.WEBM, "480p", false), + generateVideoStream("webm-240", MediaFormat.WEBM, "240p", false), + generateVideoStream("mpeg_4-240", MediaFormat.MPEG_4, "240p", false), + generateVideoStream("webm-144", MediaFormat.WEBM, "144p", false), + generateVideoStream("mpeg_4-360", MediaFormat.MPEG_4, "360p", false), + generateVideoStream("webm-360", MediaFormat.WEBM, "360p", false))) + var result = testList[getDefaultResolutionIndex( + "720p", BEST_RESOLUTION_KEY, MediaFormat.MPEG_4, testList)] + Assert.assertEquals("720p", result!!.getResolution()) + Assert.assertEquals(MediaFormat.MPEG_4, result.format) + + // Have resolution and the format + result = testList[getDefaultResolutionIndex( + "480p", BEST_RESOLUTION_KEY, MediaFormat.WEBM, testList)] + Assert.assertEquals("480p", result!!.getResolution()) + Assert.assertEquals(MediaFormat.WEBM, result.format) + + // Have resolution but not the format + result = testList[getDefaultResolutionIndex( + "480p", BEST_RESOLUTION_KEY, MediaFormat.MPEG_4, testList)] + Assert.assertEquals("480p", result!!.getResolution()) + Assert.assertEquals(MediaFormat.WEBM, result.format) + + // Have resolution and the format + result = testList[getDefaultResolutionIndex( + "240p", BEST_RESOLUTION_KEY, MediaFormat.WEBM, testList)] + Assert.assertEquals("240p", result!!.getResolution()) + Assert.assertEquals(MediaFormat.WEBM, result.format) + + // The best resolution + result = testList[getDefaultResolutionIndex( + BEST_RESOLUTION_KEY, BEST_RESOLUTION_KEY, MediaFormat.WEBM, testList)] + Assert.assertEquals("720p", result!!.getResolution()) + Assert.assertEquals(MediaFormat.MPEG_4, result.format) + + // Doesn't have the 60fps variant and format + result = testList[getDefaultResolutionIndex( + "720p60", BEST_RESOLUTION_KEY, MediaFormat.WEBM, testList)] + Assert.assertEquals("720p", result!!.getResolution()) + Assert.assertEquals(MediaFormat.MPEG_4, result.format) + + // Doesn't have the 60fps variant + result = testList[getDefaultResolutionIndex( + "480p60", BEST_RESOLUTION_KEY, MediaFormat.WEBM, testList)] + Assert.assertEquals("480p", result!!.getResolution()) + Assert.assertEquals(MediaFormat.WEBM, result.format) + + // Doesn't have the resolution, will return the best one + result = testList[getDefaultResolutionIndex( + "2160p60", BEST_RESOLUTION_KEY, MediaFormat.WEBM, testList)] + Assert.assertEquals("720p", result!!.getResolution()) + Assert.assertEquals(MediaFormat.MPEG_4, result.format) + } + + @get:Test + val highestQualityAudioFormatTest: Unit + get() { + var cmp = getAudioFormatComparator(MediaFormat.M4A, false) + var stream = AUDIO_STREAMS_TEST_LIST[getAudioIndexByHighestRank( + AUDIO_STREAMS_TEST_LIST, cmp)] + Assert.assertEquals(320, stream!!.averageBitrate.toLong()) + Assert.assertEquals(MediaFormat.M4A, stream.format) + cmp = getAudioFormatComparator(MediaFormat.WEBMA, false) + stream = AUDIO_STREAMS_TEST_LIST[getAudioIndexByHighestRank( + AUDIO_STREAMS_TEST_LIST, cmp)] + Assert.assertEquals(320, stream!!.averageBitrate.toLong()) + Assert.assertEquals(MediaFormat.WEBMA, stream.format) + cmp = getAudioFormatComparator(MediaFormat.MP3, false) + stream = AUDIO_STREAMS_TEST_LIST[getAudioIndexByHighestRank( + AUDIO_STREAMS_TEST_LIST, cmp)] + Assert.assertEquals(192, stream!!.averageBitrate.toLong()) + Assert.assertEquals(MediaFormat.MP3, stream.format) + } + + @get:Test + val highestQualityAudioFormatPreferredAbsent: Unit + get() { + val cmp = getAudioFormatComparator(MediaFormat.MP3, false) + + ////////////////////////////////////////// + // Doesn't contain the preferred format // + //////////////////////////////////////// + var testList = java.util.List.of( + generateAudioStream("m4a-128", MediaFormat.M4A, 128), + generateAudioStream("webma-192", MediaFormat.WEBMA, 192)) + // List doesn't contains this format + // It should fallback to the highest bitrate audio no matter what format it is + var stream = testList[getAudioIndexByHighestRank(testList, cmp)] + Assert.assertEquals(192, stream!!.averageBitrate.toLong()) + Assert.assertEquals(MediaFormat.WEBMA, stream.format) + + //////////////////////////////////////////////////////// + // Multiple not-preferred-formats and equal bitrates // + ////////////////////////////////////////////////////// + testList = ArrayList(java.util.List.of( + generateAudioStream("webma-192-1", MediaFormat.WEBMA, 192), + generateAudioStream("m4a-192-1", MediaFormat.M4A, 192), + generateAudioStream("webma-192-2", MediaFormat.WEBMA, 192), + generateAudioStream("m4a-192-2", MediaFormat.M4A, 192), + generateAudioStream("webma-192-3", MediaFormat.WEBMA, 192), + generateAudioStream("m4a-192-3", MediaFormat.M4A, 192), + generateAudioStream("webma-192-4", MediaFormat.WEBMA, 192))) + // List doesn't contains this format, it should fallback to the highest bitrate audio and + // the highest quality format. + stream = testList[getAudioIndexByHighestRank(testList, cmp)] + Assert.assertEquals(192, stream!!.averageBitrate.toLong()) + Assert.assertEquals(MediaFormat.M4A, stream.format) + + // Adding a new format and bitrate. Adding another stream will have no impact since + // it's not a preferred format. + testList.add(generateAudioStream("webma-192-5", MediaFormat.WEBMA, 192)) + stream = testList[getAudioIndexByHighestRank(testList, cmp)] + Assert.assertEquals(192, stream!!.averageBitrate.toLong()) + Assert.assertEquals(MediaFormat.M4A, stream.format) + } + + @get:Test + val highestQualityAudioNull: Unit + get() { + val cmp = getAudioFormatComparator(null, false) + Assert.assertEquals(-1, getAudioIndexByHighestRank(null, cmp).toLong()) + Assert.assertEquals(-1, getAudioIndexByHighestRank(ArrayList(), cmp).toLong()) + } + + @get:Test + val lowestQualityAudioFormatTest: Unit + get() { + var cmp = getAudioFormatComparator(MediaFormat.M4A, true) + var stream = AUDIO_STREAMS_TEST_LIST[getAudioIndexByHighestRank( + AUDIO_STREAMS_TEST_LIST, cmp)] + Assert.assertEquals(128, stream!!.averageBitrate.toLong()) + Assert.assertEquals(MediaFormat.M4A, stream.format) + cmp = getAudioFormatComparator(MediaFormat.WEBMA, true) + stream = AUDIO_STREAMS_TEST_LIST[getAudioIndexByHighestRank( + AUDIO_STREAMS_TEST_LIST, cmp)] + Assert.assertEquals(64, stream!!.averageBitrate.toLong()) + Assert.assertEquals(MediaFormat.WEBMA, stream.format) + cmp = getAudioFormatComparator(MediaFormat.MP3, true) + stream = AUDIO_STREAMS_TEST_LIST[getAudioIndexByHighestRank( + AUDIO_STREAMS_TEST_LIST, cmp)] + Assert.assertEquals(64, stream!!.averageBitrate.toLong()) + Assert.assertEquals(MediaFormat.MP3, stream.format) + } + + @get:Test + val lowestQualityAudioFormatPreferredAbsent: Unit + get() { + var cmp = getAudioFormatComparator(MediaFormat.MP3, true) + + ////////////////////////////////////////// + // Doesn't contain the preferred format // + //////////////////////////////////////// + var testList: MutableList = ArrayList(java.util.List.of( + generateAudioStream("m4a-128", MediaFormat.M4A, 128), + generateAudioStream("webma-192-1", MediaFormat.WEBMA, 192))) + // List doesn't contains this format + // It should fallback to the most compact audio no matter what format it is. + var stream = testList[getAudioIndexByHighestRank(testList, cmp)] + Assert.assertEquals(128, stream!!.averageBitrate.toLong()) + Assert.assertEquals(MediaFormat.M4A, stream.format) + + // WEBMA is more compact than M4A + testList.add(generateAudioStream("webma-192-2", MediaFormat.WEBMA, 128)) + stream = testList[getAudioIndexByHighestRank(testList, cmp)] + Assert.assertEquals(128, stream!!.averageBitrate.toLong()) + Assert.assertEquals(MediaFormat.WEBMA, stream.format) + + //////////////////////////////////////////////////////// + // Multiple not-preferred-formats and equal bitrates // + ////////////////////////////////////////////////////// + testList = ArrayList(java.util.List.of( + generateAudioStream("webma-192-1", MediaFormat.WEBMA, 192), + generateAudioStream("m4a-192-1", MediaFormat.M4A, 192), + generateAudioStream("webma-256", MediaFormat.WEBMA, 256), + generateAudioStream("m4a-192-2", MediaFormat.M4A, 192), + generateAudioStream("webma-192-2", MediaFormat.WEBMA, 192), + generateAudioStream("m4a-192-3", MediaFormat.M4A, 192))) + // List doesn't contain this format + // It should fallback to the most compact audio no matter what format it is. + stream = testList[getAudioIndexByHighestRank(testList, cmp)] + Assert.assertEquals(192, stream!!.averageBitrate.toLong()) + Assert.assertEquals(MediaFormat.WEBMA, stream.format) + + // Should be same as above + cmp = getAudioFormatComparator(null, true) + stream = testList[getAudioIndexByHighestRank(testList, cmp)] + Assert.assertEquals(192, stream!!.averageBitrate.toLong()) + Assert.assertEquals(MediaFormat.WEBMA, stream.format) + } + + @get:Test + val lowestQualityAudioNull: Unit + get() { + val cmp = getAudioFormatComparator(null, false) + Assert.assertEquals(-1, getAudioIndexByHighestRank(null, cmp).toLong()) + Assert.assertEquals(-1, getAudioIndexByHighestRank(ArrayList(), cmp).toLong()) + } + + @get:Test + val audioTrack: Unit + get() { + // English language + var cmp = getAudioTrackComparator(Locale.ENGLISH, false, false) + var stream = AUDIO_TRACKS_TEST_LIST[getAudioIndexByHighestRank( + AUDIO_TRACKS_TEST_LIST, cmp)] + Assert.assertEquals("en.or", stream!!.id) + + // German language + cmp = getAudioTrackComparator(Locale.GERMAN, false, false) + stream = AUDIO_TRACKS_TEST_LIST[getAudioIndexByHighestRank( + AUDIO_TRACKS_TEST_LIST, cmp)] + Assert.assertEquals("de.du", stream!!.id) + + // German language, but prefer original + cmp = getAudioTrackComparator(Locale.GERMAN, true, false) + stream = AUDIO_TRACKS_TEST_LIST[getAudioIndexByHighestRank( + AUDIO_TRACKS_TEST_LIST, cmp)] + Assert.assertEquals("en.or", stream!!.id) + + // Prefer descriptive audio + cmp = getAudioTrackComparator(Locale.ENGLISH, false, true) + stream = AUDIO_TRACKS_TEST_LIST[getAudioIndexByHighestRank( + AUDIO_TRACKS_TEST_LIST, cmp)] + Assert.assertEquals("en.ds", stream!!.id) + + // Japanese language, fall back to original + cmp = getAudioTrackComparator(Locale.JAPANESE, true, false) + stream = AUDIO_TRACKS_TEST_LIST[getAudioIndexByHighestRank( + AUDIO_TRACKS_TEST_LIST, cmp)] + Assert.assertEquals("en.or", stream!!.id) + } + + @get:Test + val videoDefaultStreamIndexCombinations: Unit + get() { + val testList = java.util.List.of( + generateVideoStream("mpeg_4-1080", MediaFormat.MPEG_4, "1080p", false), + generateVideoStream("mpeg_4-720_60", MediaFormat.MPEG_4, "720p60", false), + generateVideoStream("mpeg_4-720", MediaFormat.MPEG_4, "720p", false), + generateVideoStream("webm-480", MediaFormat.WEBM, "480p", false), + generateVideoStream("mpeg_4-360", MediaFormat.MPEG_4, "360p", false), + generateVideoStream("webm-360", MediaFormat.WEBM, "360p", false), + generateVideoStream("v3gpp-240_60", MediaFormat.v3GPP, "240p60", false), + generateVideoStream("webm-144", MediaFormat.WEBM, "144p", false)) + + // exact matches + Assert.assertEquals(1, getVideoStreamIndex("720p60", MediaFormat.MPEG_4, testList).toLong()) + Assert.assertEquals(2, getVideoStreamIndex("720p", MediaFormat.MPEG_4, testList).toLong()) + + // match but not refresh + Assert.assertEquals(0, getVideoStreamIndex("1080p60", MediaFormat.MPEG_4, testList).toLong()) + Assert.assertEquals(6, getVideoStreamIndex("240p", MediaFormat.v3GPP, testList).toLong()) + + // match but not format + Assert.assertEquals(1, getVideoStreamIndex("720p60", MediaFormat.WEBM, testList).toLong()) + Assert.assertEquals(2, getVideoStreamIndex("720p", MediaFormat.WEBM, testList).toLong()) + Assert.assertEquals(1, getVideoStreamIndex("720p60", null, testList).toLong()) + Assert.assertEquals(2, getVideoStreamIndex("720p", null, testList).toLong()) + + // match but not format and not refresh + Assert.assertEquals(0, getVideoStreamIndex("1080p60", MediaFormat.WEBM, testList).toLong()) + Assert.assertEquals(6, getVideoStreamIndex("240p", MediaFormat.WEBM, testList).toLong()) + Assert.assertEquals(0, getVideoStreamIndex("1080p60", null, testList).toLong()) + Assert.assertEquals(6, getVideoStreamIndex("240p", null, testList).toLong()) + + // match closest lower resolution + Assert.assertEquals(7, getVideoStreamIndex("200p", MediaFormat.WEBM, testList).toLong()) + Assert.assertEquals(7, getVideoStreamIndex("200p60", MediaFormat.WEBM, testList).toLong()) + Assert.assertEquals(7, getVideoStreamIndex("200p", MediaFormat.MPEG_4, testList).toLong()) + Assert.assertEquals(7, getVideoStreamIndex("200p60", MediaFormat.MPEG_4, testList).toLong()) + Assert.assertEquals(7, getVideoStreamIndex("200p", null, testList).toLong()) + Assert.assertEquals(7, getVideoStreamIndex("200p60", null, testList).toLong()) + + // Can't find a match + Assert.assertEquals(-1, getVideoStreamIndex("100p", null, testList).toLong()) + } + + companion object { + private const val BEST_RESOLUTION_KEY = "best_resolution" + private val AUDIO_STREAMS_TEST_LIST = java.util.List.of( + generateAudioStream("m4a-128-1", MediaFormat.M4A, 128), + generateAudioStream("webma-192", MediaFormat.WEBMA, 192), + generateAudioStream("mp3-64", MediaFormat.MP3, 64), + generateAudioStream("webma-192", MediaFormat.WEBMA, 192), + generateAudioStream("m4a-128-2", MediaFormat.M4A, 128), + generateAudioStream("mp3-128", MediaFormat.MP3, 128), + generateAudioStream("webma-64", MediaFormat.WEBMA, 64), + generateAudioStream("m4a-320", MediaFormat.M4A, 320), + generateAudioStream("mp3-192", MediaFormat.MP3, 192), + generateAudioStream("webma-320", MediaFormat.WEBMA, 320)) + private val AUDIO_TRACKS_TEST_LIST = java.util.List.of( + generateAudioTrack("en.or", "en.or", Locale.ENGLISH, AudioTrackType.ORIGINAL), + generateAudioTrack("en.du", "en.du", Locale.ENGLISH, AudioTrackType.DUBBED), + generateAudioTrack("en.ds", "en.ds", Locale.ENGLISH, AudioTrackType.DESCRIPTIVE), + generateAudioTrack("unknown", null, null, null), + generateAudioTrack("de.du", "de.du", Locale.GERMAN, AudioTrackType.DUBBED), + generateAudioTrack("de.ds", "de.ds", Locale.GERMAN, AudioTrackType.DESCRIPTIVE) + ) + private val VIDEO_STREAMS_TEST_LIST = java.util.List.of( + generateVideoStream("mpeg_4-720", MediaFormat.MPEG_4, "720p", false), + generateVideoStream("v3gpp-240", MediaFormat.v3GPP, "240p", false), + generateVideoStream("webm-480", MediaFormat.WEBM, "480p", false), + generateVideoStream("v3gpp-144", MediaFormat.v3GPP, "144p", false), + generateVideoStream("mpeg_4-360", MediaFormat.MPEG_4, "360p", false), + generateVideoStream("webm-360", MediaFormat.WEBM, "360p", false)) + private val VIDEO_ONLY_STREAMS_TEST_LIST = java.util.List.of( + generateVideoStream("mpeg_4-720-1", MediaFormat.MPEG_4, "720p", true), + generateVideoStream("mpeg_4-720-2", MediaFormat.MPEG_4, "720p", true), + generateVideoStream("mpeg_4-2160", MediaFormat.MPEG_4, "2160p", true), + generateVideoStream("mpeg_4-1440_60", MediaFormat.MPEG_4, "1440p60", true), + generateVideoStream("webm-720_60", MediaFormat.WEBM, "720p60", true), + generateVideoStream("mpeg_4-2160_60", MediaFormat.MPEG_4, "2160p60", true), + generateVideoStream("mpeg_4-720_60", MediaFormat.MPEG_4, "720p60", true), + generateVideoStream("mpeg_4-1080", MediaFormat.MPEG_4, "1080p", true), + generateVideoStream("mpeg_4-1080_60", MediaFormat.MPEG_4, "1080p60", true)) + + private fun generateAudioStream(id: String, + mediaFormat: MediaFormat?, + averageBitrate: Int): AudioStream { + return AudioStream.Builder() + .setId(id) + .setContent("", true) + .setMediaFormat(mediaFormat) + .setAverageBitrate(averageBitrate) + .build() + } + + private fun generateAudioTrack( + id: String, + trackId: String?, + locale: Locale?, + trackType: AudioTrackType?): AudioStream { + return AudioStream.Builder() + .setId(id) + .setContent("", true) + .setMediaFormat(MediaFormat.M4A) + .setAverageBitrate(128) + .setAudioTrackId(trackId) + .setAudioLocale(locale) + .setAudioTrackType(trackType) + .build() + } + + private fun generateVideoStream(id: String, + mediaFormat: MediaFormat?, + resolution: String, + isVideoOnly: Boolean): VideoStream { + return VideoStream.Builder() + .setId(id) + .setContent("", true) + .setIsVideoOnly(isVideoOnly) + .setResolution(resolution) + .setMediaFormat(mediaFormat) + .build() + } + } +} diff --git a/app/src/test/java/org/schabi/newpipe/util/QuadraticSliderStrategyTest.java b/app/src/test/java/org/schabi/newpipe/util/QuadraticSliderStrategyTest.java deleted file mode 100644 index f5bb0c89a..000000000 --- a/app/src/test/java/org/schabi/newpipe/util/QuadraticSliderStrategyTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.schabi.newpipe.util; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class QuadraticSliderStrategyTest { - private static final int STEP = 100; - private static final float DELTA = 1f / (float) STEP; - - private final SliderStrategy.Quadratic standard = - new SliderStrategy.Quadratic(0f, 100f, 50f, STEP); - - @Test - public void testLeftBound() { - assertEquals(standard.progressOf(0), 0); - assertEquals(standard.valueOf(0), 0f, DELTA); - } - - @Test - public void testCenter() { - assertEquals(standard.progressOf(50), 50); - assertEquals(standard.valueOf(50), 50f, DELTA); - } - - @Test - public void testRightBound() { - assertEquals(standard.progressOf(100), 100); - assertEquals(standard.valueOf(100), 100f, DELTA); - } - - @Test - public void testLeftRegion() { - final int leftProgress = standard.progressOf(25); - final double leftValue = standard.valueOf(25); - assertTrue(leftProgress > 0 && leftProgress < 50); - assertTrue(leftValue > 0f && leftValue < 50); - } - - @Test - public void testRightRegion() { - final int leftProgress = standard.progressOf(75); - final double leftValue = standard.valueOf(75); - assertTrue(leftProgress > 50 && leftProgress < 100); - assertTrue(leftValue > 50f && leftValue < 100); - } - - @Test - public void testConversion() { - assertEquals(standard.progressOf(standard.valueOf(0)), 0); - assertEquals(standard.progressOf(standard.valueOf(25)), 25); - assertEquals(standard.progressOf(standard.valueOf(50)), 50); - assertEquals(standard.progressOf(standard.valueOf(75)), 75); - assertEquals(standard.progressOf(standard.valueOf(100)), 100); - } - - @Test - public void testReverseConversion() { - // Need a larger delta since step size / granularity is too small and causes - // floating point round-off errors during conversion - final float largeDelta = 1f; - - assertEquals(standard.valueOf(standard.progressOf(0)), 0f, largeDelta); - assertEquals(standard.valueOf(standard.progressOf(25)), 25f, largeDelta); - assertEquals(standard.valueOf(standard.progressOf(50)), 50f, largeDelta); - assertEquals(standard.valueOf(standard.progressOf(75)), 75f, largeDelta); - assertEquals(standard.valueOf(standard.progressOf(100)), 100f, largeDelta); - } - - @Test - public void testQuadraticPropertyLeftRegion() { - final double differenceCloserToCenter = - Math.abs(standard.valueOf(40) - standard.valueOf(45)); - final double differenceFurtherFromCenter = - Math.abs(standard.valueOf(10) - standard.valueOf(15)); - assertTrue(differenceCloserToCenter < differenceFurtherFromCenter); - } - - @Test - public void testQuadraticPropertyRightRegion() { - final double differenceCloserToCenter = - Math.abs(standard.valueOf(75) - standard.valueOf(70)); - final double differenceFurtherFromCenter = - Math.abs(standard.valueOf(95) - standard.valueOf(90)); - assertTrue(differenceCloserToCenter < differenceFurtherFromCenter); - } -} diff --git a/app/src/test/java/org/schabi/newpipe/util/QuadraticSliderStrategyTest.kt b/app/src/test/java/org/schabi/newpipe/util/QuadraticSliderStrategyTest.kt new file mode 100644 index 000000000..3b2b9975a --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/util/QuadraticSliderStrategyTest.kt @@ -0,0 +1,83 @@ +package org.schabi.newpipe.util + +import org.junit.Assert +import org.junit.Test +import org.schabi.newpipe.util.SliderStrategy.Quadratic +import kotlin.math.abs + +class QuadraticSliderStrategyTest { + private val standard = Quadratic(0.0, 100.0, 50.0, STEP) + @Test + fun testLeftBound() { + Assert.assertEquals(standard.progressOf(0.0).toLong(), 0) + Assert.assertEquals(standard.valueOf(0), 0.0, DELTA.toDouble()) + } + + @Test + fun testCenter() { + Assert.assertEquals(standard.progressOf(50.0).toLong(), 50) + Assert.assertEquals(standard.valueOf(50), 50.0, DELTA.toDouble()) + } + + @Test + fun testRightBound() { + Assert.assertEquals(standard.progressOf(100.0).toLong(), 100) + Assert.assertEquals(standard.valueOf(100), 100.0, DELTA.toDouble()) + } + + @Test + fun testLeftRegion() { + val leftProgress = standard.progressOf(25.0) + val leftValue = standard.valueOf(25) + Assert.assertTrue(leftProgress > 0 && leftProgress < 50) + Assert.assertTrue(leftValue > 0f && leftValue < 50) + } + + @Test + fun testRightRegion() { + val leftProgress = standard.progressOf(75.0) + val leftValue = standard.valueOf(75) + Assert.assertTrue(leftProgress > 50 && leftProgress < 100) + Assert.assertTrue(leftValue > 50f && leftValue < 100) + } + + @Test + fun testConversion() { + Assert.assertEquals(standard.progressOf(standard.valueOf(0)).toLong(), 0) + Assert.assertEquals(standard.progressOf(standard.valueOf(25)).toLong(), 25) + Assert.assertEquals(standard.progressOf(standard.valueOf(50)).toLong(), 50) + Assert.assertEquals(standard.progressOf(standard.valueOf(75)).toLong(), 75) + Assert.assertEquals(standard.progressOf(standard.valueOf(100)).toLong(), 100) + } + + @Test + fun testReverseConversion() { + // Need a larger delta since step size / granularity is too small and causes + // floating point round-off errors during conversion + val largeDelta = 1f + Assert.assertEquals(standard.valueOf(standard.progressOf(0.0)), 0.0, largeDelta.toDouble()) + Assert.assertEquals(standard.valueOf(standard.progressOf(25.0)), 25.0, largeDelta.toDouble()) + Assert.assertEquals(standard.valueOf(standard.progressOf(50.0)), 50.0, largeDelta.toDouble()) + Assert.assertEquals(standard.valueOf(standard.progressOf(75.0)), 75.0, largeDelta.toDouble()) + Assert.assertEquals(standard.valueOf(standard.progressOf(100.0)), 100.0, largeDelta.toDouble()) + } + + @Test + fun testQuadraticPropertyLeftRegion() { + val differenceCloserToCenter = abs(standard.valueOf(40) - standard.valueOf(45)) + val differenceFurtherFromCenter = abs(standard.valueOf(10) - standard.valueOf(15)) + Assert.assertTrue(differenceCloserToCenter < differenceFurtherFromCenter) + } + + @Test + fun testQuadraticPropertyRightRegion() { + val differenceCloserToCenter = abs(standard.valueOf(75) - standard.valueOf(70)) + val differenceFurtherFromCenter = abs(standard.valueOf(95) - standard.valueOf(90)) + Assert.assertTrue(differenceCloserToCenter < differenceFurtherFromCenter) + } + + companion object { + private const val STEP = 100 + private const val DELTA = 1f / STEP.toFloat() + } +} diff --git a/app/src/test/java/org/schabi/newpipe/util/external_communication/TimestampExtractorTest.java b/app/src/test/java/org/schabi/newpipe/util/external_communication/TimestampExtractorTest.java deleted file mode 100644 index 47853bd7f..000000000 --- a/app/src/test/java/org/schabi/newpipe/util/external_communication/TimestampExtractorTest.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.schabi.newpipe.util.external_communication; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.schabi.newpipe.util.text.TimestampExtractor; - -import java.time.Duration; -import java.util.Arrays; -import java.util.List; -import java.util.regex.Matcher; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - -@RunWith(Parameterized.class) -public class TimestampExtractorTest { - - @Parameterized.Parameter(0) - public Duration expected; - - @Parameterized.Parameter(1) - public String stringToProcess; - - @Parameterized.Parameters(name = "Expecting {0} for \"{1}\"") - public static List dataForTests() { - return Arrays.asList(new Object[][]{ - // Simple valid values - {Duration.ofSeconds(1), "0:01"}, - {Duration.ofSeconds(1), "00:01"}, - {Duration.ofSeconds(1), "0:00:01"}, - {Duration.ofSeconds(1), "00:00:01"}, - {Duration.ofMinutes(1).plusSeconds(23), "1:23"}, - {Duration.ofMinutes(1).plusSeconds(23), "01:23"}, - {Duration.ofMinutes(1).plusSeconds(23), "0:01:23"}, - {Duration.ofMinutes(1).plusSeconds(23), "00:01:23"}, - {Duration.ofHours(1).plusMinutes(23).plusSeconds(45), "1:23:45"}, - {Duration.ofHours(1).plusMinutes(23).plusSeconds(45), "01:23:45"}, - // Check with additional text - {Duration.ofSeconds(1), "Wow 0:01 words"}, - {Duration.ofMinutes(1).plusSeconds(23), "Wow 1:23 words"}, - {Duration.ofSeconds(1), "Wow 0:01 words! 33:"}, - {null, "Wow0:01 abc"}, - {null, "Wow 0:01abc"}, - {null, "Wow0:01abc"}, - {null, "Wow0:01"}, - {null, "0:01abc"}, - // Boundary checks - {Duration.ofSeconds(0), "0:00"}, - {Duration.ofHours(59).plusMinutes(59).plusSeconds(59), "59:59:59"}, - {null, "60:59:59"}, - {null, "60:59"}, - {null, "0:60"}, - // Format checks - {null, "000:0"}, - {null, "123:01"}, - {null, "123:123"}, - {null, "2:123"}, - {null, "2:3"}, - {null, "1:2:3"}, - {null, ":3"}, - {null, "01:"}, - {null, ":01"}, - {null, "a:b:c"}, - {null, "abc:def:ghj"}, - {null, "::"}, - {null, ":"}, - {null, ""} - }); - } - - @Test - public void testExtract() { - final Matcher m = TimestampExtractor.TIMESTAMPS_PATTERN.matcher(this.stringToProcess); - - if (!m.find()) { - if (expected == null) { - return; - } - fail("No match found but expected one"); - } - - final TimestampExtractor.TimestampMatchDTO timestampMatchDTO = - TimestampExtractor - .getTimestampFromMatcher(m, this.stringToProcess); - - if (timestampMatchDTO == null) { - if (expected == null) { - return; - } - fail("Result shouldn't be null"); - } else if (expected == null) { - assertNull("Expected that the dto is null, but it isn't", timestampMatchDTO); - return; - } - - final int actualSeconds = timestampMatchDTO.seconds(); - - assertEquals(expected.getSeconds(), actualSeconds); - } -} diff --git a/app/src/test/java/org/schabi/newpipe/util/external_communication/TimestampExtractorTest.kt b/app/src/test/java/org/schabi/newpipe/util/external_communication/TimestampExtractorTest.kt new file mode 100644 index 000000000..93499e67b --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/util/external_communication/TimestampExtractorTest.kt @@ -0,0 +1,48 @@ +package org.schabi.newpipe.util.external_communication + +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized +import org.schabi.newpipe.util.text.TimestampExtractor +import org.schabi.newpipe.util.text.TimestampExtractor.getTimestampFromMatcher +import java.time.Duration +import java.util.Arrays + +@RunWith(Parameterized::class) +class TimestampExtractorTest { + @Parameterized.Parameter(0) + var expected: Duration? = null + + @Parameterized.Parameter(1) + var stringToProcess: String? = null + @Test + fun testExtract() { + val m = TimestampExtractor.TIMESTAMPS_PATTERN.matcher(stringToProcess) + if (!m.find()) { + if (expected == null) { + return + } + Assert.fail("No match found but expected one") + } + val timestampMatchDTO = getTimestampFromMatcher(m, stringToProcess!!) + if (timestampMatchDTO == null) { + if (expected == null) { + return + } + Assert.fail("Result shouldn't be null") + } else if (expected == null) { + Assert.assertNull("Expected that the dto is null, but it isn't", timestampMatchDTO) + return + } + val actualSeconds = timestampMatchDTO!!.seconds() + Assert.assertEquals(expected!!.seconds, actualSeconds.toLong()) + } + + companion object { + @Parameterized.Parameters(name = "Expecting {0} for \"{1}\"") + fun dataForTests(): List> { + return Arrays.asList>(*arrayOf(arrayOf(Duration.ofSeconds(1), "0:01"), arrayOf(Duration.ofSeconds(1), "00:01"), arrayOf(Duration.ofSeconds(1), "0:00:01"), arrayOf(Duration.ofSeconds(1), "00:00:01"), arrayOf(Duration.ofMinutes(1).plusSeconds(23), "1:23"), arrayOf(Duration.ofMinutes(1).plusSeconds(23), "01:23"), arrayOf(Duration.ofMinutes(1).plusSeconds(23), "0:01:23"), arrayOf(Duration.ofMinutes(1).plusSeconds(23), "00:01:23"), arrayOf(Duration.ofHours(1).plusMinutes(23).plusSeconds(45), "1:23:45"), arrayOf(Duration.ofHours(1).plusMinutes(23).plusSeconds(45), "01:23:45"), arrayOf(Duration.ofSeconds(1), "Wow 0:01 words"), arrayOf(Duration.ofMinutes(1).plusSeconds(23), "Wow 1:23 words"), arrayOf(Duration.ofSeconds(1), "Wow 0:01 words! 33:"), arrayOf(null, "Wow0:01 abc"), arrayOf(null, "Wow 0:01abc"), arrayOf(null, "Wow0:01abc"), arrayOf(null, "Wow0:01"), arrayOf(null, "0:01abc"), arrayOf(Duration.ofSeconds(0), "0:00"), arrayOf(Duration.ofHours(59).plusMinutes(59).plusSeconds(59), "59:59:59"), arrayOf(null, "60:59:59"), arrayOf(null, "60:59"), arrayOf(null, "0:60"), arrayOf(null, "000:0"), arrayOf(null, "123:01"), arrayOf(null, "123:123"), arrayOf(null, "2:123"), arrayOf(null, "2:3"), arrayOf(null, "1:2:3"), arrayOf(null, ":3"), arrayOf(null, "01:"), arrayOf(null, ":01"), arrayOf(null, "a:b:c"), arrayOf(null, "abc:def:ghj"), arrayOf(null, "::"), arrayOf(null, ":"), arrayOf(null, ""))) + } + } +} diff --git a/app/src/test/java/org/schabi/newpipe/util/image/ImageStrategyTest.java b/app/src/test/java/org/schabi/newpipe/util/image/ImageStrategyTest.java deleted file mode 100644 index 8c8bf6937..000000000 --- a/app/src/test/java/org/schabi/newpipe/util/image/ImageStrategyTest.java +++ /dev/null @@ -1,195 +0,0 @@ -package org.schabi.newpipe.util.image; - -import static org.junit.Assert.assertEquals; -import static org.schabi.newpipe.extractor.Image.HEIGHT_UNKNOWN; -import static org.schabi.newpipe.extractor.Image.WIDTH_UNKNOWN; -import static org.schabi.newpipe.util.image.ImageStrategy.choosePreferredImage; -import static org.schabi.newpipe.util.image.ImageStrategy.estimatePixelCount; - -import org.junit.Test; -import org.schabi.newpipe.extractor.Image; -import org.schabi.newpipe.extractor.Image.ResolutionLevel; - -import java.util.List; - -public class ImageStrategyTest { - - private static final List RESOLUTION_LEVELS = List.of( - ResolutionLevel.LOW, ResolutionLevel.MEDIUM, ResolutionLevel.HIGH); - - private Image img(final int height, final int width) { - return new Image("", height, width, ResolutionLevel.UNKNOWN); - } - - private Image img(final String url, final ResolutionLevel resolutionLevel) { - return new Image(url, HEIGHT_UNKNOWN, WIDTH_UNKNOWN, resolutionLevel); - } - - private Image img(final String url, - final int height, - final int width, - final ResolutionLevel resolutionLevel) { - return new Image(url, height, width, resolutionLevel); - } - - private void assertChoosePreferredImage(final String low, - final String medium, - final String high, - final List images) { - assertEquals(low, choosePreferredImage(images, PreferredImageQuality.LOW)); - assertEquals(medium, choosePreferredImage(images, PreferredImageQuality.MEDIUM)); - assertEquals(high, choosePreferredImage(images, PreferredImageQuality.HIGH)); - } - - - // CHECKSTYLE:OFF - @Test - public void testEstimatePixelCountAllKnown() { - assertEquals(20000.0, estimatePixelCount(img(100, 200), 1.0), 0.0); - assertEquals(20000.0, estimatePixelCount(img(100, 200), 12.0), 0.0); - assertEquals( 100.0, estimatePixelCount(img(100, 1), 12.0), 0.0); - assertEquals( 100.0, estimatePixelCount(img( 1, 100), 0.5), 0.0); - } - - @Test - public void testEstimatePixelCountHeightUnknown() { - assertEquals( 10000.0, estimatePixelCount(img(HEIGHT_UNKNOWN, 100), 1.0 ), 0.0); - assertEquals( 20000.0, estimatePixelCount(img(HEIGHT_UNKNOWN, 200), 2.0 ), 0.0); - assertEquals( 10.0, estimatePixelCount(img(HEIGHT_UNKNOWN, 1), 0.1 ), 0.0); - assertEquals(230400.0, estimatePixelCount(img(HEIGHT_UNKNOWN, 640), 16.0/9.0), 0.0); - } - - @Test - public void testEstimatePixelCountWidthUnknown() { - assertEquals( 10000.0, estimatePixelCount(img(100, WIDTH_UNKNOWN), 1.0 ), 0.0); - assertEquals( 20000.0, estimatePixelCount(img(200, WIDTH_UNKNOWN), 0.5 ), 0.0); - assertEquals( 12.0, estimatePixelCount(img( 1, WIDTH_UNKNOWN), 12.0 ), 0.0); - assertEquals(230400.0, estimatePixelCount(img(360, WIDTH_UNKNOWN), 16.0/9.0), 0.0); - } - - @Test - public void testEstimatePixelCountAllUnknown() { - assertEquals(0.0, estimatePixelCount(img(HEIGHT_UNKNOWN, WIDTH_UNKNOWN), 1.0 ), 0.0); - assertEquals(0.0, estimatePixelCount(img(HEIGHT_UNKNOWN, WIDTH_UNKNOWN), 12.0 ), 0.0); - assertEquals(0.0, estimatePixelCount(img(HEIGHT_UNKNOWN, WIDTH_UNKNOWN), 0.1 ), 0.0); - assertEquals(0.0, estimatePixelCount(img(HEIGHT_UNKNOWN, WIDTH_UNKNOWN), 16.0/9.0), 0.0); - } - // CHECKSTYLE:ON - - - @Test - public void testChoosePreferredImageAllKnown() { - // the resolution level of the images is more important than the actual resolution - assertChoosePreferredImage("a", "b", "c", List.of( - img("a", 1, 1, ResolutionLevel.LOW), - img("b", 200, 200, ResolutionLevel.MEDIUM), - img("c", 10000, 10000, ResolutionLevel.HIGH) - )); - assertChoosePreferredImage("a", "b", "c", List.of( - img("a", 10000, 10000, ResolutionLevel.LOW), - img("b", 200, 200, ResolutionLevel.MEDIUM), - img("c", 1, 1, ResolutionLevel.HIGH) - )); - - assertChoosePreferredImage("b", "c", "d", List.of( - img("a", 2, 1, ResolutionLevel.LOW), - img("b", 50, 25, ResolutionLevel.LOW), - img("c", 200, 100, ResolutionLevel.LOW), - img("d", 300, 150, ResolutionLevel.LOW) - )); - - assertChoosePreferredImage("c", "d", "d", List.of( - img("a", 2, 1, ResolutionLevel.MEDIUM), - img("b", 50, 25, ResolutionLevel.MEDIUM), - img("c", 60, 30, ResolutionLevel.MEDIUM), - img("d", 300, 150, ResolutionLevel.MEDIUM) - )); - } - - @Test - public void testChoosePreferredImageSomeKnown() { - // the resolution level of the images is more important than the actual resolution - assertChoosePreferredImage("a", "b", "c", List.of( - img("a", 1, WIDTH_UNKNOWN, ResolutionLevel.LOW), - img("b", HEIGHT_UNKNOWN, 200, ResolutionLevel.MEDIUM), - img("c", 10000, WIDTH_UNKNOWN, ResolutionLevel.HIGH) - )); - assertChoosePreferredImage("a", "b", "c", List.of( - img("a", HEIGHT_UNKNOWN, 10000, ResolutionLevel.LOW), - img("b", 200, WIDTH_UNKNOWN, ResolutionLevel.MEDIUM), - img("c", HEIGHT_UNKNOWN, 1, ResolutionLevel.HIGH) - )); - - assertChoosePreferredImage("b", "c", "d", List.of( - img("a", HEIGHT_UNKNOWN, 1, ResolutionLevel.HIGH), - img("b", 50, WIDTH_UNKNOWN, ResolutionLevel.HIGH), - img("c", HEIGHT_UNKNOWN, 120, ResolutionLevel.HIGH), - img("d", 340, WIDTH_UNKNOWN, ResolutionLevel.HIGH) - )); - - assertChoosePreferredImage("c", "d", "d", List.of( - img("a", 2, WIDTH_UNKNOWN, ResolutionLevel.MEDIUM), - img("b", HEIGHT_UNKNOWN, 50, ResolutionLevel.MEDIUM), - img("c", 60, WIDTH_UNKNOWN, ResolutionLevel.MEDIUM), - img("d", HEIGHT_UNKNOWN, 340, ResolutionLevel.MEDIUM) - )); - } - - @Test - public void testChoosePreferredImageMixed() { - for (final ResolutionLevel resolutionLevel : RESOLUTION_LEVELS) { - assertChoosePreferredImage("d", "b", "c", List.of( - img("a", ResolutionLevel.UNKNOWN), - img("b", 200, 100, resolutionLevel), - img("c", 400, WIDTH_UNKNOWN, resolutionLevel), - img("d", HEIGHT_UNKNOWN, 50, resolutionLevel), - img("e", resolutionLevel) - )); - } - for (final ResolutionLevel resolutionLevel : RESOLUTION_LEVELS) { - assertChoosePreferredImage("b", "b", "b", List.of( - img("a", ResolutionLevel.UNKNOWN), - img("b", 200, 100, resolutionLevel), - img("e", resolutionLevel) - )); - } - assertChoosePreferredImage("b", "b", "e", List.of( - img("a", ResolutionLevel.UNKNOWN), - img("b", 200, 100, ResolutionLevel.LOW), - img("e", ResolutionLevel.HIGH) - )); - } - - @Test - public void testChoosePreferredImageAllUnknown() { - assertChoosePreferredImage("b", "c", "d", List.of( - img("a", ResolutionLevel.UNKNOWN), - img("b", ResolutionLevel.LOW), - img("c", ResolutionLevel.MEDIUM), - img("d", ResolutionLevel.HIGH) - )); - assertChoosePreferredImage("c", "c", "d", List.of( - img("a", ResolutionLevel.UNKNOWN), - img("c", ResolutionLevel.MEDIUM), - img("d", ResolutionLevel.HIGH) - )); - assertChoosePreferredImage("b", "c", "c", List.of( - img("a", ResolutionLevel.UNKNOWN), - img("b", ResolutionLevel.LOW), - img("c", ResolutionLevel.MEDIUM) - )); - - // UNKNOWN is avoided as much as possible - assertChoosePreferredImage("d", "d", "d", List.of( - img("a", ResolutionLevel.UNKNOWN), - img("d", ResolutionLevel.HIGH) - )); - assertChoosePreferredImage("b", "b", "b", List.of( - img("a", ResolutionLevel.UNKNOWN), - img("b", ResolutionLevel.LOW) - )); - assertChoosePreferredImage("a", "a", "a", List.of( - img("a", ResolutionLevel.UNKNOWN) - )); - } -} diff --git a/app/src/test/java/org/schabi/newpipe/util/image/ImageStrategyTest.kt b/app/src/test/java/org/schabi/newpipe/util/image/ImageStrategyTest.kt new file mode 100644 index 000000000..89b866f83 --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/util/image/ImageStrategyTest.kt @@ -0,0 +1,184 @@ +package org.schabi.newpipe.util.image + +import org.junit.Assert +import org.junit.Test +import org.schabi.newpipe.extractor.Image +import org.schabi.newpipe.extractor.Image.ResolutionLevel +import org.schabi.newpipe.util.image.ImageStrategy.estimatePixelCount + +class ImageStrategyTest { + private fun img(height: Int, width: Int): Image { + return Image("", height, width, ResolutionLevel.UNKNOWN) + } + + private fun img(url: String, resolutionLevel: ResolutionLevel): Image { + return Image(url, Image.HEIGHT_UNKNOWN, Image.WIDTH_UNKNOWN, resolutionLevel) + } + + private fun img(url: String, + height: Int, + width: Int, + resolutionLevel: ResolutionLevel): Image { + return Image(url, height, width, resolutionLevel) + } + + private fun assertChoosePreferredImage(low: String, + medium: String, + high: String, + images: List) { + assertEquals(low, choosePreferredImage(images, PreferredImageQuality.LOW)) + assertEquals(medium, choosePreferredImage(images, PreferredImageQuality.MEDIUM)) + assertEquals(high, choosePreferredImage(images, PreferredImageQuality.HIGH)) + } + + // CHECKSTYLE:OFF + @Test + fun testEstimatePixelCountAllKnown() { + Assert.assertEquals(20000.0, estimatePixelCount(img(100, 200), 1.0), 0.0) + Assert.assertEquals(20000.0, estimatePixelCount(img(100, 200), 12.0), 0.0) + Assert.assertEquals(100.0, estimatePixelCount(img(100, 1), 12.0), 0.0) + Assert.assertEquals(100.0, estimatePixelCount(img(1, 100), 0.5), 0.0) + } + + @Test + fun testEstimatePixelCountHeightUnknown() { + Assert.assertEquals(10000.0, estimatePixelCount(img(Image.HEIGHT_UNKNOWN, 100), 1.0), 0.0) + Assert.assertEquals(20000.0, estimatePixelCount(img(Image.HEIGHT_UNKNOWN, 200), 2.0), 0.0) + Assert.assertEquals(10.0, estimatePixelCount(img(Image.HEIGHT_UNKNOWN, 1), 0.1), 0.0) + Assert.assertEquals(230400.0, estimatePixelCount(img(Image.HEIGHT_UNKNOWN, 640), 16.0 / 9.0), 0.0) + } + + @Test + fun testEstimatePixelCountWidthUnknown() { + Assert.assertEquals(10000.0, estimatePixelCount(img(100, Image.WIDTH_UNKNOWN), 1.0), 0.0) + Assert.assertEquals(20000.0, estimatePixelCount(img(200, Image.WIDTH_UNKNOWN), 0.5), 0.0) + Assert.assertEquals(12.0, estimatePixelCount(img(1, Image.WIDTH_UNKNOWN), 12.0), 0.0) + Assert.assertEquals(230400.0, estimatePixelCount(img(360, Image.WIDTH_UNKNOWN), 16.0 / 9.0), 0.0) + } + + @Test + fun testEstimatePixelCountAllUnknown() { + Assert.assertEquals(0.0, estimatePixelCount(img(Image.HEIGHT_UNKNOWN, Image.WIDTH_UNKNOWN), 1.0), 0.0) + Assert.assertEquals(0.0, estimatePixelCount(img(Image.HEIGHT_UNKNOWN, Image.WIDTH_UNKNOWN), 12.0), 0.0) + Assert.assertEquals(0.0, estimatePixelCount(img(Image.HEIGHT_UNKNOWN, Image.WIDTH_UNKNOWN), 0.1), 0.0) + Assert.assertEquals(0.0, estimatePixelCount(img(Image.HEIGHT_UNKNOWN, Image.WIDTH_UNKNOWN), 16.0 / 9.0), 0.0) + } + + // CHECKSTYLE:ON + @Test + fun testChoosePreferredImageAllKnown() { + // the resolution level of the images is more important than the actual resolution + assertChoosePreferredImage("a", "b", "c", java.util.List.of( + img("a", 1, 1, ResolutionLevel.LOW), + img("b", 200, 200, ResolutionLevel.MEDIUM), + img("c", 10000, 10000, ResolutionLevel.HIGH) + )) + assertChoosePreferredImage("a", "b", "c", java.util.List.of( + img("a", 10000, 10000, ResolutionLevel.LOW), + img("b", 200, 200, ResolutionLevel.MEDIUM), + img("c", 1, 1, ResolutionLevel.HIGH) + )) + assertChoosePreferredImage("b", "c", "d", java.util.List.of( + img("a", 2, 1, ResolutionLevel.LOW), + img("b", 50, 25, ResolutionLevel.LOW), + img("c", 200, 100, ResolutionLevel.LOW), + img("d", 300, 150, ResolutionLevel.LOW) + )) + assertChoosePreferredImage("c", "d", "d", java.util.List.of( + img("a", 2, 1, ResolutionLevel.MEDIUM), + img("b", 50, 25, ResolutionLevel.MEDIUM), + img("c", 60, 30, ResolutionLevel.MEDIUM), + img("d", 300, 150, ResolutionLevel.MEDIUM) + )) + } + + @Test + fun testChoosePreferredImageSomeKnown() { + // the resolution level of the images is more important than the actual resolution + assertChoosePreferredImage("a", "b", "c", java.util.List.of( + img("a", 1, Image.WIDTH_UNKNOWN, ResolutionLevel.LOW), + img("b", Image.HEIGHT_UNKNOWN, 200, ResolutionLevel.MEDIUM), + img("c", 10000, Image.WIDTH_UNKNOWN, ResolutionLevel.HIGH) + )) + assertChoosePreferredImage("a", "b", "c", java.util.List.of( + img("a", Image.HEIGHT_UNKNOWN, 10000, ResolutionLevel.LOW), + img("b", 200, Image.WIDTH_UNKNOWN, ResolutionLevel.MEDIUM), + img("c", Image.HEIGHT_UNKNOWN, 1, ResolutionLevel.HIGH) + )) + assertChoosePreferredImage("b", "c", "d", java.util.List.of( + img("a", Image.HEIGHT_UNKNOWN, 1, ResolutionLevel.HIGH), + img("b", 50, Image.WIDTH_UNKNOWN, ResolutionLevel.HIGH), + img("c", Image.HEIGHT_UNKNOWN, 120, ResolutionLevel.HIGH), + img("d", 340, Image.WIDTH_UNKNOWN, ResolutionLevel.HIGH) + )) + assertChoosePreferredImage("c", "d", "d", java.util.List.of( + img("a", 2, Image.WIDTH_UNKNOWN, ResolutionLevel.MEDIUM), + img("b", Image.HEIGHT_UNKNOWN, 50, ResolutionLevel.MEDIUM), + img("c", 60, Image.WIDTH_UNKNOWN, ResolutionLevel.MEDIUM), + img("d", Image.HEIGHT_UNKNOWN, 340, ResolutionLevel.MEDIUM) + )) + } + + @Test + fun testChoosePreferredImageMixed() { + for (resolutionLevel in RESOLUTION_LEVELS) { + assertChoosePreferredImage("d", "b", "c", java.util.List.of( + img("a", ResolutionLevel.UNKNOWN), + img("b", 200, 100, resolutionLevel), + img("c", 400, Image.WIDTH_UNKNOWN, resolutionLevel), + img("d", Image.HEIGHT_UNKNOWN, 50, resolutionLevel), + img("e", resolutionLevel) + )) + } + for (resolutionLevel in RESOLUTION_LEVELS) { + assertChoosePreferredImage("b", "b", "b", java.util.List.of( + img("a", ResolutionLevel.UNKNOWN), + img("b", 200, 100, resolutionLevel), + img("e", resolutionLevel) + )) + } + assertChoosePreferredImage("b", "b", "e", java.util.List.of( + img("a", ResolutionLevel.UNKNOWN), + img("b", 200, 100, ResolutionLevel.LOW), + img("e", ResolutionLevel.HIGH) + )) + } + + @Test + fun testChoosePreferredImageAllUnknown() { + assertChoosePreferredImage("b", "c", "d", java.util.List.of( + img("a", ResolutionLevel.UNKNOWN), + img("b", ResolutionLevel.LOW), + img("c", ResolutionLevel.MEDIUM), + img("d", ResolutionLevel.HIGH) + )) + assertChoosePreferredImage("c", "c", "d", java.util.List.of( + img("a", ResolutionLevel.UNKNOWN), + img("c", ResolutionLevel.MEDIUM), + img("d", ResolutionLevel.HIGH) + )) + assertChoosePreferredImage("b", "c", "c", java.util.List.of( + img("a", ResolutionLevel.UNKNOWN), + img("b", ResolutionLevel.LOW), + img("c", ResolutionLevel.MEDIUM) + )) + + // UNKNOWN is avoided as much as possible + assertChoosePreferredImage("d", "d", "d", java.util.List.of( + img("a", ResolutionLevel.UNKNOWN), + img("d", ResolutionLevel.HIGH) + )) + assertChoosePreferredImage("b", "b", "b", java.util.List.of( + img("a", ResolutionLevel.UNKNOWN), + img("b", ResolutionLevel.LOW) + )) + assertChoosePreferredImage("a", "a", "a", java.util.List.of( + img("a", ResolutionLevel.UNKNOWN) + )) + } + + companion object { + private val RESOLUTION_LEVELS = java.util.List.of( + ResolutionLevel.LOW, ResolutionLevel.MEDIUM, ResolutionLevel.HIGH) + } +}