From e944524d9d51dfee01f4e5dad5fd3538dd8873b0 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Wed, 03 Jul 2013 15:22:12 +0000
Subject: [PATCH] Fix OPENDJ-1049: ReferenceCountedObject can be released twice in some circumstances
---
opendj3/opendj-ldap-sdk/src/test/java/com/forgerock/opendj/util/ReferenceCountedObjectTestCase.java | 58 ++++++++++++++++++++++++++++++++++------------------------
1 files changed, 34 insertions(+), 24 deletions(-)
diff --git a/opendj3/opendj-ldap-sdk/src/test/java/com/forgerock/opendj/util/ReferenceCountedObjectTestCase.java b/opendj3/opendj-ldap-sdk/src/test/java/com/forgerock/opendj/util/ReferenceCountedObjectTestCase.java
index ec51fd9..7fde80c 100644
--- a/opendj3/opendj-ldap-sdk/src/test/java/com/forgerock/opendj/util/ReferenceCountedObjectTestCase.java
+++ b/opendj3/opendj-ldap-sdk/src/test/java/com/forgerock/opendj/util/ReferenceCountedObjectTestCase.java
@@ -91,36 +91,46 @@
}
/**
- * This test attempts to test that finalization works. It loops at most 100
- * times performing GCs and checking to see if the finalizer was called.
- * Usually objects are finalized after 2 GCs, so the loop should complete
- * quite quickly.
- *
- * @throws Exception
- * If an unexpected error occurred.
+ * This test attempts to test that finalization works.
*/
@Test
- public void testFinalization() throws Exception {
+ public void testFinalization() {
final Impl impl = mock(Impl.class);
when(impl.newInstance()).thenReturn(object);
final ReferenceCountedObject<Object> rco = rco(impl);
- ReferenceCountedObject<Object>.Reference ref = rco.acquire();
- System.gc();
- System.gc();
+ final ReferenceCountedObject<Object>.Reference ref = rco.acquire();
verify(impl, never()).destroyInstance(object);
- // Read in order to prevent optimization.
- if (ref != null) {
- ref = null;
- }
- for (int i = 0; i < 100; i++) {
- System.gc();
- try {
- verify(impl).destroyInstance(object);
- break; // Finalized so stop.
- } catch (final Throwable t) {
- // Retry.
- }
- }
+ ref.finalize(); // Simulate GC.
+ verify(impl).destroyInstance(object);
+ }
+
+ /**
+ * Test for issue OPENDJ-1049.
+ */
+ @Test
+ public void testReleaseOnceOnly() {
+ final Impl impl = mock(Impl.class);
+ when(impl.newInstance()).thenReturn(object);
+ final ReferenceCountedObject<Object> rco = rco(impl);
+
+ // Create two references.
+ final ReferenceCountedObject<Object>.Reference ref1 = rco.acquire();
+ final ReferenceCountedObject<Object>.Reference ref2 = rco.acquire();
+
+ /*
+ * Now release first reference multiple times and make sure that the
+ * resource is not destroyed.
+ */
+ ref1.release();
+ ref1.release(); // Redundant release.
+ ref1.finalize(); // Simulate GC.
+ verify(impl, never()).destroyInstance(object);
+
+ /*
+ * Now release second reference which should cause the resource to be
+ * destroyed.
+ */
+ ref2.release();
verify(impl).destroyInstance(object);
}
--
Gitblit v1.10.0