Skip to content

Commit

Permalink
Merge branch 'release/5.36.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
CDRussell committed Nov 6, 2019
2 parents d46ea99 + 001a398 commit a9ba7db
Show file tree
Hide file tree
Showing 30 changed files with 1,385 additions and 123 deletions.
584 changes: 584 additions & 0 deletions app/schemas/com.duckduckgo.app.global.db.AppDatabase/15.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import android.webkit.WebChromeClient
import android.webkit.WebView
import androidx.test.annotation.UiThreadTest
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import com.duckduckgo.app.global.exception.UncaughtExceptionRepository
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.times
Expand All @@ -36,12 +37,14 @@ class BrowserChromeClientTest {
private lateinit var testee: BrowserChromeClient
private lateinit var webView: TestWebView
private lateinit var mockWebViewClientListener: WebViewClientListener
private lateinit var mockUncaughtExceptionRepository: UncaughtExceptionRepository
private val fakeView = View(getInstrumentation().targetContext)

@UiThreadTest
@Before
fun setup() {
testee = BrowserChromeClient()
mockUncaughtExceptionRepository = mock()
testee = BrowserChromeClient(mockUncaughtExceptionRepository)
mockWebViewClientListener = mock()
testee.webViewClientListener = mockWebViewClientListener
webView = TestWebView(getInstrumentation().targetContext)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ import androidx.test.annotation.UiThreadTest
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import com.duckduckgo.app.browser.model.BasicAuthenticationRequest
import com.duckduckgo.app.statistics.store.OfflinePixelDataStore
import com.duckduckgo.app.global.exception.UncaughtExceptionRepository
import com.duckduckgo.app.statistics.store.OfflinePixelCountDataStore
import com.nhaarman.mockitokotlin2.*
import org.junit.Before
import org.junit.Test
Expand All @@ -39,7 +40,8 @@ class BrowserWebViewClientTest {
private val specialUrlDetector: SpecialUrlDetector = mock()
private val requestInterceptor: RequestInterceptor = mock()
private val listener: WebViewClientListener = mock()
private val offlinePixelDataStore: OfflinePixelDataStore = mock()
private val offlinePixelCountDataStore: OfflinePixelCountDataStore = mock()
private val uncaughtExceptionRepository: UncaughtExceptionRepository = mock()

@UiThreadTest
@Before
Expand All @@ -49,7 +51,8 @@ class BrowserWebViewClientTest {
requestRewriter,
specialUrlDetector,
requestInterceptor,
offlinePixelDataStore
offlinePixelCountDataStore,
uncaughtExceptionRepository
)
testee.webViewClientListener = listener
}
Expand Down Expand Up @@ -99,7 +102,7 @@ class BrowserWebViewClientTest {
val detail: RenderProcessGoneDetail = mock()
whenever(detail.didCrash()).thenReturn(true)
testee.onRenderProcessGone(webView, detail)
verify(offlinePixelDataStore, times(1)).webRendererGoneCrashCount = 1
verify(offlinePixelCountDataStore, times(1)).webRendererGoneCrashCount = 1
}

@Test
Expand All @@ -108,7 +111,7 @@ class BrowserWebViewClientTest {
val detail: RenderProcessGoneDetail = mock()
whenever(detail.didCrash()).thenReturn(false)
testee.onRenderProcessGone(webView, detail)
verify(offlinePixelDataStore, times(1)).webRendererGoneKilledCount = 1
verify(offlinePixelCountDataStore, times(1)).webRendererGoneKilledCount = 1
}

private class TestWebView(context: Context) : WebView(context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.duckduckgo.app.browser.autocomplete.BrowserAutoCompleteModule
import com.duckduckgo.app.browser.di.BrowserModule
import com.duckduckgo.app.browser.favicon.FaviconModule
import com.duckduckgo.app.browser.rating.di.RatingModule
import com.duckduckgo.app.global.exception.UncaughtExceptionModule
import com.duckduckgo.app.httpsupgrade.di.HttpsUpgraderModule
import com.duckduckgo.app.onboarding.di.OnboardingModule
import com.duckduckgo.app.surrogates.di.ResourceSurrogateModule
Expand Down Expand Up @@ -66,7 +67,8 @@ import javax.inject.Singleton
WidgetModule::class,
RatingModule::class,
AppUsageModule::class,
FileModule::class
FileModule::class,
UncaughtExceptionModule::class
]
)
interface TestAppComponent : AppComponent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ class AppDatabaseTest {
createDatabaseAndMigrate(13, 14, AppDatabase.MIGRATION_13_TO_14)
}

@Test
fun whenMigratingFromVersion14To15ThenValidationSucceeds() {
createDatabaseAndMigrate(14, 15, AppDatabase.MIGRATION_14_TO_15)
}


private fun createDatabase(version: Int) {
testHelper.createDatabase(TEST_DB_NAME, version).close()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2019 DuckDuckGo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.duckduckgo.app.global.exception

import org.junit.Assert.*
import org.junit.Before
import org.junit.Test

class RootExceptionFinderTest {

private lateinit var testee: RootExceptionFinder
private val actualRoot = IllegalArgumentException("0")

@Before
fun setup() {
testee = RootExceptionFinder()
}

@Test
fun whenExceptionIsNullThenNullIsReturned() {
val calculatedRoot = testee.findRootException(null)
assertNull(calculatedRoot)
}

@Test
fun whenExceptionHasNoAdditionalCausesItIsIdentifiedAsRoot() {
val calculatedRoot = testee.findRootException(actualRoot)
assertRootFound(calculatedRoot)
}

@Test
fun whenSingleCauseThenCorrectRootIsFound() {
val nestedException = buildNestedException(actualRoot, 1)
val calculatedRoot = testee.findRootException(nestedException)
assertRootFound(calculatedRoot)
}

@Test
fun whenManyCausesThenCorrectRootIsFound() {
val nestedException = buildNestedException(actualRoot, 15)
val calculatedRoot = testee.findRootException(nestedException)
assertRootFound(calculatedRoot)
}

@Test
fun whenNestedCausesAreTooDeepThenReturnsExceptionFoundAtThreshold() {
val nestedException = buildNestedException(actualRoot, 100)
val calculatedRoot = testee.findRootException(nestedException)
assertRootNotNull(calculatedRoot)
assertEquals("80", calculatedRoot?.message)
}

private fun assertRootFound(calculatedRoot: Throwable?) {
assertRootNotNull(calculatedRoot)
assertEquals("Wrong cause identified", calculatedRoot?.message, actualRoot.message)
}

private fun assertRootNotNull(calculatedRoot: Throwable?) {
assertNotNull("Root was null; not found correctly", calculatedRoot)
}

private fun buildNestedException(root: Throwable, depthRequired: Int): Throwable {
var nested = root
for (i in 0 until depthRequired) {
nested = IllegalArgumentException((i + 1).toString(), nested)
}
return nested
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright (c) 2019 DuckDuckGo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.duckduckgo.app.global.exception

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.room.Room
import androidx.test.platform.app.InstrumentationRegistry
import com.duckduckgo.app.CoroutineTestRule
import com.duckduckgo.app.global.db.AppDatabase
import com.duckduckgo.app.global.exception.UncaughtExceptionSource.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test

class UncaughtExceptionDaoTest {

@get:Rule
@Suppress("unused")
var instantTaskExecutorRule = InstantTaskExecutorRule()

@ExperimentalCoroutinesApi
@get:Rule
var coroutinesTestRule = CoroutineTestRule()

private lateinit var db: AppDatabase
private lateinit var dao: UncaughtExceptionDao

@Before
fun before() {
db = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getInstrumentation().targetContext, AppDatabase::class.java)
.allowMainThreadQueries()
.build()
dao = db.uncaughtExceptionDao()
}

@After
fun after() {
db.close()
}

@Test
fun whenInitialisedThereAre0ExceptionsRecorded() {
assertEquals(0, dao.count())
}

@Test
fun whenNewExceptionAddedThenCountIsIncreased() {
dao.add(anUncaughtExceptionEntity())
assertEquals(1, dao.count())
}

@Test
fun whenSeveralExceptionsAddedAndOneDeletedThenNotAllEntriesDeleted() {
dao.add(anUncaughtExceptionEntity(id = 1))
dao.add(anUncaughtExceptionEntity(id = 2))
dao.add(anUncaughtExceptionEntity(id = 3))
dao.delete(2)
assertEquals(2, dao.count())
}

@Test
fun whenSeveralExceptionExistAndOneDeletedThenCorrectEntryIsRemoved() {
val exception1 = UncaughtExceptionEntity(id = 1, exceptionSource = GLOBAL, message = "foo1")
val exception2 = UncaughtExceptionEntity(id = 2, exceptionSource = ON_PROGRESS_CHANGED, message = "foo2")
val exception3 = UncaughtExceptionEntity(id = 3, exceptionSource = ON_PAGE_STARTED, message = "foo3")
dao.add(exception1)
dao.add(exception2)
dao.add(exception3)

dao.delete(2)

val list = dao.all()
list.first().apply {
assertEquals(1, id)
assertEquals(exception1.exceptionSource, exceptionSource)
assertEquals(exception1.message, message)
}

list.last().apply {
assertEquals(3, id)
assertEquals(exception3.exceptionSource, exceptionSource)
assertEquals(exception3.message, message)
}
}

@Test
fun whenExceptionRetrievedFromDatabaseThenAllDetailsRestored() {
val exception = UncaughtExceptionEntity(id = 1, exceptionSource = GLOBAL, message = "foo")
dao.add(exception)
val list = dao.all()
assertEquals(1, list.size)
list.first().apply {
assertEquals(1, id)
assertEquals(exception.exceptionSource, exceptionSource)
assertEquals(exception.message, message)
}
}

private fun anUncaughtExceptionEntity(id: Long? = null) =
UncaughtExceptionEntity(id = id ?: 0, exceptionSource = GLOBAL, message = "foo")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019 DuckDuckGo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.duckduckgo.app.statistics.pixels

import org.junit.Assert.fail
import org.junit.Test

class PixelNameTest {

@Test
fun verifyNoDuplicatePixelNames() {
val existingNames = mutableSetOf<String>()
Pixel.PixelName.values().forEach {
if (!existingNames.add(it.pixelName)) {
fail("Duplicate pixel name found: ${it.pixelName}")
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ import org.junit.Test

class OfflinePixelSharedPreferencesTest {

private lateinit var testee: OfflinePixelSharedPreferences
private lateinit var testee: OfflinePixelCountSharedPreferences

private val context = InstrumentationRegistry.getInstrumentation().targetContext

@Before
fun setup() {
context.getSharedPreferences(OfflinePixelSharedPreferences.FILENAME, Context.MODE_PRIVATE).edit { clear() }
testee = OfflinePixelSharedPreferences(context)
context.getSharedPreferences(OfflinePixelCountSharedPreferences.FILENAME, Context.MODE_PRIVATE).edit { clear() }
testee = OfflinePixelCountSharedPreferences(context)
}

@Test
Expand Down
Loading

0 comments on commit a9ba7db

Please sign in to comment.