Commit 5ec752f2 authored by Alessio Placitelli's avatar Alessio Placitelli
Browse files

Test the 'baseline' ping in the glean-sample app

This adds an instrumented test that sends the app
to background, triggers a ping and then validates
the received data.
parent 87f5ad27
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -46,13 +46,14 @@ data class Configuration internal constructor(
    // constructor and only initialized with a proper default when calling the primary
    // constructor from the secondary, public one, below.
    constructor(
        serverEndpoint: String = DEFAULT_TELEMETRY_ENDPOINT,
        connectionTimeout: Long = DEFAULT_CONNECTION_TIMEOUT,
        readTimeout: Long = DEFAULT_READ_TIMEOUT,
        maxEvents: Int = DEFAULT_MAX_EVENTS,
        httpClient: Lazy<Client> = lazy { HttpURLConnectionClient() },
        channel: String? = null
    ) : this (
        serverEndpoint = DEFAULT_TELEMETRY_ENDPOINT,
        serverEndpoint = serverEndpoint,
        userAgent = DEFAULT_USER_AGENT,
        connectionTimeout = connectionTimeout,
        readTimeout = readTimeout,
+6 −2
Original line number Diff line number Diff line
@@ -25,10 +25,14 @@ import org.junit.runner.Description
 * @get:Rule
 * val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext())
 * ```
 *
 * @param context the application context
 * @param configToUse an optional [Configuration] to initialize the Glean SDK with
 */
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
class GleanTestRule(
    val context: Context
    val context: Context,
    val configToUse: Configuration = Configuration()
) : TestWatcher() {
    override fun starting(description: Description?) {
        // We're using the WorkManager in a bunch of places, and Glean will crash
@@ -37,7 +41,7 @@ class GleanTestRule(

        Glean.resetGlean(
            context = context,
            config = Configuration(),
            config = configToUse,
            clearStores = true
        )
    }
+3 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ android {
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        testInstrumentationRunner "org.mozilla.samples.glean.GleanTestRunner"
    }

    buildTypes {
@@ -51,8 +51,10 @@ dependencies {
    androidTestImplementation Dependencies.androidx_test_runner
    androidTestImplementation Dependencies.androidx_test_rules
    androidTestImplementation Dependencies.androidx_test_junit
    androidTestImplementation Dependencies.androidx_test_uiautomator
    androidTestImplementation Dependencies.androidx_espresso_core
    androidTestImplementation Dependencies.androidx_work_testing
    androidTestImplementation Dependencies.testing_mockwebserver
}

apply from: '../../components/service/glean/scripts/sdk_generator.gradle'
+89 −0
Original line number Diff line number Diff line
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.samples.glean

import androidx.annotation.VisibleForTesting
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnitRunner
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import okhttp3.mockwebserver.RecordedRequest

/**
 * Create a mock webserver that accepts all requests and replies with "OK".
 * @return a [MockWebServer] instance
 */
private fun createMockWebServer(): MockWebServer {
    val server = MockWebServer()
    server.setDispatcher(object : Dispatcher() {
        override fun dispatch(request: RecordedRequest): MockResponse {
            return MockResponse().setBody("OK")
        }
    })
    return server
}

/**
 * Returns the currently active instance of the ping server.
 *
 * @return the active [MockWebServer] instance
 */
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
internal fun getPingServer(): MockWebServer {
    val testRunner: GleanTestRunner = InstrumentationRegistry.getInstrumentation() as GleanTestRunner
    return testRunner.pingServer
}

/**
 * Returns the address the local ping server is listening to.
 *
 * @return a `String` containing the server address.
 */
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
internal fun getPingServerAddress(): String {
    val testRunner: GleanTestRunner = InstrumentationRegistry.getInstrumentation() as GleanTestRunner
    return testRunner.pingServerAddress!!
}

/**
 * The test runner to be used in the instrumentation tests for the Glean SDK
 * sample app in order to point it to a local ping server.
 */
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
class GleanTestRunner : AndroidJUnitRunner() {
    // Add a lazy ping server to the app runner. This is only initialized once
    // since the `Application` object is re-used.
    internal val pingServer: MockWebServer by lazy { createMockWebServer() }
    internal var pingServerAddress: String? = null

    init {
        // We need to start the server off the main thread, otherwise
        // Android will throw a `NetworkOnMainThreadException`. Spawning
        // a thread and joining seems fine.
        val thread = Thread {
            pingServer.start()
            pingServerAddress = "http://${pingServer.hostName}:${pingServer.port}"
        }
        thread.start()
        thread.join()
    }

    /**
     * Called before the application code runs, this starts the ping server.
     */
    override fun onStart() {
        super.onStart()
        pingServer.start()
    }

    /**
     * Called after the application code cleans up, this stops the ping server.
     */
    override fun onDestroy() {
        super.onDestroy()
        pingServer.shutdown()
    }
}
+5 −1
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule
import mozilla.components.service.glean.config.Configuration
import mozilla.components.service.glean.testing.GleanTestRule
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
@@ -25,7 +26,10 @@ class MainActivityTest {
    val activityRule: ActivityTestRule<MainActivity> = ActivityTestRule(MainActivity::class.java)

    @get:Rule
    val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext())
    val gleanRule = GleanTestRule(
        ApplicationProvider.getApplicationContext(),
        Configuration(serverEndpoint = getPingServerAddress())
    )

    @Test
    fun checkGleanClickData() {
Loading