/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.kernel.test.rule; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.exception.SystemException; import com.liferay.portal.kernel.transaction.Isolation; import com.liferay.portal.kernel.transaction.Propagation; import com.liferay.portal.kernel.transaction.TransactionConfig; import com.liferay.portal.kernel.transaction.Transactional; import java.lang.reflect.Method; import java.util.ArrayDeque; import java.util.Deque; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; /** * @author Shuyang Zhou */ public class BaseTransactionalTestRuleTest { @BeforeClass public static void setUpClass1() throws ReflectiveOperationException { assertTransactionConfig(); } @BeforeClass @Transactional public static void setUpClass2() throws ReflectiveOperationException { assertTransactionConfig(); } @BeforeClass @Transactional(propagation = Propagation.REQUIRES_NEW) public static void setUpClass3() throws ReflectiveOperationException { assertTransactionConfig(); } @AfterClass public static void tearDownClass1() throws ReflectiveOperationException { assertTransactionConfig(); } @AfterClass @Transactional public static void tearDownClass2() throws ReflectiveOperationException { assertTransactionConfig(); } @AfterClass @Transactional( isolation = Isolation.REPEATABLE_READ, readOnly = true, rollbackFor = {Exception.class} ) public static void tearDownClass3() throws ReflectiveOperationException { assertTransactionConfig(); } @Before public void setUp1() throws ReflectiveOperationException { assertTransactionConfig(); } @Before @Transactional public void setUp2() throws ReflectiveOperationException { assertTransactionConfig(); } @Before @Transactional(enabled = false) public void setUp3() throws ReflectiveOperationException { assertTransactionConfig(); } @After public void tearDown1() throws ReflectiveOperationException { assertTransactionConfig(); } @After @Transactional public void tearDown2() throws ReflectiveOperationException { assertTransactionConfig(); } @After @Transactional(noRollbackFor = {Exception.class}, timeout = 10) public void tearDown3() throws ReflectiveOperationException { assertTransactionConfig(); } @Test public void test1() throws ReflectiveOperationException { assertTransactionConfig(); } @Test @Transactional public void test2() throws ReflectiveOperationException { assertTransactionConfig(); } @Test @Transactional( noRollbackForClassName = "RuntimeException", propagation = Propagation.SUPPORTS ) public void test3() throws ReflectiveOperationException { assertTransactionConfig(); } protected static void assertTransactionConfig() throws ReflectiveOperationException { Thread currentThread = Thread.currentThread(); StackTraceElement[] stackTraceElements = currentThread.getStackTrace(); StackTraceElement stackTraceElement = stackTraceElements[2]; Method method = BaseTransactionalTestRuleTest.class.getMethod( stackTraceElement.getMethodName()); Deque<TransactionConfig> transactionConfigs = transactionConfigThreadLocal.get(); TransactionConfig transactionConfig = transactionConfigs.peek(); Transactional transactional = method.getAnnotation(Transactional.class); if (transactional == null) { Assert.assertEquals( TransactionConfig.Factory.create( Propagation.SUPPORTS, new Class<?>[] { PortalException.class, SystemException.class }), transactionConfig); return; } Assert.assertEquals( TransactionConfig.Factory.create( transactional.isolation(), transactional.propagation(), transactional.readOnly(), transactional.timeout(), transactional.rollbackFor(), transactional.rollbackForClassName(), transactional.noRollbackFor(), transactional.noRollbackForClassName()), transactionConfig); } protected static final ThreadLocal<Deque<TransactionConfig>> transactionConfigThreadLocal = new ThreadLocal<Deque<TransactionConfig>>() { @Override protected Deque<TransactionConfig> initialValue() { return new ArrayDeque<>(); } }; }