test: re-implement tests
Reimplement the tests of music modeling, and re-enable the automatic test workflow in GH actions. I'm actually going to work on reimplementing these.
This commit is contained in:
parent
2c2bd79ae2
commit
59e42acad9
16 changed files with 567 additions and 790 deletions
4
.github/workflows/android.yml
vendored
4
.github/workflows/android.yml
vendored
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<Name> {
|
|||
abstract val sort: String?
|
||||
|
||||
/** A tokenized version of the name that will be compared. */
|
||||
protected abstract val sortTokens: List<SortToken>
|
||||
@VisibleForTesting(VisibleForTesting.PROTECTED) abstract val sortTokens: List<SortToken>
|
||||
|
||||
/** 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<SortToken> {
|
||||
override fun compareTo(other: SortToken): Int {
|
||||
// Numeric tokens should always be lower than lexicographic tokens.
|
||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<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 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<Artist>
|
||||
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()
|
||||
}
|
||||
|
||||
open class FakeArtist : Artist {
|
||||
override val name: Name
|
||||
get() = throw NotImplementedError()
|
||||
|
||||
override val albums: List<Album>
|
||||
get() = throw NotImplementedError()
|
||||
|
||||
override val explicitAlbums: List<Album>
|
||||
get() = throw NotImplementedError()
|
||||
|
||||
override val implicitAlbums: List<Album>
|
||||
get() = throw NotImplementedError()
|
||||
|
||||
override val genres: List<Genre>
|
||||
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()
|
||||
}
|
||||
|
||||
open class FakeGenre : Genre {
|
||||
override val name: Name
|
||||
get() = throw NotImplementedError()
|
||||
|
||||
override val artists: List<Artist>
|
||||
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()
|
||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<Song>) {
|
||||
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<Song>, playlist: Playlist) {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
override suspend fun rewritePlaylist(playlist: Playlist, songs: List<Song>) {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
override fun requestIndex(withCache: Boolean) {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
override fun index(worker: MusicRepository.IndexingWorker, withCache: Boolean): Job {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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()
|
||||
}
|
|
@ -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 <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(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))
|
||||
}
|
||||
}
|
|
@ -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 <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.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<Boolean>()
|
||||
|
||||
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<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
|
||||
}
|
||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<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 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()
|
||||
}
|
||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.music.info
|
||||
|
||||
class NameTest {
|
||||
}
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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 {
|
||||
}
|
||||
private fun mockIntelligentSorting(enabled: Boolean) =
|
||||
mockk<MusicSettings>().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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<MusicSettings>().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(",")))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"])
|
||||
}
|
||||
|
|
|
@ -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 <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