1 /* 2 * Copyright (C) 2016 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 package libcore.dalvik.system; 17 18 import org.junit.Rule; 19 import org.junit.Test; 20 import org.junit.rules.TestRule; 21 import org.junit.runner.Description; 22 import org.junit.runners.model.Statement; 23 24 import dalvik.system.CloseGuard; 25 26 /** 27 * Tests {@link CloseGuard}. 28 */ 29 public class CloseGuardTest { 30 31 /** 32 * Resets the {@link CloseGuard#ENABLED} state back to the value it had when the test started. 33 */ 34 @Rule 35 public TestRule rule = this::preserveEnabledState; 36 37 private Statement preserveEnabledState(final Statement base, Description description) { 38 return new Statement() { 39 @Override 40 public void evaluate() throws Throwable { 41 boolean oldEnabledState = CloseGuard.isEnabled(); 42 try { 43 base.evaluate(); 44 } finally { 45 CloseGuard.setEnabled(oldEnabledState); 46 } 47 } 48 }; 49 } 50 51 @Test 52 public void testEnabled_NotOpen() throws Throwable { 53 CloseGuard.setEnabled(true); 54 ResourceOwner owner = new ResourceOwner(); 55 assertUnreleasedResources(owner, 0); 56 } 57 58 @Test 59 public void testEnabled_OpenNotClosed() throws Throwable { 60 CloseGuard.setEnabled(true); 61 ResourceOwner owner = new ResourceOwner(); 62 owner.open(); 63 assertUnreleasedResources(owner, 1); 64 } 65 66 @Test 67 public void testEnabled_OpenThenClosed() throws Throwable { 68 CloseGuard.setEnabled(true); 69 ResourceOwner owner = new ResourceOwner(); 70 owner.open(); 71 owner.close(); 72 assertUnreleasedResources(owner, 0); 73 } 74 75 @Test 76 public void testEnabledWhenCreated_DisabledWhenOpen() throws Throwable { 77 CloseGuard.setEnabled(true); 78 ResourceOwner owner = new ResourceOwner(); 79 CloseGuard.setEnabled(false); 80 owner.open(); 81 82 // Although the resource was not released it should not report it because CloseGuard was 83 // not enabled when the CloseGuard was opened. 84 assertUnreleasedResources(owner, 0); 85 } 86 87 @Test 88 public void testEnabledWhenOpened_DisabledWhenFinalized() throws Throwable { 89 CloseGuard.setEnabled(true); 90 ResourceOwner owner = new ResourceOwner(); 91 owner.open(); 92 CloseGuard.setEnabled(false); 93 94 // We report if CloseGuard was enabled on open. 95 assertUnreleasedResources(owner, 1); 96 } 97 98 @Test 99 public void testDisabled_NotOpen() throws Throwable { 100 CloseGuard.setEnabled(false); 101 ResourceOwner owner = new ResourceOwner(); 102 assertUnreleasedResources(owner, 0); 103 } 104 105 @Test 106 public void testDisabled_OpenNotClosed() throws Throwable { 107 CloseGuard.setEnabled(false); 108 ResourceOwner owner = new ResourceOwner(); 109 owner.open(); 110 assertUnreleasedResources(owner, 0); 111 } 112 113 @Test 114 public void testDisabled_OpenThenClosed() throws Throwable { 115 CloseGuard.setEnabled(false); 116 ResourceOwner owner = new ResourceOwner(); 117 owner.open(); 118 owner.close(); 119 assertUnreleasedResources(owner, 0); 120 } 121 122 @Test 123 public void testDisabledWhenCreated_EnabledWhenOpen() throws Throwable { 124 CloseGuard.setEnabled(false); 125 ResourceOwner owner = new ResourceOwner(); 126 CloseGuard.setEnabled(true); 127 owner.open(); 128 129 // The enabled state only matters during the open call. 130 assertUnreleasedResources(owner, 1); 131 } 132 133 private void assertUnreleasedResources(ResourceOwner owner, int expectedCount) 134 throws Throwable { 135 try { 136 CloseGuardSupport.getFinalizerChecker().accept(owner, expectedCount); 137 } finally { 138 // Close the resource so that CloseGuard does not generate a warning for real when it 139 // is actually finalized. 140 owner.close(); 141 } 142 } 143 144 /** 145 * A test user of {@link CloseGuard}. 146 */ 147 private static class ResourceOwner { 148 149 private final CloseGuard closeGuard; 150 151 ResourceOwner() { 152 closeGuard = CloseGuard.get(); 153 } 154 155 public void open() { 156 closeGuard.open("close"); 157 } 158 159 public void close() { 160 closeGuard.close(); 161 } 162 163 /** 164 * Make finalize public so that it can be tested directly without relying on garbage 165 * collection to trigger it. 166 */ 167 @Override 168 public void finalize() throws Throwable { 169 closeGuard.warnIfOpen(); 170 super.finalize(); 171 } 172 } 173 } 174