package com.path.android.jobqueue.test.jobmanager; import android.content.Context; import com.path.android.jobqueue.JobHolder; import com.path.android.jobqueue.JobManager; import com.path.android.jobqueue.Params; import com.path.android.jobqueue.config.Configuration; import com.path.android.jobqueue.executor.JobConsumerExecutor; import com.path.android.jobqueue.network.NetworkEventProvider; import com.path.android.jobqueue.network.NetworkUtil; import com.path.android.jobqueue.test.TestBase; import com.path.android.jobqueue.test.jobs.DummyJob; import org.fest.reflect.core.*; import org.fest.reflect.method.*; import static org.hamcrest.CoreMatchers.*; import org.hamcrest.*; import org.robolectric.*; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicInteger; public class JobManagerTestBase extends TestBase { protected JobManager createJobManager() { return new JobManager(Robolectric.application, UUID.randomUUID().toString()); } protected JobManager createJobManager(Configuration.Builder configurationBuilder) { return new JobManager(Robolectric.application, configurationBuilder.id(UUID.randomUUID().toString()).build()); } protected static class DummyTwoLatchJob extends DummyJob { private final CountDownLatch waitFor; private final CountDownLatch trigger; private final CountDownLatch onRunLatch; protected DummyTwoLatchJob(Params params, CountDownLatch waitFor, CountDownLatch trigger) { super(params); this.waitFor = waitFor; this.trigger = trigger; onRunLatch = new CountDownLatch(1); } public void waitTillOnRun() throws InterruptedException { onRunLatch.await(); } @Override public void onRun() throws Throwable { onRunLatch.countDown(); waitFor.await(); super.onRun(); trigger.countDown(); } } protected static class DummyLatchJob extends DummyJob { private final CountDownLatch latch; protected DummyLatchJob(Params params, CountDownLatch latch) { super(params); this.latch = latch; } @Override public void onRun() throws Throwable { super.onRun(); latch.countDown(); } } protected static class DummyJobWithRunCount extends DummyJob { public static int runCount; protected DummyJobWithRunCount(boolean persistent) { super(new Params(0).setPersistent(persistent)); } @Override public void onRun() throws Throwable { runCount++; super.onRun(); throw new RuntimeException("i am dummy, i throw exception when running"); } @Override protected boolean shouldReRunOnThrowable(Throwable throwable) { return true; } @Override protected int getRetryLimit() { return 5; } } protected static class DummyNetworkUtil implements NetworkUtil { private boolean hasNetwork; protected void setHasNetwork(boolean hasNetwork) { this.hasNetwork = hasNetwork; } @Override public boolean isConnected(Context context) { return hasNetwork; } } protected static class DummyNetworkUtilWithConnectivityEventSupport implements NetworkUtil, NetworkEventProvider { private boolean hasNetwork; private Listener listener; protected void setHasNetwork(boolean hasNetwork, boolean notifyListener) { this.hasNetwork = hasNetwork; if(notifyListener && listener != null) { listener.onNetworkChange(hasNetwork); } } @Override public boolean isConnected(Context context) { return hasNetwork; } @Override public void setListener(Listener listener) { this.listener = listener; } public boolean isConnected() { return hasNetwork; } } protected static class ObjectReference { Object object; Object getObject() { return object; } void setObject(Object object) { this.object = object; } } protected Invoker<JobHolder> getNextJobMethod(JobManager jobManager) { return Reflection.method("getNextJob").withReturnType(JobHolder.class).in(jobManager); } protected Invoker<Void> getRemoveJobMethod(JobManager jobManager) { return Reflection.method("removeJob").withParameterTypes(JobHolder.class).in(jobManager); } protected JobConsumerExecutor getConsumerExecutor(JobManager jobManager) { return Reflection.field("jobConsumerExecutor").ofType(JobConsumerExecutor.class).in(jobManager).get(); } protected org.fest.reflect.field.Invoker<AtomicInteger> getActiveConsumerCount(JobConsumerExecutor jobConsumerExecutor) { return Reflection.field("activeConsumerCount").ofType(AtomicInteger.class).in(jobConsumerExecutor); } public static class NeverEndingDummyJob extends DummyJob { final Object lock; final Semaphore semaphore; public NeverEndingDummyJob(Params params, Object lock, Semaphore semaphore) { super(params); this.lock = lock; this.semaphore = semaphore; } @Override public void onRun() throws Throwable { super.onRun(); MatcherAssert.assertThat("job should be able to acquire a semaphore", semaphore.tryAcquire(), equalTo(true)); synchronized (lock) { lock.wait(); } semaphore.release(); } } }