diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index e43172f83..587b6780a 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -67,12 +67,15 @@ jobs: matrix: include: - variant: "PlayDebug" + base-variant: "Debug" execute-tests: true upload-artifact: true - variant: "PlayRelease" + base-variant: "Release" execute-tests: true upload-artifact: false - variant: "FreeRelease" + base-variant: "Release" execute-tests: false upload-artifact: false steps: @@ -90,7 +93,7 @@ jobs: run: ./gradlew assemble${{ matrix.variant }} - name: Test if: matrix.execute-tests == true - run: ./gradlew test${{ matrix.variant }}UnitTest + run: ./gradlew test${{ matrix.variant }}UnitTest test${{ matrix.base-variant }}UnitTest - uses: actions/upload-artifact@v2 if: matrix.upload-artifact == true with: diff --git a/.github/workflows/runEmulatorTests.sh b/.github/workflows/runEmulatorTests.sh index ee7a42e0a..106b69444 100644 --- a/.github/workflows/runEmulatorTests.sh +++ b/.github/workflows/runEmulatorTests.sh @@ -3,7 +3,7 @@ set -o pipefail runTests() { - ./gradlew connectedPlayDebugAndroidTest \ + ./gradlew connectedPlayDebugAndroidTest connectedDebugAndroidTest \ -Pandroid.testInstrumentationRunnerArguments.notAnnotation=de.test.antennapod.IgnoreOnCi \ | grep -v "V/InstrumentationResultParser: INSTRUMENTATION_STATUS" } diff --git a/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java b/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java index 2ab2361d7..67a660ae1 100644 --- a/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java +++ b/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java @@ -223,10 +223,6 @@ public class PlaybackTest { startLocalPlayback(); } - protected MainActivity getActivity() { - return activityTestRule.getActivity(); - } - protected void setContinuousPlaybackPreference(boolean value) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); prefs.edit().putBoolean(UserPreferences.PREF_FOLLOW_QUEUE, value).commit(); diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java index 74414240f..902cad98c 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java @@ -35,7 +35,9 @@ import de.test.antennapod.EspressoTestUtils; import static androidx.test.espresso.Espresso.onData; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard; import static androidx.test.espresso.action.ViewActions.replaceText; +import static androidx.test.espresso.action.ViewActions.scrollTo; import static androidx.test.espresso.action.ViewActions.swipeDown; import static androidx.test.espresso.action.ViewActions.swipeUp; import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; @@ -302,6 +304,7 @@ public class PreferencesTest { clickPreference(R.string.pref_parallel_downloads_title); onView(isRoot()).perform(waitForView(withClassName(endsWith("EditText")), 1000)); onView(withClassName(endsWith("EditText"))).perform(replaceText("10")); + onView(withClassName(endsWith("EditText"))).perform(closeSoftKeyboard()); onView(withText(android.R.string.ok)).perform(click()); Awaitility.await().atMost(1000, MILLISECONDS) .until(() -> UserPreferences.getParallelDownloads() == 10); @@ -391,7 +394,7 @@ public class PreferencesTest { clickPreference(R.string.network_pref); onView(withText(R.string.pref_automatic_download_title)).perform(click()); onView(withText(R.string.pref_episode_cleanup_title)).perform(click()); - onView(isRoot()).perform(waitForView(withText(R.string.episode_cleanup_except_favorite_removal), 1000)); + onView(withId(R.id.select_dialog_listview)).perform(swipeDown()); onView(withText(R.string.episode_cleanup_except_favorite_removal)).perform(click()); Awaitility.await().atMost(1000, MILLISECONDS) .until(() -> UserPreferences.getEpisodeCleanupAlgorithm() instanceof ExceptFavoriteCleanupAlgorithm); @@ -402,7 +405,7 @@ public class PreferencesTest { clickPreference(R.string.network_pref); onView(withText(R.string.pref_automatic_download_title)).perform(click()); onView(withText(R.string.pref_episode_cleanup_title)).perform(click()); - onView(isRoot()).perform(waitForView(withText(R.string.episode_cleanup_queue_removal), 1000)); + onView(withId(R.id.select_dialog_listview)).perform(swipeDown()); onView(withText(R.string.episode_cleanup_queue_removal)).perform(click()); Awaitility.await().atMost(1000, MILLISECONDS) .until(() -> UserPreferences.getEpisodeCleanupAlgorithm() instanceof APQueueCleanupAlgorithm); @@ -424,7 +427,7 @@ public class PreferencesTest { clickPreference(R.string.network_pref); onView(withText(R.string.pref_automatic_download_title)).perform(click()); onView(withText(R.string.pref_episode_cleanup_title)).perform(click()); - onView(isRoot()).perform(waitForView(withText(R.string.episode_cleanup_after_listening), 1000)); + onView(withId(R.id.select_dialog_listview)).perform(swipeUp()); onView(withText(R.string.episode_cleanup_after_listening)).perform(click()); Awaitility.await().atMost(1000, MILLISECONDS) .until(() -> { @@ -443,7 +446,7 @@ public class PreferencesTest { clickPreference(R.string.pref_automatic_download_title); clickPreference(R.string.pref_episode_cleanup_title); String search = res.getQuantityString(R.plurals.episode_cleanup_days_after_listening, 3, 3); - onView(isRoot()).perform(waitForView(withText(search), 1000)); + onView(withText(search)).perform(scrollTo()); onView(withText(search)).perform(click()); Awaitility.await().atMost(1000, MILLISECONDS) .until(() -> { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index dd445258e..982800b1c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -257,6 +257,11 @@ public class DownloadService extends Service { reportQueue.clear(); } + unregisterReceiver(cancelDownloadReceiver); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + connectionMonitor.disable(getApplicationContext()); + } + EventBus.getDefault().postSticky(DownloadEvent.refresh(Collections.emptyList())); cancelNotificationUpdater(); downloadHandleExecutor.shutdown(); @@ -266,10 +271,6 @@ public class DownloadService extends Service { downloadPostFuture.cancel(true); } downloads.clear(); - unregisterReceiver(cancelDownloadReceiver); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - connectionMonitor.disable(getApplicationContext()); - } // start auto download in case anything new has shown up DBTasks.autodownloadUndownloadedItems(getApplicationContext()); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index 0daa6b483..db6088d8d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -730,6 +730,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { } mediaPlayer.release(); mediaPlayer = null; + playerStatus = PlayerStatus.STOPPED; } isShutDown = true; executor.shutdown(); @@ -836,6 +837,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { } if (media == null) { mediaPlayer = null; + playerStatus = PlayerStatus.STOPPED; return; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java index c948d98a3..d9f5811e2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java @@ -38,7 +38,11 @@ public class AudioPlayer extends MediaPlayer implements IPlayer { @Override public void setPlaybackParams(float speed, boolean skipSilence) { if (canSetSpeed()) { - setPlaybackSpeed(speed); + try { + setPlaybackSpeed(speed); + } catch (Exception e) { + e.printStackTrace(); + } } //Default player does not support silence skipping } diff --git a/parser/media/build.gradle b/parser/media/build.gradle index 106247d1d..e463040b9 100644 --- a/parser/media/build.gradle +++ b/parser/media/build.gradle @@ -9,4 +9,5 @@ dependencies { implementation "commons-io:commons-io:$commonsioVersion" testImplementation "junit:junit:$junitVersion" + testImplementation "org.robolectric:robolectric:$robolectricVersion" } diff --git a/parser/media/src/main/java/de/danoeh/antennapod/parser/media/vorbis/VorbisCommentReader.java b/parser/media/src/main/java/de/danoeh/antennapod/parser/media/vorbis/VorbisCommentReader.java index b4f87bd70..607172531 100644 --- a/parser/media/src/main/java/de/danoeh/antennapod/parser/media/vorbis/VorbisCommentReader.java +++ b/parser/media/src/main/java/de/danoeh/antennapod/parser/media/vorbis/VorbisCommentReader.java @@ -41,7 +41,7 @@ public abstract class VorbisCommentReader { public void readInputStream(InputStream input) throws VorbisCommentReaderException { try { - findIdentificationHeader(input); + skipIdentificationHeader(input); onVorbisCommentFound(); findOggPage(input); findCommentHeader(input); @@ -101,21 +101,20 @@ public abstract class VorbisCommentReader { /** * Looks for an identification header in the first page of the file. If an - * identification header is found, it will be skipped completely and the - * method will return true, otherwise false. + * identification header is found, it will be skipped completely */ - private void findIdentificationHeader(InputStream input) throws IOException { + private void skipIdentificationHeader(InputStream input) throws IOException { byte[] buffer = new byte[FIRST_OPUS_PAGE_LENGTH]; IOUtils.readFully(input, buffer); final byte[] oggIdentificationHeader = new byte[]{ PACKET_TYPE_IDENTIFICATION, 'v', 'o', 'r', 'b', 'i', 's' }; for (int i = 6; i < buffer.length; i++) { if (bufferMatches(buffer, oggIdentificationHeader, i)) { IOUtils.skip(input, FIRST_OGG_PAGE_LENGTH - FIRST_OPUS_PAGE_LENGTH); + return; } else if (bufferMatches(buffer, "OpusHead".getBytes(), i)) { return; } } - throw new IOException("No identification header found"); } private void findCommentHeader(InputStream input) throws IOException { diff --git a/parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/ChapterReaderTest.java b/parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/ChapterReaderTest.java index af535b12a..f87764c7f 100644 --- a/parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/ChapterReaderTest.java +++ b/parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/ChapterReaderTest.java @@ -5,6 +5,8 @@ import de.danoeh.antennapod.model.feed.EmbeddedChapterImage; import de.danoeh.antennapod.parser.media.id3.model.FrameHeader; import org.apache.commons.io.input.CountingInputStream; import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -12,6 +14,7 @@ import java.util.List; import static org.junit.Assert.assertEquals; +@RunWith(RobolectricTestRunner.class) public class ChapterReaderTest { private static final byte CHAPTER_WITHOUT_SUBFRAME_START_TIME = 23; private static final byte[] CHAPTER_WITHOUT_SUBFRAME = { diff --git a/parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/Id3ReaderTest.java b/parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/Id3ReaderTest.java index 4b0bb2113..39757025f 100644 --- a/parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/Id3ReaderTest.java +++ b/parser/media/src/test/java/de/danoeh/antennapod/parser/media/id3/Id3ReaderTest.java @@ -4,6 +4,8 @@ import de.danoeh.antennapod.parser.media.id3.model.FrameHeader; import de.danoeh.antennapod.parser.media.id3.model.TagHeader; import org.apache.commons.io.input.CountingInputStream; import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -14,6 +16,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +@RunWith(RobolectricTestRunner.class) public class Id3ReaderTest { @Test public void testReadString() throws IOException { diff --git a/parser/media/src/test/java/de/danoeh/antennapod/parser/media/vorbis/VorbisCommentChapterReaderTest.java b/parser/media/src/test/java/de/danoeh/antennapod/parser/media/vorbis/VorbisCommentChapterReaderTest.java index b81ce4651..6ebe875d9 100644 --- a/parser/media/src/test/java/de/danoeh/antennapod/parser/media/vorbis/VorbisCommentChapterReaderTest.java +++ b/parser/media/src/test/java/de/danoeh/antennapod/parser/media/vorbis/VorbisCommentChapterReaderTest.java @@ -2,6 +2,8 @@ package de.danoeh.antennapod.parser.media.vorbis; import de.danoeh.antennapod.model.feed.Chapter; import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; import java.io.IOException; import java.io.InputStream; @@ -9,6 +11,7 @@ import java.util.List; import static org.junit.Assert.assertEquals; +@RunWith(RobolectricTestRunner.class) public class VorbisCommentChapterReaderTest { @Test