1 package com.atlassian.sal.core.features;
2
3 import com.atlassian.fugue.Option;
4 import com.atlassian.sal.api.features.EnabledDarkFeatures;
5 import com.atlassian.sal.api.features.InvalidFeatureKeyException;
6 import com.atlassian.sal.api.features.MissingPermissionException;
7 import com.atlassian.sal.api.features.SiteDarkFeaturesStorage;
8 import com.atlassian.sal.api.user.UserManager;
9 import com.google.common.collect.ImmutableSet;
10 import org.junit.Before;
11 import org.junit.Rule;
12 import org.junit.Test;
13 import org.junit.runner.RunWith;
14 import org.mockito.Mock;
15 import org.mockito.runners.MockitoJUnitRunner;
16
17 import java.security.Principal;
18
19 import static org.hamcrest.Matchers.hasItem;
20 import static org.hamcrest.Matchers.is;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertThat;
24 import static org.junit.Assert.assertTrue;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.Mockito.verifyNoMoreInteractions;
27 import static org.mockito.Mockito.verifyZeroInteractions;
28 import static org.mockito.Mockito.when;
29
30 @RunWith(MockitoJUnitRunner.class)
31 public class TestDefaultDarkFeatureManager
32 {
33 private static final String FEATURE_FOO = "foo";
34 private static final String INVALID_FEATURE_KEY = "invalid feature key";
35 private static final String USER_NAME = "foobar";
36
37 @Rule public final ClearSystemPropertyRule systemPropertyRule = new ClearSystemPropertyRule();
38 @Mock private UserManager userManager;
39 @Mock private Principal user;
40 @Mock private SiteDarkFeaturesStorage siteDarkFeaturesStorage;
41
42 @Before
43 public void setUp()
44 {
45 when(siteDarkFeaturesStorage.getEnabledDarkFeatures()).thenReturn(ImmutableSet.<String>of());
46 }
47
48 @Test
49 public void systemFeatureEnabledForAllUsers()
50 {
51 enableDarkFeatureViaSystemProperty(FEATURE_FOO);
52 assertTrue(createFeatureManager().isFeatureEnabledForAllUsers(FEATURE_FOO));
53 }
54
55 @Test
56 public void systemFeatureNotEnabledForAllUsers()
57 {
58 assertNull(System.getProperty(FEATURE_FOO));
59 assertFalse(createFeatureManager().isFeatureEnabledForAllUsers(FEATURE_FOO));
60 }
61
62 @Test
63 public void invalidFeatureKeyIsNeverEnabledForAllUsers()
64 {
65 assertFalse(createFeatureManager().isFeatureEnabledForAllUsers(INVALID_FEATURE_KEY));
66 }
67
68 @Test
69 public void systemFeatureEnabledForAnonymous()
70 {
71 enableDarkFeatureViaSystemProperty(FEATURE_FOO);
72 final Option<Boolean> featureEnabledForUser = createFeatureManager().isFeatureEnabledForUser(null, FEATURE_FOO);
73 assertThat(featureEnabledForUser, is(Option.some(true)));
74 }
75
76 @Test
77 public void systemFeatureDisabledForAnonymous()
78 {
79 final Option<Boolean> featureEnabledForUser = createFeatureManager().isFeatureEnabledForUser(null, FEATURE_FOO);
80 assertThat(featureEnabledForUser, is(Option.some(false)));
81 }
82
83 @Test
84 public void systemFeatureEnabledForAuthenticatedUser()
85 {
86 enableDarkFeatureViaSystemProperty(FEATURE_FOO);
87 givenUserResolved();
88 final Option<Boolean> featureEnabledForUser = createFeatureManager().isFeatureEnabledForUser(USER_NAME, FEATURE_FOO);
89 assertThat(featureEnabledForUser, is(Option.some(true)));
90 }
91
92 @Test
93 public void systemFeatureDisabledForAuthenticatedUser()
94 {
95 givenUserResolved();
96 final Option<Boolean> featureEnabledForUser = createFeatureManager().isFeatureEnabledForUser(USER_NAME, FEATURE_FOO);
97 assertThat(featureEnabledForUser, is(Option.some(false)));
98 }
99
100 @Test
101 public void featureUndefinedForInvalidUserName()
102 {
103 enableDarkFeatureViaSystemProperty(FEATURE_FOO);
104 givenUserNotResolved();
105 final Option<Boolean> featureEnabledForUser = createFeatureManager().isFeatureEnabledForUser(USER_NAME, FEATURE_FOO);
106 assertThat(featureEnabledForUser, is(Option.<Boolean>none()));
107 }
108
109 @Test
110 public void enableFeatureForAllUsersViaSystemProperty()
111 {
112 enableDarkFeatureViaSystemProperty(FEATURE_FOO);
113 final EnabledDarkFeatures enabledDarkFeatures = createFeatureManager().getFeaturesEnabledForAllUsers();
114 assertThat(enabledDarkFeatures.getFeatureKeys(), hasItem(FEATURE_FOO));
115 }
116
117 @Test
118 public void enableFeatureForAllUsersDuringRuntime()
119 {
120 enableDarkFeatureForAllUsersDuringRuntime(FEATURE_FOO);
121 final EnabledDarkFeatures enabledDarkFeatures = createFeatureManager().getFeaturesEnabledForAllUsers();
122 assertThat(enabledDarkFeatures.getFeatureKeys(), hasItem(FEATURE_FOO));
123 }
124
125 @Test
126 public void enabledFeaturesForAnonymous()
127 {
128 enableDarkFeatureForAllUsersDuringRuntime(FEATURE_FOO);
129 final Option<EnabledDarkFeatures> enabledDarkFeatures = createFeatureManager().getFeaturesEnabledForUser(null);
130 assertTrue(enabledDarkFeatures.isDefined());
131 assertThat(enabledDarkFeatures.get().getFeatureKeys(), hasItem(FEATURE_FOO));
132 }
133
134 @Test
135 public void enabledFeaturesForAuthenticatedUser()
136 {
137 enableDarkFeatureForAllUsersDuringRuntime(FEATURE_FOO);
138 givenUserResolved();
139 final Option<EnabledDarkFeatures> enabledDarkFeatures = createFeatureManager().getFeaturesEnabledForUser(USER_NAME);
140 assertTrue(enabledDarkFeatures.isDefined());
141 assertThat(enabledDarkFeatures.get().getFeatureKeys(), hasItem(FEATURE_FOO));
142 }
143
144 @Test
145 public void enabledFeaturesUndefinedForInvalidUserName()
146 {
147 givenUserNotResolved();
148 final Option<EnabledDarkFeatures> enabledDarkFeatures = createFeatureManager().getFeaturesEnabledForUser(USER_NAME);
149 assertThat(enabledDarkFeatures, is(Option.<EnabledDarkFeatures>none()));
150 }
151
152 @Test
153 public void featureEnabledViaSystemFeature()
154 {
155 enableDarkFeatureViaSystemProperty(FEATURE_FOO);
156 assertTrue(createFeatureManager().isFeatureEnabledForCurrentUser(FEATURE_FOO));
157 }
158
159 @Test
160 public void featureNotEnabled()
161 {
162 assertNull(System.getProperty(FEATURE_FOO));
163 assertFalse(createFeatureManager().isFeatureEnabledForCurrentUser(FEATURE_FOO));
164 }
165
166 @Test
167 public void invalidFeatureKeyIsNeverEnabled()
168 {
169 assertFalse(createFeatureManager().isFeatureEnabledForCurrentUser(INVALID_FEATURE_KEY));
170 }
171
172 @Test
173 public void sysadminCanManageFeaturesForAllUsers()
174 {
175 givenUserIsAuthenticated();
176 givenUserIsSysadmin();
177 assertTrue(createFeatureManager().canManageFeaturesForAllUsers());
178 }
179
180 @Test
181 public void nonSysadminCannotManageFeaturesForAllUsers()
182 {
183 givenUserIsAuthenticated();
184 givenUserIsNotSysadmin();
185 assertFalse(createFeatureManager().canManageFeaturesForAllUsers());
186 }
187
188 @Test
189 public void anonymousCannotManageFeaturesForAllUsers()
190 {
191 givenUserIsNotAuthenticated();
192 assertFalse(createFeatureManager().canManageFeaturesForAllUsers());
193 }
194
195 @Test(expected = MissingPermissionException.class)
196 public void enableFeatureForAllUsersRequiresManagePermission()
197 {
198 try
199 {
200 givenUserIsNotAuthenticated();
201 createFeatureManager().enableFeatureForAllUsers(FEATURE_FOO);
202 }
203 finally
204 {
205 verifyZeroInteractions(siteDarkFeaturesStorage);
206 }
207 }
208
209 @Test(expected = InvalidFeatureKeyException.class)
210 public void enableFeatureForAllUsersRequiresValidFeatureKey()
211 {
212 try
213 {
214 createFeatureManager().enableFeatureForAllUsers(INVALID_FEATURE_KEY);
215 }
216 finally
217 {
218 verifyNoMoreInteractions(siteDarkFeaturesStorage);
219 }
220 }
221
222 @Test
223 public void enableFeatureForAllUsers()
224 {
225 givenUserCanManageFeaturesForAllUsers();
226 createFeatureManager().enableFeatureForAllUsers(FEATURE_FOO);
227 verify(siteDarkFeaturesStorage).enable(FEATURE_FOO);
228 }
229
230 @Test(expected = MissingPermissionException.class)
231 public void disableFeatureForAllUsersRequiresManagePermission()
232 {
233 try
234 {
235 givenUserIsNotAuthenticated();
236 createFeatureManager().disableFeatureForAllUsers(FEATURE_FOO);
237 }
238 finally
239 {
240 verifyZeroInteractions(siteDarkFeaturesStorage);
241 }
242 }
243
244 @Test(expected = InvalidFeatureKeyException.class)
245 public void disableFeatureForAllUsersRequiresValidFeatureKey()
246 {
247 try
248 {
249 createFeatureManager().disableFeatureForAllUsers(INVALID_FEATURE_KEY);
250 }
251 finally
252 {
253 verifyNoMoreInteractions(siteDarkFeaturesStorage);
254 }
255
256 }
257
258 @Test
259 public void disableFeatureForAllUsers()
260 {
261 givenUserCanManageFeaturesForAllUsers();
262 createFeatureManager().disableFeatureForAllUsers(FEATURE_FOO);
263 verify(siteDarkFeaturesStorage).disable(FEATURE_FOO);
264 }
265
266 private void givenUserCanManageFeaturesForAllUsers()
267 {
268 givenUserIsAuthenticated();
269 givenUserIsSysadmin();
270 }
271
272 private void givenUserNotResolved()
273 {
274 when(userManager.resolve(USER_NAME)).thenReturn(null);
275 }
276
277 private void givenUserResolved()
278 {
279 when(userManager.resolve(USER_NAME)).thenReturn(user);
280 }
281
282 private void givenUserIsNotAuthenticated()
283 {
284 when(userManager.getRemoteUsername()).thenReturn(null);
285 }
286
287 private void givenUserIsAuthenticated()
288 {
289 when(userManager.getRemoteUsername()).thenReturn(USER_NAME);
290 }
291
292 private void givenUserIsSysadmin()
293 {
294 when(userManager.isSystemAdmin(USER_NAME)).thenReturn(Boolean.TRUE);
295 }
296
297 private void givenUserIsNotSysadmin()
298 {
299 when(userManager.isSystemAdmin(USER_NAME)).thenReturn(Boolean.FALSE);
300 }
301
302 private void enableDarkFeatureViaSystemProperty(final String systemPropertyKey)
303 {
304 systemPropertyRule.setPropertyWithDarkFeaturePrefix(systemPropertyKey, "true");
305 }
306
307 private void enableDarkFeatureForAllUsersDuringRuntime(final String darkFeatureKey)
308 {
309 when(siteDarkFeaturesStorage.getEnabledDarkFeatures()).thenReturn(ImmutableSet.of(darkFeatureKey));
310 }
311
312 private DefaultDarkFeatureManager createFeatureManager()
313 {
314 return new DefaultDarkFeatureManager(userManager, siteDarkFeaturesStorage);
315 }
316 }