Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8891cca authored by Anna Trostanetski's avatar Anna Trostanetski Committed by android-build-merger
Browse files

Merge "Add a unit test for ChangeReporter."

am: 7b577376

Change-Id: I4af55d71ed16a1e4702ed02a5751105f33327cbb
parents 7f5ca69a 7b577376
Loading
Loading
Loading
Loading
+70 −9
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.util.Slog;
import android.util.StatsLog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;

import java.util.HashMap;
import java.util.HashSet;
@@ -37,7 +38,7 @@ public final class ChangeReporter {
    private static final String TAG = "CompatibilityChangeReporter";
    private int mSource;

    private final class ChangeReport {
    private static final class ChangeReport {
        long mChangeId;
        int mState;

@@ -65,9 +66,13 @@ public final class ChangeReporter {
    @GuardedBy("mReportedChanges")
    private final Map<Integer, Set<ChangeReport>> mReportedChanges;

    // When true will of every time to debug (logcat).
    private boolean mDebugLogAll;

    public ChangeReporter(int source) {
        mSource = source;
        mReportedChanges =  new HashMap<>();
        mDebugLogAll = false;
    }

    /**
@@ -79,21 +84,77 @@ public final class ChangeReporter {
     * @param state    of the reported change - enabled/disabled/only logged
     */
    public void reportChange(int uid, long changeId, int state) {
        ChangeReport report = new ChangeReport(changeId, state);
        if (shouldWriteToStatsLog(uid, changeId, state)) {
            StatsLog.write(StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED, uid, changeId,
                    state, mSource);
        }
        if (shouldWriteToDebug(uid, changeId, state)) {
            debugLog(uid, changeId, state);
        }
        markAsReported(uid, new ChangeReport(changeId, state));
    }

    /**
     * Start logging all the time to logcat.
     */
    public void startDebugLogAll() {
        mDebugLogAll = true;
    }

    /**
     * Stop logging all the time to logcat.
     */
    public void stopDebugLogAll() {
        mDebugLogAll = false;
    }


    /**
     * Returns whether the next report should be logged to statsLog.
     *
     * @param uid      affected by the change
     * @param changeId the reported change id
     * @param state    of the reported change - enabled/disabled/only logged
     * @return true if the report should be logged
     */
    @VisibleForTesting
    public boolean shouldWriteToStatsLog(int uid, long changeId, int state) {
        return !isAlreadyReported(uid, new ChangeReport(changeId, state));
    }

    /**
     * Returns whether the next report should be logged to logcat.
     *
     * @param uid      affected by the change
     * @param changeId the reported change id
     * @param state    of the reported change - enabled/disabled/only logged
     * @return true if the report should be logged
     */
    @VisibleForTesting
    public boolean shouldWriteToDebug(int uid, long changeId, int state) {
        return mDebugLogAll || !isAlreadyReported(uid, new ChangeReport(changeId, state));
    }

    private boolean isAlreadyReported(int uid, ChangeReport report) {
        synchronized (mReportedChanges) {
            Set<ChangeReport> reportedChangesForUid = mReportedChanges.get(uid);
            if (reportedChangesForUid == null) {
                return false;
            } else {
                return reportedChangesForUid.contains(report);
            }
        }
    }

    private void markAsReported(int uid, ChangeReport report) {
        synchronized (mReportedChanges) {
            Set<ChangeReport> reportedChangesForUid = mReportedChanges.get(uid);
            if (reportedChangesForUid == null) {
                mReportedChanges.put(uid, new HashSet<ChangeReport>());
                reportedChangesForUid = mReportedChanges.get(uid);
            }
            if (!reportedChangesForUid.contains(report)) {
                debugLog(uid, changeId, state);
                StatsLog.write(StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED, uid, changeId,
                        state, mSource);
            reportedChangesForUid.add(report);
        }

        }
    }

    /**
+14 −0
Original line number Diff line number Diff line
android_test {
    name: "PlatformCompatFrameworkTests",
    // Include all test java files.
    srcs: ["src/**/*.java"],
    libs: [
        "android.test.runner",
        "android.test.base",
    ],
    static_libs: [
        "junit",
        "androidx.test.rules",
    ],
    platform_apis: true,
}
+11 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.android.internal.compat">
    <application android:label="ChangeReporterTest">
        <uses-library android:name="android.test.runner" />
    </application>

    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                     android:targetPackage="com.android.internal.compat"/>
</manifest>
 No newline at end of file
+7 −0
Original line number Diff line number Diff line
# Use this reviewer by default.
platform-compat-eng+reviews@google.com

andreionea@google.com
atrost@google.com
mathewi@google.com
satayev@google.com
+115 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.compat;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class ChangeReporterTest {
    @Test
    public void testStatsLogOnce() {
        ChangeReporter reporter = new ChangeReporter(0);
        int myUid = 1022, otherUid = 1023;
        long myChangeId = 500L, otherChangeId = 600L;
        int myState = 1, otherState = 2;

        assertTrue(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
        reporter.reportChange(myUid, myChangeId, myState);

        // Same report will not be logged again.
        assertFalse(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
        // Other reports will be logged.
        assertTrue(reporter.shouldWriteToStatsLog(otherUid, myChangeId, myState));
        assertTrue(reporter.shouldWriteToStatsLog(myUid, otherChangeId, myState));
        assertTrue(reporter.shouldWriteToStatsLog(myUid, myChangeId, otherState));
    }

    @Test
    public void testStatsLogAfterReset() {
        ChangeReporter reporter = new ChangeReporter(0);
        int myUid = 1022;
        long myChangeId = 500L;
        int myState = 1;

        assertTrue(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
        reporter.reportChange(myUid, myChangeId, myState);

        // Same report will not be logged again.
        assertFalse(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
        reporter.resetReportedChanges(myUid);

        // Same report will be logged again after reset.
        assertTrue(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
    }

    @Test
    public void testDebugLogOnce() {
        ChangeReporter reporter = new ChangeReporter(0);
        int myUid = 1022, otherUid = 1023;
        long myChangeId = 500L, otherChangeId = 600L;
        int myState = 1, otherState = 2;

        assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
        reporter.reportChange(myUid, myChangeId, myState);

        // Same report will not be logged again.
        assertFalse(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
        // Other reports will be logged.
        assertTrue(reporter.shouldWriteToDebug(otherUid, myChangeId, myState));
        assertTrue(reporter.shouldWriteToDebug(myUid, otherChangeId, myState));
        assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, otherState));
    }

    @Test
    public void testDebugLogAfterReset() {
        ChangeReporter reporter = new ChangeReporter(0);
        int myUid = 1022;
        long myChangeId = 500L;
        int myState = 1;

        assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
        reporter.reportChange(myUid, myChangeId, myState);

        // Same report will not be logged again.
        assertFalse(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
        reporter.resetReportedChanges(myUid);

        // Same report will be logged again after reset.
        assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
    }

    @Test
    public void testDebugLogWithLogAll() {
        ChangeReporter reporter = new ChangeReporter(0);
        int myUid = 1022;
        long myChangeId = 500L;
        int myState = 1;

        assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
        reporter.reportChange(myUid, myChangeId, myState);

        reporter.startDebugLogAll();
        // Same report will be logged again.
        assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
        assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, myState));

        reporter.stopDebugLogAll();
        assertFalse(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
    }
}