Fix tests

This commit is contained in:
len
2016-06-14 15:17:44 +02:00
parent 237af4b07d
commit eed295587d
9 changed files with 815 additions and 834 deletions

View File

@@ -0,0 +1,568 @@
package eu.kanade.tachiyomi.data.backup
import android.os.Build
import com.google.gson.Gson
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.*
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RuntimeEnvironment
import org.robolectric.annotation.Config
import uy.kohesive.injekt.injectLazy
import java.util.*
@Config(constants = BuildConfig::class, sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP))
@RunWith(CustomRobolectricGradleTestRunner::class)
class BackupTest {
val gson: Gson by injectLazy()
lateinit var db: DatabaseHelper
lateinit var backupManager: BackupManager
lateinit var root: JsonObject
@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)
}
@Test
fun testRestoreEmptyCategory() {
root = createRootJson(null, toJson(ArrayList<Any>()))
backupManager.restoreFromJson(root)
val dbCats = db.getCategories().executeAsBlocking()
assertThat(dbCats).isEmpty()
}
@Test
fun testRestoreExistingCategory() {
val catName = "cat"
db.insertCategory(createCategory(catName)).executeAsBlocking()
root = createRootJson(null, toJson(createCategories(catName)))
backupManager.restoreFromJson(root)
val dbCats = db.getCategories().executeAsBlocking()
assertThat(dbCats).hasSize(1)
assertThat(dbCats[0].name).isEqualTo(catName)
}
@Test
fun testRestoreCategories() {
root = createRootJson(null, toJson(createCategories("cat", "cat2", "cat3")))
backupManager.restoreFromJson(root)
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)
}
@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)
val dbMangas = db.getMangas().executeAsBlocking()
assertThat(dbMangas).hasSize(1)
assertThat(dbMangas[0].title).isEqualTo(mangaName)
}
@Test
fun testRestoreExistingManga() {
val mangaName = "title"
val manga = createManga(mangaName)
db.insertManga(manga).executeAsBlocking()
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 mangaSync
val manga = createManga("title")
manga.id = 1L
val mangaSync = createMangaSync(manga, 1, 2, 3)
// Add an entry for the manga
val entry = JsonObject()
entry.add("manga", toJson(manga))
entry.add("sync", toJson(mangaSync))
// 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.getMangasSync(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 mangaSync = createMangaSync(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(mangaSync))
// 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.getMangasSync(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 mangaSync = createMangaSync(manga, 1, 2, 3)
db.insertManga(manga).executeAsBlocking()
db.insertMangasSync(mangaSync).executeAsBlocking()
// The backup contains a existing sync and a new one, so it should have 4 sync
mangaSync = createMangaSync(manga, 3, 4)
// Add an entry for the manga
val entry = JsonObject()
entry.add("manga", toJson(manga))
entry.add("sync", toJson(mangaSync))
// 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.getMangasSync(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> {
val chapters = ArrayList<Chapter>()
for (url in urls) {
chapters.add(createChapter(manga, url))
}
return chapters
}
private fun createMangaSync(manga: Manga, syncId: Int): MangaSync {
val m = MangaSync.create(syncId)
m.manga_id = manga.id!!
m.title = "title"
return m
}
private fun createMangaSync(manga: Manga, vararg syncIds: Int): List<MangaSync> {
val ms = ArrayList<MangaSync>()
for (title in syncIds) {
ms.add(createMangaSync(manga, title))
}
return ms
}
private fun toJson(element: Any): JsonElement {
return gson.toJsonTree(element)
}
}

View File

@@ -1,115 +0,0 @@
package eu.kanade.tachiyomi.data.library;
import android.content.Context;
import android.os.Build;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import java.util.ArrayList;
import java.util.List;
import eu.kanade.tachiyomi.BuildConfig;
import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner;
import eu.kanade.tachiyomi.data.database.models.Chapter;
import eu.kanade.tachiyomi.data.database.models.Manga;
import eu.kanade.tachiyomi.data.source.online.OnlineSource;
import rx.Observable;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP)
@RunWith(CustomRobolectricGradleTestRunner.class)
public class LibraryUpdateServiceTest {
ShadowApplication app;
Context context;
LibraryUpdateService service;
OnlineSource source;
@Before
public void setup() {
app = ShadowApplication.getInstance();
context = app.getApplicationContext();
service = Robolectric.setupService(LibraryUpdateService.class);
source = mock(OnlineSource.class);
when(service.sourceManager.get(anyInt())).thenReturn(source);
}
@Test
public void testLifecycle() {
// Smoke test
Robolectric.buildService(LibraryUpdateService.class)
.attach()
.create()
.startCommand(0, 0)
.destroy()
.get();
}
@Test
public void testUpdateManga() {
Manga manga = createManga("/manga1").get(0);
manga.id = 1L;
service.db.insertManga(manga).executeAsBlocking();
List<Chapter> sourceChapters = createChapters("/chapter1", "/chapter2");
when(source.fetchChapterList(manga)).thenReturn(Observable.just(sourceChapters));
service.updateManga(manga).subscribe();
assertThat(service.db.getChapters(manga).executeAsBlocking()).hasSize(2);
}
@Test
public void testContinuesUpdatingWhenAMangaFails() {
List<Manga> favManga = createManga("/manga1", "/manga2", "/manga3");
service.db.insertMangas(favManga).executeAsBlocking();
favManga = service.db.getFavoriteMangas().executeAsBlocking();
List<Chapter> chapters = createChapters("/chapter1", "/chapter2");
List<Chapter> chapters3 = createChapters("/achapter1", "/achapter2");
// One of the updates will fail
when(source.fetchChapterList(favManga.get(0))).thenReturn(Observable.just(chapters));
when(source.fetchChapterList(favManga.get(1))).thenReturn(Observable.<List<Chapter>>error(new Exception()));
when(source.fetchChapterList(favManga.get(2))).thenReturn(Observable.just(chapters3));
service.updateMangaList(service.getMangaToUpdate(null)).subscribe();
// There are 3 network attempts and 2 insertions (1 request failed)
assertThat(service.db.getChapters(favManga.get(0)).executeAsBlocking()).hasSize(2);
assertThat(service.db.getChapters(favManga.get(1)).executeAsBlocking()).hasSize(0);
assertThat(service.db.getChapters(favManga.get(2)).executeAsBlocking()).hasSize(2);
}
private List<Chapter> createChapters(String... urls) {
List<Chapter> list = new ArrayList<>();
for (String url : urls) {
Chapter c = Chapter.create();
c.url = url;
c.name = url.substring(1);
list.add(c);
}
return list;
}
private List<Manga> createManga(String... urls) {
List<Manga> list = new ArrayList<>();
for (String url : urls) {
Manga m = Manga.create(url);
m.title = url.substring(1);
m.favorite = true;
list.add(m);
}
return list;
}
}

View File

@@ -0,0 +1,137 @@
package eu.kanade.tachiyomi.data.library
import android.app.Application
import android.content.Context
import android.os.Build
import eu.kanade.tachiyomi.AppModule
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.source.SourceManager
import eu.kanade.tachiyomi.data.source.online.OnlineSource
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Matchers.anyInt
import org.mockito.Mockito
import org.mockito.Mockito.*
import org.robolectric.Robolectric
import org.robolectric.RuntimeEnvironment
import org.robolectric.annotation.Config
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.InjektModule
import uy.kohesive.injekt.api.InjektRegistrar
import uy.kohesive.injekt.api.InjektScope
import uy.kohesive.injekt.api.addSingleton
import uy.kohesive.injekt.registry.default.DefaultRegistrar
import java.util.*
@Config(constants = BuildConfig::class, sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP))
@RunWith(CustomRobolectricGradleTestRunner::class)
class LibraryUpdateServiceTest {
lateinit var app: Application
lateinit var context: Context
lateinit var service: LibraryUpdateService
lateinit var source: OnlineSource
@Before
fun setup() {
app = RuntimeEnvironment.application
context = app.applicationContext
// Mock the source manager
val module = object : InjektModule {
override fun InjektRegistrar.registerInjectables() {
addSingleton(Mockito.mock(SourceManager::class.java, RETURNS_DEEP_STUBS))
}
}
// Restart injections for each test
Injekt = InjektScope(DefaultRegistrar())
Injekt.importModule(AppModule(app))
Injekt.importModule(module)
service = Robolectric.setupService(LibraryUpdateService::class.java)
source = mock(OnlineSource::class.java)
`when`(service.sourceManager.get(anyInt())).thenReturn(source)
}
@Test
fun testLifecycle() {
println(service.db)
// Smoke test
Robolectric.buildService(LibraryUpdateService::class.java)
.attach()
.create()
.startCommand(0, 0)
.destroy()
.get()
}
@Test
fun testUpdateManga() {
println(service.db)
val manga = createManga("/manga1")[0]
manga.id = 1L
service.db.insertManga(manga).executeAsBlocking()
val sourceChapters = createChapters("/chapter1", "/chapter2")
`when`(source.fetchChapterList(manga)).thenReturn(Observable.just(sourceChapters))
service.updateManga(manga).subscribe()
assertThat(service.db.getChapters(manga).executeAsBlocking()).hasSize(2)
}
@Test
fun testContinuesUpdatingWhenAMangaFails() {
var favManga = createManga("/manga1", "/manga2", "/manga3")
println(service.db)
service.db.insertMangas(favManga).executeAsBlocking()
favManga = service.db.getFavoriteMangas().executeAsBlocking()
val chapters = createChapters("/chapter1", "/chapter2")
val chapters3 = createChapters("/achapter1", "/achapter2")
// One of the updates will fail
`when`(source.fetchChapterList(favManga[0])).thenReturn(Observable.just(chapters))
`when`(source.fetchChapterList(favManga[1])).thenReturn(Observable.error<List<Chapter>>(Exception()))
`when`(source.fetchChapterList(favManga[2])).thenReturn(Observable.just(chapters3))
service.updateMangaList(service.getMangaToUpdate(null)).subscribe()
// There are 3 network attempts and 2 insertions (1 request failed)
assertThat(service.db.getChapters(favManga[0]).executeAsBlocking()).hasSize(2)
assertThat(service.db.getChapters(favManga[1]).executeAsBlocking()).hasSize(0)
assertThat(service.db.getChapters(favManga[2]).executeAsBlocking()).hasSize(2)
}
private fun createChapters(vararg urls: String): List<Chapter> {
val list = ArrayList<Chapter>()
for (url in urls) {
val c = Chapter.create()
c.url = url
c.name = url.substring(1)
list.add(c)
}
return list
}
private fun createManga(vararg urls: String): List<Manga> {
val list = ArrayList<Manga>()
for (url in urls) {
val m = Manga.create(url)
m.title = url.substring(1)
m.favorite = true
list.add(m)
}
return list
}
}