fb0d1102e4e71e1818e80cf3ba7f286a647f914e
[policy/drools-pdp.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  * feature-session-persistence
4  * ================================================================================
5  * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.drools.persistence;
22
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.fail;
25 import static org.mockito.Mockito.doThrow;
26 import static org.mockito.Mockito.mock;
27 import static org.mockito.Mockito.never;
28 import static org.mockito.Mockito.times;
29 import static org.mockito.Mockito.verify;
30 import static org.mockito.Mockito.when;
31
32 import java.util.HashMap;
33 import java.util.Map;
34 import javax.persistence.EntityManager;
35 import javax.persistence.EntityManagerFactory;
36 import javax.persistence.Persistence;
37 import javax.transaction.HeuristicMixedException;
38 import javax.transaction.HeuristicRollbackException;
39 import javax.transaction.NotSupportedException;
40 import javax.transaction.RollbackException;
41 import javax.transaction.Status;
42 import javax.transaction.SystemException;
43 import javax.transaction.UserTransaction;
44 import org.junit.AfterClass;
45 import org.junit.Before;
46 import org.junit.BeforeClass;
47 import org.junit.Test;
48 import org.onap.policy.drools.persistence.EntityMgrTrans.EntityMgrException;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 public class EntityMgrTransTest {
53
54     private static final Logger logger = LoggerFactory.getLogger(PersistenceFeatureTest.class);
55
56     private static UserTransaction savetrans;
57
58     private UserTransaction trans;
59     private EntityManager mgr;
60
61     /**
62      * Configure properties for JTA.
63      */
64     @BeforeClass
65     public static void setUpBeforeClass() {
66         System.setProperty("com.arjuna.ats.arjuna.objectstore.objectStoreDir", "target/tm");
67         System.setProperty("ObjectStoreEnvironmentBean.objectStoreDir", "target/tm");
68
69         savetrans = EntityMgrTrans.getUserTrans();
70     }
71
72     @AfterClass
73     public static void tearDownAfterClass() {
74         EntityMgrTrans.setUserTrans(savetrans);
75     }
76
77     /**
78      * Creates a mock transaction and entity manager. Resets the "userTrans" field of the
79      * class under test.
80      *
81      * @throws Exception if an error occurs
82      */
83     @Before
84     public void setUp() throws Exception {
85         trans = mock(UserTransaction.class);
86         mgr = mock(EntityManager.class);
87
88         when(trans.getStatus()).thenReturn(Status.STATUS_NO_TRANSACTION, Status.STATUS_ACTIVE);
89
90         EntityMgrTrans.setUserTrans(trans);
91     }
92
93     /**
94      * Verifies that the constructor starts a transaction, but does not do anything extra
95      * before being closed.
96      *
97      * @throws Exception if an error occurs
98      */
99     @Test
100     public void testEntityMgrTrans_Inactive() throws Exception {
101         final EntityMgrTrans emt = new EntityMgrTrans(mgr);
102
103         // verify that transaction was started
104         verify(trans).begin();
105         verify(mgr).joinTransaction();
106
107         // verify not closed, committed, or rolled back yet
108         verify(trans, never()).commit();
109         verify(trans, never()).rollback();
110         verify(mgr, never()).close();
111
112         emt.close();
113     }
114
115     /**
116      * Verifies that the constructor does not start a transaction, because one is already
117      * active.
118      *
119      * @throws Exception if an error occurs
120      */
121     @Test
122     public void testEntityMgrTrans_Active() throws Exception {
123
124         when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
125
126         final EntityMgrTrans emt = new EntityMgrTrans(mgr);
127
128         // verify that transaction was not re-started started
129         verify(trans, never()).begin();
130
131         // verify that transaction was joined
132         verify(mgr).joinTransaction();
133
134         // verify not closed, committed, or rolled back yet
135         verify(trans, never()).commit();
136         verify(trans, never()).rollback();
137         verify(mgr, never()).close();
138
139         emt.close();
140     }
141
142     @Test(expected = EntityMgrException.class)
143     public void testEntityMgrTrans_RtEx() throws Exception {
144
145         doThrow(new IllegalArgumentException("expected exception")).when(trans).begin();
146
147         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
148             // Empty
149         }
150     }
151
152     @Test(expected = EntityMgrException.class)
153     public void testEntityMgrTrans_NotSuppEx() throws Exception {
154
155         doThrow(new NotSupportedException("expected exception")).when(trans).begin();
156
157         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
158             // Empty
159         }
160     }
161
162     @Test(expected = EntityMgrException.class)
163     public void testEntityMgrTrans_SysEx() throws Exception {
164
165         doThrow(new SystemException("expected exception")).when(trans).begin();
166
167         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
168             // Empty
169         }
170     }
171
172     /**
173      * Verifies that the transaction is not rolled back, but the manager is closed when a
174      * transaction is already active.
175      */
176     @Test
177     public void testClose_Active() throws Exception {
178         when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
179
180         EntityMgrTrans emt = new EntityMgrTrans(mgr);
181         emt.close();
182
183         // closed and rolled back, but not committed
184         verify(trans, never()).commit();
185         verify(trans, never()).rollback();
186         verify(mgr).close();
187     }
188
189     /**
190      * Verifies that the transaction is rolled back and the manager is closed when a
191      * transaction is begun by the constructor.
192      */
193     @Test
194     public void testClose_Begun() throws Exception {
195         EntityMgrTrans emt = new EntityMgrTrans(mgr);
196
197         emt.close();
198
199         // closed and rolled back, but not committed
200         verify(trans, never()).commit();
201         verify(trans).rollback();
202         verify(mgr).close();
203     }
204
205     /**
206      * Verifies that the manager is closed, but that the transaction is <i>not</i> rolled
207      * back when no transaction is active.
208      */
209     @Test
210     public void testClose_Inactive() throws Exception {
211         when(trans.getStatus()).thenReturn(Status.STATUS_NO_TRANSACTION);
212
213         EntityMgrTrans emt = new EntityMgrTrans(mgr);
214
215         emt.close();
216
217         // closed, but not committed or rolled back
218         verify(mgr).close();
219         verify(trans, never()).commit();
220         verify(trans, never()).rollback();
221     }
222
223     @Test(expected = EntityMgrException.class)
224     public void testClose_IllStateEx() throws Exception {
225
226         doThrow(new IllegalStateException("expected exception")).when(trans).rollback();
227
228         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
229             // Empty
230         }
231     }
232
233     @Test(expected = EntityMgrException.class)
234     public void testClose_SecEx() throws Exception {
235
236         doThrow(new SecurityException("expected exception")).when(trans).rollback();
237
238         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
239             // Empty
240         }
241     }
242
243     @Test(expected = EntityMgrException.class)
244     public void testClose_SysEx() throws Exception {
245
246         doThrow(new SystemException("expected exception")).when(trans).rollback();
247
248         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
249             // Empty
250         }
251     }
252
253     /**
254      * Verifies that the manager is closed and the transaction rolled back when "try"
255      * block exits normally and a transaction is active.
256      */
257     @Test
258     public void testClose_TryWithoutExcept_Active() throws Exception {
259         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
260             // Empty
261         }
262
263         // closed and rolled back, but not committed
264         verify(trans, never()).commit();
265         verify(trans).rollback();
266         verify(mgr).close();
267     }
268
269     /**
270      * Verifies that the manager is closed, but that the transaction is <i>not</i> rolled
271      * back when "try" block exits normally and no transaction is active.
272      */
273     @Test
274     public void testClose_TryWithoutExcept_Inactive() throws Exception {
275
276         when(trans.getStatus()).thenReturn(Status.STATUS_NO_TRANSACTION);
277
278         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
279             // Empty
280         }
281
282         // closed, but not rolled back or committed
283         verify(trans, never()).commit();
284         verify(trans, never()).rollback();
285         verify(mgr).close();
286     }
287
288     /**
289      * Verifies that the manager is closed and the transaction rolled back when "try"
290      * block throws an exception and a transaction is active.
291      */
292     @Test
293     public void testClose_TryWithExcept_Active() throws Exception {
294         try {
295             try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
296                 throw new SystemException("expected exception");
297             }
298
299         } catch (Exception e) {
300             logger.trace("expected exception", e);
301         }
302
303         // closed and rolled back, but not committed
304         verify(trans, never()).commit();
305         verify(trans).rollback();
306         verify(mgr).close();
307     }
308
309     /**
310      * Verifies that the manager is closed, but that the transaction is <i>not</i> rolled
311      * back when "try" block throws an exception and no transaction is active.
312      */
313     @Test
314     public void testClose_TryWithExcept_Inactive() throws Exception {
315
316         when(trans.getStatus()).thenReturn(Status.STATUS_NO_TRANSACTION);
317
318         try {
319             try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
320                 throw new SystemException("expected exception");
321             }
322
323         } catch (Exception e) {
324             logger.trace("expected exception", e);
325         }
326
327         // closed, but not rolled back or committed
328         verify(trans, never()).commit();
329         verify(trans, never()).rollback();
330         verify(mgr).close();
331     }
332
333     /**
334      * Verifies that commit() only commits, and that the subsequent close() does not
335      * re-commit.
336      */
337     @Test
338     public void testCommit() throws Exception {
339         EntityMgrTrans emt = new EntityMgrTrans(mgr);
340
341         emt.commit();
342
343         when(trans.getStatus()).thenReturn(Status.STATUS_COMMITTED);
344
345         // committed, but not closed or rolled back
346         verify(trans).commit();
347         verify(trans, never()).rollback();
348         verify(mgr, never()).close();
349
350         // closed, but not re-committed
351         emt.close();
352
353         verify(trans, times(1)).commit();
354         verify(mgr).close();
355     }
356
357     /**
358      * Verifies that commit() does nothing, and that the subsequent close() does not
359      * re-commit when a transaction is already active.
360      */
361     @Test
362     public void testCommit_Active() throws Exception {
363         when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
364
365         EntityMgrTrans emt = new EntityMgrTrans(mgr);
366
367         emt.commit();
368
369         // nothing happened yet
370         verify(trans, never()).commit();
371         verify(trans, never()).rollback();
372         verify(mgr, never()).close();
373
374         // closed, but not re-committed
375         emt.close();
376
377         // still no commit or rollback
378         verify(trans, never()).commit();
379         verify(trans, never()).rollback();
380         verify(mgr).close();
381     }
382
383     @Test(expected = EntityMgrException.class)
384     public void testCommit_SecEx() throws Exception {
385
386         doThrow(new SecurityException("expected exception")).when(trans).commit();
387
388         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
389             emt.commit();
390         }
391     }
392
393     @Test(expected = EntityMgrException.class)
394     public void testCommit_IllStateEx() throws Exception {
395
396         doThrow(new IllegalStateException("expected exception")).when(trans).commit();
397
398         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
399             emt.commit();
400         }
401     }
402
403     @Test(expected = EntityMgrException.class)
404     public void testCommit_RbEx() throws Exception {
405
406         doThrow(new RollbackException("expected exception")).when(trans).commit();
407
408         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
409             emt.commit();
410         }
411     }
412
413     @Test(expected = EntityMgrException.class)
414     public void testCommit_HmEx() throws Exception {
415
416         doThrow(new HeuristicMixedException("expected exception")).when(trans).commit();
417
418         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
419             emt.commit();
420         }
421     }
422
423     @Test(expected = EntityMgrException.class)
424     public void testCommit_HrbEx() throws Exception {
425
426         doThrow(new HeuristicRollbackException("expected exception")).when(trans).commit();
427
428         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
429             emt.commit();
430         }
431     }
432
433     @Test(expected = EntityMgrException.class)
434     public void testCommit_SysEx() throws Exception {
435
436         doThrow(new SystemException("expected exception")).when(trans).commit();
437
438         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
439             emt.commit();
440         }
441     }
442
443     /**
444      * Verifies that rollback() only rolls back, and that the subsequent close() does not
445      * re-roll back.
446      */
447     @Test
448     public void testRollback() throws Exception {
449         EntityMgrTrans emt = new EntityMgrTrans(mgr);
450
451         emt.rollback();
452
453         when(trans.getStatus()).thenReturn(Status.STATUS_ROLLEDBACK);
454
455         // rolled back, but not closed or committed
456         verify(trans, never()).commit();
457         verify(trans).rollback();
458         verify(mgr, never()).close();
459
460         // closed, but not re-rolled back
461         emt.close();
462
463         // still no commit or rollback
464         verify(trans, never()).commit();
465         verify(trans).rollback();
466         verify(mgr).close();
467     }
468
469     /**
470      * Verifies that rollback() does nothing, and that the subsequent close() does not
471      * re-roll back when a transaction is already active.
472      */
473     @Test
474     public void testRollback_Active() throws Exception {
475         when(trans.getStatus()).thenReturn(Status.STATUS_ACTIVE);
476         EntityMgrTrans emt = new EntityMgrTrans(mgr);
477
478         emt.rollback();
479
480         // nothing happens
481         verify(trans, never()).commit();
482         verify(trans, never()).rollback();
483         verify(mgr, never()).close();
484
485         emt.close();
486
487         // still no commit or rollback
488         verify(trans, never()).commit();
489         verify(trans, never()).rollback();
490         verify(mgr).close();
491     }
492
493     @Test(expected = EntityMgrException.class)
494     public void testRollback_IllStateEx() throws Exception {
495
496         doThrow(new IllegalStateException("expected exception")).when(trans).rollback();
497
498         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
499             emt.rollback();
500         }
501     }
502
503     @Test(expected = EntityMgrException.class)
504     public void testRollback_SecEx() throws Exception {
505
506         doThrow(new SecurityException("expected exception")).when(trans).rollback();
507
508         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
509             emt.rollback();
510         }
511     }
512
513     @Test(expected = EntityMgrException.class)
514     public void testRollback_SysEx() throws Exception {
515
516         doThrow(new SystemException("expected exception")).when(trans).rollback();
517
518         try (EntityMgrTrans emt = new EntityMgrTrans(mgr)) {
519             emt.rollback();
520         }
521     }
522
523     @Test
524     public void testEntityMgrException() {
525         SecurityException secex = new SecurityException("expected exception");
526         EntityMgrException ex = new EntityMgrException(secex);
527
528         assertEquals(secex, ex.getCause());
529
530     }
531
532     /**
533      * Tests using real (i.e., not mocked) Persistence classes.
534      */
535     @Test
536     public void testReal() {
537         EntityMgrTrans.setUserTrans(savetrans);
538
539         Map<String, Object> propMap = new HashMap<>();
540
541         propMap.put("javax.persistence.jdbc.driver", "org.h2.Driver");
542         propMap.put("javax.persistence.jdbc.url", "jdbc:h2:mem:EntityMgrTransTest");
543
544         EntityManagerFactory emf = Persistence.createEntityManagerFactory("junitDroolsSessionEntityPU", propMap);
545
546         try (EntityMgrTrans trans1 = new EntityMgrTrans(emf.createEntityManager())) {
547
548             // nest a transaction - should still be OK
549             
550             try (EntityMgrTrans trans2 = new EntityMgrTrans(emf.createEntityManager())) {                
551                 // Empty
552             }
553
554         } catch (Exception e) {
555             logger.info("persistence error", e);
556             emf.close();
557             fail("persistence error");
558         }
559
560         emf.close();
561     }
562 }