blob: d2870749b93216ef3855a67657f4500a38e830e3 [file] [log] [blame]
/*
* 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.apache.geode.util.internal.UncheckedUtils.uncheckedCast;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import org.junit.Before;
import org.junit.Test;
import org.apache.geode.internal.cache.RegionEntry;
public class ReferenceCountHelperImplTest {
private BiConsumer<String, Boolean> debugLogger;
@Before
public void setUp() {
debugLogger = uncheckedCast(mock(BiConsumer.class));
}
@Test
public void doTrackReferenceCountsWithTrackRefsTrueAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
assertThat(referenceCountHelperImpl.trackReferenceCounts()).isTrue();
}
@Test
public void doTrackReferenceCountsWithTrackRefsTrueAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
assertThat(referenceCountHelperImpl.trackReferenceCounts()).isTrue();
}
@Test
public void doTrackReferenceCountsWithTrackRefsFalseAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
assertThat(referenceCountHelperImpl.trackReferenceCounts()).isFalse();
}
@Test
public void doTrackReferenceCountsWithTrackRefsFalseAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
assertThat(referenceCountHelperImpl.trackReferenceCounts()).isFalse();
}
@Test
public void doTrackFreedReferenceCountsWithTrackRefsTrueAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
assertThat(referenceCountHelperImpl.trackFreedReferenceCounts()).isTrue();
}
@Test
public void doTrackFreedReferenceCountsWithTrackRefsTrueAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
assertThat(referenceCountHelperImpl.trackFreedReferenceCounts()).isFalse();
}
@Test
public void doTrackFreedReferenceCountsWithTrackRefsFalseAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
assertThat(referenceCountHelperImpl.trackFreedReferenceCounts()).isTrue();
}
@Test
public void doTrackFreedReferenceCountsWithTrackRefsFalseAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
assertThat(referenceCountHelperImpl.trackFreedReferenceCounts()).isFalse();
}
@Test
public void doSkipRefCountTrackingWithTrackRefsTrueAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
Object preOwner = referenceCountHelperImpl.getReferenceCountOwner();
referenceCountHelperImpl.skipRefCountTracking();
Object postOwner = referenceCountHelperImpl.getReferenceCountOwner();
// skip sets owner to SKIP_REF_COUNT_TRACKING
assertThat(postOwner).isNotEqualTo(preOwner);
assertThat(referenceCountHelperImpl.isRefCountTracking()).isFalse();
Long address = (long) 0x1000;
referenceCountHelperImpl.refCountChanged(address, false, 1);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
referenceCountHelperImpl.unskipRefCountTracking();
postOwner = referenceCountHelperImpl.getReferenceCountOwner();
assertThat(preOwner).isEqualTo(postOwner);
assertThat(referenceCountHelperImpl.isRefCountTracking()).isTrue();
}
@Test
public void doSkipRefCountTrackingWithTrackRefsFalseAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
Object preOwner = referenceCountHelperImpl.getReferenceCountOwner();
// getReferenceCountOwner returns null if not tracking
assertThat(preOwner).isNull();
referenceCountHelperImpl.skipRefCountTracking();
assertThat(referenceCountHelperImpl.isRefCountTracking()).isFalse();
referenceCountHelperImpl.unskipRefCountTracking();
assertThat(referenceCountHelperImpl.isRefCountTracking()).isFalse(); // system prop not set
}
@Test
public void doSkipRefCountTrackingWithTrackRefsFalseAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
Object preOwner = referenceCountHelperImpl.getReferenceCountOwner();
// getReferenceCountOwner returns null if not tracking
assertThat(preOwner).isNull();
referenceCountHelperImpl.skipRefCountTracking();
assertThat(referenceCountHelperImpl.isRefCountTracking()).isFalse();
referenceCountHelperImpl.unskipRefCountTracking();
// system prop not set
assertThat(referenceCountHelperImpl.isRefCountTracking()).isFalse();
}
@Test
public void doSkipRefCountTrackingWithTrackRefsTrueAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
Object preOwner = referenceCountHelperImpl.getReferenceCountOwner();
referenceCountHelperImpl.skipRefCountTracking();
Object postOwner = referenceCountHelperImpl.getReferenceCountOwner();
// skip sets owner to SKIP_REF_COUNT_TRACKING
assertThat(postOwner).isNotEqualTo(preOwner);
assertThat(referenceCountHelperImpl.isRefCountTracking()).isFalse();
referenceCountHelperImpl.unskipRefCountTracking();
postOwner = referenceCountHelperImpl.getReferenceCountOwner();
assertThat(preOwner).isEqualTo(postOwner);
assertThat(referenceCountHelperImpl.isRefCountTracking()).isTrue();
}
@Test
public void doSetReferenceCountOwnerWithTrackRefsTrueAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
String owner = null;
referenceCountHelperImpl.setReferenceCountOwner(owner);
AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isZero();
owner = "SomeOwner";
referenceCountHelperImpl.setReferenceCountOwner(owner);
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isOne();
assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isEqualTo(owner);
String owner2 = "SomeOwner2";
referenceCountHelperImpl.setReferenceCountOwner(owner2);
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isEqualTo(2);
// stays original owner until cnt = 0
assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNotEqualTo(owner2);
String owner3 = null;
referenceCountHelperImpl.setReferenceCountOwner(owner3);
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isOne();
assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isEqualTo(owner);
owner = null;
referenceCountHelperImpl.setReferenceCountOwner(owner);
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isZero();
assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
RegionEntry regionEntry = mock(RegionEntry.class);
referenceCountHelperImpl.setReferenceCountOwner(regionEntry);
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isOne();
assertThat(regionEntry).isEqualTo(referenceCountHelperImpl.getReferenceCountOwner());
Long address = (long) 0x1000;
boolean decRefCount = false;
int rc = 1;
referenceCountHelperImpl.refCountChanged(address, decRefCount, rc);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
RefCountChangeInfo refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isZero();
referenceCountHelperImpl.refCountChanged(address, decRefCount, rc);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isOne();
decRefCount = true;
referenceCountHelperImpl.refCountChanged(address, decRefCount, rc);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isZero();
referenceCountHelperImpl.refCountChanged(address, decRefCount, rc);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isEmpty();
}
@Test
public void doSetReferenceCountOwnerWithTrackRefsFalseAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
referenceCountHelperImpl.setReferenceCountOwner(null);
assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount).isNull();
}
@Test
public void doSetReferenceCountOwnerWithTrackRefsFalseAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
referenceCountHelperImpl.setReferenceCountOwner(null);
assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount).isNull();
}
@Test
public void doSetReferenceCountOwnerWithTrackRefsTrueAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
String owner = null;
referenceCountHelperImpl.setReferenceCountOwner(owner);
AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isZero();
owner = "SomeOwner";
referenceCountHelperImpl.setReferenceCountOwner(owner);
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isOne();
assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isEqualTo(owner);
String owner2 = "SomeOwner2";
referenceCountHelperImpl.setReferenceCountOwner(owner2);
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isEqualTo(2);
// stays original owner until cnt = 0
assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isEqualTo(owner);
String owner3 = null;
referenceCountHelperImpl.setReferenceCountOwner(owner3);
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isOne();
assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isEqualTo(owner);
owner = null;
referenceCountHelperImpl.setReferenceCountOwner(owner);
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isZero();
assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
}
@Test
public void doCreateReferenceCountOwnerWithTrackRefsTrueAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
Object owner = referenceCountHelperImpl.createReferenceCountOwner();
assertThat(owner).isNotNull();
AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isOne();
owner = null;
referenceCountHelperImpl.setReferenceCountOwner(owner);
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isZero();
assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
}
@Test
public void doCreateReferenceCountOwnerWithTrackRefsFalseAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
Object owner = referenceCountHelperImpl.createReferenceCountOwner();
assertThat(owner).isNull();
}
@Test
public void doCreateReferenceCountOwnerWithTrackRefsFalseAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
Object owner = referenceCountHelperImpl.createReferenceCountOwner();
assertThat(owner).isNull();
}
@Test
public void doCreateReferenceCountOwnerWithTrackRefsTrueAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
Object owner = referenceCountHelperImpl.createReferenceCountOwner();
assertThat(owner).isNotNull();
AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isOne();
owner = null;
referenceCountHelperImpl.setReferenceCountOwner(owner);
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isZero();
assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
}
@Test
public void doRefCountChangedNoOwnerWithTrackRefsTrueAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
Long address = (long) 0x1000;
// quick check of free of nonexistent info
referenceCountHelperImpl.freeRefCountInfo(address);
Object owner = referenceCountHelperImpl.getReferenceCountOwner();
assertThat(owner).isNull();
referenceCountHelperImpl.refCountChanged(address, false, 1);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
RefCountChangeInfo refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isZero();
referenceCountHelperImpl.refCountChanged(address, false, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isOne();
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
// inc and dec are tracked in different changeinfo objects (?)
assertThat(list).hasSize(2);
refCountChangeInfo = list.get(1);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isZero();
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(2);
refCountChangeInfo = list.get(1);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isOne();
list = referenceCountHelperImpl.peekRefCountInfo(address);
// list contains 2 entries from inc/dec done above
assertThat(list).hasSize(2);
List<RefCountChangeInfo> freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
// no freeRefCountInfo calls yet
assertThat(freeInfo).isNull();
// when freed, moved to FreeRefCountInfo list
referenceCountHelperImpl.freeRefCountInfo(address);
List<RefCountChangeInfo> freeInfo2 = referenceCountHelperImpl.getFreeRefCountInfo(address);
// the inc/dec info moved to freeRefCountInfo list
assertThat(freeInfo2).hasSize(2);
list = referenceCountHelperImpl.getRefCountInfo(address);
// the inc/dec ref count list should now be null
assertThat(list).isNull();
}
@Test
public void doRefCountChangedNoOwnerWithTrackRefsFalseAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
Long address = (long) 0x1000;
Object owner = referenceCountHelperImpl.getReferenceCountOwner();
assertThat(owner).isNull();
referenceCountHelperImpl.refCountChanged(address, false, 1);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
List<RefCountChangeInfo> freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
// no freeRefCountInfo calls yet
assertThat(freeInfo).isNull();
// noop when not tracking
referenceCountHelperImpl.freeRefCountInfo(address);
freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
// should still be null
assertThat(freeInfo).isNull();
}
@Test
public void doRefCountChangedNoOwnerWithTrackRefsFalseAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
Long address = (long) 0x1000;
Object owner = referenceCountHelperImpl.getReferenceCountOwner();
assertThat(owner).isNull();
referenceCountHelperImpl.refCountChanged(address, false, 1);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
List<RefCountChangeInfo> freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
// no freeRefCountInfo calls yet
assertThat(freeInfo).isNull();
// noop when not tracking
referenceCountHelperImpl.freeRefCountInfo(address);
// should still be null
freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
assertThat(freeInfo).isNull();
}
@Test
public void doRefCountChangedNoOwnerWithTrackRefsTrueAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
Long address = (long) 0x1000;
Object owner = referenceCountHelperImpl.getReferenceCountOwner();
assertThat(owner).isNull();
referenceCountHelperImpl.refCountChanged(address, false, 1);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
RefCountChangeInfo refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isZero();
referenceCountHelperImpl.refCountChanged(address, false, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isOne();
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
// inc and dec are tracked in different changeinfo objects (?)
assertThat(list).hasSize(2);
refCountChangeInfo = list.get(1);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isZero();
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(2);
refCountChangeInfo = list.get(1);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isOne();
list = referenceCountHelperImpl.peekRefCountInfo(address);
// list contains 2 entries from inc/dec done above
assertThat(list).hasSize(2);
List<RefCountChangeInfo> freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
// no freeRefCountInfo calls yet
assertThat(freeInfo).isNull();
// when freed, moved to FreeRefCountInfo list
referenceCountHelperImpl.freeRefCountInfo(address);
List<RefCountChangeInfo> freeInfo2 = referenceCountHelperImpl.getFreeRefCountInfo(address);
// not tracking freed info
assertThat(freeInfo2).isNull();
list = referenceCountHelperImpl.getRefCountInfo(address);
// the inc/dec ref count list should now be null
assertThat(list).isNull();
}
@Test
public void doRefCountChangedWithOwnerWithTrackRefsTrueAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
Long address = (long) 0x1000;
Object owner = referenceCountHelperImpl.createReferenceCountOwner();
assertThat(owner).isNotNull();
AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isOne();
owner = null;
referenceCountHelperImpl.setReferenceCountOwner(owner);
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isZero();
assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
owner = referenceCountHelperImpl.createReferenceCountOwner();
assertThat(owner).isNotNull();
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isOne();
referenceCountHelperImpl.refCountChanged(address, false, 1);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
RefCountChangeInfo refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isZero();
referenceCountHelperImpl.refCountChanged(address, false, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isOne();
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
// inc and dec are tracked in different changeinfo objects (?)
assertThat(list).hasSize(1);
refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isZero();
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.getRefCountInfo(address);
assertThat(list).isEmpty();
}
@Test
public void doRefCountChangedWithOwnerWithTrackRefsFalseAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
Long address = (long) 0x1000;
Object owner = referenceCountHelperImpl.createReferenceCountOwner();
assertThat(owner).isNull();
referenceCountHelperImpl.refCountChanged(address, false, 1);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
referenceCountHelperImpl.refCountChanged(address, false, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
// inc and dec are tracked in different changeinfo objects (?)
assertThat(list).isNull();
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
List<RefCountChangeInfo> freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
// no freeRefCountInfo calls yet
assertThat(freeInfo).isNull();
// when freed, moved to FreeRefCountInfo list
referenceCountHelperImpl.freeRefCountInfo(address);
freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
// the inc/dec info moved to freeRefCountInfo list
assertThat(freeInfo).isNull();
}
@Test
public void doRefCountChangedWithOwnerWithTrackRefsFalseAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
Long address = (long) 0x1000;
Object owner = referenceCountHelperImpl.createReferenceCountOwner();
assertThat(owner).isNull();
referenceCountHelperImpl.refCountChanged(address, false, 1);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
referenceCountHelperImpl.refCountChanged(address, false, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
// inc and dec are tracked in different changeinfo objects (?)
assertThat(list).isNull();
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
List<RefCountChangeInfo> freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
// no freeRefCountInfo calls yet
assertThat(freeInfo).isNull();
// when freed, moved to FreeRefCountInfo list
referenceCountHelperImpl.freeRefCountInfo(address);
freeInfo = referenceCountHelperImpl.getFreeRefCountInfo(address);
// the inc/dec info moved to freeRefCountInfo list
assertThat(freeInfo).isNull();
}
@Test
public void doRefCountChangedWithOwnerWithTrackRefsTrueAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
Long address = (long) 0x1000;
Object owner = referenceCountHelperImpl.createReferenceCountOwner();
assertThat(owner).isNotNull();
AtomicInteger reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isOne();
owner = null;
referenceCountHelperImpl.setReferenceCountOwner(owner);
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isZero();
assertThat(referenceCountHelperImpl.getReferenceCountOwner()).isNull();
owner = referenceCountHelperImpl.createReferenceCountOwner();
assertThat(owner).isNotNull();
reenterCount = referenceCountHelperImpl.getReenterCount();
assertThat(reenterCount.get()).isOne();
referenceCountHelperImpl.refCountChanged(address, false, 1);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
RefCountChangeInfo refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isZero();
referenceCountHelperImpl.refCountChanged(address, false, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isOne();
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
// inc and dec are tracked in different changeinfo objects (?)
assertThat(list).hasSize(1);
refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isZero();
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isEmpty();
}
@Test
public void doGetRefCountInfoWithTrackRefsTrueAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
Long address = (long) 0x1000;
referenceCountHelperImpl.refCountChanged(address, false, 1);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
RefCountChangeInfo refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isZero();
referenceCountHelperImpl.refCountChanged(address, false, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isOne();
// now getRefCountInfo
List<RefCountChangeInfo> info = referenceCountHelperImpl.getRefCountInfo(address);
assertThat(info).hasSize(1);
refCountChangeInfo = info.get(0);
assertThat(refCountChangeInfo.getUseCount()).isOne();
list = referenceCountHelperImpl.peekRefCountInfo(address);
// getRefCountInfo leaves list LOCKED (i.e. empty)
assertThat(list).isEmpty();
}
@Test
public void doRefCountChangedAfterGetRefCountInfoWithTrackRefsTrueAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueTrue();
Long address = (long) 0x1000;
referenceCountHelperImpl.refCountChanged(address, false, 1);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
RefCountChangeInfo refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isZero();
referenceCountHelperImpl.refCountChanged(address, false, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isOne();
// now getRefCountInfo
List<RefCountChangeInfo> info = referenceCountHelperImpl.getRefCountInfo(address);
assertThat(info).hasSize(1);
refCountChangeInfo = info.get(0);
assertThat(refCountChangeInfo.getUseCount()).isOne();
list = referenceCountHelperImpl.peekRefCountInfo(address);
// getRefCountInfo leaves list LOCKED (i.e. empty)
assertThat(list).isEmpty();
// this line should fail. no inc after getInfo allowed
referenceCountHelperImpl.refCountChanged(address, false, 1);
verify(debugLogger).accept("refCount inced after orphan detected for @1000", true);
// this line should fail. no inc after getInfo allowed
referenceCountHelperImpl.refCountChanged(address, true, 1);
verify(debugLogger).accept("refCount deced after orphan detected for @1000", true);
// this line should fail. no free after getInfo allowed
referenceCountHelperImpl.freeRefCountInfo(address);
verify(debugLogger).accept("freed after orphan detected for @1000", true);
}
@Test
public void doGetRefCountInfoWithTrackRefsFalseAndTrackFreesTrue() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseTrue();
Long address = (long) 0x1000;
List<RefCountChangeInfo> list = referenceCountHelperImpl.getRefCountInfo(address);
assertThat(list).isNull();
referenceCountHelperImpl.refCountChanged(address, false, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
List<RefCountChangeInfo> info = referenceCountHelperImpl.getRefCountInfo(address);
assertThat(info).isNull();
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
// TODO: add assertions for the following
// this will be ignored.
referenceCountHelperImpl.refCountChanged(address, false, 1);
// this will be ignored.
referenceCountHelperImpl.refCountChanged(address, true, 1);
// this will be ignored.
referenceCountHelperImpl.freeRefCountInfo(address);
}
@Test
public void doGetRefCountInfoWithTrackRefsFalseAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_FalseFalse();
Long address = (long) 0x1000;
List<RefCountChangeInfo> list = referenceCountHelperImpl.getRefCountInfo(address);
assertThat(list).isNull();
referenceCountHelperImpl.refCountChanged(address, false, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
List<RefCountChangeInfo> info = referenceCountHelperImpl.getRefCountInfo(address);
assertThat(info).isNull();
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).isNull();
}
@Test
public void doGetRefCountInfoWithTrackRefsTrueAndTrackFreesFalse() {
ReferenceCountHelperImpl referenceCountHelperImpl = newReferenceCountHelperImpl_TrueFalse();
long address = 0x1000;
referenceCountHelperImpl.refCountChanged(address, false, 1);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
RefCountChangeInfo refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isZero();
referenceCountHelperImpl.refCountChanged(address, false, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
refCountChangeInfo = list.get(0);
// line 258 of ref cnt helper does not set useCount = 1 when adding new entry?
assertThat(refCountChangeInfo.getUseCount()).isOne();
// now getRefCountInfo
List<RefCountChangeInfo> info = referenceCountHelperImpl.getRefCountInfo(address);
assertThat(info).hasSize(1);
refCountChangeInfo = info.get(0);
assertThat(refCountChangeInfo.getUseCount()).isOne();
list = referenceCountHelperImpl.peekRefCountInfo(address);
// getRefCountInfo leaves list LOCKED (i.e. empty)
assertThat(list).isEmpty();
}
@Test
public void doGetRefCountInfoNonRegionEntryConcurrencyTest() {
ReferenceCountHelperImpl referenceCountHelperImpl = newHookedReferenceCountHelperImpl();
Long address = (long) 0x1000;
// assume test identity
referenceCountHelperImpl.setReferenceCountOwner("TestOwner");
referenceCountHelperImpl.refCountChanged(address, false, 1);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
RefCountChangeInfo refCountChangeInfo = list.get(0);
// hooked impl simulates a concurrent update, so cnt is > expected
assertThat(refCountChangeInfo.getUseCount()).isOne();
// sets owner to null and resets count
referenceCountHelperImpl.setReferenceCountOwner(null);
// sets owner to null and resets count // sets owner to null and resets count
// assume new identity
referenceCountHelperImpl.setReferenceCountOwner("TestOwner2");
referenceCountHelperImpl.refCountChanged(address, false, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
refCountChangeInfo = list.get(0);
// list is not null, so hook not used
assertThat(refCountChangeInfo.getUseCount()).isEqualTo(2);
// dec ref count
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
// dec adds new list of stack traces
assertThat(list).hasSize(2);
refCountChangeInfo = list.get(1);
// cnt starts at 0 for new entries
assertThat(refCountChangeInfo.getUseCount()).isZero();
// now getRefCountInfo
List<RefCountChangeInfo> info = referenceCountHelperImpl.getRefCountInfo(address);
// hooked impl added one to list
assertThat(info).hasSize(3);
refCountChangeInfo = info.get(2);
// count starts at 0 for new entries
assertThat(refCountChangeInfo.getUseCount()).isZero();
list = referenceCountHelperImpl.peekRefCountInfo(address);
// getRefCountInfo leaves list LOCKED (i.e. empty)
assertThat(list).isEmpty();
}
@Test
public void doGetRefCountInfoRegionEntryConcurrencyTest() {
ReferenceCountHelperImpl referenceCountHelperImpl = newHookedReferenceCountHelperImpl();
Long address = (long) 0x1000;
RegionEntry regionEntry1 = mock(RegionEntry.class);
// set owner to region entry type
referenceCountHelperImpl.setReferenceCountOwner(regionEntry1);
referenceCountHelperImpl.refCountChanged(address, false, 1);
List<RefCountChangeInfo> list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
RefCountChangeInfo refCountChangeInfo = list.get(0);
// hooked impl simulates a concurrent update, so cnt is > expected
assertThat(refCountChangeInfo.getUseCount()).isOne();
// sets owner to null and resets count
referenceCountHelperImpl.setReferenceCountOwner(null);
// sets owner to null and resets count
referenceCountHelperImpl.setReferenceCountOwner(null);
RegionEntry regionEntry2 = mock(RegionEntry.class);
// set owner to region entry type
referenceCountHelperImpl.setReferenceCountOwner(regionEntry2);
referenceCountHelperImpl.refCountChanged(address, false, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
assertThat(list).hasSize(1);
refCountChangeInfo = list.get(0);
// list is not null, so hook not used
assertThat(refCountChangeInfo.getUseCount()).isEqualTo(2);
// dec ref count
referenceCountHelperImpl.refCountChanged(address, true, 1);
list = referenceCountHelperImpl.peekRefCountInfo(address);
// dec adds new list of stack traces
assertThat(list).hasSize(2);
refCountChangeInfo = list.get(1);
// cnt starts at 0 for new entries
assertThat(refCountChangeInfo.getUseCount()).isZero();
// now getRefCountInfo
List<RefCountChangeInfo> info = referenceCountHelperImpl.getRefCountInfo(address);
// hooked impl added one to list
assertThat(info).hasSize(3);
refCountChangeInfo = info.get(2);
// count starts at 0 for new entries
assertThat(refCountChangeInfo.getUseCount()).isZero();
list = referenceCountHelperImpl.peekRefCountInfo(address);
// getRefCountInfo leaves list LOCKED (i.e. empty)
assertThat(list).isEmpty();
}
private ReferenceCountHelperImpl newReferenceCountHelperImpl_TrueTrue() {
return new ReferenceCountHelperImpl(true, true, debugLogger);
}
private ReferenceCountHelperImpl newReferenceCountHelperImpl_TrueFalse() {
return new ReferenceCountHelperImpl(true, false, debugLogger);
}
private ReferenceCountHelperImpl newReferenceCountHelperImpl_FalseTrue() {
return new ReferenceCountHelperImpl(false, true, debugLogger);
}
private ReferenceCountHelperImpl newReferenceCountHelperImpl_FalseFalse() {
return new ReferenceCountHelperImpl(false, false, debugLogger);
}
private ReferenceCountHelperImpl newHookedReferenceCountHelperImpl() {
return new HookedReferenceCountHelperImpl(true, true, debugLogger);
}
private static class HookedReferenceCountHelperImpl extends ReferenceCountHelperImpl {
private int refCountChangedTestHookCount;
private HookedReferenceCountHelperImpl(boolean trackRefCounts, boolean trackFreedRefCounts,
BiConsumer<String, Boolean> debugLogger) {
super(trackRefCounts, trackFreedRefCounts, debugLogger);
}
/**
* 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<>(stackTraces.get(address));
RefCountChangeInfo refCountChangeInfo = new RefCountChangeInfo(false, 0, "TestOwner");
updatedList.add(refCountChangeInfo);
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--;
}
}
}
}