/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.internal.offheap; import static org.junit.Assert.*; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.SystemOutRule; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import static org.mockito.Mockito.*; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.*; import org.apache.geode.internal.cache.RegionEntry; import org.apache.geode.test.junit.categories.UnitTest; /* * PowerMock used in this test to verify static method MemoryAllocatorImpl.debugLog */ @Category(UnitTest.class) @RunWith(PowerMockRunner.class) @PowerMockIgnore({"*.UnitTest"}) @PrepareForTest({MemoryAllocatorImpl.class}) public class ReferenceCountHelperImplTest { ReferenceCountHelperImpl rchi; @Rule public SystemOutRule sor = new SystemOutRule(); @Test public void doTrackReferenceCountsWithTrackRefsTrueAndTrackFreesTrue() { rchi = getTrueTrue(); assertTrue(rchi.trackReferenceCounts()); } @Test public void doTrackReferenceCountsWithTrackRefsTrueAndTrackFreesFalse() { rchi = getTrueFalse(); assertTrue(rchi.trackReferenceCounts()); } @Test public void doTrackReferenceCountsWithTrackRefsFalseAndTrackFreesTrue() { rchi = getFalseTrue(); assertFalse(rchi.trackReferenceCounts()); } @Test public void doTrackReferenceCountsWithTrackRefsFalseAndTrackFreesFalse() { rchi = getFalseFalse(); assertFalse(rchi.trackReferenceCounts()); } @Test public void doTrackFreedReferenceCountsWithTrackRefsTrueAndTrackFreesTrue() { rchi = getTrueTrue(); assertTrue(rchi.trackFreedReferenceCounts()); } @Test public void doTrackFreedReferenceCountsWithTrackRefsTrueAndTrackFreesFalse() { rchi = getTrueFalse(); assertFalse(rchi.trackFreedReferenceCounts()); } @Test public void doTrackFreedReferenceCountsWithTrackRefsFalseAndTrackFreesTrue() { rchi = getFalseTrue(); assertTrue(rchi.trackFreedReferenceCounts()); } @Test public void doTrackFreedReferenceCountsWithTrackRefsFalseAndTrackFreesFalse() { rchi = getFalseFalse(); assertFalse(rchi.trackFreedReferenceCounts()); } @Test public void doSkipRefCountTrackingWithTrackRefsTrueAndTrackFreesTrue() { rchi = getTrueTrue(); Object preOwner = rchi.getReferenceCountOwner(); rchi.skipRefCountTracking(); Object postOwner = rchi.getReferenceCountOwner(); assertTrue(postOwner != preOwner); // skip sets owner to SKIP_REF_COUNT_TRACKING assertFalse(rchi.isRefCountTracking()); Long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; rchi.refCountChanged(address, decRefCount, rc); List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address); assertEquals(null, list); rchi.unskipRefCountTracking(); postOwner = rchi.getReferenceCountOwner(); assertEquals(postOwner, preOwner); assertTrue(rchi.isRefCountTracking()); } @Test public void doSkipRefCountTrackingWithTrackRefsFalseAndTrackFreesTrue() { rchi = getFalseTrue(); Object preOwner = rchi.getReferenceCountOwner(); assertEquals(null, preOwner); // getReferenceCountOwner returns null if not tracking rchi.skipRefCountTracking(); assertFalse(rchi.isRefCountTracking()); rchi.unskipRefCountTracking(); assertFalse(rchi.isRefCountTracking()); // system prop not set } @Test public void doSkipRefCountTrackingWithTrackRefsFalseAndTrackFreesFalse() { rchi = getFalseFalse(); Object preOwner = rchi.getReferenceCountOwner(); assertEquals(null, preOwner); // getReferenceCountOwner returns null if not tracking rchi.skipRefCountTracking(); assertFalse(rchi.isRefCountTracking()); rchi.unskipRefCountTracking(); assertFalse(rchi.isRefCountTracking()); // system prop not set } @Test public void doSkipRefCountTrackingWithTrackRefsTrueAndTrackFreesFalse() { rchi = getTrueFalse(); Object preOwner = rchi.getReferenceCountOwner(); rchi.skipRefCountTracking(); Object postOwner = rchi.getReferenceCountOwner(); assertTrue(postOwner != preOwner); // skip sets owner to SKIP_REF_COUNT_TRACKING assertFalse(rchi.isRefCountTracking()); rchi.unskipRefCountTracking(); postOwner = rchi.getReferenceCountOwner(); assertEquals(postOwner, preOwner); assertTrue(rchi.isRefCountTracking()); } @Test public void doSetReferenceCountOwnerWithTrackRefsTrueAndTrackFreesTrue() { rchi = getTrueTrue(); String owner = null; rchi.setReferenceCountOwner(owner); AtomicInteger ai = rchi.getReenterCount(); assertEquals(0, ai.get()); owner = new String("SomeOwner"); rchi.setReferenceCountOwner(owner); ai = rchi.getReenterCount(); assertEquals(1, ai.get()); assertEquals(rchi.getReferenceCountOwner(), owner); String owner2 = new String("SomeOwner2"); rchi.setReferenceCountOwner(owner2); ai = rchi.getReenterCount(); assertEquals(2, ai.get()); assertTrue(rchi.getReferenceCountOwner() != owner2); // stays original owner until cnt = 0 String owner3 = null; rchi.setReferenceCountOwner(owner3); ai = rchi.getReenterCount(); assertEquals(1, ai.get()); assertEquals(rchi.getReferenceCountOwner(), owner); owner = null; rchi.setReferenceCountOwner(owner); ai = rchi.getReenterCount(); assertEquals(0, ai.get()); assertEquals(rchi.getReferenceCountOwner(), null); RegionEntry re = mock(RegionEntry.class); rchi.setReferenceCountOwner(re); ai = rchi.getReenterCount(); assertEquals(1, ai.get()); assertEquals(rchi.getReferenceCountOwner(), re); Long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; rchi.refCountChanged(address, decRefCount, rc); List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); RefCountChangeInfo rcci = list.get(0); assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); rcci = list.get(0); assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? decRefCount = true; rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); rcci = list.get(0); assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(0, list.size()); } @Test public void doSetReferenceCountOwnerWithTrackRefsFalseAndTrackFreesTrue() { rchi = getFalseTrue(); String owner = null; rchi.setReferenceCountOwner(owner); assertEquals(rchi.getReferenceCountOwner(), owner); AtomicInteger ai = rchi.getReenterCount(); assertEquals(null, ai); } @Test public void doSetReferenceCountOwnerWithTrackRefsFalseAndTrackFreesFalse() { rchi = getFalseFalse(); String owner = null; rchi.setReferenceCountOwner(owner); assertEquals(rchi.getReferenceCountOwner(), owner); AtomicInteger ai = rchi.getReenterCount(); assertEquals(null, ai); } @Test public void doSetReferenceCountOwnerWithTrackRefsTrueAndTrackFreesFalse() { rchi = getTrueFalse(); String owner = null; rchi.setReferenceCountOwner(owner); AtomicInteger ai = rchi.getReenterCount(); assertEquals(0, ai.get()); owner = new String("SomeOwner"); rchi.setReferenceCountOwner(owner); ai = rchi.getReenterCount(); assertEquals(1, ai.get()); assertEquals(rchi.getReferenceCountOwner(), owner); String owner2 = new String("SomeOwner2"); rchi.setReferenceCountOwner(owner2); ai = rchi.getReenterCount(); assertEquals(2, ai.get()); assertTrue(rchi.getReferenceCountOwner() != owner2); // stays original owner until cnt = 0 String owner3 = null; rchi.setReferenceCountOwner(owner3); ai = rchi.getReenterCount(); assertEquals(1, ai.get()); assertEquals(rchi.getReferenceCountOwner(), owner); owner = null; rchi.setReferenceCountOwner(owner); ai = rchi.getReenterCount(); assertEquals(0, ai.get()); assertEquals(rchi.getReferenceCountOwner(), null); } @Test public void doCreateReferenceCountOwnerWithTrackRefsTrueAndTrackFreesTrue() { rchi = getTrueTrue(); Object owner = rchi.createReferenceCountOwner(); assertFalse(owner == null); AtomicInteger ai = rchi.getReenterCount(); assertEquals(1, ai.get()); owner = null; rchi.setReferenceCountOwner(owner); ai = rchi.getReenterCount(); assertEquals(0, ai.get()); assertEquals(rchi.getReferenceCountOwner(), null); } @Test public void doCreateReferenceCountOwnerWithTrackRefsFalseAndTrackFreesTrue() { rchi = getFalseTrue(); Object owner = rchi.createReferenceCountOwner(); assertTrue(owner == null); } @Test public void doCreateReferenceCountOwnerWithTrackRefsFalseAndTrackFreesFalse() { rchi = getFalseFalse(); Object owner = rchi.createReferenceCountOwner(); assertTrue(owner == null); } @Test public void doCreateReferenceCountOwnerWithTrackRefsTrueAndTrackFreesFalse() { rchi = getTrueFalse(); Object owner = rchi.createReferenceCountOwner(); assertFalse(owner == null); AtomicInteger ai = rchi.getReenterCount(); assertEquals(1, ai.get()); owner = null; rchi.setReferenceCountOwner(owner); ai = rchi.getReenterCount(); assertEquals(0, ai.get()); assertEquals(rchi.getReferenceCountOwner(), null); } @Test public void doRefCountChangedNoOwnerWithTrackRefsTrueAndTrackFreesTrue() { rchi = getTrueTrue(); Long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; rchi.freeRefCountInfo(address); // quick check of free of nonexistent info Object owner = rchi.getReferenceCountOwner(); assertTrue(owner == null); rchi.refCountChanged(address, decRefCount, rc); List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); RefCountChangeInfo rcci = list.get(0); assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); rcci = list.get(0); assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? decRefCount = true; rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(2, list.size()); // inc and dec are tracked in different changeinfo objects (?) rcci = list.get(1); assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(2, list.size()); rcci = list.get(1); assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? list = rchi.peekRefCountInfo(address); assertEquals(2, list.size()); // list contains 2 entries from inc/dec done above List<RefCountChangeInfo> freeInfo = rchi.getFreeRefCountInfo(address); assertEquals(null, freeInfo); // no freeRefCountInfo calls yet rchi.freeRefCountInfo(address); // when freed, moved to FreeRefCountInfo list List<RefCountChangeInfo> freeInfo2 = rchi.getFreeRefCountInfo(address); assertEquals(2, freeInfo2.size()); // the inc/dec info moved to freeRefCountInfo list list = rchi.getRefCountInfo(address); assertEquals(null, list); // the inc/dec ref count list should now be null } @Test public void doRefCountChangedNoOwnerWithTrackRefsFalseAndTrackFreesTrue() { rchi = getFalseTrue(); Long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; Object owner = rchi.getReferenceCountOwner(); assertTrue(owner == null); rchi.refCountChanged(address, decRefCount, rc); List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address); assertEquals(null, list); decRefCount = true; rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(null, list); List<RefCountChangeInfo> freeInfo = rchi.getFreeRefCountInfo(address); assertEquals(null, freeInfo); // no freeRefCountInfo calls yet rchi.freeRefCountInfo(address); // noop when not tracking freeInfo = rchi.getFreeRefCountInfo(address); assertEquals(null, freeInfo); // should still be null } @Test public void doRefCountChangedNoOwnerWithTrackRefsFalseAndTrackFreesFalse() { rchi = getFalseFalse(); Long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; Object owner = rchi.getReferenceCountOwner(); assertTrue(owner == null); rchi.refCountChanged(address, decRefCount, rc); List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address); assertEquals(null, list); decRefCount = true; rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(null, list); List<RefCountChangeInfo> freeInfo = rchi.getFreeRefCountInfo(address); assertEquals(null, freeInfo); // no freeRefCountInfo calls yet rchi.freeRefCountInfo(address); // noop when not tracking freeInfo = rchi.getFreeRefCountInfo(address); assertEquals(null, freeInfo); // should still be null } @Test public void doRefCountChangedNoOwnerWithTrackRefsTrueAndTrackFreesFalse() { rchi = getTrueFalse(); Long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; Object owner = rchi.getReferenceCountOwner(); assertTrue(owner == null); rchi.refCountChanged(address, decRefCount, rc); List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); RefCountChangeInfo rcci = list.get(0); assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); rcci = list.get(0); assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? decRefCount = true; rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(2, list.size()); // inc and dec are tracked in different changeinfo objects (?) rcci = list.get(1); assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(2, list.size()); rcci = list.get(1); assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? list = rchi.peekRefCountInfo(address); assertEquals(2, list.size()); // list contains 2 entries from inc/dec done above List<RefCountChangeInfo> freeInfo = rchi.getFreeRefCountInfo(address); assertEquals(null, freeInfo); // no freeRefCountInfo calls yet rchi.freeRefCountInfo(address); // when freed, moved to FreeRefCountInfo list List<RefCountChangeInfo> freeInfo2 = rchi.getFreeRefCountInfo(address); assertEquals(null, freeInfo2); // not tracking freed info list = rchi.getRefCountInfo(address); assertEquals(null, list); // the inc/dec ref count list should now be null } @Test public void doRefCountChangedWithOwnerWithTrackRefsTrueAndTrackFreesTrue() { rchi = getTrueTrue(); Long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; Object owner = rchi.createReferenceCountOwner(); assertFalse(owner == null); AtomicInteger ai = rchi.getReenterCount(); assertEquals(1, ai.get()); owner = null; rchi.setReferenceCountOwner(owner); ai = rchi.getReenterCount(); assertEquals(0, ai.get()); assertEquals(rchi.getReferenceCountOwner(), null); owner = rchi.createReferenceCountOwner(); assertFalse(owner == null); ai = rchi.getReenterCount(); assertEquals(1, ai.get()); rchi.refCountChanged(address, decRefCount, rc); List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); RefCountChangeInfo rcci = list.get(0); assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); rcci = list.get(0); assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? decRefCount = true; rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); // inc and dec are tracked in different changeinfo objects (?) rcci = list.get(0); assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? rchi.refCountChanged(address, decRefCount, rc); list = rchi.getRefCountInfo(address); assertEquals(0, list.size()); } @Test public void doRefCountChangedWithOwnerWithTrackRefsFalseAndTrackFreesTrue() { rchi = getFalseTrue(); Long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; Object owner = rchi.createReferenceCountOwner(); assertTrue(owner == null); rchi.refCountChanged(address, decRefCount, rc); List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address); assertEquals(null, list); rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(null, list); decRefCount = true; rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(null, list); // inc and dec are tracked in different changeinfo objects (?) rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(null, list); List<RefCountChangeInfo> freeInfo = rchi.getFreeRefCountInfo(address); assertEquals(null, freeInfo); // no freeRefCountInfo calls yet rchi.freeRefCountInfo(address); // when freed, moved to FreeRefCountInfo list freeInfo = rchi.getFreeRefCountInfo(address); assertEquals(null, freeInfo); // the inc/dec info moved to freeRefCountInfo list } @Test public void doRefCountChangedWithOwnerWithTrackRefsFalseAndTrackFreesFalse() { rchi = getFalseFalse(); Long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; Object owner = rchi.createReferenceCountOwner(); assertTrue(owner == null); rchi.refCountChanged(address, decRefCount, rc); List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address); assertEquals(null, list); rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(null, list); decRefCount = true; rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(null, list); // inc and dec are tracked in different changeinfo objects (?) rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(null, list); List<RefCountChangeInfo> freeInfo = rchi.getFreeRefCountInfo(address); assertEquals(null, freeInfo); // no freeRefCountInfo calls yet rchi.freeRefCountInfo(address); // when freed, moved to FreeRefCountInfo list freeInfo = rchi.getFreeRefCountInfo(address); assertEquals(null, freeInfo); // the inc/dec info moved to freeRefCountInfo list } @Test public void doRefCountChangedWithOwnerWithTrackRefsTrueAndTrackFreesFalse() { rchi = getTrueFalse(); Long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; Object owner = rchi.createReferenceCountOwner(); assertFalse(owner == null); AtomicInteger ai = rchi.getReenterCount(); assertEquals(1, ai.get()); owner = null; rchi.setReferenceCountOwner(owner); ai = rchi.getReenterCount(); assertEquals(0, ai.get()); assertEquals(rchi.getReferenceCountOwner(), null); owner = rchi.createReferenceCountOwner(); assertFalse(owner == null); ai = rchi.getReenterCount(); assertEquals(1, ai.get()); rchi.refCountChanged(address, decRefCount, rc); List<RefCountChangeInfo> list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); RefCountChangeInfo rcci = list.get(0); assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); rcci = list.get(0); assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? decRefCount = true; rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); // inc and dec are tracked in different changeinfo objects (?) rcci = list.get(0); assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(0, list.size()); } @Test public void doGetRefCountInfoWithTrackRefsTrueAndTrackFreesTrue() { rchi = getTrueTrue(); long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; List<RefCountChangeInfo> list = null; rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); RefCountChangeInfo rcci = list.get(0); assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); rcci = list.get(0); assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? List<RefCountChangeInfo> info = rchi.getRefCountInfo(address); // now getRefCountInfo assertEquals(1, info.size()); rcci = info.get(0); assertEquals(1, rcci.getUseCount()); list = rchi.peekRefCountInfo(address); assertEquals(0, list.size()); // getRefCountInfo leaves list LOCKED (i.e. empty) } @Test public void doRefCountChangedAfterGetRefCountInfoWithTrackRefsTrueAndTrackFreesTrue() throws Exception { rchi = getTrueTrue(); long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; List<RefCountChangeInfo> list = null; rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); RefCountChangeInfo rcci = list.get(0); assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); rcci = list.get(0); assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? List<RefCountChangeInfo> info = rchi.getRefCountInfo(address); // now getRefCountInfo assertEquals(1, info.size()); rcci = info.get(0); assertEquals(1, rcci.getUseCount()); list = rchi.peekRefCountInfo(address); assertEquals(0, list.size()); // getRefCountInfo leaves list LOCKED (i.e. empty) sor.mute(); // Mute system out PowerMockito.spy(MemoryAllocatorImpl.class); // Watch the impl for invocation of debugLog rchi.refCountChanged(address, decRefCount, rc); // this line should fail. no inc after getInfo // allowed PowerMockito.verifyStatic(); MemoryAllocatorImpl.debugLog("refCount inced after orphan detected for @1000", true); decRefCount = true; rchi.refCountChanged(address, decRefCount, rc); // this line should fail. no inc after getInfo // allowed PowerMockito.verifyStatic(); MemoryAllocatorImpl.debugLog("refCount deced after orphan detected for @1000", true); rchi.freeRefCountInfo(address); // this line should fail. no free after getInfo allowed PowerMockito.verifyStatic(); MemoryAllocatorImpl.debugLog("freed after orphan detected for @1000", true); } @Test public void doGetRefCountInfoWithTrackRefsFalseAndTrackFreesTrue() { rchi = getFalseTrue(); long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; List<RefCountChangeInfo> list = rchi.getRefCountInfo(address); assertEquals(null, list); rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(null, list); List<RefCountChangeInfo> info = rchi.getRefCountInfo(address); assertEquals(null, info); list = rchi.peekRefCountInfo(address); assertEquals(null, list); rchi.refCountChanged(address, decRefCount, rc); // this will be ignored. decRefCount = true; rchi.refCountChanged(address, decRefCount, rc); // this will be ignored. rchi.freeRefCountInfo(address); // this will be ignored. } @Test public void doGetRefCountInfoWithTrackRefsFalseAndTrackFreesFalse() { rchi = getFalseFalse(); long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; List<RefCountChangeInfo> list = rchi.getRefCountInfo(address); assertEquals(null, list); rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(null, list); List<RefCountChangeInfo> info = rchi.getRefCountInfo(address); assertEquals(null, info); list = rchi.peekRefCountInfo(address); assertEquals(null, list); } @Test public void doGetRefCountInfoWithTrackRefsTrueAndTrackFreesFalse() { rchi = getTrueFalse(); long address = (long) 0x1000; boolean decRefCount = false; int rc = 1; List<RefCountChangeInfo> list = null; rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); RefCountChangeInfo rcci = list.get(0); assertEquals(0, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? rchi.refCountChanged(address, decRefCount, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); rcci = list.get(0); assertEquals(1, rcci.getUseCount()); // line 258 of ref cnt helper does not set useCount = 1 // when adding new entry? List<RefCountChangeInfo> info = rchi.getRefCountInfo(address); // now getRefCountInfo assertEquals(1, info.size()); rcci = info.get(0); assertEquals(1, rcci.getUseCount()); list = rchi.peekRefCountInfo(address); assertEquals(0, list.size()); // getRefCountInfo leaves list LOCKED (i.e. empty) } private ReferenceCountHelperImpl getTrueTrue() { return new ReferenceCountHelperImpl(true, true); } private ReferenceCountHelperImpl getTrueFalse() { return new ReferenceCountHelperImpl(true, false); } private ReferenceCountHelperImpl getFalseTrue() { return new ReferenceCountHelperImpl(false, true); } private ReferenceCountHelperImpl getFalseFalse() { return new ReferenceCountHelperImpl(false, false); } private ReferenceCountHelperImpl getHookedImpl() { return new HookedReferenceCountHelperImpl(true, true); } @Test public void doGetRefCountInfoNonRegionEntryConcurrencyTest() { rchi = getHookedImpl(); long address = (long) 0x1000; int rc = 1; RefCountChangeInfo rcci; List<RefCountChangeInfo> list = null; rchi.setReferenceCountOwner("TestOwner"); // assume test identity rchi.refCountChanged(address, false, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); rcci = list.get(0); assertEquals(1, rcci.getUseCount()); // hooked impl simulates a concurrent update, so cnt is > // expected rchi.setReferenceCountOwner(null); // sets owner to null and resets count rchi.setReferenceCountOwner(null); // sets owner to null and resets count rchi.setReferenceCountOwner("TestOwner2"); // assume new identity rchi.refCountChanged(address, false, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); rcci = list.get(0); assertEquals(2, rcci.getUseCount()); // list is not null, so hook not used rchi.refCountChanged(address, true, rc); // dec ref count list = rchi.peekRefCountInfo(address); assertEquals(2, list.size()); // dec adds new list of stack traces rcci = list.get(1); assertEquals(0, rcci.getUseCount()); // cnt starts at 0 for new entries List<RefCountChangeInfo> info = rchi.getRefCountInfo(address); // now getRefCountInfo assertEquals(3, info.size()); // hooked impl added one to list rcci = info.get(2); assertEquals(0, rcci.getUseCount()); // count starts at 0 for new entries list = rchi.peekRefCountInfo(address); assertEquals(0, list.size()); // getRefCountInfo leaves list LOCKED (i.e. empty) } @Test public void doGetRefCountInfoRegionEntryConcurrencyTest() { rchi = getHookedImpl(); long address = (long) 0x1000; int rc = 1; RefCountChangeInfo rcci; List<RefCountChangeInfo> list = null; RegionEntry re = mock(RegionEntry.class); rchi.setReferenceCountOwner(re); // set owner to region entry type rchi.refCountChanged(address, false, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); rcci = list.get(0); assertEquals(1, rcci.getUseCount()); // hooked impl simulates a concurrent update, so cnt is > // expected rchi.setReferenceCountOwner(null); // sets owner to null and resets count rchi.setReferenceCountOwner(null); // sets owner to null and resets count RegionEntry re2 = mock(RegionEntry.class); rchi.setReferenceCountOwner(re2); // set owner to region entry type rchi.refCountChanged(address, false, rc); list = rchi.peekRefCountInfo(address); assertEquals(1, list.size()); rcci = list.get(0); assertEquals(2, rcci.getUseCount()); // list is not null, so hook not used rchi.refCountChanged(address, true, rc); // dec ref count list = rchi.peekRefCountInfo(address); assertEquals(2, list.size()); // dec adds new list of stack traces rcci = list.get(1); assertEquals(0, rcci.getUseCount()); // cnt starts at 0 for new entries List<RefCountChangeInfo> info = rchi.getRefCountInfo(address); // now getRefCountInfo assertEquals(3, info.size()); // hooked impl added one to list rcci = info.get(2); assertEquals(0, rcci.getUseCount()); // count starts at 0 for new entries list = rchi.peekRefCountInfo(address); assertEquals(0, list.size()); // getRefCountInfo leaves list LOCKED (i.e. empty) } private class HookedReferenceCountHelperImpl extends ReferenceCountHelperImpl { HookedReferenceCountHelperImpl(boolean trackRefCounts, boolean trackFreedRefCounts) { super(trackRefCounts, trackFreedRefCounts); } protected int refCountChangedTestHookCount = 0; /* * Update list of stack traces for address. Hooked SUT should see that the list changed. */ @Override protected void getReferenceCountInfoTestHook( ConcurrentMap<Long, List<RefCountChangeInfo>> stacktraces, long address) { List<RefCountChangeInfo> updatedList = new ArrayList<RefCountChangeInfo>(stacktraces.get(address)); RefCountChangeInfo rcci = new RefCountChangeInfo(false, 0, "TestOwner"); updatedList.add(rcci); stacktraces.put(address, updatedList); } /* * Reinvoke refCountChanged to update reference count. Hooked SUT should see that the count has * changed. */ @Override protected void refCountChangedTestHook(Long address, boolean decRefCount, int rc) { if (refCountChangedTestHookCount == 0) { refCountChangedTestHookCount++; refCountChanged(address, decRefCount, rc); } else { refCountChangedTestHookCount--; } } } }