/
NTSequenceTest.java
151 lines (127 loc) · 4.88 KB
/
NTSequenceTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/**
* Author: obullxl@163.com
* Copyright (c) 2020-2023 All Rights Reserved.
*/
package cn.ntopic.sequence;
import cn.ntopic.sequence.impl.NTSequenceImpl;
import com.alibaba.druid.pool.DruidDataSource;
import org.junit.Assert;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
/**
* 分布式序列服务单元测试
*
* @author obullxl 2023年06月22日: 新增
*/
public class NTSequenceTest {
@Test
public void test_next() {
// 1. 创建数据源
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:sqlite:/Users/obullxl/CodeSpace/sequence-jdbc/SequenceJDBC.sqlite");
dataSource.setDriverClassName("org.sqlite.JDBC");
dataSource.setPoolPreparedStatements(false);
dataSource.setMaxPoolPreparedStatementPerConnectionSize(-1);
dataSource.setTestOnBorrow(true);
dataSource.setTestOnReturn(false);
dataSource.setTestWhileIdle(true);
dataSource.setValidationQuery("SELECT '1' FROM sqlite_master LIMIT 1");
final String tableName = "nt_sequence";
final String testSeqName = "TEST-" + System.currentTimeMillis() + "-" + System.nanoTime();
try {
// 2. 清理数据
this.deleteSequence(dataSource, tableName, testSeqName);
// 3. 实例化序列服务
NTSequenceImpl ntSequence = new NTSequenceImpl(dataSource);
ntSequence.setTableName(tableName);
ntSequence.createTable();
ntSequence.setStep(5);
ntSequence.init();
// 4. 并发测试
this.multiThreadTest(ntSequence, testSeqName);
// 5. 清理测试数据
this.deleteSequence(dataSource, tableName, testSeqName);
} finally {
dataSource.close();
}
}
private void deleteSequence(DruidDataSource dataSource, String tableName, String sequenceName) {
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = dataSource.getConnection();
String deleteSQL = String.format("DELETE FROM %s WHERE name=?", tableName);
stmt = conn.prepareStatement(deleteSQL);
stmt.setString(1, sequenceName);
stmt.executeUpdate();
} catch (Throwable e) {
// ignore
} finally {
this.closeQuietly(stmt);
this.closeQuietly(conn);
}
}
private void closeQuietly(AutoCloseable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (Throwable e) {
// ignore
}
}
}
private void multiThreadTest(NTSequence ntSequence, String sequenceName) {
final int threadCount = 3;
final int valueCount = 107;
CountDownLatch countDownLatch = new CountDownLatch(threadCount);
Map<Integer, List<Long>> seqValues = new ConcurrentHashMap<>();
for (int i = 0; i < threadCount; i++) {
List<Long> sequenceValues = new ArrayList<>();
seqValues.put(i, sequenceValues);
new SequenceThread(countDownLatch, valueCount, ntSequence, sequenceName, sequenceValues).start();
}
try {
countDownLatch.await();
} catch (Throwable e) {
e.printStackTrace();
}
// 数据检测
Set<Long> allValues = new HashSet<>();
Assert.assertEquals(threadCount, seqValues.size());
for (int i = 0; i < threadCount; i++) {
allValues.addAll(seqValues.get(i));
Assert.assertEquals(valueCount, seqValues.get(i).size());
}
Assert.assertEquals(threadCount * valueCount, allValues.size());
}
private static class SequenceThread extends Thread {
private final int valueCount;
private final CountDownLatch countDownLatch;
private final NTSequence ntSequence;
private final String sequenceName;
private final List<Long> sequenceValues;
public SequenceThread(CountDownLatch countDownLatch, int valueCount, NTSequence ntSequence, String sequenceName, List<Long> sequenceValues) {
this.countDownLatch = countDownLatch;
this.valueCount = valueCount;
this.ntSequence = ntSequence;
this.sequenceName = sequenceName;
this.sequenceValues = sequenceValues;
}
@Override
public void run() {
try {
for (int i = 0; i < valueCount; i++) {
this.sequenceValues.add(ntSequence.next(this.sequenceName));
}
// 释放信号
this.countDownLatch.countDown();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
}