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

Commit 0c408008 authored by Jason Monk's avatar Jason Monk
Browse files

Try to add some more documentation to testables

Test: runtest --path frameworks/base/tests/testables/tests
Change-Id: I3dc39f05c3b91929a7d37b28879e31fb699f7334
parent 3fcdfa1b
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -52,7 +52,6 @@ public class TileServicesTest extends SysuiTestCase {

    @Before
    public void setUp() throws Exception {
        TestableLooper.get(this).setAsMainLooper();
        mManagers = new ArrayList<>();
        QSTileHost host = new QSTileHost(mContext, null,
                mock(StatusBarIconController.class));
+2 −0
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@ import java.util.List;

/**
 * A runner with support for extra annotations provided by the Testables library.
 * @see UiThreadTest
 * @see TestableLooper.RunWithLooper
 */
public class AndroidTestingRunner extends BlockJUnit4ClassRunner {

+4 −0
Original line number Diff line number Diff line
@@ -80,6 +80,10 @@ public abstract class BaseFragmentTest {
        });
    }

    /**
     * Allows tests to sub-class TestableContext if they want to provide any extended functionality
     * or provide a {@link LeakCheck} to the TestableContext upon instantiation.
     */
    protected TestableContext getContext() {
        return new TestableContext(InstrumentationRegistry.getContext());
    }
+57 −1
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@

package android.testing;

import android.content.Context;
import android.util.ArrayMap;
import android.util.Log;

@@ -28,6 +29,35 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Utility for dealing with the facts of Lifecycle. Creates trackers to check that for every
 * call to registerX, addX, bindX, a corresponding call to unregisterX, removeX, and unbindX
 * is performed. This should be applied to a test as a {@link org.junit.rules.TestRule}
 * and will only check for leaks on successful tests.
 * <p>
 * Example that will catch an allocation and fail:
 * <pre class="prettyprint">
 * public class LeakCheckTest {
 *    &#064;Rule public LeakCheck mLeakChecker = new LeakCheck();
 *
 *    &#064;Test
 *    public void testLeak() {
 *        Context context = new ContextWrapper(...) {
 *            public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
 *                mLeakChecker.getTracker("receivers").addAllocation(new Throwable());
 *            }
 *            public void unregisterReceiver(BroadcastReceiver receiver) {
 *                mLeakChecker.getTracker("receivers").clearAllocations();
 *            }
 *        };
 *        context.registerReceiver(...);
 *    }
 *  }
 * </pre>
 *
 * Note: {@link TestableContext} supports leak tracking when using
 * {@link TestableContext#TestableContext(Context, LeakCheck)}.
 */
public class LeakCheck extends TestWatcher {

    private final Map<String, Tracker> mTrackers = new HashMap<>();
@@ -40,6 +70,13 @@ public class LeakCheck extends TestWatcher {
        verify();
    }

    /**
     * Acquire a {@link Tracker}. Gets a tracker for the specified tag, creating one if necessary.
     * There should be one tracker for each pair of add/remove callbacks (e.g. one tracker for
     * registerReceiver/unregisterReceiver).
     *
     * @param tag Unique tag to use for this set of allocation tracking.
     */
    public Tracker getTracker(String tag) {
        Tracker t = mTrackers.get(tag);
        if (t == null) {
@@ -49,10 +86,13 @@ public class LeakCheck extends TestWatcher {
        return t;
    }

    public void verify() {
    private void verify() {
        mTrackers.values().forEach(Tracker::verify);
    }

    /**
     * Holds allocations associated with a specific callback (such as a BroadcastReceiver).
     */
    public static class LeakInfo {
        private static final String TAG = "LeakInfo";
        private List<Throwable> mThrowables = new ArrayList<>();
@@ -60,11 +100,20 @@ public class LeakCheck extends TestWatcher {
        LeakInfo() {
        }

        /**
         * Should be called once for each callback/listener added. addAllocation may be
         * called several times, but it only takes one clearAllocations call to remove all
         * of them.
         */
        public void addAllocation(Throwable t) {
            // TODO: Drop off the first element in the stack trace here to have a cleaner stack.
            mThrowables.add(t);
        }

        /**
         * Should be called when the callback/listener has been removed. One call to
         * clearAllocations will counteract any number of calls to addAllocation.
         */
        public void clearAllocations() {
            mThrowables.clear();
        }
@@ -82,9 +131,16 @@ public class LeakCheck extends TestWatcher {
        }
    }

    /**
     * Tracks allocations related to a specific tag or method(s).
     * @see #getTracker(String)
     */
    public static class Tracker {
        private Map<Object, LeakInfo> mObjects = new ArrayMap<>();

        private Tracker() {
        }

        public LeakInfo getLeakInfo(Object object) {
            LeakInfo leakInfo = mObjects.get(object);
            if (leakInfo == null) {
+5 −1
Original line number Diff line number Diff line
@@ -27,7 +27,11 @@ import com.google.android.collect.Maps;
import java.util.Map;

/**
 * Alternative to a MockContentResolver that falls back to real providers.
 * A version of ContentResolver that allows easy mocking of providers.
 * By default it acts as a normal ContentResolver and returns all the
 * same providers.
 * @see #addProvider(String, ContentProvider)
 * @see #setFallbackToExisting(boolean)
 */
public class TestableContentResolver extends ContentResolver {

Loading