blob: c68c9206a2d82249f90f459b9b2cf1019510fd32 [file] [log] [blame]
Adrian Roose1e0b482017-02-02 16:00:59 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.util.leak;
18
19
Brett Chabot84151d92019-02-27 15:37:59 -080020import androidx.test.filters.SmallTest;
21import androidx.test.runner.AndroidJUnit4;
Adrian Roose1e0b482017-02-02 16:00:59 -080022
Jason Monkfba8faf2017-05-23 10:42:59 -040023import com.android.systemui.SysuiTestCase;
Adrian Roose1e0b482017-02-02 16:00:59 -080024import com.android.systemui.util.leak.ReferenceTestUtils.CollectionWaiter;
25
26import org.junit.Before;
Andreas Gampe66745e92018-03-18 15:35:39 -070027import org.junit.Ignore;
Adrian Roose1e0b482017-02-02 16:00:59 -080028import org.junit.Test;
29import org.junit.runner.RunWith;
30
Adrian Roose1e0b482017-02-02 16:00:59 -080031import java.io.FileOutputStream;
32import java.io.PrintWriter;
33import java.util.ArrayList;
34import java.util.Collection;
Søren Gjesse0fded552017-12-21 11:42:30 +010035import java.util.function.BiConsumer;
36import java.util.function.Consumer;
Adrian Roose1e0b482017-02-02 16:00:59 -080037
38@SmallTest
39@RunWith(AndroidJUnit4.class)
Jason Monkfba8faf2017-05-23 10:42:59 -040040public class LeakDetectorTest extends SysuiTestCase {
Adrian Roose1e0b482017-02-02 16:00:59 -080041
42 private LeakDetector mLeakDetector;
43
Søren Gjesse0fded552017-12-21 11:42:30 +010044 // The references for which collection is observed are stored in fields. The allocation and
45 // of these references happens in separate methods (trackObjectWith/trackCollectionWith)
46 // from where they are set to null. The generated code might keep the allocated reference
47 // alive in a dex register when compiling in release mode. As R8 is used to compile this
48 // test the --dontoptimize flag is also required to ensure that these methods are not
49 // inlined, as that would defeat the purpose of having the mutation in methods.
50 private Object mObject;
51 private Collection<?> mCollection;
52
53 private CollectionWaiter trackObjectWith(Consumer<Object> tracker) {
54 mObject = new Object();
55 CollectionWaiter collectionWaiter = ReferenceTestUtils.createCollectionWaiter(mObject);
56 tracker.accept(mObject);
57 return collectionWaiter;
58 }
59
60 private CollectionWaiter trackCollectionWith(
61 BiConsumer<? super Collection<?>, String> tracker) {
62 mCollection = new ArrayList<>();
63 CollectionWaiter collectionWaiter = ReferenceTestUtils.createCollectionWaiter(mCollection);
64 tracker.accept(mCollection, "tag");
65 return collectionWaiter;
66 }
67
Adrian Roose1e0b482017-02-02 16:00:59 -080068 @Before
69 public void setup() {
70 mLeakDetector = LeakDetector.create();
71
72 // Note: Do not try to factor out object / collection waiter creation. The optimizer will
73 // try and cache accesses to fields and thus create a GC root for the duration of the test
74 // method, thus breaking the test.
75 }
76
77 @Test
78 public void trackInstance_doesNotLeakTrackedObject() {
Søren Gjesse0fded552017-12-21 11:42:30 +010079 CollectionWaiter collectionWaiter = trackObjectWith(mLeakDetector::trackInstance);
80 mObject = null;
Adrian Roose1e0b482017-02-02 16:00:59 -080081 collectionWaiter.waitForCollection();
82 }
83
Andreas Gampe66745e92018-03-18 15:35:39 -070084 @Ignore("b/75329085")
Adrian Roose1e0b482017-02-02 16:00:59 -080085 @Test
86 public void trackCollection_doesNotLeakTrackedObject() {
Søren Gjesse0fded552017-12-21 11:42:30 +010087 CollectionWaiter collectionWaiter = trackCollectionWith(mLeakDetector::trackCollection);
88 mCollection = null;
Adrian Roose1e0b482017-02-02 16:00:59 -080089 collectionWaiter.waitForCollection();
90 }
91
92 @Test
93 public void trackGarbage_doesNotLeakTrackedObject() {
Søren Gjesse0fded552017-12-21 11:42:30 +010094 CollectionWaiter collectionWaiter = trackObjectWith(mLeakDetector::trackGarbage);
95 mObject = null;
Adrian Roose1e0b482017-02-02 16:00:59 -080096 collectionWaiter.waitForCollection();
97 }
98
99 @Test
100 public void testDump() throws Exception {
101 Object o1 = new Object();
102 Object o2 = new Object();
103 Collection<Object> col1 = new ArrayList<>();
104
105 mLeakDetector.trackInstance(o1);
106 mLeakDetector.trackCollection(col1, "tag");
107 mLeakDetector.trackGarbage(o2);
108
109 FileOutputStream fos = new FileOutputStream("/dev/null");
110 mLeakDetector.dump(fos.getFD(), new PrintWriter(fos), new String[0]);
111 }
112
113 @Test
114 public void testDisabled() throws Exception {
115 mLeakDetector = new LeakDetector(null, null, null);
116
117 Object o1 = new Object();
118 Object o2 = new Object();
119 Collection<Object> col1 = new ArrayList<>();
120
121 mLeakDetector.trackInstance(o1);
122 mLeakDetector.trackCollection(col1, "tag");
123 mLeakDetector.trackGarbage(o2);
124
125 FileOutputStream fos = new FileOutputStream("/dev/null");
126 mLeakDetector.dump(fos.getFD(), new PrintWriter(fos), new String[0]);
127 }
Søren Gjesse0fded552017-12-21 11:42:30 +0100128}