chromium/android_webview/javatests/src/org/chromium/android_webview/test/MetricsFilteringDecoratorTest.java

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.android_webview.test;

import static org.chromium.android_webview.test.OnlyRunIn.ProcessMode.EITHER_PROCESS;

import androidx.test.filters.MediumTest;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.UseParametersRunnerFactory;

import org.chromium.android_webview.common.PlatformServiceBridge;
import org.chromium.android_webview.metrics.AwMetricsUtils;
import org.chromium.android_webview.metrics.MetricsFilteringDecorator;
import org.chromium.base.test.util.Batch;
import org.chromium.base.test.util.Feature;
import org.chromium.components.metrics.AndroidMetricsLogConsumer;
import org.chromium.components.metrics.ChromeUserMetricsExtensionProtos.ChromeUserMetricsExtension;
import org.chromium.components.metrics.HistogramEventProtos.HistogramEventProto;
import org.chromium.components.metrics.SystemProfileProtos.SystemProfileProto;
import org.chromium.components.metrics.SystemProfileProtos.SystemProfileProto.MetricsFilteringStatus;
import org.chromium.components.metrics.UserActionEventProtos.UserActionEventProto;

import java.net.HttpURLConnection;
import java.util.Arrays;

/** Instrumentation tests for {@link MetricsFilteringDecorator}. */
@RunWith(Parameterized.class)
@UseParametersRunnerFactory(AwJUnit4ClassRunnerWithParameters.Factory.class)
@OnlyRunIn(EITHER_PROCESS) // These tests don't use the renderer process
@MediumTest
@Batch(Batch.PER_CLASS)
public class MetricsFilteringDecoratorTest extends AwParameterizedTest {
    @Rule public AwActivityTestRule mRule;

    private MetricsTestPlatformServiceBridge mPlatformServiceBridge;
    private AndroidMetricsLogConsumer mUploader;

    public MetricsFilteringDecoratorTest(AwSettingsMutation param) {
        this.mRule = new AwActivityTestRule(param.getMutation());
    }

    @Before
    public void setUp() {
        mPlatformServiceBridge = new MetricsTestPlatformServiceBridge();
        PlatformServiceBridge.injectInstance(mPlatformServiceBridge);

        AndroidMetricsLogConsumer directUploader =
                data -> {
                    PlatformServiceBridge.getInstance().logMetrics(data);
                    return HttpURLConnection.HTTP_OK;
                };
        mUploader = new MetricsFilteringDecorator(directUploader);
    }

    private HistogramEventProto createHistogramWithName(String histogramName) {
        return HistogramEventProto.newBuilder()
                .setNameHash(AwMetricsUtils.hashHistogramName(histogramName))
                .build();
    }

    private UserActionEventProto getUserAction() {
        return UserActionEventProto.newBuilder()
                .setNameHash(6207116539890058931L)
                .setTimeSec(417309L)
                .build();
    }

    @Test
    @Feature({"AndroidWebView"})
    public void testMetricsFiltering_applied() throws Throwable {
        ChromeUserMetricsExtension log =
                ChromeUserMetricsExtension.newBuilder()
                        .setSystemProfile(
                                SystemProfileProto.newBuilder()
                                        .setMetricsFilteringStatus(
                                                MetricsFilteringStatus.METRICS_ONLY_CRITICAL))
                        .addAllHistogramEvent(
                                Arrays.asList(
                                        createHistogramWithName(
                                                "Android.WebView.Visibility.Global"),
                                        createHistogramWithName("Histogram.Not.In.Allowlist"),
                                        createHistogramWithName(
                                                "Android.WebView.SafeMode.SafeModeEnabled")))
                        .addUserActionEvent(getUserAction())
                        .build();

        ChromeUserMetricsExtension expectedReceivedLog =
                ChromeUserMetricsExtension.newBuilder()
                        .setSystemProfile(
                                SystemProfileProto.newBuilder()
                                        .setMetricsFilteringStatus(
                                                MetricsFilteringStatus.METRICS_ONLY_CRITICAL))
                        .addAllHistogramEvent(
                                Arrays.asList(
                                        createHistogramWithName(
                                                "Android.WebView.Visibility.Global"),
                                        createHistogramWithName(
                                                "Android.WebView.SafeMode.SafeModeEnabled")))
                        .build();

        int status = mUploader.log(log.toByteArray());
        Assert.assertEquals(HttpURLConnection.HTTP_OK, status);
        ChromeUserMetricsExtension receivedLog = mPlatformServiceBridge.waitForNextMetricsLog();
        Assert.assertEquals(expectedReceivedLog, receivedLog);
    }

    @Test
    @Feature({"AndroidWebView"})
    public void testMetricsFiltering_notApplied() throws Throwable {
        ChromeUserMetricsExtension log =
                ChromeUserMetricsExtension.newBuilder()
                        .setSystemProfile(
                                SystemProfileProto.newBuilder()
                                        .setMetricsFilteringStatus(
                                                MetricsFilteringStatus.METRICS_ALL))
                        .addHistogramEvent(createHistogramWithName("Histogram.Not.In.Allowlist"))
                        .addUserActionEvent(getUserAction())
                        .build();

        int status = mUploader.log(log.toByteArray());
        Assert.assertEquals(HttpURLConnection.HTTP_OK, status);
        ChromeUserMetricsExtension receivedLog = mPlatformServiceBridge.waitForNextMetricsLog();
        // We expect to receive an identical log to the one we provided.
        Assert.assertEquals(log, receivedLog);
    }

    @Test
    @Feature({"AndroidWebView"})
    public void testMetricsFiltering_missingSystemProfile() throws Throwable {
        ChromeUserMetricsExtension log =
                ChromeUserMetricsExtension.newBuilder()
                        .addHistogramEvent(createHistogramWithName("Histogram.Not.In.Allowlist"))
                        .addUserActionEvent(getUserAction())
                        .build();

        int status = mUploader.log(log.toByteArray());
        Assert.assertEquals(HttpURLConnection.HTTP_OK, status);
        ChromeUserMetricsExtension receivedLog = mPlatformServiceBridge.waitForNextMetricsLog();
        // We expect to receive an identical log to the one we provided.
        Assert.assertEquals(log, receivedLog);
    }
}