1 package com.atlassian.activeobjects.osgi;
2
3 import com.atlassian.activeobjects.config.ActiveObjectsConfiguration;
4 import com.atlassian.activeobjects.external.ActiveObjects;
5 import com.atlassian.activeobjects.external.NoDataSourceException;
6 import com.atlassian.activeobjects.internal.ActiveObjectsFactory;
7 import com.atlassian.tenancy.api.Tenant;
8 import com.atlassian.tenancy.api.TenantContext;
9 import com.atlassian.util.concurrent.Promise;
10 import com.atlassian.util.concurrent.Promises;
11 import com.google.common.base.Function;
12 import com.google.common.util.concurrent.SettableFuture;
13 import org.junit.Before;
14 import org.junit.Rule;
15 import org.junit.Test;
16 import org.junit.rules.ExpectedException;
17 import org.junit.runner.RunWith;
18 import org.mockito.Mock;
19 import org.mockito.junit.MockitoJUnitRunner;
20 import org.osgi.framework.Bundle;
21 import org.osgi.framework.BundleContext;
22 import org.osgi.framework.ServiceEvent;
23 import org.osgi.framework.ServiceReference;
24
25 import java.util.concurrent.ExecutionException;
26 import java.util.concurrent.ExecutorService;
27
28 import static org.hamcrest.Matchers.hasItem;
29 import static org.hamcrest.Matchers.is;
30 import static org.junit.Assert.assertSame;
31 import static org.junit.Assert.assertThat;
32 import static org.mockito.Mockito.when;
33
34 @RunWith(MockitoJUnitRunner.class)
35 public class TenantAwareActiveObjectsTest {
36 private TenantAwareActiveObjects babyBear;
37
38 @Rule
39 public ExpectedException expectedException = ExpectedException.none();
40
41 @Mock
42 private Bundle bundle;
43 @Mock
44 private ActiveObjectsFactory factory;
45 @Mock
46 private TenantContext tenantContext;
47 @Mock
48 private Function<Tenant, ExecutorService> initExecutorFunction;
49 @Mock
50 private BundleContext bundleContext;
51 @Mock
52 private Tenant tenant;
53 @Mock
54 private ServiceEvent serviceEvent;
55 @Mock
56 private ServiceReference serviceReference;
57 @Mock
58 private ActiveObjects ao;
59 @Mock
60 private ActiveObjectsConfiguration aoConfig1;
61 @Mock
62 private ActiveObjectsConfiguration aoConfig2;
63
64 @Before
65 public void before() {
66 babyBear = new TenantAwareActiveObjects(bundle, factory, tenantContext, initExecutorFunction);
67
68 when(bundle.getSymbolicName()).thenReturn("some.bundle");
69 when(bundle.getBundleContext()).thenReturn(bundleContext);
70
71 when(bundleContext.getService(serviceReference)).thenReturn(aoConfig1);
72
73 when(serviceEvent.getServiceReference()).thenReturn(serviceReference);
74 }
75
76 @Test
77 public void init() {
78 when(tenantContext.getCurrentTenant()).thenReturn(tenant);
79
80 babyBear.init();
81
82 assertThat(babyBear.aoPromisesByTenant.asMap().keySet(), hasItem(tenant));
83 }
84
85 @Test
86 public void setAoConfig() throws ExecutionException, InterruptedException {
87 babyBear.setAoConfiguration(aoConfig1);
88
89 assertThat(babyBear.aoConfigFuture.isDone(), is(true));
90 assertThat(babyBear.aoConfigFuture.get(), is(aoConfig1));
91 }
92
93 @Test
94 public void setAoConfigMultipleConfigurationsThrowsIllegalStateException() {
95 babyBear.aoConfigFuture.set(aoConfig1);
96
97 expectedException.expect(IllegalStateException.class);
98
99 babyBear.setAoConfiguration(aoConfig2);
100 }
101
102 @Test
103 public void setAoConfigSameConfigurationIsOK() {
104 babyBear.aoConfigFuture.set(aoConfig1);
105 babyBear.setAoConfiguration(aoConfig1);
106 }
107
108 @Test
109 public void delegate() throws ExecutionException, InterruptedException {
110 babyBear.aoConfigFuture.set(aoConfig1);
111 when(tenantContext.getCurrentTenant()).thenReturn(tenant);
112
113 final Promise<ActiveObjects> aoPromise = Promises.promise(ao);
114
115 babyBear.aoPromisesByTenant.put(tenant, aoPromise);
116
117 assertSame(babyBear.delegate().get(), ao);
118 }
119
120 @Test
121 public void delegateUntenanted() {
122 babyBear.aoConfigFuture.set(aoConfig1);
123 expectedException.expect(NoDataSourceException.class);
124
125 babyBear.delegate();
126 }
127
128 @Test
129 public void delegateNoConfig() {
130 expectedException.expect(IllegalStateException.class);
131
132 babyBear.delegate();
133 }
134
135 @Test
136 public void awaitInitNoTenant() throws ExecutionException, InterruptedException {
137 expectedException.expect(NoDataSourceException.class);
138
139 babyBear.moduleMetaData().awaitInitialization();
140 }
141
142 @Test
143 public void awaitInitTimedNoTenant() throws ExecutionException, InterruptedException {
144 expectedException.expect(NoDataSourceException.class);
145
146 babyBear.moduleMetaData().awaitInitialization();
147 }
148
149 @Test
150 public void isInitializedNoTenant() {
151 assertThat(babyBear.moduleMetaData().isInitialized(), is(false));
152 }
153
154 @Test
155 public void isInitializedNotComplete() {
156 when(tenantContext.getCurrentTenant()).thenReturn(tenant);
157
158 assertThat(babyBear.moduleMetaData().isInitialized(), is(false));
159 }
160
161 @Test
162 public void isInitializedException() {
163 when(tenantContext.getCurrentTenant()).thenReturn(tenant);
164
165 final SettableFuture<ActiveObjects> aoFuture = SettableFuture.create();
166 aoFuture.setException(new IllegalStateException());
167 final Promise<ActiveObjects> aoPromise = Promises.forFuture(aoFuture);
168 babyBear.aoPromisesByTenant.put(tenant, aoPromise);
169
170 assertThat(babyBear.moduleMetaData().isInitialized(), is(false));
171 }
172
173 @Test
174 public void isInitializedComplete() {
175 final Promise<ActiveObjects> aoPromise = Promises.promise(ao);
176 babyBear.aoPromisesByTenant.put(tenant, aoPromise);
177
178 when(tenantContext.getCurrentTenant()).thenReturn(tenant);
179
180 assertThat(babyBear.moduleMetaData().isInitialized(), is(true));
181 }
182
183 @Test
184 public void isDataSourcePresentNo() {
185 assertThat(babyBear.moduleMetaData().isDataSourcePresent(), is(false));
186 }
187
188 @Test
189 public void isDataSourcePresentYes() {
190 when(tenantContext.getCurrentTenant()).thenReturn(tenant);
191
192 assertThat(babyBear.moduleMetaData().isDataSourcePresent(), is(true));
193 }
194 }