Skip to content

Commit

Permalink
Support Glean metric unit tests (MozillaReality#2444)
Browse files Browse the repository at this point in the history
* Support Glean unit test.

* Run Glean unit test in Taskcluster.
  • Loading branch information
daoshengmu authored and Alexandre Lissy committed Jan 21, 2020
1 parent c2dfbc9 commit b67ddbb
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 9 deletions.
1 change: 1 addition & 0 deletions .taskcluster.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ tasks:
&& rm -rf gvr-android-sdk && git clone https://github.com/MozillaReality/FirefoxReality-gvr-android-sdk.git gvr-android-sdk
&& git submodule update
&& ./gradlew --no-daemon --console=plain clean `python tools/taskcluster/build_targets.py =all+googlevr+noapi`
&& ./gradlew app:testNoapiArm64DebugUnitTest
metadata:
name: Firefox Reality for Android - Build - Pull Request
description: Building Firefox Reality for Android (via Gradle) - triggered by a pull request.
Expand Down
18 changes: 13 additions & 5 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,10 @@ android {
]
}
}

testOptions {
unitTests.includeAndroidResources = true
}
}

configurations {
Expand Down Expand Up @@ -461,21 +465,18 @@ dependencies {
implementation deps.android_components.support_rustlog
implementation deps.android_components.support_rusthttp
implementation deps.android_components.glean
implementation deps.app_services.rustlog

// For production builds, the native code for all `org.mozilla.appservices`
// dependencies gets compiled together into a single "megazord" build, and
// different megazords are published for different subsets of features. Ref
// https://mozilla.github.io/application-services/docs/applications/consuming-megazord-libraries.html
// For now we can jut use the one that's specifically designed for Fenix.
implementation deps.app_services.megazord
testImplementation deps.app_services.megazord_forUnitTests
modules {
module('org.mozilla.appservices:full-megazord') {
replacedBy('org.mozilla.appservices:fenix-megazord', 'prefer the fenix megazord, to reduce final application size')
}
module('org.mozilla.appservices:fenix-megazord') {
replacedBy('org.mozilla.appservices:fenix-megazord-forUnitTests', 'prefer the forUnitTests variant if present')
}
}

// TODO this should not be necessary at all, see Services.kt
Expand All @@ -496,9 +497,16 @@ dependencies {
implementation deps.disklrucache.disklrucache

// Testing
testImplementation deps.junit
androidTestImplementation deps.atsl.runner
androidTestImplementation deps.espresso.core
testImplementation deps.junit
testImplementation deps.atsl.core
testImplementation deps.robolectric
testImplementation deps.app_services.megazord_forUnitTests
testImplementation deps.app_services.rustlog
testImplementation deps.android_components.support_test
testImplementation deps.telemetry.glean_unittests
testImplementation deps.work.testing

// Daydream
googlevrImplementation deps.google_vr.sdk_base
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,12 @@ class Accounts constructor(val context: Context) {

private fun loadDefaultProfilePicture(): BitmapDrawable? {
BitmapFactory.decodeResource(context.resources, R.drawable.ic_icon_settings_account)?.let {
BitmapCache.getInstance(context).addBitmap(PROFILE_PICTURE_TAG, it)
try {
BitmapCache.getInstance(context).addBitmap(PROFILE_PICTURE_TAG, it)
} catch (e: NullPointerException) {
Log.w(LOGTAG, "Bitmap is a null pointer.")
return null
}
profilePicture = BitmapDrawable(context.resources, ViewUtils.getRoundedCroppedBitmap(it))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import mozilla.appservices.Megazord
import mozilla.appservices.rustlog.LogAdapterCannotEnable
import mozilla.components.concept.sync.*
import mozilla.components.service.fxa.*
import mozilla.components.service.fxa.manager.FxaAccountManager
Expand All @@ -29,8 +30,6 @@ import org.mozilla.geckoview.GeckoResult
import org.mozilla.geckoview.GeckoSession
import org.mozilla.vrbrowser.R
import org.mozilla.vrbrowser.browser.engine.EngineProvider
import org.mozilla.vrbrowser.browser.engine.GeckoViewFetchClient
import org.mozilla.vrbrowser.browser.engine.SessionStore
import org.mozilla.vrbrowser.utils.SystemUtils
import org.mozilla.vrbrowser.telemetry.GleanMetricsService

Expand All @@ -52,7 +51,11 @@ class Services(val context: Context, places: Places): GeckoSession.NavigationDel
// This makes bookmarks storage accessible to background sync workers.
init {
Megazord.init()
RustLog.enable()
try {
RustLog.enable()
} catch (e: LogAdapterCannotEnable) {
android.util.Log.w(LOGTAG, "RustLog has been enabled.")
}
RustHttpConfig.setClient(lazy { EngineProvider.createClient(context) })

// Make sure we get logs out of our android-components.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
import androidx.annotation.VisibleForTesting;

import org.mozilla.vrbrowser.BuildConfig;
import org.mozilla.vrbrowser.GleanMetrics.Distribution;
Expand Down Expand Up @@ -159,6 +160,11 @@ private static void setStartupMetrics() {
Distribution.INSTANCE.getChannelName().set(DeviceType.isOculusBuild() ? "oculusvr" : BuildConfig.FLAVOR_platform);
}

@VisibleForTesting
public static void testSetStartupMetrics() {
setStartupMetrics();
}

public static class FxA {

public static void signIn() {
Expand Down
135 changes: 135 additions & 0 deletions app/src/test/java/org/mozilla/vrbrowser/GleanMetricsServiceTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package org.mozilla.vrbrowser

import androidx.test.core.app.ApplicationProvider
import mozilla.components.concept.sync.DeviceType
import mozilla.components.service.glean.testing.GleanTestRule
import org.junit.Assert.*
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.vrbrowser.GleanMetrics.*
import org.mozilla.vrbrowser.telemetry.GleanMetricsService
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config


@RunWith(RobolectricTestRunner::class)
@Config(manifest = Config.NONE)
class GleanMetricsServiceTest {

@get:Rule
val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext())

@Test
fun testURLTelemetry() {
assertFalse(Url.domains.testHasValue())
assertFalse(Url.visits.testHasValue())
GleanMetricsService.stopPageLoadTimeWithURI("https://www.example.com/test.html");
assertTrue(Url.domains.testHasValue())
assertEquals(Url.domains.testGetValue(), 1)

assertTrue(Url.visits.testHasValue())
assertEquals(Url.visits.testGetValue(), 1)

assertFalse(Url.queryType["type_link"].testHasValue())
assertFalse(Url.queryType["type_query"].testHasValue())
GleanMetricsService.urlBarEvent(true)
assertTrue(Url.queryType["type_link"].testHasValue())
assertEquals(Url.queryType["type_link"].testGetValue(), 1)
GleanMetricsService.urlBarEvent(false)
assertTrue(Url.queryType["type_query"].testHasValue())
assertEquals(Url.queryType["type_query"].testGetValue(), 1)

assertFalse(Url.queryType["voice_query"].testHasValue())
GleanMetricsService.voiceInputEvent()
assertTrue(Url.queryType["voice_query"].testHasValue())
assertEquals(Url.queryType["voice_query"].testGetValue(), 1)
}

@Test
fun testDistributionChannelTelemetry() {
assertFalse(Distribution.channelName.testHasValue())
GleanMetricsService.testSetStartupMetrics()
assertTrue(Distribution.channelName.testHasValue())
assertEquals(Distribution.channelName.testGetValue(), BuildConfig.FLAVOR_platform)
}

@Test
fun testFxAAccountTelemetry() {
assertFalse(FirefoxAccount.signIn.testHasValue())
GleanMetricsService.FxA.signIn()
assertTrue(FirefoxAccount.signIn.testHasValue())
var events = FirefoxAccount.signIn.testGetValue()
assertEquals(events.size, 1)

assertFalse(FirefoxAccount.signInResult.testHasValue())
GleanMetricsService.FxA.signInResult(false)
assertTrue(FirefoxAccount.signInResult.testHasValue())
events = FirefoxAccount.signInResult.testGetValue()
assertEquals(events.size, 1)
// We only expect 1 extra key.
assertEquals(events[0].extra!!.size, 1)
assertEquals(events[0].extra!!["state"], "false")

GleanMetricsService.FxA.signInResult(true)
events = FirefoxAccount.signInResult.testGetValue()
assertEquals(events.size, 2)
// We only expect 1 extra key.
assertEquals(events[1].extra!!.size, 1)
assertEquals(events[1].extra!!["state"], "true")

assertFalse(FirefoxAccount.signOut.testHasValue())
GleanMetricsService.FxA.signOut()
assertTrue(FirefoxAccount.signOut.testHasValue())
events = FirefoxAccount.signOut.testGetValue()
assertEquals(events.size, 1)
}

@Test
fun testFxABookmarkTelemetry() {
assertFalse(FirefoxAccount.bookmarksSyncStatus.testHasValue())
GleanMetricsService.FxA.bookmarksSyncStatus(false)
assertTrue(FirefoxAccount.bookmarksSyncStatus.testHasValue())
assertEquals(FirefoxAccount.bookmarksSyncStatus.testGetValue(), false)

GleanMetricsService.FxA.bookmarksSyncStatus(true)
assertEquals(FirefoxAccount.bookmarksSyncStatus.testGetValue(), true)
}

@Test
fun testFxAHistoryTelemetry() {
assertFalse(FirefoxAccount.historySyncStatus.testHasValue())
GleanMetricsService.FxA.historySyncStatus(false)
assertTrue(FirefoxAccount.historySyncStatus.testHasValue())
assertEquals(FirefoxAccount.historySyncStatus.testGetValue(), false)

GleanMetricsService.FxA.historySyncStatus(true)
assertEquals(FirefoxAccount.historySyncStatus.testGetValue(), true)
}

@Test
fun testFxATabTelemetry() {
assertFalse(FirefoxAccount.tabSent.testHasValue())
GleanMetricsService.FxA.sentTab()
assertTrue(FirefoxAccount.tabSent.testHasValue())
assertEquals(FirefoxAccount.tabSent.testGetValue(), 1)

assertFalse(FirefoxAccount.receivedTab[DeviceType.MOBILE.name].testHasValue())
GleanMetricsService.FxA.receivedTab(DeviceType.MOBILE)
assertTrue(FirefoxAccount.receivedTab[DeviceType.MOBILE.name].testHasValue())
assertEquals(FirefoxAccount.receivedTab[DeviceType.MOBILE.name].testGetValue(), 1)
}

@Test
fun testTabTelemetry() {
assertFalse(Tabs.opened[GleanMetricsService.Tabs.TabSource.BOOKMARKS.name].testHasValue())
GleanMetricsService.Tabs.openedCounter(GleanMetricsService.Tabs.TabSource.BOOKMARKS)
assertTrue(Tabs.opened[GleanMetricsService.Tabs.TabSource.BOOKMARKS.name].testHasValue())
assertEquals(Tabs.opened[GleanMetricsService.Tabs.TabSource.BOOKMARKS.name].testGetValue(), 1)

assertFalse(Tabs.activated.testHasValue())
GleanMetricsService.Tabs.activatedEvent()
assertTrue(Tabs.activated.testHasValue())
assertEquals(Tabs.activated.testGetValue(), 1)
}
}
15 changes: 15 additions & 0 deletions versions.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ versions.support = "1.0.0"
versions.recyclerview = "1.1.0"
versions.constraint_layout = "2.0.0-alpha2"
versions.junit = "4.12"
versions.atsl_core = "1.2.0"
versions.atsl_runner = "1.1.0-alpha4"
versions.atsl_rules = "1.1.0-alpha4"
versions.espresso = "3.1.0-alpha4"
Expand All @@ -50,7 +51,11 @@ versions.kotlin = "1.3.31"
versions.kotlin_coroutines = "1.2.1"
versions.snakeyaml = "1.24"
versions.gson = "2.8.5"
versions.robolectric = "4.2.1"
versions.work = "2.2.0"
versions.telemetry = "22.0.0"
ext.versions = versions

def deps = [:]

def gecko_view = [:]
Expand All @@ -72,11 +77,13 @@ android_components.concept_fetch = "org.mozilla.components:concept-fetch:$versio
android_components.lib_fetch = "org.mozilla.components:lib-fetch-httpurlconnection:$versions.android_components"
android_components.support_rustlog = "org.mozilla.components:support-rustlog:$versions.android_components"
android_components.support_rusthttp = "org.mozilla.components:support-rusthttp:$versions.android_components"
android_components.support_test = "org.mozilla.components:support-test:$versions.android_components"
deps.android_components = android_components

def app_services = [:]
app_services.megazord = "org.mozilla.appservices:fenix-megazord:${versions.mozilla_appservices}"
app_services.megazord_forUnitTests = "org.mozilla.appservices:fenix-megazord-forUnitTests:${versions.mozilla_appservices}"
app_services.rustlog = "org.mozilla.appservices:rustlog:${versions.mozilla_appservices}"
deps.app_services = app_services

deps.mozilla_speech = "com.github.mozilla:mozillaspeechlibrary:$versions.mozilla_speech"
Expand All @@ -102,6 +109,7 @@ deps.support = support
// TODO this should not be necessary at all, see Services.kt
def work = [:]
work.runtime = "androidx.work:work-runtime-ktx:$versions.work"
work.testing = "androidx.work:work-testing:$versions.work"
deps.work = work

def room = [:]
Expand All @@ -124,6 +132,7 @@ espresso.intents = "androidx.test.espresso:espresso-intents:$versions.espresso"
deps.espresso = espresso

def atsl = [:]
atsl.core = "androidx.test:core-ktx:$versions.atsl_core"
atsl.runner = "androidx.test:runner:$versions.atsl_runner"
atsl.rules = "androidx.test:rules:$versions.atsl_runner"
deps.atsl = atsl
Expand All @@ -145,6 +154,10 @@ kotlin.coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core:$versions.kot
kotlin.coroutines_jdk8 = "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$versions.kotlin_coroutines"
deps.kotlin = kotlin

def telemetry = [:]
telemetry.glean_unittests = "org.mozilla.telemetry:glean-forUnitTests:$versions.telemetry"
deps.telemetry = telemetry

deps.constraint_layout = "androidx.constraintlayout:constraintlayout:$versions.constraint_layout"

deps.junit = "junit:junit:$versions.junit"
Expand All @@ -157,6 +170,8 @@ deps.snakeyaml = "org.yaml:snakeyaml:$versions.snakeyaml:android"

deps.gson = "com.google.code.gson:gson:$versions.gson"

deps.robolectric = "org.robolectric:robolectric:$versions.robolectric"

ext.deps = deps

def build_versions = [:]
Expand Down

0 comments on commit b67ddbb

Please sign in to comment.