package com.adobe.prefs.testing; import org.mockito.ArgumentCaptor; import org.testng.annotations.AfterClass; import org.testng.annotations.DataProvider; import java.util.Arrays; import java.util.UUID; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.prefs.NodeChangeEvent; import java.util.prefs.NodeChangeListener; import java.util.prefs.PreferenceChangeEvent; import java.util.prefs.PreferenceChangeListener; import java.util.prefs.Preferences; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertSame; public abstract class PreferencesTestSupport { private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); private final long delay; final String namespace = UUID.randomUUID().toString(); protected PreferencesTestSupport(long delay) { this.delay = delay; } @AfterClass(alwaysRun = true) public void cleanup() throws Exception { scheduler.shutdown(); for (Preferences prefs : Arrays.asList(Preferences.systemRoot(), Preferences.userRoot())) { if (prefs.nodeExists(namespace)) { prefs.node(namespace).removeNode(); } } } protected NodeChangeListener nodeListener(Preferences prefs) { final NodeChangeListener listener = mock(NodeChangeListener.class); prefs.addNodeChangeListener(listener); return listener; } protected ScheduledFuture<?> schedule(Runnable task) { return scheduler.schedule(task, delay, TimeUnit.MILLISECONDS); } protected ScheduledFuture<?> testNodeAdded(final NodeChangeListener listener, final Preferences parent, final String childName, final int count) { final ArgumentCaptor<NodeChangeEvent> captor = ArgumentCaptor.forClass(NodeChangeEvent.class); final Runnable task = new Runnable() { @Override public void run() { verify(listener, times(count)).childAdded(captor.capture()); final NodeChangeEvent event = captor.getValue(); assertEquals(event.getParent(), parent); assertEquals(event.getChild().name(), childName); } }; return schedule(task); } protected ScheduledFuture<?> testNodeRemoved(final NodeChangeListener listener, final Preferences parent, final String childName, final int count) { final ArgumentCaptor<NodeChangeEvent> captor = ArgumentCaptor.forClass(NodeChangeEvent.class); final Runnable task = new Runnable() { @Override public void run() { verify(listener, times(count)).childRemoved(captor.capture()); final NodeChangeEvent event = captor.getValue(); assertEquals(event.getParent(), parent); assertEquals(event.getChild().name(), childName); } }; return schedule(task); } protected PreferenceChangeListener prefListener(Preferences prefs) { PreferenceChangeListener listener = mock(PreferenceChangeListener.class); prefs.addPreferenceChangeListener(listener); return listener; } protected ScheduledFuture<?> testPrefChange(final PreferenceChangeListener listener, final Preferences prefs, final String key, final String value, final int count) { final ArgumentCaptor<PreferenceChangeEvent> captor = ArgumentCaptor.forClass(PreferenceChangeEvent.class); final Runnable task = new Runnable() { @Override public void run() { verify(listener, times(count)).preferenceChange(captor.capture()); PreferenceChangeEvent event = captor.getValue(); assertSame(event.getNode(), prefs); assertEquals(event.getKey(), key); assertEquals(event.getNewValue(), value); } }; return schedule(task); } @DataProvider(parallel = true) public Object[][] root() { return new Object[][] { { Preferences.systemRoot() }, { Preferences.userRoot() } }; } @DataProvider(parallel = true) public Object[][] chroot() { return new Object[][] { { Preferences.systemRoot().node(namespace) }, { Preferences.userRoot().node(namespace) } }; } }