package com.taobao.tddl.qatest.sequence;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.sql.DataSource;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import com.taobao.tddl.sequence.exception.SequenceException;
import com.taobao.tddl.sequence.impl.DefaultSequence;
import com.taobao.tddl.sequence.impl.DefaultSequenceDao;
/**
* 对sequence正确性的验证
* <p/>
* Created Date: 2010-12-28 下午02:21:04
*/
public class DefaultSequenceTest {
protected static ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "classpath:sequence/spring_context_default_sequence.xml" });
protected static DataSource normal0DS = (DataSource) context.getBean("normal_0");
private int step = 1000;
protected static DefaultSequence seque = null;
protected static DefaultSequence sq1 = null;
protected static DefaultSequence sq2 = null;
protected static DefaultSequence sq3 = null;
protected static DefaultSequence sq4 = null;
protected static DefaultSequence sq5 = null;
protected static DefaultSequence sq6 = null;
private Set<Long> set = new HashSet<Long>();
private AtomicInteger seqCnt = new AtomicInteger();
@BeforeClass
public static void setup() {
seque = (DefaultSequence) context.getBean("sequence");
DefaultSequenceDao sequeDao = (DefaultSequenceDao) context.getBean("sequenceDao");
sq1 = new DefaultSequence();
sq1.setName("ni");
sq1.setSequenceDao(sequeDao);
sq2 = new DefaultSequence();
sq2.setName("ni");
sq2.setSequenceDao(sequeDao);
sq3 = new DefaultSequence();
sq3.setName("ni");
sq3.setSequenceDao(sequeDao);
sq4 = new DefaultSequence();
sq4.setName("ni");
sq4.setSequenceDao(sequeDao);
sq5 = new DefaultSequence();
sq5.setName("ni");
sq5.setSequenceDao(sequeDao);
sq6 = new DefaultSequence();
sq6.setName("ni");
sq6.setSequenceDao(sequeDao);
}
/**
* 验证取到下个值为上个值加1
*
* @throws SequenceException
*/
@Test
public void getNextValueTest() throws SequenceException {
long value = seque.nextValue();
long nextValue = seque.nextValue();
Assert.assertEquals(value + 1, nextValue);
}
/**
* 同个线程,验证取下个值为当前加1
*
* @throws SequenceException
*/
@Test
public void sameTreadTest() throws SequenceException {
long value = seque.nextValue();
DefaultSequence seque1 = (DefaultSequence) context.getBean("sequence");
long value1 = seque1.nextValue();
Assert.assertEquals(value + 1, value1);
}
/**
* 不同线程,验证取到的值为上个取到值的下个区间
*
* @throws SequenceException
*/
@Test
public void difTreadTest() throws SequenceException {
long value = sq1.nextValue();
long value1 = sq2.nextValue();
Assert.assertEquals(value + step, value1);
}
/**
* 不同线程,上个线程为执行数小于步长情况
*
* @throws SequenceException
*/
@Test
public void difTreadInStepTest() throws SequenceException {
int times = 10;
long value = 0;
value = sq3.nextValue();
for (int i = 0; i < 10; i++) {
sq3.nextValue();
}
long value1 = sq4.nextValue();
Assert.assertEquals(times % step == 0 ? (times / step) * step + value : (times / step + 1) * step + value,
value1);
}
/**
* 不同线程,上个本线程执行数大于步长情况
*
* @throws SequenceException
*/
@Test
public void difTreadOverStepTest() throws SequenceException {
int times = 2020;
long value = 0;
value = sq5.nextValue();
for (int i = 1; i < times; i++) {
sq5.nextValue();
}
long value1 = sq6.nextValue();
Assert.assertEquals(times % step == 0 ? (times / step) * step + value : (times / step + 1) * step + value,
value1);
}
/**
* 验证从不同的记录的正确性
*
* @throws SequenceException
*/
@Test
public void difRecordTest() throws SequenceException {
long value = 0;
long temp = 0;
int times = 10;
DefaultSequenceDao sequeDao = (DefaultSequenceDao) context.getBean("sequenceDao");
DefaultSequence sqR = new DefaultSequence();
sqR.setName("hao");
sqR.setSequenceDao(sequeDao);
value = seque.nextValue();
for (int i = 0; i < times; i++) {
temp = seque.nextValue();
}
Assert.assertEquals(value + times, temp);
value = sqR.nextValue();
for (int i = 0; i < times; i++) {
temp = sqR.nextValue();
}
Assert.assertEquals(value + times, temp);
}
/**
* 多个线程去取,验证取到的数据都不一样
*
* @throws SequenceException
*/
@Test
public void multiTest() throws SequenceException {
int times = 100;
for (int i = 0; i < times; i++) {
DefaultSequenceDao sequeDao = (DefaultSequenceDao) context.getBean("sequenceDao");
DefaultSequence sq = new DefaultSequence();
sq.setName("hao");
sq.setSequenceDao(sequeDao);
set.add(sq.nextValue());
}
Assert.assertEquals(times, set.size());
}
/**
* 同时起多个线程
*
* @throws SequenceException
* @throws InterruptedException
*/
@Test
public void multiThreadTest() throws SequenceException, InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(100);
final CountDownLatch count = new CountDownLatch(1);
int times = 100;
for (int i = 0; i < times; i++) {
es.execute(new Runnable() {
public void run() {
try {
count.await();
} catch (InterruptedException e) {
}
try {
DefaultSequenceDao sequeDao = (DefaultSequenceDao) context.getBean("sequenceDao");
DefaultSequence sq = new DefaultSequence();
sq.setName("hao");
sq.setSequenceDao(sequeDao);
set.add(sq.nextValue());
seqCnt.getAndIncrement();
} catch (DataAccessException e) {
} catch (SequenceException e) {
e.printStackTrace();
}
}
});
}
count.countDown();
while (seqCnt.get() < times) {
TimeUnit.MICROSECONDS.sleep(10);
}
Assert.assertEquals(times, set.size());
}
}