mirror of
https://github.com/mihonapp/mihon.git
synced 2025-10-28 21:07:57 +01:00
Rewrote Backup (#650)
* Rewrote Backup * Save automatic backups with datetime * Minor improvements * Remove suggested directories for backup and hardcoded strings. Rename JSON -> Backup * Bugfix * Fix tests * Run restore inside a transaction, use external cache dir for log and other minor changes
This commit is contained in:
committed by
inorichi
parent
3094d084d6
commit
0642889b64
@@ -1,568 +1,412 @@
|
||||
package eu.kanade.tachiyomi.data.backup
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonElement
|
||||
import com.github.salomonbrys.kotson.fromJson
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner
|
||||
import eu.kanade.tachiyomi.data.backup.models.Backup
|
||||
import eu.kanade.tachiyomi.data.backup.models.DHistory
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.*
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.Mockito.*
|
||||
import org.robolectric.RuntimeEnvironment
|
||||
import org.robolectric.annotation.Config
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.util.*
|
||||
import rx.Observable
|
||||
import rx.observers.TestSubscriber
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.InjektModule
|
||||
import uy.kohesive.injekt.api.InjektRegistrar
|
||||
import uy.kohesive.injekt.api.addSingleton
|
||||
|
||||
/**
|
||||
* Test class for the [BackupManager].
|
||||
* Note that this does not include the backup create/restore services.
|
||||
*/
|
||||
@Config(constants = BuildConfig::class, sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP))
|
||||
@RunWith(CustomRobolectricGradleTestRunner::class)
|
||||
class BackupTest {
|
||||
// Create root object
|
||||
var root = JsonObject()
|
||||
|
||||
val gson: Gson by injectLazy()
|
||||
// Create information object
|
||||
var information = JsonObject()
|
||||
|
||||
lateinit var db: DatabaseHelper
|
||||
// Create manga array
|
||||
var mangaEntries = JsonArray()
|
||||
|
||||
// Create category array
|
||||
var categoryEntries = JsonArray()
|
||||
|
||||
lateinit var app: Application
|
||||
lateinit var context: Context
|
||||
lateinit var source: HttpSource
|
||||
|
||||
lateinit var backupManager: BackupManager
|
||||
|
||||
lateinit var root: JsonObject
|
||||
lateinit var db: DatabaseHelper
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
val app = RuntimeEnvironment.application
|
||||
db = DatabaseHelper(app)
|
||||
backupManager = BackupManager(db)
|
||||
root = JsonObject()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRestoreCategory() {
|
||||
val catName = "cat"
|
||||
root = createRootJson(null, toJson(createCategories(catName)))
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbCats = db.getCategories().executeAsBlocking()
|
||||
assertThat(dbCats).hasSize(1)
|
||||
assertThat(dbCats[0].name).isEqualTo(catName)
|
||||
app = RuntimeEnvironment.application
|
||||
context = app.applicationContext
|
||||
backupManager = BackupManager(context)
|
||||
db = backupManager.databaseHelper
|
||||
|
||||
// Mock the source manager
|
||||
val module = object : InjektModule {
|
||||
override fun InjektRegistrar.registerInjectables() {
|
||||
addSingleton(Mockito.mock(SourceManager::class.java, RETURNS_DEEP_STUBS))
|
||||
}
|
||||
}
|
||||
Injekt.importModule(module)
|
||||
|
||||
source = mock(HttpSource::class.java)
|
||||
`when`(backupManager.sourceManager.get(anyLong())).thenReturn(source)
|
||||
|
||||
root.add(Backup.MANGAS, mangaEntries)
|
||||
root.add(Backup.CATEGORIES, categoryEntries)
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that checks if no crashes when no categories in library.
|
||||
*/
|
||||
@Test
|
||||
fun testRestoreEmptyCategory() {
|
||||
root = createRootJson(null, toJson(ArrayList<Any>()))
|
||||
backupManager.restoreFromJson(root)
|
||||
// Initialize json with version 2
|
||||
initializeJsonTest(2)
|
||||
|
||||
// Create backup of empty database
|
||||
backupManager.backupCategories(categoryEntries)
|
||||
|
||||
// Restore Json
|
||||
backupManager.restoreCategories(categoryEntries)
|
||||
|
||||
// Check if empty
|
||||
val dbCats = db.getCategories().executeAsBlocking()
|
||||
assertThat(dbCats).isEmpty()
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to check if single category gets restored
|
||||
*/
|
||||
@Test
|
||||
fun testRestoreExistingCategory() {
|
||||
val catName = "cat"
|
||||
db.insertCategory(createCategory(catName)).executeAsBlocking()
|
||||
fun testRestoreSingleCategory() {
|
||||
// Initialize json with version 2
|
||||
initializeJsonTest(2)
|
||||
|
||||
root = createRootJson(null, toJson(createCategories(catName)))
|
||||
backupManager.restoreFromJson(root)
|
||||
// Create category and add to json
|
||||
val category = addSingleCategory("category")
|
||||
|
||||
val dbCats = db.getCategories().executeAsBlocking()
|
||||
// Restore Json
|
||||
backupManager.restoreCategories(categoryEntries)
|
||||
|
||||
// Check if successful
|
||||
val dbCats = backupManager.databaseHelper.getCategories().executeAsBlocking()
|
||||
assertThat(dbCats).hasSize(1)
|
||||
assertThat(dbCats[0].name).isEqualTo(catName)
|
||||
assertThat(dbCats[0].name).isEqualTo(category.name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to check if multiple categories get restored.
|
||||
*/
|
||||
@Test
|
||||
fun testRestoreCategories() {
|
||||
root = createRootJson(null, toJson(createCategories("cat", "cat2", "cat3")))
|
||||
backupManager.restoreFromJson(root)
|
||||
fun testRestoreMultipleCategories() {
|
||||
// Initialize json with version 2
|
||||
initializeJsonTest(2)
|
||||
|
||||
val dbCats = db.getCategories().executeAsBlocking()
|
||||
assertThat(dbCats).hasSize(3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRestoreExistingCategories() {
|
||||
db.insertCategories(createCategories("cat", "cat2")).executeAsBlocking()
|
||||
|
||||
root = createRootJson(null, toJson(createCategories("cat", "cat2", "cat3")))
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbCats = db.getCategories().executeAsBlocking()
|
||||
assertThat(dbCats).hasSize(3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRestoreExistingCategoriesAlt() {
|
||||
db.insertCategories(createCategories("cat", "cat2", "cat3")).executeAsBlocking()
|
||||
|
||||
root = createRootJson(null, toJson(createCategories("cat", "cat2")))
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbCats = db.getCategories().executeAsBlocking()
|
||||
assertThat(dbCats).hasSize(3)
|
||||
// Create category and add to json
|
||||
val category = addSingleCategory("category")
|
||||
val category2 = addSingleCategory("category2")
|
||||
val category3 = addSingleCategory("category3")
|
||||
val category4 = addSingleCategory("category4")
|
||||
val category5 = addSingleCategory("category5")
|
||||
|
||||
// Insert category to test if no duplicates on restore.
|
||||
db.insertCategory(category).executeAsBlocking()
|
||||
|
||||
// Restore Json
|
||||
backupManager.restoreCategories(categoryEntries)
|
||||
|
||||
// Check if successful
|
||||
val dbCats = backupManager.databaseHelper.getCategories().executeAsBlocking()
|
||||
assertThat(dbCats).hasSize(5)
|
||||
assertThat(dbCats[0].name).isEqualTo(category.name)
|
||||
assertThat(dbCats[1].name).isEqualTo(category2.name)
|
||||
assertThat(dbCats[2].name).isEqualTo(category3.name)
|
||||
assertThat(dbCats[3].name).isEqualTo(category4.name)
|
||||
assertThat(dbCats[4].name).isEqualTo(category5.name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if restore of manga is successful
|
||||
*/
|
||||
@Test
|
||||
fun testRestoreManga() {
|
||||
val mangaName = "title"
|
||||
val mangas = createMangas(mangaName)
|
||||
val elements = ArrayList<JsonElement>()
|
||||
for (manga in mangas) {
|
||||
val entry = JsonObject()
|
||||
entry.add("manga", toJson(manga))
|
||||
elements.add(entry)
|
||||
}
|
||||
root = createRootJson(toJson(elements), null)
|
||||
backupManager.restoreFromJson(root)
|
||||
// Initialize json with version 2
|
||||
initializeJsonTest(2)
|
||||
|
||||
val dbMangas = db.getMangas().executeAsBlocking()
|
||||
assertThat(dbMangas).hasSize(1)
|
||||
assertThat(dbMangas[0].title).isEqualTo(mangaName)
|
||||
// Add manga to database
|
||||
val manga = getSingleManga("One Piece")
|
||||
manga.viewer = 3
|
||||
manga.id = db.insertManga(manga).executeAsBlocking().insertedId()
|
||||
|
||||
var favoriteManga = backupManager.databaseHelper.getFavoriteMangas().executeAsBlocking()
|
||||
assertThat(favoriteManga).hasSize(1)
|
||||
assertThat(favoriteManga[0].viewer).isEqualTo(3)
|
||||
|
||||
// Update json with all options enabled
|
||||
mangaEntries.add(backupManager.backupMangaObject(manga,1))
|
||||
|
||||
// Change manga in database to default values
|
||||
val dbManga = getSingleManga("One Piece")
|
||||
dbManga.id = manga.id
|
||||
db.insertManga(dbManga).executeAsBlocking()
|
||||
|
||||
favoriteManga = backupManager.databaseHelper.getFavoriteMangas().executeAsBlocking()
|
||||
assertThat(favoriteManga).hasSize(1)
|
||||
assertThat(favoriteManga[0].viewer).isEqualTo(0)
|
||||
|
||||
// Restore local manga
|
||||
backupManager.restoreMangaNoFetch(manga,dbManga)
|
||||
|
||||
// Test if restore successful
|
||||
favoriteManga = backupManager.databaseHelper.getFavoriteMangas().executeAsBlocking()
|
||||
assertThat(favoriteManga).hasSize(1)
|
||||
assertThat(favoriteManga[0].viewer).isEqualTo(3)
|
||||
|
||||
// Clear database to test manga fetch
|
||||
clearDatabase()
|
||||
|
||||
// Test if successful
|
||||
favoriteManga = backupManager.databaseHelper.getFavoriteMangas().executeAsBlocking()
|
||||
assertThat(favoriteManga).hasSize(0)
|
||||
|
||||
// Restore Json
|
||||
// Create JSON from manga to test parser
|
||||
val json = backupManager.parser.toJsonTree(manga)
|
||||
// Restore JSON from manga to test parser
|
||||
val jsonManga = backupManager.parser.fromJson<MangaImpl>(json)
|
||||
|
||||
// Restore manga with fetch observable
|
||||
val networkManga = getSingleManga("One Piece")
|
||||
networkManga.description = "This is a description"
|
||||
`when`(source.fetchMangaDetails(jsonManga)).thenReturn(Observable.just(networkManga))
|
||||
|
||||
val obs = backupManager.restoreMangaFetchObservable(source, jsonManga)
|
||||
val testSubscriber = TestSubscriber<Manga>()
|
||||
obs.subscribe(testSubscriber)
|
||||
|
||||
testSubscriber.assertNoErrors()
|
||||
|
||||
// Check if restore successful
|
||||
val dbCats = backupManager.databaseHelper.getFavoriteMangas().executeAsBlocking()
|
||||
assertThat(dbCats).hasSize(1)
|
||||
assertThat(dbCats[0].viewer).isEqualTo(3)
|
||||
assertThat(dbCats[0].description).isEqualTo("This is a description")
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if chapter restore is successful
|
||||
*/
|
||||
@Test
|
||||
fun testRestoreExistingManga() {
|
||||
val mangaName = "title"
|
||||
val manga = createManga(mangaName)
|
||||
fun testRestoreChapters() {
|
||||
// Initialize json with version 2
|
||||
initializeJsonTest(2)
|
||||
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
// Insert manga
|
||||
val manga = getSingleManga("One Piece")
|
||||
manga.id = backupManager.databaseHelper.insertManga(manga).executeAsBlocking().insertedId()
|
||||
|
||||
val elements = ArrayList<JsonElement>()
|
||||
val entry = JsonObject()
|
||||
entry.add("manga", toJson(manga))
|
||||
elements.add(entry)
|
||||
|
||||
root = createRootJson(toJson(elements), null)
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbMangas = db.getMangas().executeAsBlocking()
|
||||
assertThat(dbMangas).hasSize(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRestoreExistingMangaWithUpdatedFields() {
|
||||
// Store a manga in db
|
||||
val mangaName = "title"
|
||||
val updatedThumbnailUrl = "updated thumbnail url"
|
||||
var manga = createManga(mangaName)
|
||||
manga.chapter_flags = 1024
|
||||
manga.thumbnail_url = updatedThumbnailUrl
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
|
||||
// Add an entry for a new manga with different attributes
|
||||
manga = createManga(mangaName)
|
||||
manga.chapter_flags = 512
|
||||
val entry = JsonObject()
|
||||
entry.add("manga", toJson(manga))
|
||||
|
||||
// Append the entry to the backup list
|
||||
val elements = ArrayList<JsonElement>()
|
||||
elements.add(entry)
|
||||
|
||||
// Restore from json
|
||||
root = createRootJson(toJson(elements), null)
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbMangas = db.getMangas().executeAsBlocking()
|
||||
assertThat(dbMangas).hasSize(1)
|
||||
assertThat(dbMangas[0].thumbnail_url).isEqualTo(updatedThumbnailUrl)
|
||||
assertThat(dbMangas[0].chapter_flags).isEqualTo(512)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRestoreChaptersForManga() {
|
||||
// Create a manga and 3 chapters
|
||||
val manga = createManga("title")
|
||||
manga.id = 1L
|
||||
val chapters = createChapters(manga, "1", "2", "3")
|
||||
|
||||
// Add an entry for the manga
|
||||
val entry = JsonObject()
|
||||
entry.add("manga", toJson(manga))
|
||||
entry.add("chapters", toJson(chapters))
|
||||
|
||||
// Append the entry to the backup list
|
||||
val mangas = ArrayList<JsonElement>()
|
||||
mangas.add(entry)
|
||||
|
||||
// Restore from json
|
||||
root = createRootJson(toJson(mangas), null)
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbManga = db.getManga(1).executeAsBlocking()
|
||||
assertThat(dbManga).isNotNull()
|
||||
|
||||
val dbChapters = db.getChapters(dbManga!!).executeAsBlocking()
|
||||
assertThat(dbChapters).hasSize(3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRestoreChaptersForExistingManga() {
|
||||
val mangaId: Long = 3
|
||||
// Create a manga and 3 chapters
|
||||
val manga = createManga("title")
|
||||
manga.id = mangaId
|
||||
val chapters = createChapters(manga, "1", "2", "3")
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
|
||||
// Add an entry for the manga
|
||||
val entry = JsonObject()
|
||||
entry.add("manga", toJson(manga))
|
||||
entry.add("chapters", toJson(chapters))
|
||||
|
||||
// Append the entry to the backup list
|
||||
val mangas = ArrayList<JsonElement>()
|
||||
mangas.add(entry)
|
||||
|
||||
// Restore from json
|
||||
root = createRootJson(toJson(mangas), null)
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbManga = db.getManga(mangaId).executeAsBlocking()
|
||||
assertThat(dbManga).isNotNull()
|
||||
|
||||
val dbChapters = db.getChapters(dbManga!!).executeAsBlocking()
|
||||
assertThat(dbChapters).hasSize(3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRestoreExistingChaptersForExistingManga() {
|
||||
val mangaId: Long = 5
|
||||
// Store a manga and 3 chapters
|
||||
val manga = createManga("title")
|
||||
manga.id = mangaId
|
||||
var chapters = createChapters(manga, "1", "2", "3")
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
db.insertChapters(chapters).executeAsBlocking()
|
||||
|
||||
// The backup contains a existing chapter and a new one, so it should have 4 chapters
|
||||
chapters = createChapters(manga, "3", "4")
|
||||
|
||||
// Add an entry for the manga
|
||||
val entry = JsonObject()
|
||||
entry.add("manga", toJson(manga))
|
||||
entry.add("chapters", toJson(chapters))
|
||||
|
||||
// Append the entry to the backup list
|
||||
val mangas = ArrayList<JsonElement>()
|
||||
mangas.add(entry)
|
||||
|
||||
// Restore from json
|
||||
root = createRootJson(toJson(mangas), null)
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbManga = db.getManga(mangaId).executeAsBlocking()
|
||||
assertThat(dbManga).isNotNull()
|
||||
|
||||
val dbChapters = db.getChapters(dbManga!!).executeAsBlocking()
|
||||
assertThat(dbChapters).hasSize(4)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRestoreCategoriesForManga() {
|
||||
// Create a manga
|
||||
val manga = createManga("title")
|
||||
|
||||
// Create categories
|
||||
val categories = createCategories("cat1", "cat2", "cat3")
|
||||
|
||||
// Add an entry for the manga
|
||||
val entry = JsonObject()
|
||||
entry.add("manga", toJson(manga))
|
||||
entry.add("categories", toJson(createStringCategories("cat1")))
|
||||
|
||||
// Append the entry to the backup list
|
||||
val mangas = ArrayList<JsonElement>()
|
||||
mangas.add(entry)
|
||||
|
||||
// Restore from json
|
||||
root = createRootJson(toJson(mangas), toJson(categories))
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbManga = db.getManga(1).executeAsBlocking()
|
||||
assertThat(dbManga).isNotNull()
|
||||
|
||||
val result = db.getCategoriesForManga(dbManga!!).executeAsBlocking()
|
||||
|
||||
assertThat(result).hasSize(1)
|
||||
assertThat(result).contains(Category.create("cat1"))
|
||||
assertThat(result).doesNotContain(Category.create("cat2"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRestoreCategoriesForExistingManga() {
|
||||
// Store a manga
|
||||
val manga = createManga("title")
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
|
||||
// Create categories
|
||||
val categories = createCategories("cat1", "cat2", "cat3")
|
||||
|
||||
// Add an entry for the manga
|
||||
val entry = JsonObject()
|
||||
entry.add("manga", toJson(manga))
|
||||
entry.add("categories", toJson(createStringCategories("cat1")))
|
||||
|
||||
// Append the entry to the backup list
|
||||
val mangas = ArrayList<JsonElement>()
|
||||
mangas.add(entry)
|
||||
|
||||
// Restore from json
|
||||
root = createRootJson(toJson(mangas), toJson(categories))
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbManga = db.getManga(1).executeAsBlocking()
|
||||
assertThat(dbManga).isNotNull()
|
||||
|
||||
val result = db.getCategoriesForManga(dbManga!!).executeAsBlocking()
|
||||
|
||||
assertThat(result).hasSize(1)
|
||||
assertThat(result).contains(Category.create("cat1"))
|
||||
assertThat(result).doesNotContain(Category.create("cat2"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRestoreMultipleCategoriesForManga() {
|
||||
// Create a manga
|
||||
val manga = createManga("title")
|
||||
|
||||
// Create categories
|
||||
val categories = createCategories("cat1", "cat2", "cat3")
|
||||
|
||||
// Add an entry for the manga
|
||||
val entry = JsonObject()
|
||||
entry.add("manga", toJson(manga))
|
||||
entry.add("categories", toJson(createStringCategories("cat1", "cat3")))
|
||||
|
||||
// Append the entry to the backup list
|
||||
val mangas = ArrayList<JsonElement>()
|
||||
mangas.add(entry)
|
||||
|
||||
// Restore from json
|
||||
root = createRootJson(toJson(mangas), toJson(categories))
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbManga = db.getManga(1).executeAsBlocking()
|
||||
assertThat(dbManga).isNotNull()
|
||||
|
||||
val result = db.getCategoriesForManga(dbManga!!).executeAsBlocking()
|
||||
|
||||
assertThat(result).hasSize(2)
|
||||
assertThat(result).contains(Category.create("cat1"), Category.create("cat3"))
|
||||
assertThat(result).doesNotContain(Category.create("cat2"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRestoreMultipleCategoriesForExistingMangaAndCategory() {
|
||||
// Store a manga and a category
|
||||
val manga = createManga("title")
|
||||
manga.id = 1L
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
|
||||
val cat = createCategory("cat1")
|
||||
cat.id = 1
|
||||
db.insertCategory(cat).executeAsBlocking()
|
||||
db.insertMangaCategory(MangaCategory.create(manga, cat)).executeAsBlocking()
|
||||
|
||||
// Create categories
|
||||
val categories = createCategories("cat1", "cat2", "cat3")
|
||||
|
||||
// Add an entry for the manga
|
||||
val entry = JsonObject()
|
||||
entry.add("manga", toJson(manga))
|
||||
entry.add("categories", toJson(createStringCategories("cat1", "cat2")))
|
||||
|
||||
// Append the entry to the backup list
|
||||
val mangas = ArrayList<JsonElement>()
|
||||
mangas.add(entry)
|
||||
|
||||
// Restore from json
|
||||
root = createRootJson(toJson(mangas), toJson(categories))
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbManga = db.getManga(1).executeAsBlocking()
|
||||
assertThat(dbManga).isNotNull()
|
||||
|
||||
val result = db.getCategoriesForManga(dbManga!!).executeAsBlocking()
|
||||
|
||||
assertThat(result).hasSize(2)
|
||||
assertThat(result).contains(Category.create("cat1"), Category.create("cat2"))
|
||||
assertThat(result).doesNotContain(Category.create("cat3"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRestoreSyncForManga() {
|
||||
// Create a manga and track
|
||||
val manga = createManga("title")
|
||||
manga.id = 1L
|
||||
|
||||
val track = createTrack(manga, 1, 2, 3)
|
||||
|
||||
// Add an entry for the manga
|
||||
val entry = JsonObject()
|
||||
entry.add("manga", toJson(manga))
|
||||
entry.add("sync", toJson(track))
|
||||
|
||||
// Append the entry to the backup list
|
||||
val mangas = ArrayList<JsonElement>()
|
||||
mangas.add(entry)
|
||||
|
||||
// Restore from json
|
||||
root = createRootJson(toJson(mangas), null)
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbManga = db.getManga(1).executeAsBlocking()
|
||||
assertThat(dbManga).isNotNull()
|
||||
|
||||
val dbSync = db.getTracks(dbManga!!).executeAsBlocking()
|
||||
assertThat(dbSync).hasSize(3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRestoreSyncForExistingManga() {
|
||||
val mangaId: Long = 3
|
||||
// Create a manga and 3 sync
|
||||
val manga = createManga("title")
|
||||
manga.id = mangaId
|
||||
val track = createTrack(manga, 1, 2, 3)
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
|
||||
// Add an entry for the manga
|
||||
val entry = JsonObject()
|
||||
entry.add("manga", toJson(manga))
|
||||
entry.add("sync", toJson(track))
|
||||
|
||||
// Append the entry to the backup list
|
||||
val mangas = ArrayList<JsonElement>()
|
||||
mangas.add(entry)
|
||||
|
||||
// Restore from json
|
||||
root = createRootJson(toJson(mangas), null)
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbManga = db.getManga(mangaId).executeAsBlocking()
|
||||
assertThat(dbManga).isNotNull()
|
||||
|
||||
val dbSync = db.getTracks(dbManga!!).executeAsBlocking()
|
||||
assertThat(dbSync).hasSize(3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRestoreExistingSyncForExistingManga() {
|
||||
val mangaId: Long = 5
|
||||
// Store a manga and 3 sync
|
||||
val manga = createManga("title")
|
||||
manga.id = mangaId
|
||||
var track = createTrack(manga, 1, 2, 3)
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
db.insertTracks(track).executeAsBlocking()
|
||||
|
||||
// The backup contains a existing sync and a new one, so it should have 4 sync
|
||||
track = createTrack(manga, 3, 4)
|
||||
|
||||
// Add an entry for the manga
|
||||
val entry = JsonObject()
|
||||
entry.add("manga", toJson(manga))
|
||||
entry.add("sync", toJson(track))
|
||||
|
||||
// Append the entry to the backup list
|
||||
val mangas = ArrayList<JsonElement>()
|
||||
mangas.add(entry)
|
||||
|
||||
// Restore from json
|
||||
root = createRootJson(toJson(mangas), null)
|
||||
backupManager.restoreFromJson(root)
|
||||
|
||||
val dbManga = db.getManga(mangaId).executeAsBlocking()
|
||||
assertThat(dbManga).isNotNull()
|
||||
|
||||
val dbSync = db.getTracks(dbManga!!).executeAsBlocking()
|
||||
assertThat(dbSync).hasSize(4)
|
||||
}
|
||||
|
||||
private fun createRootJson(mangas: JsonElement?, categories: JsonElement?): JsonObject {
|
||||
val root = JsonObject()
|
||||
if (mangas != null)
|
||||
root.add("mangas", mangas)
|
||||
if (categories != null)
|
||||
root.add("categories", categories)
|
||||
return root
|
||||
}
|
||||
|
||||
private fun createCategory(name: String): Category {
|
||||
val c = CategoryImpl()
|
||||
c.name = name
|
||||
return c
|
||||
}
|
||||
|
||||
private fun createCategories(vararg names: String): List<Category> {
|
||||
val cats = ArrayList<Category>()
|
||||
for (name in names) {
|
||||
cats.add(createCategory(name))
|
||||
}
|
||||
return cats
|
||||
}
|
||||
|
||||
private fun createStringCategories(vararg names: String): List<String> {
|
||||
val cats = ArrayList<String>()
|
||||
for (name in names) {
|
||||
cats.add(name)
|
||||
}
|
||||
return cats
|
||||
}
|
||||
|
||||
private fun createManga(title: String): Manga {
|
||||
val m = Manga.create(1)
|
||||
m.title = title
|
||||
m.author = ""
|
||||
m.artist = ""
|
||||
m.thumbnail_url = ""
|
||||
m.genre = "a list of genres"
|
||||
m.description = "long description"
|
||||
m.url = "url to manga"
|
||||
m.favorite = true
|
||||
return m
|
||||
}
|
||||
|
||||
private fun createMangas(vararg titles: String): List<Manga> {
|
||||
val mangas = ArrayList<Manga>()
|
||||
for (title in titles) {
|
||||
mangas.add(createManga(title))
|
||||
}
|
||||
return mangas
|
||||
}
|
||||
|
||||
private fun createChapter(manga: Manga, url: String): Chapter {
|
||||
val c = Chapter.create()
|
||||
c.url = url
|
||||
c.name = url
|
||||
c.manga_id = manga.id
|
||||
return c
|
||||
}
|
||||
|
||||
private fun createChapters(manga: Manga, vararg urls: String): List<Chapter> {
|
||||
// Create restore list
|
||||
val chapters = ArrayList<Chapter>()
|
||||
for (url in urls) {
|
||||
chapters.add(createChapter(manga, url))
|
||||
for (i in 1..8){
|
||||
val chapter = getSingleChapter("Chapter $i")
|
||||
chapter.read = true
|
||||
chapters.add(chapter)
|
||||
}
|
||||
return chapters
|
||||
|
||||
// Check parser
|
||||
val chaptersJson = backupManager.parser.toJsonTree(chapters)
|
||||
val restoredChapters = backupManager.parser.fromJson<List<ChapterImpl>>(chaptersJson)
|
||||
|
||||
// Fetch chapters from upstream
|
||||
// Create list
|
||||
val chaptersRemote = ArrayList<Chapter>()
|
||||
(1..10).mapTo(chaptersRemote) { getSingleChapter("Chapter $it") }
|
||||
`when`(source.fetchChapterList(manga)).thenReturn(Observable.just(chaptersRemote))
|
||||
|
||||
// Call restoreChapterFetchObservable
|
||||
val obs = backupManager.restoreChapterFetchObservable(source, manga, restoredChapters)
|
||||
val testSubscriber = TestSubscriber<Pair<List<Chapter>, List<Chapter>>>()
|
||||
obs.subscribe(testSubscriber)
|
||||
|
||||
testSubscriber.assertNoErrors()
|
||||
|
||||
val dbCats = backupManager.databaseHelper.getChapters(manga).executeAsBlocking()
|
||||
assertThat(dbCats).hasSize(10)
|
||||
assertThat(dbCats[0].read).isEqualTo(true)
|
||||
}
|
||||
|
||||
private fun createTrack(manga: Manga, syncId: Int): Track {
|
||||
val m = Track.create(syncId)
|
||||
m.manga_id = manga.id!!
|
||||
m.title = "title"
|
||||
return m
|
||||
/**
|
||||
* Test to check if history restore works
|
||||
*/
|
||||
@Test
|
||||
fun restoreHistoryForManga(){
|
||||
// Initialize json with version 2
|
||||
initializeJsonTest(2)
|
||||
|
||||
val manga = getSingleManga("One Piece")
|
||||
manga.id = backupManager.databaseHelper.insertManga(manga).executeAsBlocking().insertedId()
|
||||
|
||||
// Create chapter
|
||||
val chapter = getSingleChapter("Chapter 1")
|
||||
chapter.manga_id = manga.id
|
||||
chapter.read = true
|
||||
chapter.id = backupManager.databaseHelper.insertChapter(chapter).executeAsBlocking().insertedId()
|
||||
|
||||
val historyJson = getSingleHistory(chapter)
|
||||
|
||||
val historyList = ArrayList<DHistory>()
|
||||
historyList.add(historyJson)
|
||||
|
||||
// Check parser
|
||||
val historyListJson = backupManager.parser.toJsonTree(historyList)
|
||||
val history = backupManager.parser.fromJson<List<DHistory>>(historyListJson)
|
||||
|
||||
// Restore categories
|
||||
backupManager.restoreHistoryForManga(history)
|
||||
|
||||
val historyDB = backupManager.databaseHelper.getHistoryByMangaId(manga.id!!).executeAsBlocking()
|
||||
assertThat(historyDB).hasSize(1)
|
||||
assertThat(historyDB[0].last_read).isEqualTo(1000)
|
||||
}
|
||||
|
||||
private fun createTrack(manga: Manga, vararg syncIds: Int): List<Track> {
|
||||
val ms = ArrayList<Track>()
|
||||
for (title in syncIds) {
|
||||
ms.add(createTrack(manga, title))
|
||||
}
|
||||
return ms
|
||||
/**
|
||||
* Test to check if tracking restore works
|
||||
*/
|
||||
@Test
|
||||
fun restoreTrackForManga() {
|
||||
// Initialize json with version 2
|
||||
initializeJsonTest(2)
|
||||
|
||||
// Create mangas
|
||||
val manga = getSingleManga("One Piece")
|
||||
val manga2 = getSingleManga("Bleach")
|
||||
manga.id = backupManager.databaseHelper.insertManga(manga).executeAsBlocking().insertedId()
|
||||
manga2.id = backupManager.databaseHelper.insertManga(manga2).executeAsBlocking().insertedId()
|
||||
|
||||
// Create track and add it to database
|
||||
// This tests duplicate errors.
|
||||
val track = getSingleTrack(manga)
|
||||
track.last_chapter_read = 5
|
||||
backupManager.databaseHelper.insertTrack(track).executeAsBlocking()
|
||||
var trackDB = backupManager.databaseHelper.getTracks(manga).executeAsBlocking()
|
||||
assertThat(trackDB).hasSize(1)
|
||||
assertThat(trackDB[0].last_chapter_read).isEqualTo(5)
|
||||
track.last_chapter_read = 7
|
||||
|
||||
// Create track for different manga to test track not in database
|
||||
val track2 = getSingleTrack(manga2)
|
||||
track2.last_chapter_read = 10
|
||||
|
||||
// Check parser and restore already in database
|
||||
var trackList = listOf(track)
|
||||
//Check parser
|
||||
var trackListJson = backupManager.parser.toJsonTree(trackList)
|
||||
var trackListRestore = backupManager.parser.fromJson<List<TrackImpl>>(trackListJson)
|
||||
backupManager.restoreTrackForManga(manga, trackListRestore)
|
||||
|
||||
// Assert if restore works.
|
||||
trackDB = backupManager.databaseHelper.getTracks(manga).executeAsBlocking()
|
||||
assertThat(trackDB).hasSize(1)
|
||||
assertThat(trackDB[0].last_chapter_read).isEqualTo(7)
|
||||
|
||||
// Check parser and restore already in database with lower chapter_read
|
||||
track.last_chapter_read = 5
|
||||
trackList = listOf(track)
|
||||
backupManager.restoreTrackForManga(manga, trackList)
|
||||
|
||||
// Assert if restore works.
|
||||
trackDB = backupManager.databaseHelper.getTracks(manga).executeAsBlocking()
|
||||
assertThat(trackDB).hasSize(1)
|
||||
assertThat(trackDB[0].last_chapter_read).isEqualTo(7)
|
||||
|
||||
// Check parser and restore, track not in database
|
||||
trackList = listOf(track2)
|
||||
|
||||
//Check parser
|
||||
trackListJson = backupManager.parser.toJsonTree(trackList)
|
||||
trackListRestore = backupManager.parser.fromJson<List<TrackImpl>>(trackListJson)
|
||||
backupManager.restoreTrackForManga(manga2, trackListRestore)
|
||||
|
||||
// Assert if restore works.
|
||||
trackDB = backupManager.databaseHelper.getTracks(manga2).executeAsBlocking()
|
||||
assertThat(trackDB).hasSize(1)
|
||||
assertThat(trackDB[0].last_chapter_read).isEqualTo(10)
|
||||
}
|
||||
|
||||
private fun toJson(element: Any): JsonElement {
|
||||
return gson.toJsonTree(element)
|
||||
fun clearJson() {
|
||||
root = JsonObject()
|
||||
information = JsonObject()
|
||||
mangaEntries = JsonArray()
|
||||
categoryEntries = JsonArray()
|
||||
}
|
||||
|
||||
fun initializeJsonTest(version: Int) {
|
||||
clearJson()
|
||||
backupManager.setVersion(version)
|
||||
}
|
||||
|
||||
fun addSingleCategory(name: String): Category {
|
||||
val category = Category.create(name)
|
||||
val catJson = backupManager.parser.toJsonTree(category)
|
||||
categoryEntries.add(catJson)
|
||||
return category
|
||||
}
|
||||
|
||||
fun clearDatabase(){
|
||||
db.deleteMangas().executeAsBlocking()
|
||||
db.deleteHistory().executeAsBlocking()
|
||||
}
|
||||
|
||||
fun getSingleHistory(chapter: Chapter): DHistory {
|
||||
return DHistory(chapter.url, 1000)
|
||||
}
|
||||
|
||||
private fun getSingleTrack(manga: Manga): TrackImpl {
|
||||
val track = TrackImpl()
|
||||
track.title = manga.title
|
||||
track.manga_id = manga.id!!
|
||||
track.remote_id = 1
|
||||
track.sync_id = 1
|
||||
return track
|
||||
}
|
||||
|
||||
private fun getSingleManga(title: String): MangaImpl {
|
||||
val manga = MangaImpl()
|
||||
manga.source = 1
|
||||
manga.title = title
|
||||
manga.url = "/manga/$title"
|
||||
manga.favorite = true
|
||||
return manga
|
||||
}
|
||||
|
||||
private fun getSingleChapter(name: String): ChapterImpl {
|
||||
val chapter = ChapterImpl()
|
||||
chapter.name = name
|
||||
chapter.url = "/read-online/$name-page-1.html"
|
||||
return chapter
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user