blob: 728ed606cffb665777dde75584832d761e5104e4 [file] [log] [blame]
Jason Monk9abca5e2016-11-11 16:18:14 -05001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11 * KIND, either express or implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
15package com.android.systemui.utils.leaks;
16
17import static org.mockito.Matchers.any;
18import static org.mockito.Mockito.doAnswer;
19
20import android.util.ArrayMap;
21
22import com.android.systemui.SysuiTestCase;
23import com.android.systemui.statusbar.phone.ManagedProfileController;
24import com.android.systemui.statusbar.policy.BatteryController;
25import com.android.systemui.statusbar.policy.BluetoothController;
26import com.android.systemui.statusbar.policy.CallbackController;
27import com.android.systemui.statusbar.policy.CastController;
28import com.android.systemui.statusbar.policy.FlashlightController;
29import com.android.systemui.statusbar.policy.HotspotController;
30import com.android.systemui.statusbar.policy.KeyguardMonitor;
31import com.android.systemui.statusbar.policy.LocationController;
32import com.android.systemui.statusbar.policy.NetworkController;
33import com.android.systemui.statusbar.policy.NextAlarmController;
34import com.android.systemui.statusbar.policy.RotationLockController;
35import com.android.systemui.statusbar.policy.SecurityController;
36import com.android.systemui.statusbar.policy.UserInfoController;
37import com.android.systemui.statusbar.policy.ZenModeController;
38
39import org.junit.Assert;
40import org.junit.Rule;
41import org.junit.rules.TestWatcher;
42import org.junit.runner.Description;
43import org.mockito.invocation.InvocationOnMock;
44import org.mockito.stubbing.Answer;
45
46import java.util.HashMap;
47import java.util.Map;
48
49/**
50 * Base class for tests to check if receivers are left registered, services bound, or other
51 * listeners listening.
52 */
53public abstract class LeakCheckedTest extends SysuiTestCase {
54 private static final String TAG = "LeakCheckedTest";
55
56 private final Map<String, Tracker> mTrackers = new HashMap<>();
57 private final Map<Class, Object> mLeakCheckers = new ArrayMap<>();
58
59 @Rule
60 public TestWatcher successWatcher = new TestWatcher() {
61 @Override
62 protected void succeeded(Description description) {
63 verify();
64 }
65 };
66
67 public <T> T getLeakChecker(Class<T> cls) {
68 Object obj = mLeakCheckers.get(cls);
69 if (obj == null) {
70 // Lazy create checkers so we only have the ones we need.
71 if (cls == BluetoothController.class) {
72 obj = new FakeBluetoothController(this);
73 } else if (cls == LocationController.class) {
74 obj = new FakeLocationController(this);
75 } else if (cls == RotationLockController.class) {
76 obj = new FakeRotationLockController(this);
77 } else if (cls == ZenModeController.class) {
78 obj = new FakeZenModeController(this);
79 } else if (cls == CastController.class) {
80 obj = new FakeCastController(this);
81 } else if (cls == HotspotController.class) {
82 obj = new FakeHotspotController(this);
83 } else if (cls == FlashlightController.class) {
84 obj = new FakeFlashlightController(this);
85 } else if (cls == UserInfoController.class) {
86 obj = new FakeUserInfoController(this);
87 } else if (cls == KeyguardMonitor.class) {
88 obj = new FakeKeyguardMonitor(this);
89 } else if (cls == BatteryController.class) {
90 obj = new FakeBatteryController(this);
91 } else if (cls == SecurityController.class) {
92 obj = new FakeSecurityController(this);
93 } else if (cls == ManagedProfileController.class) {
94 obj = new FakeManagedProfileController(this);
95 } else if (cls == NextAlarmController.class) {
96 obj = new FakeNextAlarmController(this);
97 } else if (cls == NetworkController.class) {
98 obj = new FakeNetworkController(this);
99 } else {
100 Assert.fail(cls.getName() + " is not supported by LeakCheckedTest yet");
101 }
102 mLeakCheckers.put(cls, obj);
103 }
104 return (T) obj;
105 }
106
107 @Override
108 public Tracker getTracker(String tag) {
109 Tracker t = mTrackers.get(tag);
110 if (t == null) {
111 t = new Tracker();
112 mTrackers.put(tag, t);
113 }
114 return t;
115 }
116
117 public void verify() {
118 mTrackers.values().forEach(Tracker::verify);
119 }
120
121 public <T extends CallbackController> T addListening(T mock, Class<T> cls, String tag) {
122 doAnswer(new Answer<Void>() {
123 @Override
124 public Void answer(InvocationOnMock invocation) throws Throwable {
125 getTracker(tag).getLeakInfo(invocation.getArguments()[0])
126 .addAllocation(new Throwable());
127 return null;
128 }
129 }).when(mock).addCallback(any());
130 doAnswer(new Answer<Void>() {
131 @Override
132 public Void answer(InvocationOnMock invocation) throws Throwable {
133 getTracker(tag).getLeakInfo(invocation.getArguments()[0]).clearAllocations();
134 return null;
135 }
136 }).when(mock).removeCallback(any());
137 mLeakCheckers.put(cls, mock);
138 return mock;
139 }
140}