View Javadoc
1   package com.atlassian.activeobjects.internal;
2   
3   import com.atlassian.activeobjects.ActiveObjectsPluginException;
4   import com.atlassian.activeobjects.config.ActiveObjectsConfiguration;
5   import com.atlassian.activeobjects.config.PluginKey;
6   import com.atlassian.activeobjects.spi.DatabaseType;
7   import com.atlassian.activeobjects.spi.TenantAwareDataSourceProvider;
8   import com.atlassian.activeobjects.spi.TransactionSynchronisationManager;
9   import com.atlassian.beehive.ClusterLock;
10  import com.atlassian.beehive.ClusterLockService;
11  import com.atlassian.sal.api.transaction.TransactionCallback;
12  import com.atlassian.sal.api.transaction.TransactionTemplate;
13  import com.atlassian.tenancy.api.Tenant;
14  import net.java.ao.EntityManager;
15  import org.junit.After;
16  import org.junit.Before;
17  import org.junit.Rule;
18  import org.junit.Test;
19  import org.junit.rules.ExpectedException;
20  import org.junit.runner.RunWith;
21  import org.mockito.Mock;
22  import org.mockito.Mockito;
23  import org.mockito.junit.MockitoJUnitRunner;
24  import org.osgi.framework.Bundle;
25  
26  import javax.sql.DataSource;
27  import java.util.concurrent.TimeUnit;
28  
29  import static org.hamcrest.core.Is.isA;
30  import static org.hamcrest.core.IsNull.nullValue;
31  import static org.junit.Assert.assertNotNull;
32  import static org.junit.Assert.fail;
33  import static org.mockito.ArgumentMatchers.any;
34  import static org.mockito.ArgumentMatchers.anyString;
35  import static org.mockito.ArgumentMatchers.isNull;
36  import static org.mockito.Mockito.mock;
37  import static org.mockito.Mockito.verify;
38  import static org.mockito.Mockito.when;
39  
40  /**
41   * Testing {@link com.atlassian.activeobjects.internal.DataSourceProviderActiveObjectsFactory}
42   */
43  @RunWith(MockitoJUnitRunner.class)
44  public class TenantAwareDataSourceProviderActiveObjectsFactoryTest {
45      private DataSourceProviderActiveObjectsFactory activeObjectsFactory;
46  
47      @Rule
48      public ExpectedException expectedException = ExpectedException.none();
49  
50      @Mock
51      private ActiveObjectUpgradeManager upgradeManager;
52  
53      @Mock
54      private TenantAwareDataSourceProvider tenantAwareDataSourceProvider;
55  
56      @Mock
57      private EntityManagerFactory entityManagerFactory;
58  
59      @Mock
60      private TransactionTemplate transactionTemplate;
61  
62      @Mock
63      private ActiveObjectsConfiguration configuration;
64  
65      @Mock
66      private TransactionSynchronisationManager transactionSynchronizationManager;
67  
68      @Mock
69      private Tenant tenant;
70  
71      @Mock
72      private ClusterLock clusterLock;
73  
74      @Before
75      public void setUp() {
76          Bundle bundle = mock(Bundle.class);
77          when(bundle.getSymbolicName()).thenReturn("com.example.plugin");
78          PluginKey pluginKey = PluginKey.fromBundle(bundle);
79          ClusterLockService clusterLockService = mock(ClusterLockService.class);
80          when(clusterLockService.getLockForName(anyString())).thenReturn(clusterLock);
81          when(configuration.getDataSourceType()).thenReturn(DataSourceType.APPLICATION);
82          when(configuration.getPluginKey()).thenReturn(pluginKey);
83          activeObjectsFactory = new DataSourceProviderActiveObjectsFactory(upgradeManager, entityManagerFactory,
84                  tenantAwareDataSourceProvider, transactionTemplate, clusterLockService);
85          activeObjectsFactory.setTransactionSynchronizationManager(transactionSynchronizationManager);
86          when(transactionTemplate.execute(any())).thenAnswer(invocation ->
87                  ((TransactionCallback<?>) invocation.getArgument(0)).doInTransaction());
88      }
89  
90      @After
91      public void tearDown() {
92          activeObjectsFactory = null;
93          entityManagerFactory = null;
94          tenantAwareDataSourceProvider = null;
95      }
96  
97      @Test
98      public void testCreateWithNullDataSource() throws Exception {
99          when(tenantAwareDataSourceProvider.getDataSource(tenant)).thenReturn(null); // not really needed, but just to make the test clear
100         when(clusterLock.tryLock(AbstractActiveObjectsFactory.LOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS)).thenReturn(true);
101         try {
102             activeObjectsFactory.create(configuration, tenant);
103             fail("Should have thrown " + ActiveObjectsPluginException.class.getName());
104         } catch (ActiveObjectsPluginException e) {
105             verify(clusterLock).tryLock(AbstractActiveObjectsFactory.LOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS);
106             verify(clusterLock).unlock();
107         }
108     }
109 
110     @Test
111     public void testCreateWithNullDatabaseType() throws Exception {
112         final DataSource dataSource = mock(DataSource.class);
113 
114         when(tenantAwareDataSourceProvider.getDataSource(tenant)).thenReturn(dataSource);
115         when(clusterLock.tryLock(AbstractActiveObjectsFactory.LOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS)).thenReturn(true);
116         when(tenantAwareDataSourceProvider.getDatabaseType(tenant)).thenReturn(null); // not really needed, but just to make the test clear
117         try {
118             activeObjectsFactory.create(configuration, tenant);
119             fail("Should have thrown " + ActiveObjectsPluginException.class.getName());
120         } catch (ActiveObjectsPluginException e) {
121             verify(clusterLock).tryLock(AbstractActiveObjectsFactory.LOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS);
122             verify(clusterLock).unlock();
123         }
124     }
125 
126     @Test
127     public void testCreate() throws Exception {
128         final DataSource dataSource = mock(DataSource.class);
129         final EntityManager entityManager = mock(EntityManager.class);
130 
131         when(tenantAwareDataSourceProvider.getDataSource(tenant)).thenReturn(dataSource);
132         when(entityManagerFactory.getEntityManager(anyDataSource(), anyDatabaseType(), isNull(), anyConfiguration())).thenReturn(entityManager);
133         when(configuration.getDataSourceType()).thenReturn(DataSourceType.APPLICATION);
134         when(tenantAwareDataSourceProvider.getDatabaseType(tenant)).thenReturn(DatabaseType.DERBY_EMBEDDED);
135         when(clusterLock.tryLock(AbstractActiveObjectsFactory.LOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS)).thenReturn(true);
136 
137         assertNotNull(activeObjectsFactory.create(configuration, tenant));
138         verify(entityManagerFactory).getEntityManager(anyDataSource(), anyDatabaseType(), isNull(), anyConfiguration());
139         verify(clusterLock).tryLock(AbstractActiveObjectsFactory.LOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS);
140         verify(clusterLock).unlock();
141     }
142 
143     @Test
144     public void testCreateLockTimeout() throws InterruptedException {
145         when(clusterLock.tryLock(AbstractActiveObjectsFactory.LOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS)).thenReturn(false);
146 
147         expectedException.expect(ActiveObjectsInitException.class);
148         expectedException.expectCause(nullValue(Throwable.class));
149 
150         activeObjectsFactory.create(configuration, tenant);
151     }
152 
153     @Test
154     public void testCreateLockInterrupted() throws InterruptedException {
155         when(clusterLock.tryLock(AbstractActiveObjectsFactory.LOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS)).thenThrow(new InterruptedException());
156 
157         expectedException.expect(ActiveObjectsInitException.class);
158         expectedException.expectCause(isA(InterruptedException.class));
159 
160         activeObjectsFactory.create(configuration, tenant);
161     }
162 
163     private static DataSource anyDataSource() {
164         return Mockito.any();
165     }
166 
167     private static DatabaseType anyDatabaseType() {
168         return Mockito.any();
169     }
170 
171     private static ActiveObjectsConfiguration anyConfiguration() {
172         return Mockito.any();
173     }
174 }