Skip to content

Commit 8a31ee9

Browse files
committed
Merge branch 'hotfix/5.52.6'
2 parents 3941ff3 + d8bedad commit 8a31ee9

File tree

9 files changed

+803
-7
lines changed

9 files changed

+803
-7
lines changed

app/schemas/com.duckduckgo.app.global.db.AppDatabase/19.json

Lines changed: 680 additions & 0 deletions
Large diffs are not rendered by default.

app/src/androidTest/java/com/duckduckgo/app/global/db/AppDatabaseTest.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
2626
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
2727
import com.duckduckgo.app.CoroutineTestRule
2828
import com.duckduckgo.app.blockingObserve
29+
import com.duckduckgo.app.global.exception.UncaughtExceptionEntity
30+
import com.duckduckgo.app.global.exception.UncaughtExceptionSource
2931
import com.duckduckgo.app.onboarding.store.AppStage
3032
import com.duckduckgo.app.runBlocking
3133
import com.nhaarman.mockitokotlin2.any
@@ -196,6 +198,13 @@ class AppDatabaseTest {
196198
assertEquals(AppStage.ESTABLISHED, database().userStageDao().currentUserAppStage()?.appStage)
197199
}
198200

201+
@Test
202+
fun whenMigratingFromVersion18To19ThenValidationSucceedsAndRowsDeletedFromTable() {
203+
database().uncaughtExceptionDao().add(UncaughtExceptionEntity(1, UncaughtExceptionSource.GLOBAL, "version", 1234))
204+
createDatabaseAndMigrate(18, 19, migrationsProvider.MIGRATION_18_TO_19)
205+
assertEquals(0, database().uncaughtExceptionDao().count())
206+
}
207+
199208
private fun createDatabase(version: Int) {
200209
testHelper.createDatabase(TEST_DB_NAME, version).close()
201210
}

app/src/androidTest/java/com/duckduckgo/app/global/exception/UncaughtExceptionDaoTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ class UncaughtExceptionDaoTest {
110110
assertEquals(1, id)
111111
assertEquals(exception.exceptionSource, exceptionSource)
112112
assertEquals(exception.message, message)
113+
assertEquals(exception.version, version)
114+
assertEquals(exception.timestamp, timestamp)
113115
}
114116
}
115117

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (c) 2020 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.app.statistics.api
18+
19+
import com.duckduckgo.app.CoroutineTestRule
20+
import com.duckduckgo.app.InstantSchedulersRule
21+
import com.duckduckgo.app.global.exception.UncaughtExceptionEntity
22+
import com.duckduckgo.app.global.exception.UncaughtExceptionRepository
23+
import com.duckduckgo.app.global.exception.UncaughtExceptionSource
24+
import com.duckduckgo.app.statistics.pixels.Pixel
25+
import com.duckduckgo.app.statistics.pixels.Pixel.PixelParameter.EXCEPTION_APP_VERSION
26+
import com.duckduckgo.app.statistics.pixels.Pixel.PixelParameter.EXCEPTION_MESSAGE
27+
import com.duckduckgo.app.statistics.pixels.Pixel.PixelParameter.EXCEPTION_TIMESTAMP
28+
import com.duckduckgo.app.statistics.store.OfflinePixelCountDataStore
29+
import com.nhaarman.mockitokotlin2.*
30+
import io.reactivex.Completable
31+
import kotlinx.coroutines.ExperimentalCoroutinesApi
32+
import kotlinx.coroutines.runBlocking
33+
import org.junit.Before
34+
import org.junit.Rule
35+
import org.junit.Test
36+
37+
@ExperimentalCoroutinesApi
38+
class OfflinePixelSenderTest {
39+
40+
private var mockOfflinePixelCountDataStore: OfflinePixelCountDataStore = mock()
41+
private var mockUncaughtExceptionRepository: UncaughtExceptionRepository = mock()
42+
private var mockPixel: Pixel = mock()
43+
44+
private var testee: OfflinePixelSender = OfflinePixelSender(mockOfflinePixelCountDataStore, mockUncaughtExceptionRepository, mockPixel)
45+
46+
@get:Rule
47+
val schedulers = InstantSchedulersRule()
48+
49+
@ExperimentalCoroutinesApi
50+
@get:Rule
51+
var coroutineRule = CoroutineTestRule()
52+
53+
@Before
54+
fun before() {
55+
val exceptionEntity = UncaughtExceptionEntity(1, UncaughtExceptionSource.GLOBAL, "test", 1588167165000, "version")
56+
57+
runBlocking<Unit> {
58+
whenever(mockPixel.fireCompletable(any(), any(), any())).thenReturn(Completable.complete())
59+
whenever(mockUncaughtExceptionRepository.getExceptions()).thenReturn(listOf(exceptionEntity))
60+
}
61+
}
62+
63+
@Test
64+
fun whenSendUncaughtExceptionsPixelThenTimestampFormattedToUtc() {
65+
val params = mapOf(
66+
EXCEPTION_MESSAGE to "test",
67+
EXCEPTION_APP_VERSION to "version",
68+
EXCEPTION_TIMESTAMP to "2020-04-29T13:32:45+0000"
69+
)
70+
71+
testee.sendOfflinePixels().blockingAwait()
72+
73+
verify(mockPixel).fireCompletable(Pixel.PixelName.APPLICATION_CRASH_GLOBAL.pixelName, params)
74+
}
75+
}

app/src/main/java/com/duckduckgo/app/global/db/AppDatabase.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ import com.duckduckgo.app.usage.search.SearchCountDao
5858
import com.duckduckgo.app.usage.search.SearchCountEntity
5959

6060
@Database(
61-
exportSchema = true, version = 18, entities = [
61+
exportSchema = true, version = 19, entities = [
6262
TdsTracker::class,
6363
TdsEntity::class,
6464
TdsDomainEntity::class,
@@ -269,6 +269,13 @@ class MigrationsProvider(val context: Context) {
269269
}
270270
}
271271

272+
val MIGRATION_18_TO_19: Migration = object : Migration(18, 19) {
273+
override fun migrate(database: SupportSQLiteDatabase) {
274+
database.execSQL("DROP TABLE `UncaughtExceptionEntity`")
275+
database.execSQL("CREATE TABLE IF NOT EXISTS `UncaughtExceptionEntity` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `exceptionSource` TEXT NOT NULL, `message` TEXT NOT NULL, `version` TEXT NOT NULL, `timestamp` INTEGER NOT NULL)")
276+
}
277+
}
278+
272279
val ALL_MIGRATIONS: List<Migration>
273280
get() = listOf(
274281
MIGRATION_1_TO_2,
@@ -287,7 +294,8 @@ class MigrationsProvider(val context: Context) {
287294
MIGRATION_14_TO_15,
288295
MIGRATION_15_TO_16,
289296
MIGRATION_16_TO_17,
290-
MIGRATION_17_TO_18
297+
MIGRATION_17_TO_18,
298+
MIGRATION_18_TO_19
291299
)
292300

293301
@Deprecated(

app/src/main/java/com/duckduckgo/app/global/exception/UncaughtExceptionEntity.kt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,24 @@ package com.duckduckgo.app.global.exception
1818

1919
import androidx.room.Entity
2020
import androidx.room.PrimaryKey
21+
import com.duckduckgo.app.browser.BuildConfig
22+
import java.text.SimpleDateFormat
23+
import java.util.*
2124

2225
@Entity
2326
data class UncaughtExceptionEntity(
2427
@PrimaryKey(autoGenerate = true) val id: Long = 0,
2528
val exceptionSource: UncaughtExceptionSource,
26-
val message: String
27-
)
29+
val message: String,
30+
val timestamp: Long = System.currentTimeMillis(),
31+
val version: String = BuildConfig.VERSION_NAME
32+
) {
33+
34+
fun formattedTimestamp(): String = formatter.format(Date(timestamp))
35+
36+
companion object {
37+
val formatter: SimpleDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US).apply {
38+
timeZone = TimeZone.getTimeZone("UTC")
39+
}
40+
}
41+
}

app/src/main/java/com/duckduckgo/app/statistics/api/OfflinePixelSender.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ import com.duckduckgo.app.global.exception.UncaughtExceptionSource.*
2222
import com.duckduckgo.app.statistics.pixels.Pixel
2323
import com.duckduckgo.app.statistics.pixels.Pixel.PixelName.*
2424
import com.duckduckgo.app.statistics.pixels.Pixel.PixelParameter.COUNT
25+
import com.duckduckgo.app.statistics.pixels.Pixel.PixelParameter.EXCEPTION_APP_VERSION
2526
import com.duckduckgo.app.statistics.pixels.Pixel.PixelParameter.EXCEPTION_MESSAGE
27+
import com.duckduckgo.app.statistics.pixels.Pixel.PixelParameter.EXCEPTION_TIMESTAMP
2628
import com.duckduckgo.app.statistics.store.OfflinePixelCountDataStore
2729
import io.reactivex.Completable
2830
import io.reactivex.Completable.*
@@ -103,11 +105,15 @@ class OfflinePixelSender @Inject constructor(
103105
exceptions.forEach { exception ->
104106
Timber.d("Analysing exception $exception")
105107
val pixelName = determinePixelName(exception)
106-
val params = mapOf(EXCEPTION_MESSAGE to exception.message)
108+
val params = mapOf(
109+
EXCEPTION_MESSAGE to exception.message,
110+
EXCEPTION_APP_VERSION to exception.version,
111+
EXCEPTION_TIMESTAMP to exception.formattedTimestamp()
112+
)
107113

108114
val pixel = pixel.fireCompletable(pixelName, params)
109115
.doOnComplete {
110-
Timber.d("Sent pixel containing exception; deleting exception with id=${exception.id}")
116+
Timber.d("Sent pixel with params: $params containing exception; deleting exception with id=${exception.id}")
111117
runBlocking { uncaughtExceptionRepository.deleteException(exception.id) }
112118
}
113119

app/src/main/java/com/duckduckgo/app/statistics/pixels/Pixel.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ interface Pixel {
178178
const val URL = "url"
179179
const val COUNT = "count"
180180
const val EXCEPTION_MESSAGE = "m"
181+
const val EXCEPTION_APP_VERSION = "v"
182+
const val EXCEPTION_TIMESTAMP = "t"
181183
const val BOOKMARK_CAPABLE = "bc"
182184
const val SHOWED_BOOKMARKS = "sb"
183185
const val DEFAULT_BROWSER_BEHAVIOUR_TRIGGERED = "bt"

app/version/version.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
VERSION=5.52.5
1+
VERSION=5.52.6

0 commit comments

Comments
 (0)