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 dalvik.system; 17 18 import java.util.Collections; 19 import java.util.List; 20 import org.junit.Rule; 21 import org.junit.Test; 22 import org.junit.rules.TestRule; 23 import org.junit.runner.JUnitCore; 24 import org.junit.runner.RunWith; 25 import org.junit.runner.notification.Failure; 26 import org.junit.runners.JUnit4; 27 28 import static org.junit.Assert.assertEquals; 29 import static org.junit.Assert.fail; 30 31 @RunWith(JUnit4.class) 32 public class CloseGuardSupportTest { 33 34 @Test 35 public void testDoesReleaseResource() { 36 List<Failure> failures = JUnitCore.runClasses(DoesReleaseResource.class).getFailures(); 37 assertEquals(Collections.emptyList(), failures); 38 } 39 40 public static class DoesReleaseResource { 41 @Rule public TestRule rule = CloseGuardSupport.getRule(); 42 @Test public void test() { 43 CloseGuard closeGuard = CloseGuard.get(); 44 closeGuard.open("test resource"); 45 closeGuard.close(); 46 } 47 } 48 49 @Test 50 public void testDoesReleaseResourceTwice() { 51 List<Failure> failures = JUnitCore.runClasses(DoesReleaseResourceTwice.class).getFailures(); 52 assertEquals(Collections.emptyList(), failures); 53 } 54 55 public static class DoesReleaseResourceTwice { 56 @Rule public TestRule rule = CloseGuardSupport.getRule(); 57 @Test public void test() { 58 CloseGuard closeGuard = CloseGuard.get(); 59 closeGuard.open("test resource"); 60 closeGuard.close(); 61 closeGuard.close(); 62 } 63 } 64 65 @Test 66 public void testDoesNotReleaseResource() { 67 List<Failure> failures = JUnitCore.runClasses(DoesNotReleaseResource.class).getFailures(); 68 assertEquals("Failure count", 1, failures.size()); 69 Failure failure = failures.get(0); 70 checkResourceNotReleased(failure, "Unreleased resources found in test"); 71 } 72 73 public static class DoesNotReleaseResource { 74 @Rule public TestRule rule = CloseGuardSupport.getRule(); 75 @Test public void test() { 76 CloseGuard closeGuard = CloseGuard.get(); 77 closeGuard.open("test resource"); 78 } 79 } 80 81 @Test 82 public void testDoesNotReleaseResourceDueToFailure() { 83 List<Failure> failures = JUnitCore 84 .runClasses(DoesNotReleaseResourceDueToFailure.class) 85 .getFailures(); 86 assertEquals("Failure count", 1, failures.size()); 87 Failure failure = failures.get(0); 88 checkResourceNotReleased(failure, "failure"); 89 } 90 91 public static class DoesNotReleaseResourceDueToFailure { 92 @Rule public TestRule rule = CloseGuardSupport.getRule(); 93 @Test public void test() { 94 CloseGuard closeGuard = CloseGuard.get(); 95 closeGuard.open("test resource"); 96 fail("failure"); 97 } 98 } 99 100 @Test 101 public void testResourceOwnerDoesNotOverrideFinalize() { 102 List<Failure> failures = JUnitCore 103 .runClasses(ResourceOwnerDoesNotOverrideFinalize.class) 104 .getFailures(); 105 assertEquals("Failure count", 1, failures.size()); 106 Failure failure = failures.get(0); 107 assertEquals("Class java.lang.String does not have a finalize() method", 108 failure.getMessage()); 109 } 110 111 public static class ResourceOwnerDoesNotOverrideFinalize { 112 @Rule public TestRule rule = CloseGuardSupport.getRule(); 113 @Test 114 public void test() { 115 CloseGuardSupport.getFinalizerChecker().accept("not resource owner", 0); 116 } 117 } 118 119 @Test 120 public void testResourceOwnerOverridesFinalizeButDoesNotReportLeak() { 121 List<Failure> failures = JUnitCore 122 .runClasses(ResourceOwnerOverridesFinalizeButDoesNotReportLeak.class) 123 .getFailures(); 124 assertEquals("Failure count", 1, failures.size()); 125 Failure failure = failures.get(0); 126 assertEquals("Expected 1 unreleased resources, found 0;" 127 + " see suppressed exceptions for details", 128 failure.getMessage()); 129 } 130 131 public static class ResourceOwnerOverridesFinalizeButDoesNotReportLeak { 132 @Rule public TestRule rule = CloseGuardSupport.getRule(); 133 @Test 134 public void test() { 135 CloseGuardSupport.getFinalizerChecker().accept(new Object() { 136 @Override 137 protected void finalize() throws Throwable { 138 super.finalize(); 139 } 140 }, 1); 141 } 142 } 143 144 @Test 145 public void testResourceOwnerOverridesFinalizeAndReportsLeak() { 146 List<Failure> failures = JUnitCore 147 .runClasses(ResourceOwnerOverridesFinalizeAndReportsLeak.class) 148 .getFailures(); 149 assertEquals("Failure count", 1, failures.size()); 150 Failure failure = failures.get(0); 151 checkResourceNotReleased(failure, "Unreleased resources found in test"); 152 } 153 154 public static class ResourceOwnerOverridesFinalizeAndReportsLeak { 155 @Rule public TestRule rule = CloseGuardSupport.getRule(); 156 @Test 157 public void test() { 158 CloseGuardSupport.getFinalizerChecker().accept(new Object() { 159 private CloseGuard guard = CloseGuard.get(); 160 { 161 guard.open("test resource"); 162 } 163 @Override 164 protected void finalize() throws Throwable { 165 guard.warnIfOpen(); 166 super.finalize(); 167 } 168 }, 1); 169 } 170 } 171 172 private void checkResourceNotReleased(Failure failure, String expectedMessage) { 173 @SuppressWarnings("ThrowableResultOfMethodCallIgnored") 174 Throwable exception = failure.getException(); 175 assertEquals(expectedMessage, exception.getMessage()); 176 Throwable[] suppressed = exception.getSuppressed(); 177 assertEquals("Suppressed count", 1, suppressed.length); 178 exception = suppressed[0]; 179 assertEquals("Explicit termination method 'test resource' not called", 180 exception.getMessage()); 181 } 182 } 183