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