diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index f0aff366e..f106a3aac 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -23,8 +23,8 @@ jobs: cache: gradle - name: Grant execute permission for gradlew run: chmod +x gradlew - # - name: Test app with Gradle - # run: ./gradlew app:testDebug + - name: Test app with Gradle + run: ./gradlew app:testDebug - name: Build debug APK with Gradle run: ./gradlew app:packageDebug - name: Upload debug APK artifact diff --git a/app/build.gradle b/app/build.gradle index 6ab20ef92..45fdff5ea 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -145,8 +145,10 @@ dependencies { // Testing debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12' testImplementation "junit:junit:4.13.2" + testImplementation "io.mockk:mockk:1.13.7" androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + } spotless { diff --git a/app/src/main/java/org/oxycblt/auxio/music/info/Name.kt b/app/src/main/java/org/oxycblt/auxio/music/info/Name.kt index fb753f641..c47e561cf 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/info/Name.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/info/Name.kt @@ -20,6 +20,7 @@ package org.oxycblt.auxio.music.info import android.content.Context import androidx.annotation.StringRes +import androidx.annotation.VisibleForTesting import java.text.CollationKey import java.text.Collator import org.oxycblt.auxio.music.MusicSettings @@ -54,10 +55,11 @@ sealed interface Name : Comparable { abstract val sort: String? /** A tokenized version of the name that will be compared. */ - protected abstract val sortTokens: List + @VisibleForTesting(VisibleForTesting.PROTECTED) abstract val sortTokens: List /** An individual part of a name string that can be compared intelligently. */ - protected data class SortToken(val collationKey: CollationKey, val type: Type) : + @VisibleForTesting(VisibleForTesting.PROTECTED) + data class SortToken(val collationKey: CollationKey, val type: Type) : Comparable { override fun compareTo(other: SortToken): Int { // Numeric tokens should always be lower than lexicographic tokens. diff --git a/app/src/test/java/org/oxycblt/auxio/music/FakeMusic.kt b/app/src/test/java/org/oxycblt/auxio/music/FakeMusic.kt deleted file mode 100644 index 32d8c0df2..000000000 --- a/app/src/test/java/org/oxycblt/auxio/music/FakeMusic.kt +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2023 Auxio Project - * FakeMusic.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.music - -import android.net.Uri -import org.oxycblt.auxio.music.fs.MimeType -import org.oxycblt.auxio.music.fs.Path -import org.oxycblt.auxio.music.info.Date -import org.oxycblt.auxio.music.info.Disc -import org.oxycblt.auxio.music.info.Name -import org.oxycblt.auxio.music.info.ReleaseType - -open class FakeSong : Song { - override val name: Name - get() = throw NotImplementedError() - - override val date: Date? - get() = throw NotImplementedError() - - override val dateAdded: Long - get() = throw NotImplementedError() - - override val disc: Disc? - get() = throw NotImplementedError() - - override val genres: List - get() = throw NotImplementedError() - - override val mimeType: MimeType - get() = throw NotImplementedError() - - override val track: Int? - get() = throw NotImplementedError() - - override val path: Path - get() = throw NotImplementedError() - - override val size: Long - get() = throw NotImplementedError() - - override val uri: Uri - get() = throw NotImplementedError() - - override val album: Album - get() = throw NotImplementedError() - - override val artists: List - get() = throw NotImplementedError() - - override val durationMs: Long - get() = throw NotImplementedError() - - override val uid: Music.UID - get() = throw NotImplementedError() -} - -open class FakeAlbum : Album { - override val name: Name - get() = throw NotImplementedError() - - override val coverUri: Uri - get() = throw NotImplementedError() - - override val dateAdded: Long - get() = throw NotImplementedError() - - override val dates: Date.Range? - get() = throw NotImplementedError() - - override val releaseType: ReleaseType - get() = throw NotImplementedError() - - override val artists: List - get() = throw NotImplementedError() - - override val durationMs: Long - get() = throw NotImplementedError() - - override val songs: List - get() = throw NotImplementedError() - - override val uid: Music.UID - get() = throw NotImplementedError() -} - -open class FakeArtist : Artist { - override val name: Name - get() = throw NotImplementedError() - - override val albums: List - get() = throw NotImplementedError() - - override val explicitAlbums: List - get() = throw NotImplementedError() - - override val implicitAlbums: List - get() = throw NotImplementedError() - - override val genres: List - get() = throw NotImplementedError() - - override val durationMs: Long - get() = throw NotImplementedError() - - override val songs: List - get() = throw NotImplementedError() - - override val uid: Music.UID - get() = throw NotImplementedError() -} - -open class FakeGenre : Genre { - override val name: Name - get() = throw NotImplementedError() - - override val artists: List - get() = throw NotImplementedError() - - override val durationMs: Long - get() = throw NotImplementedError() - - override val songs: List - get() = throw NotImplementedError() - - override val uid: Music.UID - get() = throw NotImplementedError() -} diff --git a/app/src/test/java/org/oxycblt/auxio/music/FakeMusicRepository.kt b/app/src/test/java/org/oxycblt/auxio/music/FakeMusicRepository.kt deleted file mode 100644 index 8c79f0e9a..000000000 --- a/app/src/test/java/org/oxycblt/auxio/music/FakeMusicRepository.kt +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2023 Auxio Project - * FakeMusicRepository.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.music - -import kotlinx.coroutines.Job -import org.oxycblt.auxio.music.device.DeviceLibrary -import org.oxycblt.auxio.music.user.UserLibrary - -open class FakeMusicRepository : MusicRepository { - override val indexingState: IndexingState? - get() = throw NotImplementedError() - - override val deviceLibrary: DeviceLibrary? - get() = throw NotImplementedError() - - override val userLibrary: UserLibrary? - get() = throw NotImplementedError() - - override fun addUpdateListener(listener: MusicRepository.UpdateListener) { - throw NotImplementedError() - } - - override fun removeUpdateListener(listener: MusicRepository.UpdateListener) { - throw NotImplementedError() - } - - override fun addIndexingListener(listener: MusicRepository.IndexingListener) { - throw NotImplementedError() - } - - override fun removeIndexingListener(listener: MusicRepository.IndexingListener) { - throw NotImplementedError() - } - - override fun registerWorker(worker: MusicRepository.IndexingWorker) { - throw NotImplementedError() - } - - override fun unregisterWorker(worker: MusicRepository.IndexingWorker) { - throw NotImplementedError() - } - - override fun find(uid: Music.UID): Music? { - throw NotImplementedError() - } - - override suspend fun createPlaylist(name: String, songs: List) { - throw NotImplementedError() - } - - override suspend fun renamePlaylist(playlist: Playlist, name: String) { - throw NotImplementedError() - } - - override suspend fun deletePlaylist(playlist: Playlist) { - throw NotImplementedError() - } - - override suspend fun addToPlaylist(songs: List, playlist: Playlist) { - throw NotImplementedError() - } - - override suspend fun rewritePlaylist(playlist: Playlist, songs: List) { - throw NotImplementedError() - } - - override fun requestIndex(withCache: Boolean) { - throw NotImplementedError() - } - - override fun index(worker: MusicRepository.IndexingWorker, withCache: Boolean): Job { - throw NotImplementedError() - } -} diff --git a/app/src/test/java/org/oxycblt/auxio/music/FakeMusicSettings.kt b/app/src/test/java/org/oxycblt/auxio/music/FakeMusicSettings.kt deleted file mode 100644 index 14924f4f1..000000000 --- a/app/src/test/java/org/oxycblt/auxio/music/FakeMusicSettings.kt +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2023 Auxio Project - * FakeMusicSettings.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.music - -import org.oxycblt.auxio.list.sort.Sort -import org.oxycblt.auxio.music.fs.MusicDirectories - -open class FakeMusicSettings : MusicSettings { - override fun registerListener(listener: MusicSettings.Listener) = throw NotImplementedError() - - override fun unregisterListener(listener: MusicSettings.Listener) = throw NotImplementedError() - - override var musicDirs: MusicDirectories - get() = throw NotImplementedError() - set(_) = throw NotImplementedError() - - override val excludeNonMusic: Boolean - get() = throw NotImplementedError() - - override val shouldBeObserving: Boolean - get() = throw NotImplementedError() - - override var multiValueSeparators: String - get() = throw NotImplementedError() - set(_) = throw NotImplementedError() - - override val intelligentSorting: Boolean - get() = throw NotImplementedError() - - override var songSort: Sort - get() = throw NotImplementedError() - set(_) = throw NotImplementedError() - - override var albumSort: Sort - get() = throw NotImplementedError() - set(_) = throw NotImplementedError() - - override var artistSort: Sort - get() = throw NotImplementedError() - set(_) = throw NotImplementedError() - - override var genreSort: Sort - get() = throw NotImplementedError() - set(_) = throw NotImplementedError() - - override var playlistSort: Sort - get() = throw NotImplementedError() - set(_) = throw NotImplementedError() - - override var albumSongSort: Sort - get() = throw NotImplementedError() - set(_) = throw NotImplementedError() - - override var artistSongSort: Sort - get() = throw NotImplementedError() - set(_) = throw NotImplementedError() - - override var genreSongSort: Sort - get() = throw NotImplementedError() - set(_) = throw NotImplementedError() -} diff --git a/app/src/test/java/org/oxycblt/auxio/music/MusicModeTest.kt b/app/src/test/java/org/oxycblt/auxio/music/MusicModeTest.kt deleted file mode 100644 index c11985970..000000000 --- a/app/src/test/java/org/oxycblt/auxio/music/MusicModeTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2023 Auxio Project - * MusicModeTest.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.music - -import org.junit.Assert.assertEquals -import org.junit.Test - -class MusicModeTest { - @Test - fun intCode() { - assertEquals(MusicType.SONGS, MusicType.fromIntCode(MusicType.SONGS.intCode)) - assertEquals(MusicType.ALBUMS, MusicType.fromIntCode(MusicType.ALBUMS.intCode)) - assertEquals(MusicType.ARTISTS, MusicType.fromIntCode(MusicType.ARTISTS.intCode)) - assertEquals(MusicType.GENRES, MusicType.fromIntCode(MusicType.GENRES.intCode)) - } -} diff --git a/app/src/test/java/org/oxycblt/auxio/music/MusicViewModelTest.kt b/app/src/test/java/org/oxycblt/auxio/music/MusicViewModelTest.kt deleted file mode 100644 index b25c2c0b1..000000000 --- a/app/src/test/java/org/oxycblt/auxio/music/MusicViewModelTest.kt +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2023 Auxio Project - * MusicViewModelTest.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.music - -import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue -import org.junit.Test -import org.oxycblt.auxio.music.device.DeviceLibrary -import org.oxycblt.auxio.music.device.FakeDeviceLibrary -import org.oxycblt.auxio.util.forceClear - -class MusicViewModelTest { - @Test - fun indexerState() { - val indexer = - TestMusicRepository().apply { - indexingState = IndexingState.Indexing(IndexingProgress.Indeterminate) - } - val musicViewModel = MusicViewModel(indexer, FakeMusicSettings()) - assertTrue(indexer.updateListener is MusicViewModel) - assertTrue(indexer.indexingListener is MusicViewModel) - assertEquals( - IndexingProgress.Indeterminate, - (musicViewModel.indexingState.value as IndexingState.Indexing).progress) - indexer.indexingState = null - assertEquals(null, musicViewModel.indexingState.value) - musicViewModel.forceClear() - assertTrue(indexer.indexingListener == null) - } - - @Test - fun statistics() { - val musicRepository = TestMusicRepository() - val musicViewModel = MusicViewModel(musicRepository, FakeMusicSettings()) - assertEquals(null, musicViewModel.statistics.value) - musicRepository.deviceLibrary = TestDeviceLibrary() - assertEquals( - MusicViewModel.Statistics( - 2, - 3, - 4, - 1, - 161616 * 2, - ), - musicViewModel.statistics.value) - } - - @Test - fun requests() { - val indexer = TestMusicRepository() - val musicViewModel = MusicViewModel(indexer, FakeMusicSettings()) - musicViewModel.refresh() - musicViewModel.rescan() - assertEquals(listOf(true, false), indexer.requests) - } - - private class TestMusicRepository : FakeMusicRepository() { - override var deviceLibrary: DeviceLibrary? = null - set(value) { - field = value - updateListener?.onMusicChanges( - MusicRepository.Changes(deviceLibrary = true, userLibrary = false)) - } - - override var indexingState: IndexingState? = null - set(value) { - field = value - indexingListener?.onIndexingStateChanged() - } - - var updateListener: MusicRepository.UpdateListener? = null - var indexingListener: MusicRepository.IndexingListener? = null - val requests = mutableListOf() - - override fun addUpdateListener(listener: MusicRepository.UpdateListener) { - listener.onMusicChanges( - MusicRepository.Changes(deviceLibrary = true, userLibrary = false)) - this.updateListener = listener - } - - override fun removeUpdateListener(listener: MusicRepository.UpdateListener) { - this.updateListener = null - } - - override fun addIndexingListener(listener: MusicRepository.IndexingListener) { - listener.onIndexingStateChanged() - this.indexingListener = listener - } - - override fun removeIndexingListener(listener: MusicRepository.IndexingListener) { - this.indexingListener = null - } - - override fun requestIndex(withCache: Boolean) { - requests.add(withCache) - } - } - - private class TestDeviceLibrary : FakeDeviceLibrary() { - override val songs: List - get() = listOf(TestSong(), TestSong()) - - override val albums: List - get() = listOf(FakeAlbum(), FakeAlbum(), FakeAlbum()) - - override val artists: List - get() = listOf(FakeArtist(), FakeArtist(), FakeArtist(), FakeArtist()) - - override val genres: List - get() = listOf(FakeGenre()) - } - - private class TestSong : FakeSong() { - override val durationMs: Long - get() = 161616 - } -} diff --git a/app/src/test/java/org/oxycblt/auxio/music/device/DeviceMusicImplTest.kt b/app/src/test/java/org/oxycblt/auxio/music/device/DeviceMusicImplTest.kt deleted file mode 100644 index 2c4805486..000000000 --- a/app/src/test/java/org/oxycblt/auxio/music/device/DeviceMusicImplTest.kt +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2023 Auxio Project - * DeviceMusicImplTest.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.music.device - -import java.util.UUID -import org.junit.Assert.assertTrue -import org.junit.Test - -class DeviceMusicImplTest { - @Test - fun albumRaw_equals_inconsistentCase() { - val a = - RawAlbum( - mediaStoreId = -1, - musicBrainzId = null, - name = "Paraglow", - sortName = null, - releaseType = null, - rawArtists = listOf(RawArtist(name = "Parannoul"), RawArtist(name = "Asian Glow"))) - val b = - RawAlbum( - mediaStoreId = -1, - musicBrainzId = null, - name = "paraglow", - sortName = null, - releaseType = null, - rawArtists = listOf(RawArtist(name = "Parannoul"), RawArtist(name = "Asian glow"))) - assertTrue(a == b) - assertTrue(a.hashCode() == b.hashCode()) - } - - @Test - fun albumRaw_equals_withMbids() { - val a = - RawAlbum( - mediaStoreId = -1, - musicBrainzId = UUID.fromString("c7b245c9-8099-32ea-af95-893acedde2cf"), - name = "Weezer", - sortName = "Blue Album", - releaseType = null, - rawArtists = listOf(RawArtist(name = "Weezer"))) - val b = - RawAlbum( - mediaStoreId = -1, - musicBrainzId = UUID.fromString("923d5ba6-7eee-3bce-bcb2-c913b2bd69d4"), - name = "Weezer", - sortName = "Green Album", - releaseType = null, - rawArtists = listOf(RawArtist(name = "Weezer"))) - assertTrue(a != b) - assertTrue(a.hashCode() != b.hashCode()) - } - - @Test - fun albumRaw_equals_inconsistentMbids() { - val a = - RawAlbum( - mediaStoreId = -1, - musicBrainzId = UUID.fromString("c7b245c9-8099-32ea-af95-893acedde2cf"), - name = "Weezer", - sortName = "Blue Album", - releaseType = null, - rawArtists = listOf(RawArtist(name = "Weezer"))) - val b = - RawAlbum( - mediaStoreId = -1, - musicBrainzId = null, - name = "Weezer", - sortName = "Green Album", - releaseType = null, - rawArtists = listOf(RawArtist(name = "Weezer"))) - assertTrue(a != b) - assertTrue(a.hashCode() != b.hashCode()) - } - - @Test - fun albumRaw_equals_withArtists() { - val a = - RawAlbum( - mediaStoreId = -1, - musicBrainzId = null, - name = "Album", - sortName = null, - releaseType = null, - rawArtists = listOf(RawArtist(name = "Artist A"))) - val b = - RawAlbum( - mediaStoreId = -1, - musicBrainzId = null, - name = "Album", - sortName = null, - releaseType = null, - rawArtists = listOf(RawArtist(name = "Artist B"))) - assertTrue(a != b) - assertTrue(a.hashCode() != b.hashCode()) - } - - @Test - fun artistRaw_equals_inconsistentCase() { - val a = RawArtist(musicBrainzId = null, name = "Parannoul") - val b = RawArtist(musicBrainzId = null, name = "parannoul") - assertTrue(a == b) - assertTrue(a.hashCode() == b.hashCode()) - } - - @Test - fun artistRaw_equals_withMbids() { - val a = - RawArtist( - musicBrainzId = UUID.fromString("677325ef-d850-44bb-8258-0d69bbc0b3f7"), - name = "Artist") - val b = - RawArtist( - musicBrainzId = UUID.fromString("6b625592-d88d-48c8-ac1a-c5b476d78bcc"), - name = "Artist") - assertTrue(a != b) - assertTrue(a.hashCode() != b.hashCode()) - } - - @Test - fun artistRaw_equals_inconsistentMbids() { - val a = - RawArtist( - musicBrainzId = UUID.fromString("677325ef-d850-44bb-8258-0d69bbc0b3f7"), - name = "Artist") - val b = RawArtist(musicBrainzId = null, name = "Artist") - assertTrue(a != b) - assertTrue(a.hashCode() != b.hashCode()) - } - - @Test - fun artistRaw_equals_missingNames() { - val a = RawArtist(name = null) - val b = RawArtist(name = null) - assertTrue(a == b) - assertTrue(a.hashCode() == b.hashCode()) - } - - @Test - fun artistRaw_equals_inconsistentNames() { - val a = RawArtist(name = null) - val b = RawArtist(name = "Parannoul") - assertTrue(a != b) - assertTrue(a.hashCode() != b.hashCode()) - } - - @Test - fun genreRaw_equals_inconsistentCase() { - val a = RawGenre("Future Garage") - val b = RawGenre("future garage") - assertTrue(a == b) - assertTrue(a.hashCode() == b.hashCode()) - } - - @Test - fun genreRaw_equals_missingNames() { - val a = RawGenre(name = null) - val b = RawGenre(name = null) - assertTrue(a == b) - assertTrue(a.hashCode() == b.hashCode()) - } - - @Test - fun genreRaw_equals_inconsistentNames() { - val a = RawGenre(name = null) - val b = RawGenre(name = "Future Garage") - assertTrue(a != b) - assertTrue(a.hashCode() != b.hashCode()) - } -} diff --git a/app/src/test/java/org/oxycblt/auxio/music/device/FakeDeviceLibrary.kt b/app/src/test/java/org/oxycblt/auxio/music/device/FakeDeviceLibrary.kt deleted file mode 100644 index dab0834a3..000000000 --- a/app/src/test/java/org/oxycblt/auxio/music/device/FakeDeviceLibrary.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2023 Auxio Project - * FakeDeviceLibrary.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.music.device - -import android.content.Context -import android.net.Uri -import org.oxycblt.auxio.music.Album -import org.oxycblt.auxio.music.Artist -import org.oxycblt.auxio.music.Genre -import org.oxycblt.auxio.music.Music -import org.oxycblt.auxio.music.Song - -open class FakeDeviceLibrary : DeviceLibrary { - override val songs: List - get() = throw NotImplementedError() - - override val albums: List - get() = throw NotImplementedError() - - override val artists: List - get() = throw NotImplementedError() - - override val genres: List - get() = throw NotImplementedError() - - override fun findSong(uid: Music.UID): Song? { - throw NotImplementedError() - } - - override fun findSongForUri(context: Context, uri: Uri): Song? { - throw NotImplementedError() - } - - override fun findAlbum(uid: Music.UID): Album? { - throw NotImplementedError() - } - - override fun findArtist(uid: Music.UID): Artist? { - throw NotImplementedError() - } - - override fun findGenre(uid: Music.UID): Genre? { - throw NotImplementedError() - } -} diff --git a/app/src/test/java/org/oxycblt/auxio/music/info/DateTest.kt b/app/src/test/java/org/oxycblt/auxio/music/info/DateTest.kt index 40c95bc56..b63639e27 100644 --- a/app/src/test/java/org/oxycblt/auxio/music/info/DateTest.kt +++ b/app/src/test/java/org/oxycblt/auxio/music/info/DateTest.kt @@ -1,4 +1,91 @@ +/* + * Copyright (c) 2023 Auxio Project + * DateTest.kt is part of Auxio. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package org.oxycblt.auxio.music.info -class NameTest { -} \ No newline at end of file +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test + +class DateTest { + @Test + fun date_equals_varyingPrecision() { + assertTrue( + requireNotNull(Date.from("2016-08-16T00:01:02")) != + requireNotNull(Date.from("2016-08-16"))) + } + + @Test + fun date_compareTo_dates() { + val a = requireNotNull(Date.from("2016-08-16T00:01:02")) + val b = requireNotNull(Date.from("2016-09-16T00:01:02")) + assertEquals(-1, a.compareTo(b)) + } + + @Test + fun date_compareTo_times() { + val a = requireNotNull(Date.from("2016-08-16T00:02:02")) + val b = requireNotNull(Date.from("2016-08-16T00:01:02")) + assertEquals(1, a.compareTo(b)) + } + + @Test + fun date_compareTo_varyingPrecision() { + val a = requireNotNull(Date.from("2016-08-16T00:01:02")) + val b = requireNotNull(Date.from("2016-08-16")) + assertEquals( + 1, + a.compareTo(b), + ) + } + + @Test + fun date_from_values() { + assertEquals("2016", Date.from(2016).toString()) + assertEquals("2016-08-16", Date.from(2016, 8, 16).toString()) + assertEquals("2016-08-16T00:01Z", Date.from(2016, 8, 16, 0, 1).toString()) + } + + @Test + fun date_from_yearDate() { + assertEquals("2016-08-16", Date.from(20160816).toString()) + assertEquals("2016-08-16", Date.from("20160816").toString()) + } + + @Test + fun date_from_timestamp() { + assertEquals("2016-08-16T00:01:02Z", Date.from("2016-08-16T00:01:02").toString()) + assertEquals("2016-08-16T00:01:02Z", Date.from("2016-08-16 00:01:02").toString()) + } + + @Test + fun date_from_lesserPrecision() { + assertEquals("2016", Date.from("2016").toString()) + assertEquals("2016-08", Date.from("2016-08").toString()) + assertEquals("2016-08-16", Date.from("2016-08-16").toString()) + assertEquals("2016-08-16T00:01Z", Date.from("2016-08-16T00:01").toString()) + } + + @Test + fun date_from_wack() { + assertEquals(null, Date.from(0)) + assertEquals(null, Date.from("")) + assertEquals(null, Date.from("2016-08-16:00:01:02")) + assertEquals("2016-11", Date.from("2016-11-32 25:43:01").toString()) + } +} diff --git a/app/src/test/java/org/oxycblt/auxio/music/info/DiscTest.kt b/app/src/test/java/org/oxycblt/auxio/music/info/DiscTest.kt index 260ca67cb..9b428acac 100644 --- a/app/src/test/java/org/oxycblt/auxio/music/info/DiscTest.kt +++ b/app/src/test/java/org/oxycblt/auxio/music/info/DiscTest.kt @@ -19,30 +19,36 @@ package org.oxycblt.auxio.music.info import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue import org.junit.Test class DiscTest { @Test - fun disc_compare() { - val a = Disc(1, "Part I") - val b = Disc(2, "Part II") + fun disc_equals_byNum() { + val a = Disc(0, null) + val b = Disc(0, null) + assertEquals(a, b) + assertEquals(a.hashCode(), b.hashCode()) + } + + @Test + fun disc_equals_bySubtitle() { + val a = Disc(0, "z subtitle") + val b = Disc(0, "a subtitle") + assertEquals(a, b) + assertEquals(a.hashCode(), b.hashCode()) + } + + @Test + fun disc_compareTo_byNum() { + val a = Disc(0, null) + val b = Disc(1, null) assertEquals(-1, a.compareTo(b)) } @Test - fun disc_equals_correct() { - val a = Disc(1, "Part I") - val b = Disc(1, "Part I") - assertTrue(a == b) - assertTrue(a.hashCode() == b.hashCode()) - } - - @Test - fun disc_equals_inconsistentNames() { - val a = Disc(1, "Part I") - val b = Disc(1, null) - assertTrue(a == b) - assertTrue(a.hashCode() == b.hashCode()) + fun disc_compareTo_bySubtitle() { + val a = Disc(0, "z subtitle") + val b = Disc(1, "a subtitle") + assertEquals(-1, a.compareTo(b)) } } diff --git a/app/src/test/java/org/oxycblt/auxio/music/info/NameTest.kt b/app/src/test/java/org/oxycblt/auxio/music/info/NameTest.kt index 40c95bc56..9ede93b5e 100644 --- a/app/src/test/java/org/oxycblt/auxio/music/info/NameTest.kt +++ b/app/src/test/java/org/oxycblt/auxio/music/info/NameTest.kt @@ -1,4 +1,430 @@ +/* + * Copyright (c) 2023 Auxio Project + * NameTest.kt is part of Auxio. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package org.oxycblt.auxio.music.info +import io.mockk.every +import io.mockk.mockk +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotEquals +import org.junit.Test +import org.oxycblt.auxio.music.MusicSettings + class NameTest { -} \ No newline at end of file + private fun mockIntelligentSorting(enabled: Boolean) = + mockk().apply { every { intelligentSorting } returns enabled } + + @Test + fun name_from_simple_withoutPunct() { + val name = Name.Known.from("Loveless", null, mockIntelligentSorting(false)) + assertEquals("Loveless", name.raw) + assertEquals(null, name.sort) + assertEquals("L", name.thumb) + val only = name.sortTokens.single() + assertEquals("Loveless", only.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, only.type) + } + + @Test + fun name_from_simple_withPunct() { + val name = Name.Known.from("alt-J", null, mockIntelligentSorting(false)) + assertEquals("alt-J", name.raw) + assertEquals(null, name.sort) + assertEquals("A", name.thumb) + val only = name.sortTokens.single() + assertEquals("altJ", only.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, only.type) + } + + @Test + fun name_from_simple_oopsAllPunct() { + val name = Name.Known.from("!!!", null, mockIntelligentSorting(false)) + assertEquals("!!!", name.raw) + assertEquals(null, name.sort) + assertEquals("!", name.thumb) + val only = name.sortTokens.single() + assertEquals("!!!", only.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, only.type) + } + + @Test + fun name_from_simple_spacedPunct() { + val name = Name.Known.from("& Yet & Yet", null, mockIntelligentSorting(false)) + assertEquals("& Yet & Yet", name.raw) + assertEquals(null, name.sort) + assertEquals("Y", name.thumb) + val first = name.sortTokens[0] + assertEquals("Yet Yet", first.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, first.type) + } + + @Test + fun name_from_simple_withSort() { + val name = Name.Known.from("The Smile", "Smile", mockIntelligentSorting(false)) + assertEquals("The Smile", name.raw) + assertEquals("Smile", name.sort) + assertEquals("S", name.thumb) + val only = name.sortTokens.single() + assertEquals("Smile", only.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, only.type) + } + + @Test + fun name_from_intelligent_withoutPunct_withoutArticle_withoutNumerics() { + val name = Name.Known.from("Loveless", null, mockIntelligentSorting(true)) + assertEquals("Loveless", name.raw) + assertEquals(null, name.sort) + assertEquals("L", name.thumb) + val only = name.sortTokens.single() + assertEquals("Loveless", only.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, only.type) + } + + @Test + fun name_from_intelligent_withoutPunct_withoutArticle_withSpacedStartNumerics() { + val name = Name.Known.from("15 Step", null, mockIntelligentSorting(true)) + assertEquals("15 Step", name.raw) + assertEquals(null, name.sort) + assertEquals("#", name.thumb) + val first = name.sortTokens[0] + assertEquals("15", first.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.NUMERIC, first.type) + val second = name.sortTokens[1] + assertEquals("Step", second.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, second.type) + } + + @Test + fun name_from_intelligent_withoutPunct_withoutArticle_withPackedStartNumerics() { + val name = Name.Known.from("23Kid", null, mockIntelligentSorting(true)) + assertEquals("23Kid", name.raw) + assertEquals(null, name.sort) + assertEquals("#", name.thumb) + val first = name.sortTokens[0] + assertEquals("23", first.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.NUMERIC, first.type) + val second = name.sortTokens[1] + assertEquals("Kid", second.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, second.type) + } + + @Test + fun name_from_intelligent_withoutPunct_withoutArticle_withSpacedMiddleNumerics() { + val name = Name.Known.from("Foo 1 2 Bar", null, mockIntelligentSorting(true)) + assertEquals("Foo 1 2 Bar", name.raw) + assertEquals(null, name.sort) + assertEquals("F", name.thumb) + val first = name.sortTokens[0] + assertEquals("Foo", first.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, first.type) + val second = name.sortTokens[1] + assertEquals("1", second.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.NUMERIC, second.type) + val third = name.sortTokens[2] + assertEquals(" ", third.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, third.type) + val fourth = name.sortTokens[3] + assertEquals("2", fourth.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.NUMERIC, fourth.type) + val fifth = name.sortTokens[4] + assertEquals("Bar", fifth.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, fifth.type) + } + + @Test + fun name_from_intelligent_withoutPunct_withoutArticle_withPackedMiddleNumerics() { + val name = Name.Known.from("Foo12Bar", null, mockIntelligentSorting(true)) + assertEquals("Foo12Bar", name.raw) + assertEquals(null, name.sort) + assertEquals("F", name.thumb) + val first = name.sortTokens[0] + assertEquals("Foo", first.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, first.type) + val second = name.sortTokens[1] + assertEquals("12", second.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.NUMERIC, second.type) + val third = name.sortTokens[2] + assertEquals("Bar", third.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, third.type) + } + + @Test + fun name_from_intelligent_withoutPunct_withoutArticle_withSpacedEndNumerics() { + val name = Name.Known.from("Foo 1", null, mockIntelligentSorting(true)) + assertEquals("Foo 1", name.raw) + assertEquals(null, name.sort) + assertEquals("F", name.thumb) + val first = name.sortTokens[0] + assertEquals("Foo", first.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, first.type) + val second = name.sortTokens[1] + assertEquals("1", second.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.NUMERIC, second.type) + } + + @Test + fun name_from_intelligent_withoutPunct_withoutArticle_withPackedEndNumerics() { + val name = Name.Known.from("Error404", null, mockIntelligentSorting(true)) + assertEquals("Error404", name.raw) + assertEquals(null, name.sort) + assertEquals("E", name.thumb) + val first = name.sortTokens[0] + assertEquals("Error", first.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, first.type) + val second = name.sortTokens[1] + assertEquals("404", second.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.NUMERIC, second.type) + } + + @Test + fun name_from_intelligent_withoutPunct_withThe_withoutNumerics() { + val name = Name.Known.from("The National Anthem", null, mockIntelligentSorting(true)) + assertEquals("The National Anthem", name.raw) + assertEquals(null, name.sort) + assertEquals("N", name.thumb) + val first = name.sortTokens[0] + assertEquals("National Anthem", first.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, first.type) + } + + @Test + fun name_from_intelligent_withoutPunct_withAn_withoutNumerics() { + val name = Name.Known.from("An Eagle in Your Mind", null, mockIntelligentSorting(true)) + assertEquals("An Eagle in Your Mind", name.raw) + assertEquals(null, name.sort) + assertEquals("E", name.thumb) + val first = name.sortTokens[0] + assertEquals("Eagle in Your Mind", first.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, first.type) + } + + @Test + fun name_from_intelligent_withoutPunct_withA_withoutNumerics() { + val name = Name.Known.from("A Song For Our Fathers", null, mockIntelligentSorting(true)) + assertEquals("A Song For Our Fathers", name.raw) + assertEquals(null, name.sort) + assertEquals("S", name.thumb) + val first = name.sortTokens[0] + assertEquals("Song For Our Fathers", first.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, first.type) + } + + @Test + fun name_from_intelligent_withPunct_withoutArticle_withoutNumerics() { + val name = Name.Known.from("alt-J", null, mockIntelligentSorting(true)) + assertEquals("alt-J", name.raw) + assertEquals(null, name.sort) + assertEquals("A", name.thumb) + val only = name.sortTokens.single() + assertEquals("altJ", only.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, only.type) + } + + @Test + fun name_from_intelligent_oopsAllPunct_withoutArticle_withoutNumerics() { + val name = Name.Known.from("!!!", null, mockIntelligentSorting(true)) + assertEquals("!!!", name.raw) + assertEquals(null, name.sort) + assertEquals("!", name.thumb) + val only = name.sortTokens.single() + assertEquals("!!!", only.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, only.type) + } + + @Test + fun name_from_intelligent_withoutPunct_shortArticle_withNumerics() { + val name = Name.Known.from("the 1", null, mockIntelligentSorting(true)) + assertEquals("the 1", name.raw) + assertEquals(null, name.sort) + assertEquals("#", name.thumb) + val first = name.sortTokens[0] + assertEquals("1", first.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.NUMERIC, first.type) + } + + @Test + fun name_from_intelligent_spacedPunct_withoutArticle_withoutNumerics() { + val name = Name.Known.from("& Yet & Yet", null, mockIntelligentSorting(true)) + assertEquals("& Yet & Yet", name.raw) + assertEquals(null, name.sort) + assertEquals("Y", name.thumb) + val first = name.sortTokens[0] + assertEquals("Yet Yet", first.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, first.type) + } + + @Test + fun name_from_intelligent_withPunct_withoutArticle_withNumerics() { + val name = Name.Known.from("Design : 2 : 3", null, mockIntelligentSorting(true)) + assertEquals("Design : 2 : 3", name.raw) + assertEquals(null, name.sort) + assertEquals("D", name.thumb) + val first = name.sortTokens[0] + assertEquals("Design", first.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, first.type) + val second = name.sortTokens[1] + assertEquals("2", second.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.NUMERIC, second.type) + val third = name.sortTokens[2] + assertEquals(" ", third.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, third.type) + val fourth = name.sortTokens[3] + assertEquals("3", fourth.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.NUMERIC, fourth.type) + } + + @Test + fun name_from_intelligent_oopsAllPunct_withoutArticle_oopsAllNumerics() { + val name = Name.Known.from("2 + 2 = 5", null, mockIntelligentSorting(true)) + assertEquals("2 + 2 = 5", name.raw) + assertEquals(null, name.sort) + assertEquals("#", name.thumb) + val first = name.sortTokens[0] + assertEquals("2", first.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.NUMERIC, first.type) + val second = name.sortTokens[1] + assertEquals(" ", second.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, second.type) + val third = name.sortTokens[2] + assertEquals("2", third.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.NUMERIC, third.type) + val fourth = name.sortTokens[3] + assertEquals(" ", fourth.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, fourth.type) + val fifth = name.sortTokens[4] + assertEquals("5", fifth.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.NUMERIC, fifth.type) + } + + @Test + fun name_from_intelligent_withSort() { + val name = Name.Known.from("The Smile", "Smile", mockIntelligentSorting(true)) + assertEquals("The Smile", name.raw) + assertEquals("Smile", name.sort) + assertEquals("S", name.thumb) + val only = name.sortTokens.single() + assertEquals("Smile", only.collationKey.sourceString) + assertEquals(Name.Known.SortToken.Type.LEXICOGRAPHIC, only.type) + } + + @Test + fun name_equals_simple() { + val a = Name.Known.from("The Same", "Same", mockIntelligentSorting(false)) + val b = Name.Known.from("The Same", "Same", mockIntelligentSorting(false)) + assertEquals(a, b) + } + + @Test + fun name_equals_differentSort() { + val a = Name.Known.from("The Same", "Same", mockIntelligentSorting(false)) + val b = Name.Known.from("The Same", null, mockIntelligentSorting(false)) + assertNotEquals(a, b) + assertNotEquals(a.hashCode(), b.hashCode()) + } + + @Test + fun name_equals_intelligent_differentTokens() { + val a = Name.Known.from("The Same", "Same", mockIntelligentSorting(true)) + val b = Name.Known.from("Same", "Same", mockIntelligentSorting(true)) + assertNotEquals(a, b) + assertNotEquals(a.hashCode(), b.hashCode()) + } + + @Test + fun name_compareTo_simple_withoutSort_withoutArticle_withoutNumeric() { + val a = Name.Known.from("A", null, mockIntelligentSorting(false)) + val b = Name.Known.from("B", null, mockIntelligentSorting(false)) + assertEquals(-1, a.compareTo(b)) + } + + @Test + fun name_compareTo_simple_withoutSort_withArticle_withoutNumeric() { + val a = Name.Known.from("A Brain in a Bottle", null, mockIntelligentSorting(false)) + val b = Name.Known.from("Acid Rain", null, mockIntelligentSorting(false)) + val c = Name.Known.from("Boralis / Contrastellar", null, mockIntelligentSorting(false)) + val d = Name.Known.from("Breathe In", null, mockIntelligentSorting(false)) + assertEquals(-1, a.compareTo(b)) + assertEquals(-1, a.compareTo(c)) + assertEquals(-1, a.compareTo(d)) + } + + @Test + fun name_compareTo_simple_withSort_withoutArticle_withNumeric() { + val a = Name.Known.from("15 Step", null, mockIntelligentSorting(false)) + val b = Name.Known.from("128 Harps", null, mockIntelligentSorting(false)) + val c = Name.Known.from("1969", null, mockIntelligentSorting(false)) + assertEquals(1, a.compareTo(b)) + assertEquals(-1, a.compareTo(c)) + } + + @Test + fun name_compareTo_simple_withPartialSort() { + val a = Name.Known.from("A", "C", mockIntelligentSorting(false)) + val b = Name.Known.from("B", null, mockIntelligentSorting(false)) + assertEquals(1, a.compareTo(b)) + } + + @Test + fun name_compareTo_simple_withSort() { + val a = Name.Known.from("D", "A", mockIntelligentSorting(false)) + val b = Name.Known.from("C", "B", mockIntelligentSorting(false)) + assertEquals(-1, a.compareTo(b)) + } + + @Test + fun name_compareTo_intelligent_withoutSort_withoutArticle_withoutNumeric() { + val a = Name.Known.from("A", null, mockIntelligentSorting(true)) + val b = Name.Known.from("B", null, mockIntelligentSorting(true)) + assertEquals(-1, a.compareTo(b)) + } + + @Test + fun name_compareTo_intelligent_withoutSort_withArticle_withoutNumeric() { + val a = Name.Known.from("A Brain in a Bottle", null, mockIntelligentSorting(true)) + val b = Name.Known.from("Acid Rain", null, mockIntelligentSorting(true)) + val c = Name.Known.from("Boralis / Contrastellar", null, mockIntelligentSorting(true)) + val d = Name.Known.from("Breathe In", null, mockIntelligentSorting(true)) + assertEquals(1, a.compareTo(b)) + assertEquals(1, a.compareTo(c)) + assertEquals(-1, a.compareTo(d)) + } + + @Test + fun name_compareTo_intelligent_withoutSort_withoutArticle_withNumeric() { + val a = Name.Known.from("15 Step", null, mockIntelligentSorting(true)) + val b = Name.Known.from("128 Harps", null, mockIntelligentSorting(true)) + val c = Name.Known.from("1969", null, mockIntelligentSorting(true)) + assertEquals(-1, a.compareTo(b)) + assertEquals(-1, b.compareTo(c)) + assertEquals(-2, a.compareTo(c)) + } + + @Test + fun name_compareTo_intelligent_withPartialSort_withoutArticle_withoutNumeric() { + val a = Name.Known.from("A", "C", mockIntelligentSorting(false)) + val b = Name.Known.from("B", null, mockIntelligentSorting(false)) + assertEquals(1, a.compareTo(b)) + } + + @Test + fun name_compareTo_intelligent_withSort_withoutArticle_withoutNumeric() { + val a = Name.Known.from("D", "A", mockIntelligentSorting(true)) + val b = Name.Known.from("C", "B", mockIntelligentSorting(true)) + assertEquals(-1, a.compareTo(b)) + } +} diff --git a/app/src/test/java/org/oxycblt/auxio/music/metadata/TagUtilTest.kt b/app/src/test/java/org/oxycblt/auxio/music/metadata/TagUtilTest.kt index db340f187..5f6c67c89 100644 --- a/app/src/test/java/org/oxycblt/auxio/music/metadata/TagUtilTest.kt +++ b/app/src/test/java/org/oxycblt/auxio/music/metadata/TagUtilTest.kt @@ -18,27 +18,32 @@ package org.oxycblt.auxio.music.metadata +import io.mockk.every +import io.mockk.mockk import org.junit.Assert.assertEquals import org.junit.Test -import org.oxycblt.auxio.music.FakeMusicSettings +import org.oxycblt.auxio.music.MusicSettings class TagUtilTest { + private fun mockSeparators(separators: String) = + mockk().apply { every { multiValueSeparators } returns separators } + @Test fun parseMultiValue_single() { - assertEquals(listOf("a", "b", "c"), listOf("a,b,c").parseMultiValue(TestMusicSettings(","))) + assertEquals(listOf("a", "b", "c"), listOf("a,b,c").parseMultiValue(mockSeparators(","))) } @Test fun parseMultiValue_many() { assertEquals( - listOf("a", "b", "c"), listOf("a", "b", "c").parseMultiValue(TestMusicSettings(","))) + listOf("a", "b", "c"), listOf("a", "b", "c").parseMultiValue(mockSeparators(","))) } @Test fun parseMultiValue_several() { assertEquals( listOf("a", "b", "c", "d", "e", "f"), - listOf("a,b;c/d+e&f").parseMultiValue(TestMusicSettings(",;/+&"))) + listOf("a,b;c/d+e&f").parseMultiValue(mockSeparators(",;/+&"))) } @Test @@ -131,43 +136,37 @@ class TagUtilTest { fun parseId3v2Genre_multi() { assertEquals( listOf("Post-Rock", "Shoegaze", "Glitch"), - listOf("Post-Rock", "Shoegaze", "Glitch").parseId3GenreNames(TestMusicSettings(","))) + listOf("Post-Rock", "Shoegaze", "Glitch").parseId3GenreNames(mockSeparators(","))) } @Test fun parseId3v2Genre_multiId3v1() { assertEquals( listOf("Post-Rock", "Shoegaze", "Glitch"), - listOf("176", "178", "Glitch").parseId3GenreNames(TestMusicSettings(","))) + listOf("176", "178", "Glitch").parseId3GenreNames(mockSeparators(","))) } @Test fun parseId3v2Genre_wackId3() { - assertEquals(listOf("2941"), listOf("2941").parseId3GenreNames(TestMusicSettings(","))) + assertEquals(listOf("2941"), listOf("2941").parseId3GenreNames(mockSeparators(","))) } @Test fun parseId3v2Genre_singleId3v23() { assertEquals( listOf("Post-Rock", "Shoegaze", "Remix", "Cover", "Glitch"), - listOf("(176)(178)(RX)(CR)Glitch").parseId3GenreNames(TestMusicSettings(","))) + listOf("(176)(178)(RX)(CR)Glitch").parseId3GenreNames(mockSeparators(","))) } @Test fun parseId3v2Genre_singleSeparated() { assertEquals( listOf("Post-Rock", "Shoegaze", "Glitch"), - listOf("Post-Rock, Shoegaze, Glitch").parseId3GenreNames(TestMusicSettings(","))) + listOf("Post-Rock, Shoegaze, Glitch").parseId3GenreNames(mockSeparators(","))) } @Test fun parsId3v2Genre_singleId3v1() { - assertEquals(listOf("Post-Rock"), listOf("176").parseId3GenreNames(TestMusicSettings(","))) - } - - class TestMusicSettings(private val separators: String) : FakeMusicSettings() { - override var multiValueSeparators: String - get() = separators - set(_) = throw NotImplementedError() + assertEquals(listOf("Post-Rock"), listOf("176").parseId3GenreNames(mockSeparators(","))) } } diff --git a/app/src/test/java/org/oxycblt/auxio/music/metadata/TextTagsTest.kt b/app/src/test/java/org/oxycblt/auxio/music/metadata/TextTagsTest.kt index 6cd22fdcb..73c5b926d 100644 --- a/app/src/test/java/org/oxycblt/auxio/music/metadata/TextTagsTest.kt +++ b/app/src/test/java/org/oxycblt/auxio/music/metadata/TextTagsTest.kt @@ -39,6 +39,7 @@ class TextTagsTest { assertEquals(listOf("2022"), textTags.vorbis["date"]) assertEquals(listOf("ep"), textTags.vorbis["releasetype"]) assertEquals(listOf("+2 dB"), textTags.vorbis["replaygain_track_gain"]) + assertEquals(null, textTags.id3v2["APIC"]) } @Test @@ -51,6 +52,7 @@ class TextTagsTest { assertEquals(listOf("2022"), textTags.id3v2["TDRC"]) assertEquals(listOf("ep"), textTags.id3v2["TXXX:musicbrainz album type"]) assertEquals(listOf("+2 dB"), textTags.id3v2["TXXX:replaygain_track_gain"]) + assertEquals(null, textTags.id3v2["metadata_block_picture"]) } @Test @@ -62,10 +64,13 @@ class TextTagsTest { assertEquals(listOf("2022"), textTags.vorbis["date"]) assertEquals(listOf("ep"), textTags.vorbis["releasetype"]) assertEquals(listOf("+2 dB"), textTags.vorbis["replaygain_track_gain"]) + assertEquals(null, textTags.id3v2["metadata_block_picture"]) + assertEquals(listOf("Wheel"), textTags.id3v2["TIT2"]) assertEquals(listOf("Paraglow"), textTags.id3v2["TALB"]) assertEquals(listOf("Parannoul", "Asian Glow"), textTags.id3v2["TPE1"]) assertEquals(listOf("2022"), textTags.id3v2["TDRC"]) + assertEquals(null, textTags.id3v2["APIC"]) assertEquals(listOf("ep"), textTags.id3v2["TXXX:musicbrainz album type"]) assertEquals(listOf("+2 dB"), textTags.id3v2["TXXX:replaygain_track_gain"]) } diff --git a/app/src/test/java/org/oxycblt/auxio/util/TestingUtil.kt b/app/src/test/java/org/oxycblt/auxio/util/TestingUtil.kt deleted file mode 100644 index 5da90ab54..000000000 --- a/app/src/test/java/org/oxycblt/auxio/util/TestingUtil.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2023 Auxio Project - * TestingUtil.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.util - -import androidx.lifecycle.ViewModel - -private val VM_CLEAR_METHOD = - ViewModel::class.java.getDeclaredMethod("clear").apply { isAccessible = true } - -fun ViewModel.forceClear() { - VM_CLEAR_METHOD.invoke(this) -}