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 libcore.junit.util;
17fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
1827604018f783bf6354a13870b3e7785edca69b5fPaul Duffinimport java.lang.annotation.ElementType;
1927604018f783bf6354a13870b3e7785edca69b5fPaul Duffinimport java.lang.annotation.Retention;
2027604018f783bf6354a13870b3e7785edca69b5fPaul Duffinimport java.lang.annotation.RetentionPolicy;
2127604018f783bf6354a13870b3e7785edca69b5fPaul Duffinimport java.lang.annotation.Target;
22fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffinimport java.lang.reflect.Method;
23fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffinimport java.util.function.BiConsumer;
24fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffinimport org.junit.rules.RuleChain;
25fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffinimport org.junit.rules.TestRule;
26fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffinimport org.junit.runner.Description;
27fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffinimport org.junit.runners.model.Statement;
28fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
29fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin/**
3088df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin * Provides support for testing classes that own resources (using {@code CloseGuard} mechanism)
3188df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin * which must not leak.
32fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin *
33fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin * <p><strong>This will not detect any resource leakages in OpenJDK</strong></p>
3488df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin *
3588df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin * <p>Typical usage for developers that want to ensure that their tests do not leak resources:
3688df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin * <pre>
3788df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin * public class ResourceTest {
3888df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin *  {@code @Rule}
3988df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin *   public LeakageDetectorRule leakageDetectorRule = ResourceLeakageDetector.getRule();
4088df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin *
4188df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin *  ...
4288df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin * }
4388df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin * </pre>
4488df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin *
4588df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin * <p>Developers that need to test the resource itself to ensure it is properly protected can
4688df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin * use {@link LeakageDetectorRule#assertUnreleasedResourceCount(Object, int)
4788df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin * assertUnreleasedResourceCount(Object, int)}.
48fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin */
49fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffinpublic class ResourceLeakageDetector {
50fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    private static final LeakageDetectorRule LEAKAGE_DETECTOR_RULE;
51fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    private static final BiConsumer<Object, Integer> FINALIZER_CHECKER;
52fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
53fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    static {
54fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        LeakageDetectorRule leakageDetectorRule;
55fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        BiConsumer<Object, Integer> finalizerChecker;
56fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        try {
57fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            // Make sure that the CloseGuard class exists; this ensures that this is not
58fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            // running on a RI JVM.
59fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            Class.forName("dalvik.system.CloseGuard");
60fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
61fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            // Access the underlying support class using reflection in order to prevent any compile
62fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            // time dependencies on it so as to allow this to compile on OpenJDK.
63fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            Class<?> closeGuardSupportClass = Class.forName("dalvik.system.CloseGuardSupport");
64fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            Method method = closeGuardSupportClass.getMethod("getRule");
65fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            leakageDetectorRule = new LeakageDetectorRule((TestRule) method.invoke(null));
66fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
67fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            finalizerChecker = getFinalizerChecker(closeGuardSupportClass);
68fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
69fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        } catch (ReflectiveOperationException e) {
70fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            System.err.println("Resource leakage will not be detected; "
71fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin                    + "this is expected in the reference implementation");
72fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            e.printStackTrace(System.err);
73fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
74fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            // Could not access the class for some reason so have a rule that does nothing and a
75fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            // finalizer checker that checks nothing. This should ensure that tests work properly
76fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            // on OpenJDK even though it does not support CloseGuard.
77fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            leakageDetectorRule = new LeakageDetectorRule(RuleChain.emptyRuleChain());
78fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            finalizerChecker = new BiConsumer<Object, Integer>() {
79fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin                @Override
80fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin                public void accept(Object o, Integer integer) {
81fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin                    // Do nothing.
82fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin                }
83fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            };
84fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        }
85fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
86fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        LEAKAGE_DETECTOR_RULE = leakageDetectorRule;
87fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        FINALIZER_CHECKER = finalizerChecker;
88fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
89fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
90fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    @SuppressWarnings("unchecked")
91fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    private static BiConsumer<Object, Integer> getFinalizerChecker(Class<?> closeGuardSupportClass)
92fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            throws ReflectiveOperationException {
93fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        Method method = closeGuardSupportClass.getMethod("getFinalizerChecker");
94fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        return (BiConsumer<Object, Integer>) method.invoke(null);
95fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
96fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
97fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    /**
98fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     * @return the {@link LeakageDetectorRule}
99fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     */
100fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    public static LeakageDetectorRule getRule() {
101fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin       return LEAKAGE_DETECTOR_RULE;
102fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
103fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
104fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    /**
105fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     * A {@link TestRule} that will fail a test if it detects any resources that were allocated
106fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     * during the test but were not released.
107fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     *
108fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     * <p>This only tracks resources that were allocated on the test thread, although it does not
109fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     * care what thread they were released on. This avoids flaky false positives where a background
110fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     * thread allocates a resource during a test but releases it after the test.
111fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     *
112fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     * <p>It is still possible to have a false positive in the case where the test causes a caching
113fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     * mechanism to open a resource and hold it open past the end of the test. In that case if there
114fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     * is no way to clear the cached data then it should be relatively simple to move the code that
115fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     * invokes the caching mechanism to outside the scope of this rule. i.e.
116fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     *
11788df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin     * <pre>
11888df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin     *    {@code @Rule}
119fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     *     public final TestRule ruleChain = org.junit.rules.RuleChain
120fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     *         .outerRule(new ...invoke caching mechanism...)
12188df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin     *         .around(ResourceLeakageDetector.getRule());
12288df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin     * </pre>
123fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin     */
124fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    public static class LeakageDetectorRule implements TestRule {
125fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
126fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        private final TestRule leakageDetectorRule;
12788df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin        private boolean leakageDetectionEnabledForTest;
128fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
129fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        private LeakageDetectorRule(TestRule leakageDetectorRule) {
130fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin            this.leakageDetectorRule = leakageDetectorRule;
131fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        }
132fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
133fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        @Override
134fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        public Statement apply(Statement base, Description description) {
13527604018f783bf6354a13870b3e7785edca69b5fPaul Duffin            // Make the resource leakage detector rule optional based on the presence of an
13627604018f783bf6354a13870b3e7785edca69b5fPaul Duffin            // annotation.
13727604018f783bf6354a13870b3e7785edca69b5fPaul Duffin            if (description.getAnnotation(DisableResourceLeakageDetection.class) != null) {
13888df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin                leakageDetectionEnabledForTest = false;
13927604018f783bf6354a13870b3e7785edca69b5fPaul Duffin                return base;
14027604018f783bf6354a13870b3e7785edca69b5fPaul Duffin            } else {
14188df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin                leakageDetectionEnabledForTest = true;
14227604018f783bf6354a13870b3e7785edca69b5fPaul Duffin                return leakageDetectorRule.apply(base, description);
14327604018f783bf6354a13870b3e7785edca69b5fPaul Duffin            }
144fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        }
145fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin
146fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        /**
147fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         * Ensure that when the supplied object is finalized that it detects the expected number of
148fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         * unreleased resources.
149fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         *
150fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         * <p>This helps ensure that classes which own resources protected using {@code CloseGuard}
151fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         * support leakage detection.
152fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         *
15388df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * <p>This must only be called as part of the currently running test and the test must not
15488df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * be annotated with {@link DisableResourceLeakageDetection} as that will disable leakage
15588df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * detection. Attempting to use it with leakage detection disabled by the annotation will
15688df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * result in a test failure.
157fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         *
15888df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * <p>Use as follows, 'open' and 'close' refer to the methods in {@code CloseGuard}:
159fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         * <pre>
16088df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * public class ResourceTest {
16188df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *  {@code @Rule}
16288df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *   public LeakageDetectorRule leakageDetectorRule = ResourceLeakageDetector.getRule();
16388df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *
16488df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *  {@code @Test}
16588df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *   public void testAutoCloseableResourceIsProtected() {
16688df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *     try (AutoCloseable object = ...open a protected resource...) {
16788df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *       leakageDetectorRule.assertUnreleasedResourceCount(object, 1);
16888df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *     }
16988df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *   }
170fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         *
17188df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *  {@code @Test}
17288df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *   public void testResourceIsProtected() {
17388df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *     NonAutoCloseable object = ...open a protected resource...;
17488df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *     leakageDetectorRule.assertUnreleasedResourceCount(object, 1);
17588df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *     object.release();
17688df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *   }
17788df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * }
178fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         * </pre>
179fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         *
18088df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * <p>There are two test method templates, the one to use depends on whether the resource is
18188df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * {@link AutoCloseable} or not. Each method tests the following:</p>
18288df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * <ul>
18388df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * <li>The {@code @Rule} will ensure that the test method does not leak any resources. That
18488df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * will make sure that if it actually is protected by {@code CloseGuard} that it correctly
18588df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * closes it. It does not actually ensure that it is protected.
18688df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * <li>The call to this method will ensure that the resource is actually protected by
18788df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * {@code CloseGuard}.
18888df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * </ul>
18988df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *
19088df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * <p>The above tests will work on the reference implementation as this method does nothing
19188df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * when {@code CloseGuard} is not supported.
19288df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *
19388df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * @param owner the object that owns the resource and uses {@code CloseGuard} object to
19488df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *         detect when the resource is not released.
19588df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         * @param expectedCount the expected number of unreleased resources, i.e. the number of
19688df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *         {@code CloseGuard} objects owned by the resource, and on which it calls
19788df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin         *         {@code CloseGuard.warnIfOpen()} in its {@link #finalize()} method; usually 1.
198fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin         */
199fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        public void assertUnreleasedResourceCount(Object owner, int expectedCount) {
20088df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin            if (leakageDetectionEnabledForTest) {
20188df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin                FINALIZER_CHECKER.accept(owner, expectedCount);
20288df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin            } else {
20388df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin                throw new IllegalStateException(
20488df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin                        "Does not work when leakage detection has been disabled; remove the "
20588df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin                                + "@DisableResourceLeakageDetection from the test method");
20688df7911980a895f9379d9a0e4cbf46aaadf90d0Paul Duffin            }
207fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin        }
208fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin    }
20927604018f783bf6354a13870b3e7785edca69b5fPaul Duffin
21027604018f783bf6354a13870b3e7785edca69b5fPaul Duffin    /**
21127604018f783bf6354a13870b3e7785edca69b5fPaul Duffin     * An annotation that indicates that the test should not be run with resource leakage detection
21227604018f783bf6354a13870b3e7785edca69b5fPaul Duffin     * enabled.
21327604018f783bf6354a13870b3e7785edca69b5fPaul Duffin     */
21427604018f783bf6354a13870b3e7785edca69b5fPaul Duffin    @Retention(RetentionPolicy.RUNTIME)
21527604018f783bf6354a13870b3e7785edca69b5fPaul Duffin    @Target(ElementType.METHOD)
21627604018f783bf6354a13870b3e7785edca69b5fPaul Duffin    public @interface DisableResourceLeakageDetection {
21727604018f783bf6354a13870b3e7785edca69b5fPaul Duffin
21827604018f783bf6354a13870b3e7785edca69b5fPaul Duffin        /**
21927604018f783bf6354a13870b3e7785edca69b5fPaul Duffin         * The explanation as to why resource leakage detection is disabled for this test.
22027604018f783bf6354a13870b3e7785edca69b5fPaul Duffin         */
22127604018f783bf6354a13870b3e7785edca69b5fPaul Duffin        String why();
22227604018f783bf6354a13870b3e7785edca69b5fPaul Duffin
22327604018f783bf6354a13870b3e7785edca69b5fPaul Duffin        /**
22427604018f783bf6354a13870b3e7785edca69b5fPaul Duffin         * The bug reference to the bug that was opened to fix the issue.
22527604018f783bf6354a13870b3e7785edca69b5fPaul Duffin         */
22627604018f783bf6354a13870b3e7785edca69b5fPaul Duffin        String bug();
22727604018f783bf6354a13870b3e7785edca69b5fPaul Duffin    }
228fe0ee8ef8870338ad67ebfb6b62785e0cbdb325bPaul Duffin}
229