123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- /*
- * Nextcloud Android client application
- *
- * @author Chris Narkiewicz
- * Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package com.nextcloud.client.logger.ui
- import android.content.Context
- import androidx.arch.core.executor.testing.InstantTaskExecutorRule
- import com.nextcloud.client.core.Clock
- import com.nextcloud.client.core.ManualAsyncRunner
- import com.nextcloud.client.logger.Level
- import com.nextcloud.client.logger.LogEntry
- import com.nextcloud.client.logger.LogsRepository
- import com.nextcloud.client.logger.OnLogsLoaded
- import org.junit.Assert.assertEquals
- import org.junit.Assert.assertFalse
- import org.junit.Assert.assertNotNull
- import org.junit.Assert.assertNull
- import org.junit.Assert.assertSame
- import org.junit.Assert.assertTrue
- import org.junit.Before
- import org.junit.Rule
- import org.junit.Test
- import org.junit.runner.RunWith
- import org.junit.runners.Suite
- import org.mockito.MockitoAnnotations
- import org.mockito.kotlin.any
- import org.mockito.kotlin.mock
- import org.mockito.kotlin.whenever
- import java.util.Date
- @RunWith(Suite::class)
- @Suite.SuiteClasses(
- LogsViewModelTest.Loading::class,
- LogsViewModelTest.Filtering::class
- )
- class LogsViewModelTest {
- private companion object {
- val TEST_LOG_ENTRIES = listOf(
- LogEntry(Date(), Level.DEBUG, "test", "entry 1"),
- LogEntry(Date(), Level.DEBUG, "test", "entry 2"),
- LogEntry(Date(), Level.DEBUG, "test", "entry 3")
- )
- val TEST_LOG_SIZE_KILOBYTES = 42L
- val TEST_LOG_SIZE_BYTES = TEST_LOG_SIZE_KILOBYTES * 1024L
- const val TOTAL_ENTRY_COUNT = 3
- const val QUERY_TIME = 4
- }
- class TestLogRepository : LogsRepository {
- var loadRequestCount = 0
- var onLoadedCallback: OnLogsLoaded? = null
- override val lostEntries: Boolean = false
- override fun load(onLoaded: OnLogsLoaded) { this.onLoadedCallback = onLoaded; loadRequestCount++ }
- override fun deleteAll() { /* no implementation neeeded */
- }
- }
- abstract class Fixture {
- protected lateinit var context: Context
- protected lateinit var clock: Clock
- protected lateinit var repository: TestLogRepository
- protected lateinit var runner: ManualAsyncRunner
- protected lateinit var vm: LogsViewModel
- @get:Rule
- val rule = InstantTaskExecutorRule()
- @Before
- fun setUpFixture() {
- MockitoAnnotations.initMocks(this)
- context = mock()
- clock = mock()
- repository = TestLogRepository()
- runner = ManualAsyncRunner()
- vm = LogsViewModel(context, clock, runner, repository)
- whenever(context.getString(any(), any())).thenAnswer {
- "${it.arguments}"
- }
- }
- }
- class Loading : Fixture() {
- @Test
- fun `all observable properties have initial values`() {
- assertNotNull(vm.isLoading)
- assertNotNull(vm.size)
- assertNotNull(vm.entries)
- assertNotNull(vm.status)
- }
- @Test
- fun `load logs entries from repository`() {
- // GIVEN
- // entries are not loaded
- assertEquals(0, vm.entries.value!!.size)
- assertEquals(false, vm.isLoading.value)
- // WHEN
- // load is initiated
- vm.load()
- // THEN
- // loading status is true
- // repository request is posted
- assertTrue(vm.isLoading.value!!)
- assertNotNull(repository.onLoadedCallback)
- }
- @Test
- fun `on logs loaded`() {
- // GIVEN
- // logs are being loaded
- vm.load()
- assertNotNull(repository.onLoadedCallback)
- assertTrue(vm.isLoading.value!!)
- // WHEN
- // logs loading finishes
- repository.onLoadedCallback?.invoke(TEST_LOG_ENTRIES, TEST_LOG_SIZE_BYTES)
- // THEN
- // logs are displayed
- // logs size is displyed
- // status is displayed
- assertFalse(vm.isLoading.value!!)
- assertSame(vm.entries.value, TEST_LOG_ENTRIES)
- assertNotNull(vm.status.value)
- }
- @Test
- fun `cannot start loading when loading is in progress`() {
- // GIVEN
- // logs loading is started
- vm.load()
- assertEquals(1, repository.loadRequestCount)
- assertTrue(vm.isLoading.value!!)
- // WHEN
- // load is requested
- repository.onLoadedCallback = null
- vm.load()
- // THEN
- // request is ignored
- assertNull(repository.onLoadedCallback)
- assertEquals(1, repository.loadRequestCount)
- }
- }
- class Filtering : Fixture() {
- @Before
- fun setUp() {
- vm.load()
- repository.onLoadedCallback?.invoke(TEST_LOG_ENTRIES, TEST_LOG_SIZE_BYTES)
- assertFalse(vm.isLoading.value!!)
- assertEquals(TEST_LOG_ENTRIES.size, vm.entries.value?.size)
- }
- @Test
- fun `filtering cannot be started when loading`() {
- // GIVEN
- // loading is in progress
- vm.load()
- assertTrue(vm.isLoading.value!!)
- // WHEN
- // filtering is requested
- vm.filter("some pattern")
- // THEN
- // filtering is not enqueued
- assertTrue(runner.isEmpty)
- }
- @Test
- fun `filtering task is started`() {
- // GIVEN
- // logs are loaded
- assertEquals(TEST_LOG_ENTRIES.size, vm.entries.value?.size)
- // WHEN
- // logs filtering is not running
- // logs filtering is requested
- assertTrue(runner.isEmpty)
- vm.filter(TEST_LOG_ENTRIES[0].message)
- // THEN
- // filter request is enqueued
- assertEquals(1, runner.size)
- }
- @Test
- fun `filtered logs are displayed`() {
- var statusArgs: Array<Any> = emptyArray()
- whenever(context.getString(any(), any())).thenAnswer {
- statusArgs = it.arguments
- "${it.arguments}"
- }
- // GIVEN
- // filtering is in progress
- val pattern = TEST_LOG_ENTRIES[0].message
- vm.filter(pattern)
- // WHEN
- // filtering finishes
- assertEquals(1, runner.runAll())
- // THEN
- // vm displays filtered results
- // vm displays status
- assertNotNull(vm.entries.value)
- assertEquals(1, vm.entries.value?.size)
- val filteredEntry = vm.entries.value?.get(0)!!
- assertTrue(filteredEntry.message.contains(pattern))
- assertEquals("Status should contain size in kB", TEST_LOG_SIZE_KILOBYTES, statusArgs[1])
- assertEquals("Status should show matched entries count", vm.entries.value?.size, statusArgs[2])
- assertEquals(
- "Status should contain total entries count",
- TEST_LOG_ENTRIES.size,
- statusArgs[TOTAL_ENTRY_COUNT]
- )
- assertTrue("Status should contain query time in ms", statusArgs[QUERY_TIME] is Long)
- }
- }
- }
|