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