27
27
import java .util .concurrent .atomic .AtomicInteger ;
28
28
import java .util .concurrent .atomic .AtomicLong ;
29
29
30
+ import org .apache .activemq .artemis .api .core .SimpleString ;
30
31
import org .apache .activemq .artemis .core .config .Configuration ;
31
32
import org .apache .activemq .artemis .core .config .impl .ConfigurationImpl ;
32
33
import org .apache .activemq .artemis .core .io .IOCallback ;
37
38
import org .apache .activemq .artemis .core .persistence .OperationContext ;
38
39
import org .apache .activemq .artemis .core .persistence .StorageManager ;
39
40
import org .apache .activemq .artemis .core .persistence .impl .journal .JournalStorageManager ;
41
+ import org .apache .activemq .artemis .core .persistence .impl .journal .JournalStorageManagerAccessor ;
40
42
import org .apache .activemq .artemis .core .persistence .impl .journal .OperationContextImpl ;
43
+ import org .apache .activemq .artemis .core .replication .ReplicationManager ;
41
44
import org .apache .activemq .artemis .core .server .JournalType ;
42
45
import org .apache .activemq .artemis .core .server .RouteContextList ;
43
46
import org .apache .activemq .artemis .core .transaction .Transaction ;
44
47
import org .apache .activemq .artemis .core .transaction .TransactionOperationAbstract ;
45
48
import org .apache .activemq .artemis .core .transaction .impl .TransactionImpl ;
46
49
import org .apache .activemq .artemis .tests .util .ArtemisTestCase ;
47
50
import org .apache .activemq .artemis .utils .ExecutorFactory ;
51
+ import org .apache .activemq .artemis .utils .ReusableLatch ;
48
52
import org .apache .activemq .artemis .utils .actors .OrderedExecutorFactory ;
49
53
import org .apache .activemq .artemis .utils .critical .CriticalAnalyzer ;
50
54
import org .junit .jupiter .api .BeforeEach ;
51
55
import org .junit .jupiter .api .Test ;
56
+ import org .mockito .Mock ;
52
57
import org .mockito .Mockito ;
53
58
import org .slf4j .Logger ;
54
59
import org .slf4j .LoggerFactory ;
@@ -66,11 +71,13 @@ public class PageTimedWriterUnitTest extends ArtemisTestCase {
66
71
ExecutorService executorService ;
67
72
OrderedExecutorFactory executorFactory ;
68
73
OperationContext context ;
69
- JournalStorageManager journalStorageManager ;
74
+
75
+ // almost real as we use an extension that can allow mocking internal objects such as journals and replicationManager
76
+ JournalStorageManager realJournalStorageManager ;
70
77
71
78
PagingStoreImpl mockPageStore ;
72
79
73
- CountDownLatch allowRunning ;
80
+ ReusableLatch allowRunning ;
74
81
75
82
PageTimedWriter timer ;
76
83
@@ -79,6 +86,10 @@ public class PageTimedWriterUnitTest extends ArtemisTestCase {
79
86
Journal mockBindingsJournal ;
80
87
Journal mockMessageJournal ;
81
88
89
+ AtomicBoolean useReplication = new AtomicBoolean (false );
90
+ AtomicBoolean returnSynchronizing = new AtomicBoolean (false );
91
+ ReplicationManager mockReplicationManager ;
92
+
82
93
83
94
class MockableJournalStorageManager extends JournalStorageManager {
84
95
@@ -106,7 +117,7 @@ protected void createDirectories() {
106
117
107
118
108
119
@ BeforeEach
109
- public void prepareTest () throws Exception {
120
+ public void prepareMocks () throws Exception {
110
121
configuration = new ConfigurationImpl ();
111
122
configuration .setJournalType (JournalType .NIO );
112
123
scheduledExecutorService = Executors .newScheduledThreadPool (10 );
@@ -121,14 +132,34 @@ public void prepareTest() throws Exception {
121
132
mockBindingsJournal = Mockito .mock (Journal .class );
122
133
mockMessageJournal = Mockito .mock (Journal .class );
123
134
124
- journalStorageManager = new MockableJournalStorageManager (configuration , mockBindingsJournal , mockMessageJournal , executorFactory , executorFactory );
125
- journalStorageManager .start ();
135
+ mockReplicationManager = Mockito .mock (ReplicationManager .class );
136
+ Mockito .when (mockReplicationManager .isStarted ()).thenAnswer (a -> useReplication .get ());
137
+ Mockito .when (mockReplicationManager .isSynchronizing ()).thenAnswer (a -> returnSynchronizing .get ());
138
+ Mockito .doAnswer (a -> {
139
+ if (useReplication .get ()) {
140
+ OperationContext ctx = OperationContextImpl .getContext ();
141
+ if (ctx != null ) {
142
+ ctx .replicationDone ();
143
+ }
144
+ }
145
+ return null ;
146
+ }).when (mockReplicationManager ).pageWrite (Mockito .any (SimpleString .class ), Mockito .any (PagedMessage .class ), Mockito .anyLong (), Mockito .anyBoolean ());
126
147
127
- allowRunning = new CountDownLatch (1 );
148
+ realJournalStorageManager = new MockableJournalStorageManager (configuration , mockBindingsJournal , mockMessageJournal , executorFactory , executorFactory );
149
+ realJournalStorageManager .start ();
150
+
151
+ JournalStorageManagerAccessor .setReplicationManager (realJournalStorageManager , mockReplicationManager );
152
+
153
+ allowRunning = new ReusableLatch (1 );
128
154
129
155
mockPageStore = Mockito .mock (PagingStoreImpl .class );
156
+ Mockito .doAnswer (a -> {
157
+ realJournalStorageManager .pageWrite (SimpleString .of ("whatever" ), a .getArgument (0 ), 1L , a .getArgument (1 ));
158
+ return null ;
159
+ }).when (mockPageStore ).directWritePage (Mockito .any (PagedMessage .class ), Mockito .anyBoolean ());
160
+
130
161
131
- timer = new PageTimedWriter (journalStorageManager , mockPageStore , scheduledExecutorService , executorFactory .getExecutor (), 100 ) {
162
+ timer = new PageTimedWriter (realJournalStorageManager , mockPageStore , scheduledExecutorService , executorFactory .getExecutor (), 100 ) {
132
163
@ Override
133
164
public void run () {
134
165
try {
@@ -148,7 +179,7 @@ public void run() {
148
179
// a test to validate if the Mocks are correctly setup
149
180
@ Test
150
181
public void testValidateMocks () throws Exception {
151
- TransactionImpl tx = new TransactionImpl (journalStorageManager );
182
+ TransactionImpl tx = new TransactionImpl (realJournalStorageManager );
152
183
tx .setContainsPersistent ();
153
184
AtomicInteger count = new AtomicInteger (0 );
154
185
tx .addOperation (new TransactionOperationAbstract () {
@@ -162,7 +193,7 @@ public void afterCommit(Transaction tx) {
162
193
assertEquals (1 , count .get (), "tx.commit is not correctly wired on mocking" );
163
194
164
195
165
- journalStorageManager .afterCompleteOperations (new IOCallback () {
196
+ realJournalStorageManager .afterCompleteOperations (new IOCallback () {
166
197
@ Override
167
198
public void done () {
168
199
count .incrementAndGet ();
@@ -174,7 +205,7 @@ public void onError(int errorCode, String errorMessage) {
174
205
}
175
206
});
176
207
177
- journalStorageManager .afterCompleteOperations (new IOCallback () {
208
+ realJournalStorageManager .afterCompleteOperations (new IOCallback () {
178
209
@ Override
179
210
public void done () {
180
211
count .incrementAndGet ();
@@ -188,8 +219,8 @@ public void onError(int errorCode, String errorMessage) {
188
219
189
220
assertEquals (3 , count .get (), "afterCompletion is not correctly wired on mocking" );
190
221
191
- long id = journalStorageManager .generateID ();
192
- long newID = journalStorageManager .generateID ();
222
+ long id = realJournalStorageManager .generateID ();
223
+ long newID = realJournalStorageManager .generateID ();
193
224
assertEquals (1L , newID - id );
194
225
195
226
}
@@ -221,9 +252,34 @@ public void onError(int errorCode, String errorMessage) {
221
252
public void testIOCompletionWhileReplica () throws Exception {
222
253
CountDownLatch latch = new CountDownLatch (1 );
223
254
224
- AtomicBoolean replicated = new AtomicBoolean (true );
255
+ useReplication .set (true );
256
+
257
+ timer .addTask (context , Mockito .mock (PagedMessage .class ), null , Mockito .mock (RouteContextList .class ));
258
+
259
+ context .executeOnCompletion (new IOCallback () {
260
+ @ Override
261
+ public void done () {
262
+ latch .countDown ();
263
+ }
264
+
265
+ @ Override
266
+ public void onError (int errorCode , String errorMessage ) {
267
+ }
268
+ });
269
+
270
+ assertFalse (latch .await (10 , TimeUnit .MILLISECONDS ));
271
+ allowRunning .countDown ();
272
+ assertTrue (latch .await (10 , TimeUnit .MINUTES ));
273
+
274
+ allowRunning .setCount (1 );
275
+ }
276
+
277
+ // add a task while replicating, process it when no longer replicating (disconnect a node scenario)
278
+ @ Test
279
+ public void testDisableReplica () throws Exception {
280
+ CountDownLatch latch = new CountDownLatch (1 );
225
281
226
- Mockito . when ( journalStorageManager . isReplicated ()). then ( r -> replicated . get () );
282
+ useReplication . set ( true );
227
283
228
284
timer .addTask (context , Mockito .mock (PagedMessage .class ), null , Mockito .mock (RouteContextList .class ));
229
285
@@ -239,9 +295,11 @@ public void onError(int errorCode, String errorMessage) {
239
295
});
240
296
241
297
assertFalse (latch .await (10 , TimeUnit .MILLISECONDS ));
298
+ useReplication .set (false );
242
299
allowRunning .countDown ();
243
300
assertTrue (latch .await (10 , TimeUnit .SECONDS ));
244
301
302
+ allowRunning .setCount (1 );
245
303
}
246
304
247
305
@ Test
@@ -260,7 +318,7 @@ public void testTXCompletion() throws Exception {
260
318
261
319
CountDownLatch latch = new CountDownLatch (1 );
262
320
263
- Transaction tx = new TransactionImpl (journalStorageManager , Integer .MAX_VALUE );
321
+ Transaction tx = new TransactionImpl (realJournalStorageManager , Integer .MAX_VALUE );
264
322
tx .setContainsPersistent ();
265
323
266
324
timer .addTask (context , Mockito .mock (PagedMessage .class ), tx , Mockito .mock (RouteContextList .class ));
0 commit comments