1fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin/*
2fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin * Copyright (C) 2016 The Android Open Source Project
3fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin *
4fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin * Licensed under the Apache License, Version 2.0 (the "License");
5fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin * you may not use this file except in compliance with the License.
6fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin * You may obtain a copy of the License at
7fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin *
8fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin *      http://www.apache.org/licenses/LICENSE-2.0
9fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin *
10fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin * Unless required by applicable law or agreed to in writing, software
11fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin * distributed under the License is distributed on an "AS IS" BASIS,
12fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin * See the License for the specific language governing permissions and
14fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin * limitations under the License.
15fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin */
16fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffinpackage dalvik.system;
17fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
18fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffinimport org.junit.Rule;
19fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffinimport org.junit.Test;
20fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffinimport org.junit.rules.TestRule;
21fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffinimport org.junit.runner.Description;
22fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffinimport org.junit.runners.model.Statement;
23fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
24fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin/**
25fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin * Tests {@link CloseGuard}.
26fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin */
27fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffinpublic class CloseGuardTest {
28fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
29fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    /**
30fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     * Resets the {@link CloseGuard#ENABLED} state back to the value it had when the test started.
31fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     */
32fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    @Rule
33fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    public TestRule rule = this::preserveEnabledState;
34fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
35fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    private Statement preserveEnabledState(final Statement base, Description description) {
36fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        return new Statement() {
37fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            @Override
38fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            public void evaluate() throws Throwable {
39fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin                boolean oldEnabledState = CloseGuard.isEnabled();
40fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin                try {
41fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin                    base.evaluate();
42fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin                } finally {
43fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin                    CloseGuard.setEnabled(oldEnabledState);
44fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin                }
45fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            }
46fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        };
47fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
48fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
49fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    @Test
50fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    public void testEnabled_NotOpen() throws Throwable {
51fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        CloseGuard.setEnabled(true);
52fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        ResourceOwner owner = new ResourceOwner();
53fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        assertUnreleasedResources(owner, 0);
54fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
55fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
56fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    @Test
57fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    public void testEnabled_OpenNotClosed() throws Throwable {
58fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        CloseGuard.setEnabled(true);
59fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        ResourceOwner owner = new ResourceOwner();
60fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        owner.open();
61fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        assertUnreleasedResources(owner, 1);
62fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
63fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
64fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    @Test
65fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    public void testEnabled_OpenThenClosed() throws Throwable {
66fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        CloseGuard.setEnabled(true);
67fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        ResourceOwner owner = new ResourceOwner();
68fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        owner.open();
69fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        owner.close();
70fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        assertUnreleasedResources(owner, 0);
71fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
72fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
73fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    @Test
74fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    public void testEnabledWhenCreated_DisabledWhenOpen() throws Throwable {
75fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        CloseGuard.setEnabled(true);
76fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        ResourceOwner owner = new ResourceOwner();
77fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        CloseGuard.setEnabled(false);
78fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        owner.open();
79fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
80fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        // Although the resource was not released it should not report it because CloseGuard was
81fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        // not enabled when the CloseGuard was opened.
82fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        assertUnreleasedResources(owner, 0);
83fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
84fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
85fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    @Test
86fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    public void testEnabledWhenOpened_DisabledWhenFinalized() throws Throwable {
87fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        CloseGuard.setEnabled(true);
88fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        ResourceOwner owner = new ResourceOwner();
89fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        owner.open();
90fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        CloseGuard.setEnabled(false);
91fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
92fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        // Although the resource was not released it should not report it because CloseGuard was
93fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        // not enabled when the CloseGuard was finalized.
94fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        assertUnreleasedResources(owner, 0);
95fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
96fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
97fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    @Test
98fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    public void testDisabled_NotOpen() throws Throwable {
99fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        CloseGuard.setEnabled(false);
100fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        ResourceOwner owner = new ResourceOwner();
101fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        assertUnreleasedResources(owner, 0);
102fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
103fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
104fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    @Test
105fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    public void testDisabled_OpenNotClosed() throws Throwable {
106fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        CloseGuard.setEnabled(false);
107fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        ResourceOwner owner = new ResourceOwner();
108fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        owner.open();
109fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        assertUnreleasedResources(owner, 0);
110fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
111fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
112fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    @Test
113fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    public void testDisabled_OpenThenClosed() throws Throwable {
114fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        CloseGuard.setEnabled(false);
115fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        ResourceOwner owner = new ResourceOwner();
116fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        owner.open();
117fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        owner.close();
118fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        assertUnreleasedResources(owner, 0);
119fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
120fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
121fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    @Test
122fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    public void testDisabledWhenCreated_EnabledWhenOpen() throws Throwable {
123fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        CloseGuard.setEnabled(false);
124fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        ResourceOwner owner = new ResourceOwner();
125fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        CloseGuard.setEnabled(true);
126fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        owner.open();
127fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
128fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        // Although the resource was not released it should not report it because CloseGuard was
129fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        // not enabled when the CloseGuard was created.
130fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        assertUnreleasedResources(owner, 0);
131fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
132fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
133fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    private void assertUnreleasedResources(ResourceOwner owner, int expectedCount)
134fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            throws Throwable {
135fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        try {
136fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            CloseGuardSupport.getFinalizerChecker().accept(owner, expectedCount);
137fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        } finally {
138fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            // Close the resource so that CloseGuard does not generate a warning for real when it
139fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            // is actually finalized.
140fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            owner.close();
141fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        }
142fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
143fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
144fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    /**
145fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     * A test user of {@link CloseGuard}.
146fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     */
147fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    private static class ResourceOwner {
148fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
149fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        private final CloseGuard closeGuard;
150fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
151fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        ResourceOwner() {
152fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            closeGuard = CloseGuard.get();
153fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        }
154fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
155fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        public void open() {
156fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            closeGuard.open("close");
157fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        }
158fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
159fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        public void close() {
160fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            closeGuard.close();
161fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        }
162fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
163fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        /**
164fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         * Make finalize public so that it can be tested directly without relying on garbage
165fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         * collection to trigger it.
166fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         */
167fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        @Override
168fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        public void finalize() throws Throwable {
169fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            closeGuard.warnIfOpen();
170fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            super.finalize();
171fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        }
172fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
173fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin}
174