package com.path.android.jobqueue.test.jobmanager;
import android.util.Log;
import com.path.android.jobqueue.JobManager;
import com.path.android.jobqueue.Params;
import com.path.android.jobqueue.config.Configuration;
import com.path.android.jobqueue.test.jobs.DummyJob;
import static org.hamcrest.CoreMatchers.*;
import org.hamcrest.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.*;
import java.util.Collection;
import java.util.LinkedList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@RunWith(RobolectricTestRunner.class)
public class MultiThreadTest extends JobManagerTestBase {
private static AtomicInteger multiThreadedJobCounter;
@Test
public void testMultiThreaded() throws Exception {
multiThreadedJobCounter = new AtomicInteger(0);
final JobManager jobManager = createJobManager(new Configuration.Builder(Robolectric.application)
.loadFactor(3).maxConsumerCount(10));
int limit = 200;
ExecutorService executor = new ThreadPoolExecutor(20, 20, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(limit));
Collection<Future<?>> futures = new LinkedList<Future<?>>();
for(int i = 0; i < limit; i++) {
final int id = i;
futures.add(executor.submit(new Runnable() {
@Override
public void run() {
final boolean persistent = Math.round(Math.random()) % 2 == 0;
boolean requiresNetwork = Math.round(Math.random()) % 2 == 0;
int priority = (int) (Math.round(Math.random()) % 10);
multiThreadedJobCounter.incrementAndGet();
jobManager.addJob(new DummyJobForMultiThread(id, new Params(priority).setRequiresNetwork(requiresNetwork).setPersistent(persistent)));
}
}));
}
for (Future<?> future:futures) {
future.get();
}
Log.d("TAG", "added all jobs");
//wait until all jobs are added
long start = System.nanoTime();
long timeLimit = JobManager.NS_PER_MS * 20000;//20 seconds
while(System.nanoTime() - start < timeLimit && multiThreadedJobCounter.get() != 0) {
Thread.sleep(1000);
}
Log.d("TAG", "did we reach timeout? " + (System.nanoTime() - start >= timeLimit));
MatcherAssert.assertThat("jobmanager count should be 0",
jobManager.count(), equalTo(0));
MatcherAssert.assertThat("multiThreadedJobCounter should be 0",
multiThreadedJobCounter.get(), equalTo(0));
}
public static class DummyJobForMultiThread extends DummyJob {
private int id;
private DummyJobForMultiThread(int id, Params params) {
super(params);
this.id = id;
}
@Override
public void onRun() throws Throwable {
super.onRun();
int remaining = multiThreadedJobCounter.decrementAndGet();
//take some time
Thread.sleep((long) (Math.random() * 1000));
//throw exception w/ small change
if(Math.random() < .1) {
throw new Exception("decided to die, will retry");
}
Log.d("DummyJobForMultiThread", "persistent:" + isPersistent() + ", requires network:" + requiresNetwork() + ", running " + id + ", remaining: " + remaining);
}
@Override
protected boolean shouldReRunOnThrowable(Throwable throwable) {
multiThreadedJobCounter.incrementAndGet();
return true;
}
};
}