music: add more tests
Add tests for MusicViewModel, MusicMode, and MusicRepository. Going further requires me to really learn instrumentation tests.
This commit is contained in:
parent
f9857355bb
commit
2d9a5ad5cd
12 changed files with 493 additions and 16 deletions
|
@ -91,7 +91,7 @@ class SongDetailDialog : ViewBindingDialogFragment<DialogSongDetailBinding>() {
|
||||||
val formattedNumber = getString(R.string.fmt_number, it.number)
|
val formattedNumber = getString(R.string.fmt_number, it.number)
|
||||||
val zipped =
|
val zipped =
|
||||||
if (it.name != null) {
|
if (it.name != null) {
|
||||||
getString(R.string.fmt_zipped_names, it.name, formattedNumber)
|
getString(R.string.fmt_zipped_names, formattedNumber, it.name)
|
||||||
} else {
|
} else {
|
||||||
formattedNumber
|
formattedNumber
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ constructor(
|
||||||
private val musicRepository: MusicRepository,
|
private val musicRepository: MusicRepository,
|
||||||
private val musicSettings: MusicSettings
|
private val musicSettings: MusicSettings
|
||||||
) : ViewModel(), MusicRepository.Listener, HomeSettings.Listener {
|
) : ViewModel(), MusicRepository.Listener, HomeSettings.Listener {
|
||||||
|
|
||||||
private val _songsList = MutableStateFlow(listOf<Song>())
|
private val _songsList = MutableStateFlow(listOf<Song>())
|
||||||
/** A list of [Song]s, sorted by the preferred [Sort], to be shown in the home view. */
|
/** A list of [Song]s, sorted by the preferred [Sort], to be shown in the home view. */
|
||||||
val songsList: StateFlow<List<Song>>
|
val songsList: StateFlow<List<Song>>
|
||||||
|
|
|
@ -347,9 +347,21 @@ interface Genre : MusicParent {
|
||||||
val durationMs: Long
|
val durationMs: Long
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run [Music.resolveName] on each instance in the given list and concatenate them into a [String]
|
||||||
|
* in a localized manner.
|
||||||
|
* @param context [Context] required
|
||||||
|
* @return A concatenated string.
|
||||||
|
*/
|
||||||
fun <T : Music> List<T>.resolveNames(context: Context) =
|
fun <T : Music> List<T>.resolveNames(context: Context) =
|
||||||
concatLocalized(context) { it.resolveName(context) }
|
concatLocalized(context) { it.resolveName(context) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if [Music.rawName] matches for each item in a list. Useful for scenarios where the
|
||||||
|
* display information of an item must be compared without a context.
|
||||||
|
* @param other The list of items to compare to.
|
||||||
|
* @return True if they are the same (by [Music.rawName]), false otherwise.
|
||||||
|
*/
|
||||||
fun <T : Music> List<T>.areRawNamesTheSame(other: List<T>): Boolean {
|
fun <T : Music> List<T>.areRawNamesTheSame(other: List<T>): Boolean {
|
||||||
for (i in 0 until max(size, other.size)) {
|
for (i in 0 until max(size, other.size)) {
|
||||||
val a = getOrNull(i) ?: return false
|
val a = getOrNull(i) ?: return false
|
||||||
|
|
144
app/src/test/java/org/oxycblt/auxio/music/FakeMusic.kt
Normal file
144
app/src/test/java/org/oxycblt/auxio/music/FakeMusic.kt
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Auxio Project
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.oxycblt.auxio.music
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
import java.text.CollationKey
|
||||||
|
import org.oxycblt.auxio.music.*
|
||||||
|
import org.oxycblt.auxio.music.metadata.Date
|
||||||
|
import org.oxycblt.auxio.music.metadata.Disc
|
||||||
|
import org.oxycblt.auxio.music.metadata.ReleaseType
|
||||||
|
import org.oxycblt.auxio.music.storage.MimeType
|
||||||
|
import org.oxycblt.auxio.music.storage.Path
|
||||||
|
|
||||||
|
open class FakeSong : Song {
|
||||||
|
override val rawName: String?
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val rawSortName: String?
|
||||||
|
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<Genre>
|
||||||
|
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<Artist>
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val collationKey: CollationKey?
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val durationMs: Long
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val uid: Music.UID
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
|
||||||
|
override fun resolveName(context: Context): String {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class FakeAlbum : Album {
|
||||||
|
override val rawName: String?
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val rawSortName: String?
|
||||||
|
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<Artist>
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val collationKey: CollationKey?
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val durationMs: Long
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val songs: List<Song>
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val uid: Music.UID
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
|
||||||
|
override fun resolveName(context: Context): String {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class FakeArtist : Artist {
|
||||||
|
override val rawName: String?
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val rawSortName: String?
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val albums: List<Album>
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val genres: List<Genre>
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val isCollaborator: Boolean
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val collationKey: CollationKey?
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val durationMs: Long
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val songs: List<Song>
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val uid: Music.UID
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
|
||||||
|
override fun resolveName(context: Context): String {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class FakeGenre : Genre {
|
||||||
|
override val rawName: String?
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val rawSortName: String?
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val albums: List<Album>
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val artists: List<Artist>
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val collationKey: CollationKey?
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val durationMs: Long
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val songs: List<Song>
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val uid: Music.UID
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
|
||||||
|
override fun resolveName(context: Context): String {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ package org.oxycblt.auxio.music
|
||||||
import org.oxycblt.auxio.list.Sort
|
import org.oxycblt.auxio.list.Sort
|
||||||
import org.oxycblt.auxio.music.storage.MusicDirectories
|
import org.oxycblt.auxio.music.storage.MusicDirectories
|
||||||
|
|
||||||
interface FakeMusicSettings : MusicSettings {
|
open class FakeMusicSettings : MusicSettings {
|
||||||
override fun registerListener(listener: MusicSettings.Listener) = throw NotImplementedError()
|
override fun registerListener(listener: MusicSettings.Listener) = throw NotImplementedError()
|
||||||
override fun unregisterListener(listener: MusicSettings.Listener) = throw NotImplementedError()
|
override fun unregisterListener(listener: MusicSettings.Listener) = throw NotImplementedError()
|
||||||
override var musicDirs: MusicDirectories
|
override var musicDirs: MusicDirectories
|
||||||
|
|
31
app/src/test/java/org/oxycblt/auxio/music/MusicModeTest.kt
Normal file
31
app/src/test/java/org/oxycblt/auxio/music/MusicModeTest.kt
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Auxio Project
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.oxycblt.auxio.music
|
||||||
|
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class MusicModeTest {
|
||||||
|
@Test
|
||||||
|
fun intCode() {
|
||||||
|
assertEquals(MusicMode.SONGS, MusicMode.fromIntCode(MusicMode.SONGS.intCode))
|
||||||
|
assertEquals(MusicMode.ALBUMS, MusicMode.fromIntCode(MusicMode.ALBUMS.intCode))
|
||||||
|
assertEquals(MusicMode.ARTISTS, MusicMode.fromIntCode(MusicMode.ARTISTS.intCode))
|
||||||
|
assertEquals(MusicMode.GENRES, MusicMode.fromIntCode(MusicMode.GENRES.intCode))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Auxio Project
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.oxycblt.auxio.music
|
||||||
|
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
import org.oxycblt.auxio.music.model.FakeLibrary
|
||||||
|
import org.oxycblt.auxio.music.model.Library
|
||||||
|
|
||||||
|
class MusicRepositoryTest {
|
||||||
|
@Test
|
||||||
|
fun listeners() {
|
||||||
|
val listener = TestListener()
|
||||||
|
val impl =
|
||||||
|
MusicRepositoryImpl().apply {
|
||||||
|
library = null
|
||||||
|
addListener(listener)
|
||||||
|
}
|
||||||
|
impl.library = TestLibrary(0)
|
||||||
|
assertEquals(listOf(null, TestLibrary(0)), listener.updates)
|
||||||
|
|
||||||
|
val listener2 = TestListener()
|
||||||
|
impl.addListener(listener2)
|
||||||
|
impl.library = TestLibrary(1)
|
||||||
|
assertEquals(listOf(TestLibrary(0), TestLibrary(1)), listener2.updates)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestListener : MusicRepository.Listener {
|
||||||
|
val updates = mutableListOf<Library?>()
|
||||||
|
|
||||||
|
override fun onLibraryChanged(library: Library?) {
|
||||||
|
updates.add(library)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private data class TestLibrary(private val id: Int) : FakeLibrary()
|
||||||
|
}
|
108
app/src/test/java/org/oxycblt/auxio/music/MusicViewModelTest.kt
Normal file
108
app/src/test/java/org/oxycblt/auxio/music/MusicViewModelTest.kt
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Auxio Project
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.oxycblt.auxio.music
|
||||||
|
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Test
|
||||||
|
import org.oxycblt.auxio.music.model.FakeLibrary
|
||||||
|
import org.oxycblt.auxio.music.system.FakeIndexer
|
||||||
|
import org.oxycblt.auxio.music.system.Indexer
|
||||||
|
import org.oxycblt.auxio.util.forceClear
|
||||||
|
|
||||||
|
class MusicViewModelTest {
|
||||||
|
@Test
|
||||||
|
fun indexerState() {
|
||||||
|
val indexer =
|
||||||
|
TestIndexer().apply { state = Indexer.State.Indexing(Indexer.Indexing.Indeterminate) }
|
||||||
|
val musicViewModel = MusicViewModel(indexer)
|
||||||
|
assertTrue(indexer.listener is MusicViewModel)
|
||||||
|
assertEquals(
|
||||||
|
Indexer.Indexing.Indeterminate,
|
||||||
|
(musicViewModel.indexerState.value as Indexer.State.Indexing).indexing)
|
||||||
|
indexer.state = null
|
||||||
|
assertEquals(null, musicViewModel.indexerState.value)
|
||||||
|
musicViewModel.forceClear()
|
||||||
|
assertTrue(indexer.listener == null)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun statistics() {
|
||||||
|
val indexer =
|
||||||
|
TestIndexer().apply { state = Indexer.State.Complete(Result.success(TestLibrary())) }
|
||||||
|
val musicViewModel = MusicViewModel(indexer)
|
||||||
|
assertEquals(
|
||||||
|
MusicViewModel.Statistics(
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
1,
|
||||||
|
161616 * 2,
|
||||||
|
),
|
||||||
|
musicViewModel.statistics.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun requests() {
|
||||||
|
val indexer = TestIndexer()
|
||||||
|
val musicViewModel = MusicViewModel(indexer)
|
||||||
|
musicViewModel.refresh()
|
||||||
|
musicViewModel.rescan()
|
||||||
|
assertEquals(listOf(true, false), indexer.requests)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestIndexer : FakeIndexer() {
|
||||||
|
var listener: Indexer.Listener? = null
|
||||||
|
var state: Indexer.State? = null
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
listener?.onIndexerStateChanged(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
val requests = mutableListOf<Boolean>()
|
||||||
|
|
||||||
|
override fun registerListener(listener: Indexer.Listener) {
|
||||||
|
this.listener = listener
|
||||||
|
listener.onIndexerStateChanged(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unregisterListener(listener: Indexer.Listener) {
|
||||||
|
this.listener = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun requestReindex(withCache: Boolean) {
|
||||||
|
requests.add(withCache)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestLibrary : FakeLibrary() {
|
||||||
|
override val songs: List<Song>
|
||||||
|
get() = listOf(TestSong(), TestSong())
|
||||||
|
override val albums: List<Album>
|
||||||
|
get() = listOf(FakeAlbum(), FakeAlbum(), FakeAlbum())
|
||||||
|
override val artists: List<Artist>
|
||||||
|
get() = listOf(FakeArtist(), FakeArtist(), FakeArtist(), FakeArtist())
|
||||||
|
override val genres: List<Genre>
|
||||||
|
get() = listOf(FakeGenre())
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestSong : FakeSong() {
|
||||||
|
override val durationMs: Long
|
||||||
|
get() = 161616
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,22 +24,20 @@ import org.oxycblt.auxio.music.FakeMusicSettings
|
||||||
class TagUtilTest {
|
class TagUtilTest {
|
||||||
@Test
|
@Test
|
||||||
fun parseMultiValue_single() {
|
fun parseMultiValue_single() {
|
||||||
assertEquals(
|
assertEquals(listOf("a", "b", "c"), listOf("a,b,c").parseMultiValue(TestMusicSettings(",")))
|
||||||
listOf("a", "b", "c"), listOf("a,b,c").parseMultiValue(SeparatorMusicSettings(",")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parseMultiValue_many() {
|
fun parseMultiValue_many() {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
listOf("a", "b", "c"),
|
listOf("a", "b", "c"), listOf("a", "b", "c").parseMultiValue(TestMusicSettings(",")))
|
||||||
listOf("a", "b", "c").parseMultiValue(SeparatorMusicSettings(",")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parseMultiValue_several() {
|
fun parseMultiValue_several() {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
listOf("a", "b", "c", "d", "e", "f"),
|
listOf("a", "b", "c", "d", "e", "f"),
|
||||||
listOf("a,b;c/d+e&f").parseMultiValue(SeparatorMusicSettings(",;/+&")))
|
listOf("a,b;c/d+e&f").parseMultiValue(TestMusicSettings(",;/+&")))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -132,43 +130,41 @@ class TagUtilTest {
|
||||||
fun parseId3v2Genre_multi() {
|
fun parseId3v2Genre_multi() {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
listOf("Post-Rock", "Shoegaze", "Glitch"),
|
listOf("Post-Rock", "Shoegaze", "Glitch"),
|
||||||
listOf("Post-Rock", "Shoegaze", "Glitch")
|
listOf("Post-Rock", "Shoegaze", "Glitch").parseId3GenreNames(TestMusicSettings(",")))
|
||||||
.parseId3GenreNames(SeparatorMusicSettings(",")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parseId3v2Genre_multiId3v1() {
|
fun parseId3v2Genre_multiId3v1() {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
listOf("Post-Rock", "Shoegaze", "Glitch"),
|
listOf("Post-Rock", "Shoegaze", "Glitch"),
|
||||||
listOf("176", "178", "Glitch").parseId3GenreNames(SeparatorMusicSettings(",")))
|
listOf("176", "178", "Glitch").parseId3GenreNames(TestMusicSettings(",")))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parseId3v2Genre_wackId3() {
|
fun parseId3v2Genre_wackId3() {
|
||||||
assertEquals(listOf("2941"), listOf("2941").parseId3GenreNames(SeparatorMusicSettings(",")))
|
assertEquals(listOf("2941"), listOf("2941").parseId3GenreNames(TestMusicSettings(",")))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parseId3v2Genre_singleId3v23() {
|
fun parseId3v2Genre_singleId3v23() {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
listOf("Post-Rock", "Shoegaze", "Remix", "Cover", "Glitch"),
|
listOf("Post-Rock", "Shoegaze", "Remix", "Cover", "Glitch"),
|
||||||
listOf("(176)(178)(RX)(CR)Glitch").parseId3GenreNames(SeparatorMusicSettings(",")))
|
listOf("(176)(178)(RX)(CR)Glitch").parseId3GenreNames(TestMusicSettings(",")))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parseId3v2Genre_singleSeparated() {
|
fun parseId3v2Genre_singleSeparated() {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
listOf("Post-Rock", "Shoegaze", "Glitch"),
|
listOf("Post-Rock", "Shoegaze", "Glitch"),
|
||||||
listOf("Post-Rock, Shoegaze, Glitch").parseId3GenreNames(SeparatorMusicSettings(",")))
|
listOf("Post-Rock, Shoegaze, Glitch").parseId3GenreNames(TestMusicSettings(",")))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parsId3v2Genre_singleId3v1() {
|
fun parsId3v2Genre_singleId3v1() {
|
||||||
assertEquals(
|
assertEquals(listOf("Post-Rock"), listOf("176").parseId3GenreNames(TestMusicSettings(",")))
|
||||||
listOf("Post-Rock"), listOf("176").parseId3GenreNames(SeparatorMusicSettings(",")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SeparatorMusicSettings(private val separators: String) : FakeMusicSettings {
|
class TestMusicSettings(private val separators: String) : FakeMusicSettings() {
|
||||||
override var multiValueSeparators: String
|
override var multiValueSeparators: String
|
||||||
get() = separators
|
get() = separators
|
||||||
set(_) = throw NotImplementedError()
|
set(_) = throw NotImplementedError()
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Auxio Project
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.oxycblt.auxio.music.model
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
import org.oxycblt.auxio.music.*
|
||||||
|
|
||||||
|
open class FakeLibrary : Library {
|
||||||
|
override val songs: List<Song>
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val albums: List<Album>
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val artists: List<Artist>
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val genres: List<Genre>
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
|
||||||
|
override fun <T : Music> find(uid: Music.UID): T? {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findSongForUri(context: Context, uri: Uri): Song? {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : MusicParent> sanitize(parent: T): T? {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun sanitize(song: Song): Song? {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Auxio Project
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.oxycblt.auxio.music.system
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
|
||||||
|
open class FakeIndexer : Indexer {
|
||||||
|
override val isIndeterminate: Boolean
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
override val isIndexing: Boolean
|
||||||
|
get() = throw NotImplementedError()
|
||||||
|
|
||||||
|
override fun index(context: Context, withCache: Boolean, scope: CoroutineScope): Job {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun registerController(controller: Indexer.Controller) {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unregisterController(controller: Indexer.Controller) {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun registerListener(listener: Indexer.Listener) {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unregisterListener(listener: Indexer.Listener) {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun requestReindex(withCache: Boolean) {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun reset() {
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
}
|
27
app/src/test/java/org/oxycblt/auxio/util/TestingUtil.kt
Normal file
27
app/src/test/java/org/oxycblt/auxio/util/TestingUtil.kt
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Auxio Project
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
Loading…
Reference in a new issue