forked from quickfix-j/quickfixj
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMemoryStoreStressTest.java
More file actions
136 lines (110 loc) · 3.81 KB
/
Copy pathMemoryStoreStressTest.java
File metadata and controls
136 lines (110 loc) · 3.81 KB
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
package quickfix;
import org.openjdk.jcstress.annotations.Actor;
import org.openjdk.jcstress.annotations.Arbiter;
import org.openjdk.jcstress.annotations.Expect;
import org.openjdk.jcstress.annotations.JCStressTest;
import org.openjdk.jcstress.annotations.Outcome;
import org.openjdk.jcstress.annotations.State;
import org.openjdk.jcstress.infra.results.JJ_Result;
import java.io.IOException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@SuppressWarnings("unused")
public class MemoryStoreStressTest {
@State
@JCStressTest
@Outcome(id = "2, 2", expect = Expect.ACCEPTABLE)
@Outcome(id = "1, 2", expect = Expect.FORBIDDEN, desc = "Source sequence update lost")
@Outcome(id = "2, 1", expect = Expect.FORBIDDEN, desc = "Target sequence update lost")
public static class SingleSenderSequenceTest {
private final MemoryStoreWrapper underTest;
public SingleSenderSequenceTest() {
this.underTest = new MemoryStoreWrapper();
}
// application thread
@Actor
public void incrementSender() {
underTest.incrementSenderSequence();
}
// QFJ Message Processor
@Actor
public void incrementTarget() {
underTest.incrementTargetSequence();
}
@Arbiter
public void captureResult(JJ_Result result) {
result.r1 = underTest.getSenderSequence();
result.r2 = underTest.getTargetSequence();
}
}
@State
@JCStressTest
@Outcome(id = "3, 2", expect = Expect.ACCEPTABLE)
@Outcome(expect = Expect.FORBIDDEN)
public static class TwoSendersSequenceTest {
private final MemoryStoreWrapper underTest;
public TwoSendersSequenceTest() {
this.underTest = new MemoryStoreWrapper();
}
// application thread
@Actor
public void incrementSender1() {
underTest.incrementSenderSequence();
}
// application thread
@Actor
public void incrementSender2() {
underTest.incrementSenderSequence();
}
// QFJ Message Processor
@Actor
public void incrementTarget() {
underTest.incrementTargetSequence();
}
@Arbiter
public void captureResult(JJ_Result result) {
result.r1 = underTest.getSenderSequence();
result.r2 = underTest.getTargetSequence();
}
}
private static final class MemoryStoreWrapper {
private final MemoryStore store;
private final Lock senderSequenceLock;
private final Lock targetSequenceLock;
public MemoryStoreWrapper() {
try {
this.store = new MemoryStore();
} catch (IOException e) {
throw new RuntimeException(e);
}
this.senderSequenceLock = new ReentrantLock();
this.targetSequenceLock = new ReentrantLock();
}
public void incrementSenderSequence() {
senderSequenceLock.lock();
try {
store.incrNextSenderMsgSeqNum();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
senderSequenceLock.unlock();
}
}
public void incrementTargetSequence() {
targetSequenceLock.lock();
try {
store.incrNextTargetMsgSeqNum();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
targetSequenceLock.unlock();
}
}
public int getSenderSequence() {
return store.getNextSenderMsgSeqNum();
}
public int getTargetSequence() {
return store.getNextTargetMsgSeqNum();
}
}
}