Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Glean metric unit tests #2444

Merged
merged 2 commits into from
Dec 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -460,21 +464,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 @@ -495,9 +496,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 {
daoshengmu marked this conversation as resolved.
Show resolved Hide resolved

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

@Test
fun testURLTelemetry() {
daoshengmu marked this conversation as resolved.
Show resolved Hide resolved
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() {
daoshengmu marked this conversation as resolved.
Show resolved Hide resolved
assertFalse(Distribution.channelName.testHasValue())
GleanMetricsService.testSetStartupMetrics()
assertTrue(Distribution.channelName.testHasValue())
assertEquals(Distribution.channelName.testGetValue(), BuildConfig.FLAVOR_platform)
}

@Test
fun testFxAAccountTelemetry() {
daoshengmu marked this conversation as resolved.
Show resolved Hide resolved
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() {
daoshengmu marked this conversation as resolved.
Show resolved Hide resolved
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() {
daoshengmu marked this conversation as resolved.
Show resolved Hide resolved
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() {
daoshengmu marked this conversation as resolved.
Show resolved Hide resolved
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() {
daoshengmu marked this conversation as resolved.
Show resolved Hide resolved
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