package org.netbeans.gradle.project.properties;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.jtrim.event.CopyOnTriggerListenerManager;
import org.jtrim.event.EventListeners;
import org.jtrim.event.ListenerManager;
import org.jtrim.event.ListenerRef;
import org.jtrim.property.MutableProperty;
import org.jtrim.property.PropertySource;
import org.junit.Test;
import static org.junit.Assert.*;
public class NbPropertiesTest {
private static void runGC() {
System.gc();
System.gc();
Runtime.getRuntime().runFinalization();
System.gc();
System.gc();
Runtime.getRuntime().runFinalization();
}
private static void addWeakListener(
PropertySource<?> property,
final AtomicInteger listenerCallCount,
AtomicReference<ListenerRef> resultRef) {
// We do this in a separate method to decrease the chance that
// some hidden local variable will keep a hard reference to the listener
// or the ListenerRef.
PropertySource<?> weakProperty = NbProperties.weakListenerProperty(property);
resultRef.set(weakProperty.addChangeListener(new Runnable() {
@Override
public void run() {
listenerCallCount.incrementAndGet();
}
}));
}
@Test
public void testWeakListener() {
AtomicReference<ListenerRef> listenerRef = new AtomicReference<>(null);
final AtomicInteger listenerCallCount = new AtomicInteger(0);
TestProperty<Integer> property = new TestProperty<>(0);
addWeakListener(property, listenerCallCount, listenerRef);
runGC();
property.setValue(1);
assertEquals("expected call count", 1, listenerCallCount.get());
assertEquals("listener count", 1, property.getListenerCount());
listenerRef.set(null);
runGC();
property.setValue(2);
assertEquals("expected call count", 1, listenerCallCount.get());
assertEquals("listener count", 0, property.getListenerCount());
}
private static final class TestProperty<ValueType> implements MutableProperty<ValueType> {
private volatile ValueType value;
private final ListenerManager<Runnable> listeners;
public TestProperty(ValueType value) {
this.value = value;
this.listeners = new CopyOnTriggerListenerManager<>();
}
public int getListenerCount() {
return listeners.getListenerCount();
}
@Override
public void setValue(ValueType value) {
this.value = value;
EventListeners.dispatchRunnable(listeners);
}
@Override
public ValueType getValue() {
return value;
}
@Override
public ListenerRef addChangeListener(Runnable listener) {
return listeners.registerListener(listener);
}
}
}