зеркало из https://github.com/mozilla/glean.git
Import test coverage from Glean-legacy for Counters and Strings
This commit is contained in:
Родитель
139fdd72ef
Коммит
202ee528a2
|
@ -10,8 +10,17 @@ apply plugin: 'com.android.library'
|
|||
apply plugin: 'org.mozilla.rust-android-gradle.rust-android'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
|
||||
/*
|
||||
* This defines the location of the JSON schema used to validate the pings
|
||||
* created during unit testing.
|
||||
* This uses a specific version of the schema identified by a git commit hash.
|
||||
*/
|
||||
String GLEAN_PING_SCHEMA_GIT_HASH = "64b852c"
|
||||
String GLEAN_PING_SCHEMA_URL = "https://raw.githubusercontent.com/mozilla-services/mozilla-pipeline-schemas/$GLEAN_PING_SCHEMA_GIT_HASH/schemas/glean/baseline/baseline.1.schema.json"
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
|
||||
|
@ -19,6 +28,8 @@ android {
|
|||
minSdkVersion rootProject.ext.build['minSdkVersion']
|
||||
targetSdkVersion rootProject.ext.build['targetSdkVersion']
|
||||
|
||||
buildConfigField("String", "GLEAN_PING_SCHEMA_URL", "\"" + GLEAN_PING_SCHEMA_URL + "\"")
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
|
@ -151,8 +162,8 @@ dependencies {
|
|||
// avoiding other configurations from being resolved. Tricky!
|
||||
testImplementation files(configurations.jnaForTest.copyRecursive().files)
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation 'org.robolectric:robolectric:4.1'
|
||||
testImplementation 'org.mockito:mockito-core:2.21.0'
|
||||
testImplementation 'org.robolectric:robolectric:4.2.1'
|
||||
testImplementation 'org.mockito:mockito-core:2.24.5'
|
||||
testImplementation 'androidx.test:core-ktx:1.1.0'
|
||||
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
|
|
|
@ -111,6 +111,20 @@ open class GleanInternalAPI internal constructor () {
|
|||
private fun sendPing(pingName: String) {
|
||||
LibGleanFFI.INSTANCE.glean_send_ping(handle, pingName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Test-only method to destroy the owned glean-core handle.
|
||||
*/
|
||||
internal fun testDestroyGleanHandle() {
|
||||
if (!isInitialized()) {
|
||||
// We don't need to destroy the Glean handle: it wasn't initialized.
|
||||
return
|
||||
}
|
||||
|
||||
val e = RustError.ByReference()
|
||||
LibGleanFFI.INSTANCE.glean_destroy_glean(handle, e)
|
||||
handle = 0L
|
||||
}
|
||||
}
|
||||
|
||||
object Glean : GleanInternalAPI()
|
||||
|
|
|
@ -102,6 +102,9 @@ class CounterMetricType(
|
|||
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
|
||||
fun testGetValue(pingName: String = sendInPings.first()): Int {
|
||||
// FIXME(#19): glean-core should give us an int to begin with
|
||||
if (!testHasValue(pingName)) {
|
||||
throw NullPointerException()
|
||||
}
|
||||
return LibGleanFFI.INSTANCE.glean_counter_test_get_value(Glean.handle, this.handle, pingName).toInt()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,246 @@
|
|||
/* 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 mozilla.telemetry.glean
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
/*import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.testing.WorkManagerTestInitHelper
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import mozilla.components.concept.fetch.Client
|
||||
import mozilla.components.concept.fetch.Headers
|
||||
import mozilla.components.concept.fetch.MutableHeaders
|
||||
import mozilla.components.concept.fetch.Request
|
||||
import mozilla.components.concept.fetch.Response
|
||||
import mozilla.components.service.glean.config.Configuration
|
||||
import mozilla.components.service.glean.firstrun.FileFirstRunDetector
|
||||
import mozilla.components.service.glean.ping.PingMaker
|
||||
import mozilla.components.service.glean.private.PingType
|
||||
import mozilla.components.service.glean.scheduler.PingUploadWorker
|
||||
import mozilla.components.service.glean.storages.ExperimentsStorageEngine
|
||||
import mozilla.components.service.glean.storages.StorageEngineManager*/
|
||||
import org.json.JSONObject
|
||||
import org.junit.Assert
|
||||
import org.mockito.ArgumentMatchers
|
||||
import org.mockito.Mockito
|
||||
import org.mozilla.glean_rs.BuildConfig
|
||||
import java.io.File
|
||||
import java.util.concurrent.ExecutionException
|
||||
|
||||
/**
|
||||
* Checks ping content against the Glean ping schema.
|
||||
*
|
||||
* This uses the Python utility, glean_parser, to perform the actual checking.
|
||||
* This is installed in its own Miniconda environment as part of the build
|
||||
* configuration in sdk_generator.gradle.
|
||||
*
|
||||
* @param content The JSON content of the ping
|
||||
* @throws AssertionError If the JSON content is not valid
|
||||
*/
|
||||
internal fun checkPingSchema(content: JSONObject) {
|
||||
val os = System.getProperty("os.name")?.toLowerCase()
|
||||
val pythonExecutable =
|
||||
if (os?.indexOf("win")?.compareTo(0) == 0)
|
||||
"${BuildConfig.GLEAN_MINICONDA_DIR}/python"
|
||||
else
|
||||
"${BuildConfig.GLEAN_MINICONDA_DIR}/bin/python"
|
||||
|
||||
val proc = ProcessBuilder(
|
||||
listOf(
|
||||
pythonExecutable,
|
||||
"-m",
|
||||
"glean_parser",
|
||||
"check",
|
||||
"-s",
|
||||
"${BuildConfig.GLEAN_PING_SCHEMA_URL}"
|
||||
)
|
||||
).redirectOutput(ProcessBuilder.Redirect.INHERIT)
|
||||
.redirectError(ProcessBuilder.Redirect.INHERIT)
|
||||
val process = proc.start()
|
||||
|
||||
val jsonString = content.toString()
|
||||
with(process.outputStream.bufferedWriter()) {
|
||||
write(jsonString)
|
||||
newLine()
|
||||
flush()
|
||||
close()
|
||||
}
|
||||
|
||||
val exitCode = process.waitFor()
|
||||
assert(exitCode == 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks ping content against the Glean ping schema.
|
||||
*
|
||||
* This uses the Python utility, glean_parser, to perform the actual checking.
|
||||
* This is installed in its own Miniconda environment as part of the build
|
||||
* configuration in sdk_generator.gradle.
|
||||
*
|
||||
* @param content The JSON content of the ping
|
||||
* @return the content string, parsed into a JSONObject
|
||||
* @throws AssertionError If the JSON content is not valid
|
||||
*/
|
||||
internal fun checkPingSchema(content: String): JSONObject {
|
||||
val jsonContent = JSONObject(content)
|
||||
checkPingSchema(jsonContent)
|
||||
return jsonContent
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects a specified ping type and checks it against the Glean ping schema.
|
||||
*
|
||||
* @param ping The ping to check
|
||||
* @return the ping contents, in a JSONObject
|
||||
* @throws AssertionError If the JSON content is not valid
|
||||
*/
|
||||
/*internal fun collectAndCheckPingSchema(ping: PingType): JSONObject {
|
||||
val appContext = ApplicationProvider.getApplicationContext<Context>()
|
||||
val jsonString = PingMaker(
|
||||
StorageEngineManager(applicationContext = appContext),
|
||||
appContext
|
||||
).collect(ping)!!
|
||||
return checkPingSchema(jsonString)
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Resets the Glean state and trigger init again.
|
||||
*
|
||||
* @param context the application context to init Glean with
|
||||
* @param config the [Configuration] to init Glean with
|
||||
* @param clearStores if true, clear the contents of all stores
|
||||
*/
|
||||
internal fun resetGlean(
|
||||
context: Context = ApplicationProvider.getApplicationContext(),
|
||||
//config: Configuration = Configuration(),
|
||||
clearStores: Boolean = true
|
||||
) {
|
||||
//Glean.enableTestingMode()
|
||||
|
||||
// We're using the WorkManager in a bunch of places, and Glean will crash
|
||||
// in tests without this line. Let's simply put it here.
|
||||
//WorkManagerTestInitHelper.initializeTestWorkManager(context)
|
||||
|
||||
/*if (clearStores) {
|
||||
// Clear all the stored data.
|
||||
val storageManager = StorageEngineManager(applicationContext = context)
|
||||
storageManager.clearAllStores()
|
||||
// The experiments storage engine needs to be cleared manually as it's not listed
|
||||
// in the `StorageEngineManager`.
|
||||
ExperimentsStorageEngine.clearAllStores()
|
||||
}*/
|
||||
|
||||
// Clear the "first run" flag.
|
||||
//val firstRun = FileFirstRunDetector(File(context.applicationInfo.dataDir, Glean.GLEAN_DATA_DIR))
|
||||
//firstRun.reset()
|
||||
// Init Glean.
|
||||
//Glean.setUploadEnabled(true)
|
||||
Glean.testDestroyGleanHandle()
|
||||
Glean.initialize(context)//, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a context that contains [PackageInfo.versionName] mocked to
|
||||
* "glean.version.name".
|
||||
*
|
||||
* @return an application [Context] that can be used to init Glean
|
||||
*/
|
||||
internal fun getContextWithMockedInfo(): Context {
|
||||
val context = Mockito.spy<Context>(ApplicationProvider.getApplicationContext<Context>())
|
||||
val packageInfo = Mockito.mock(PackageInfo::class.java)
|
||||
packageInfo.versionName = "glean.version.name"
|
||||
val packageManager = Mockito.mock(PackageManager::class.java)
|
||||
Mockito.`when`(packageManager.getPackageInfo(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenReturn(packageInfo)
|
||||
Mockito.`when`(context.packageManager).thenReturn(packageManager)
|
||||
return context
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to check to see if a worker has been scheduled with the [WorkManager]
|
||||
*
|
||||
* @param tag a string representing the worker tag
|
||||
* @return True if the task found in [WorkManager], false otherwise
|
||||
*/
|
||||
/*internal fun isWorkScheduled(tag: String): Boolean {
|
||||
val instance = WorkManager.getInstance()
|
||||
val statuses = instance.getWorkInfosByTag(tag)
|
||||
try {
|
||||
val workInfoList = statuses.get()
|
||||
for (workInfo in workInfoList) {
|
||||
val state = workInfo.state
|
||||
if ((state === WorkInfo.State.RUNNING) || (state === WorkInfo.State.ENQUEUED)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
} catch (e: ExecutionException) {
|
||||
// Do nothing but will return false
|
||||
} catch (e: InterruptedException) {
|
||||
// Do nothing but will return false
|
||||
}
|
||||
|
||||
return false
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Wait for a specifically tagged [WorkManager]'s Worker to be enqueued.
|
||||
*
|
||||
* @param workTag the tag of the expected Worker
|
||||
* @param timeoutMillis how log before stopping the wait. This defaults to 5000ms (5 seconds).
|
||||
*/
|
||||
/*internal fun waitForEnqueuedWorker(workTag: String, timeoutMillis: Long = 5000) = runBlocking {
|
||||
runBlocking {
|
||||
withTimeout(timeoutMillis) {
|
||||
do {
|
||||
if (isWorkScheduled(workTag)) {
|
||||
return@withTimeout
|
||||
}
|
||||
} while (true)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Helper function to simulate WorkManager being triggered since there appears to be a bug in
|
||||
* the current WorkManager test utilites that prevent it from being triggered by a test. Once this
|
||||
* is fixed, the contents of this can be amended to trigger WorkManager directly.
|
||||
*/
|
||||
/*internal fun triggerWorkManager() {
|
||||
// Check that the work is scheduled
|
||||
Assert.assertTrue("A scheduled PingUploadWorker must exist",
|
||||
isWorkScheduled(PingUploadWorker.PING_WORKER_TAG))
|
||||
|
||||
// Since WorkManager does not properly run in tests, simulate the work being done
|
||||
// We also assertTrue here to ensure that uploadPings() was successful
|
||||
Assert.assertTrue("Upload Pings must return true", PingUploadWorker.uploadPings())
|
||||
}*/
|
||||
|
||||
/**
|
||||
* This is a helper class to facilitate testing of ping tagging
|
||||
*/
|
||||
/*internal class TestPingTagClient(
|
||||
private val responseUrl: String = Configuration.DEFAULT_DEBUGVIEW_ENDPOINT,
|
||||
private val responseStatus: Int = 200,
|
||||
private val responseHeaders: Headers = MutableHeaders(),
|
||||
private val responseBody: Response.Body = Response.Body.empty(),
|
||||
private val debugHeaderValue: String? = null
|
||||
) : Client() {
|
||||
override fun fetch(request: Request): Response {
|
||||
Assert.assertTrue("URL must be redirected for tagged pings",
|
||||
request.url.startsWith(responseUrl))
|
||||
Assert.assertEquals("Debug headers must match what the ping tag was set to",
|
||||
debugHeaderValue, request.headers!!["X-Debug-ID"])
|
||||
|
||||
// Have to return a response here.
|
||||
return Response(
|
||||
responseUrl,
|
||||
responseStatus,
|
||||
request.headers ?: responseHeaders,
|
||||
responseBody)
|
||||
}
|
||||
}*/
|
|
@ -0,0 +1,136 @@
|
|||
/* 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 mozilla.telemetry.glean.private
|
||||
|
||||
//import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
//import kotlinx.coroutines.ObsoleteCoroutinesApi
|
||||
//import mozilla.components.service.glean.resetGlean
|
||||
import mozilla.telemetry.glean.resetGlean
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import java.lang.NullPointerException
|
||||
|
||||
//@ObsoleteCoroutinesApi
|
||||
//@ExperimentalCoroutinesApi
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class CounterMetricTypeTest {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
resetGlean()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `The API saves to its storage engine`() {
|
||||
// Define a 'counterMetric' counter metric, which will be stored in "store1"
|
||||
val counterMetric = CounterMetricType(
|
||||
disabled = false,
|
||||
category = "telemetry",
|
||||
lifetime = Lifetime.Application,
|
||||
name = "counter_metric",
|
||||
sendInPings = listOf("store1")
|
||||
)
|
||||
|
||||
assertFalse(counterMetric.testHasValue())
|
||||
|
||||
// Add to the counter a couple of times with a little delay. The first call will check
|
||||
// calling add() without parameters to test increment by 1.
|
||||
counterMetric.add()
|
||||
|
||||
// Check that the count was incremented and properly recorded.
|
||||
assertTrue(counterMetric.testHasValue())
|
||||
assertEquals(1, counterMetric.testGetValue())
|
||||
|
||||
counterMetric.add(10)
|
||||
// Check that count was incremented and properly recorded. This second call will check
|
||||
// calling add() with 10 to test increment by other amount
|
||||
assertTrue(counterMetric.testHasValue())
|
||||
assertEquals(11, counterMetric.testGetValue())
|
||||
}
|
||||
|
||||
@Ignore("Ignoring the test as 'disabled' is not passed through FFI")
|
||||
@Test
|
||||
fun `counters with no lifetime must not record data`() {
|
||||
// Define a 'counterMetric' counter metric, which will be stored in "store1".
|
||||
// It's disabled so it should not record anything.
|
||||
val counterMetric = CounterMetricType(
|
||||
disabled = true,
|
||||
category = "telemetry",
|
||||
lifetime = Lifetime.Ping,
|
||||
name = "counter_metric",
|
||||
sendInPings = listOf("store1")
|
||||
)
|
||||
|
||||
// Attempt to increment the counter
|
||||
counterMetric.add(1)
|
||||
// Check that nothing was recorded.
|
||||
assertFalse("Counters must not be recorded if they are disabled",
|
||||
counterMetric.testHasValue())
|
||||
}
|
||||
|
||||
@Ignore("Ignoring the test as 'disabled' is not passed through FFI")
|
||||
@Test
|
||||
fun `disabled counters must not record data`() {
|
||||
// Define a 'counterMetric' counter metric, which will be stored in "store1". It's disabled
|
||||
// so it should not record anything.
|
||||
val counterMetric = CounterMetricType(
|
||||
disabled = true,
|
||||
category = "telemetry",
|
||||
lifetime = Lifetime.Application,
|
||||
name = "counter_metric",
|
||||
sendInPings = listOf("store1")
|
||||
)
|
||||
|
||||
// Attempt to store the counter.
|
||||
counterMetric.add()
|
||||
// Check that nothing was recorded.
|
||||
assertFalse("Counters must not be recorded if they are disabled",
|
||||
counterMetric.testHasValue())
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException::class)
|
||||
fun `testGetValue() throws NullPointerException if nothing is stored`() {
|
||||
val counterMetric = CounterMetricType(
|
||||
disabled = true,
|
||||
category = "telemetry",
|
||||
lifetime = Lifetime.Application,
|
||||
name = "counter_metric",
|
||||
sendInPings = listOf("store1")
|
||||
)
|
||||
counterMetric.testGetValue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `The API saves to secondary pings`() {
|
||||
// Define a 'counterMetric' counter metric, which will be stored in "store1" and "store2"
|
||||
val counterMetric = CounterMetricType(
|
||||
disabled = false,
|
||||
category = "telemetry",
|
||||
lifetime = Lifetime.Application,
|
||||
name = "counter_metric",
|
||||
sendInPings = listOf("store1", "store2")
|
||||
)
|
||||
|
||||
// Add to the counter a couple of times with a little delay. The first call will check
|
||||
// calling add() without parameters to test increment by 1.
|
||||
counterMetric.add()
|
||||
|
||||
// Check that the count was incremented and properly recorded for the second ping.
|
||||
assertTrue(counterMetric.testHasValue("store2"))
|
||||
assertEquals(1, counterMetric.testGetValue("store2"))
|
||||
|
||||
counterMetric.add(10)
|
||||
// Check that count was incremented and properly recorded for the second ping.
|
||||
// This second call will check calling add() with 10 to test increment by other amount
|
||||
assertTrue(counterMetric.testHasValue("store2"))
|
||||
assertEquals(11, counterMetric.testGetValue("store2"))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/* 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 mozilla.telemetry.glean.private
|
||||
|
||||
// import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
// import kotlinx.coroutines.ObsoleteCoroutinesApi
|
||||
import mozilla.telemetry.glean.resetGlean
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import java.lang.NullPointerException
|
||||
|
||||
// @ObsoleteCoroutinesApi
|
||||
// @ExperimentalCoroutinesApi
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class StringMetricTypeTest {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
resetGlean()
|
||||
}
|
||||
|
||||
@Ignore("Ignoring the test as the testing API for strings is not implemented")
|
||||
@Test
|
||||
fun `The API saves to its storage engine`() {
|
||||
// Define a 'stringMetric' string metric, which will be stored in "store1"
|
||||
val stringMetric = StringMetricType(
|
||||
disabled = false,
|
||||
category = "telemetry",
|
||||
lifetime = Lifetime.Application,
|
||||
name = "string_metric",
|
||||
sendInPings = listOf("store1")
|
||||
)
|
||||
|
||||
// Record two strings of the same type, with a little delay.
|
||||
stringMetric.set("value")
|
||||
|
||||
// Check that data was properly recorded.
|
||||
assertTrue(stringMetric.testHasValue())
|
||||
assertEquals("value", stringMetric.testGetValue())
|
||||
|
||||
stringMetric.set("overriddenValue")
|
||||
// Check that data was properly recorded.
|
||||
assertTrue(stringMetric.testHasValue())
|
||||
assertEquals("overriddenValue", stringMetric.testGetValue())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `strings with no lifetime must not record data`() {
|
||||
// Define a 'stringMetric' string metric, which will be stored in
|
||||
// "store1". It's disabled so it should not record anything.
|
||||
val stringMetric = StringMetricType(
|
||||
disabled = true,
|
||||
category = "telemetry",
|
||||
lifetime = Lifetime.Ping,
|
||||
name = "stringMetric",
|
||||
sendInPings = listOf("store1")
|
||||
)
|
||||
|
||||
// Attempt to store the string.
|
||||
stringMetric.set("value")
|
||||
// Check that nothing was recorded.
|
||||
assertFalse("Strings must not be recorded if they have no lifetime",
|
||||
stringMetric.testHasValue())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `disabled strings must not record data`() {
|
||||
// Define a 'stringMetric' string metric, which will be stored in "store1". It's disabled
|
||||
// so it should not record anything.
|
||||
val stringMetric = StringMetricType(
|
||||
disabled = true,
|
||||
category = "telemetry",
|
||||
lifetime = Lifetime.Application,
|
||||
name = "stringMetric",
|
||||
sendInPings = listOf("store1")
|
||||
)
|
||||
|
||||
// Attempt to store the string.
|
||||
stringMetric.set("value")
|
||||
// Check that nothing was recorded.
|
||||
assertFalse("Strings must not be recorded if they are disabled",
|
||||
stringMetric.testHasValue())
|
||||
}
|
||||
|
||||
@Ignore("Ignoring the test as the testing API for strings is not implemented")
|
||||
@Test(expected = NullPointerException::class)
|
||||
fun `testGetValue() throws NullPointerException if nothing is stored`() {
|
||||
val stringMetric = StringMetricType(
|
||||
disabled = true,
|
||||
category = "telemetry",
|
||||
lifetime = Lifetime.Application,
|
||||
name = "stringMetric",
|
||||
sendInPings = listOf("store1")
|
||||
)
|
||||
stringMetric.testGetValue()
|
||||
}
|
||||
|
||||
@Ignore("Ignoring the test as the testing API for strings is not implemented")
|
||||
@Test
|
||||
fun `The API saves to secondary pings`() {
|
||||
// Define a 'stringMetric' string metric, which will be stored in "store1" and "store2"
|
||||
val stringMetric = StringMetricType(
|
||||
disabled = false,
|
||||
category = "telemetry",
|
||||
lifetime = Lifetime.Application,
|
||||
name = "string_metric",
|
||||
sendInPings = listOf("store1", "store2")
|
||||
)
|
||||
|
||||
// Record two strings of the same type, with a little delay.
|
||||
stringMetric.set("value")
|
||||
|
||||
// Check that data was properly recorded in the second ping.
|
||||
assertTrue(stringMetric.testHasValue("store2"))
|
||||
assertEquals("value", stringMetric.testGetValue("store2"))
|
||||
|
||||
stringMetric.set("overriddenValue")
|
||||
// Check that data was properly recorded in the second ping.
|
||||
assertTrue(stringMetric.testHasValue("store2"))
|
||||
assertEquals("overriddenValue", stringMetric.testGetValue("store2"))
|
||||
}
|
||||
}
|
|
@ -203,7 +203,7 @@ pub extern "C" fn glean_counter_test_has_value(
|
|||
COUNTER_METRICS.call_with_output(&mut err, metric_id, |metric| {
|
||||
metric
|
||||
.test_get_value(glean, storage_name.as_str())
|
||||
.is_none()
|
||||
.is_some()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче