Adding UI extensibility
[aai/sparky-be.git] / src / test / java / org / onap / aai / sparky / security / portal / TestUserManager.java
1 /**
2  * ============LICENSE_START===================================================
3  * SPARKY (AAI UI service)
4  * ============================================================================
5  * Copyright © 2017 AT&T Intellectual Property.
6  * Copyright © 2017 Amdocs
7  * All rights reserved.
8  * ============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=====================================================
21  *
22  * ECOMP and OpenECOMP are trademarks
23  * and service marks of AT&T Intellectual Property.
24  */
25
26 package org.onap.aai.sparky.security.portal;
27
28 import static org.hamcrest.Matchers.empty;
29 import static org.hamcrest.Matchers.is;
30 import static org.junit.Assert.assertThat;
31
32 import java.io.File;
33 import java.io.IOException;
34 import java.nio.file.Files;
35 import java.nio.file.Paths;
36 import java.util.Arrays;
37 import java.util.List;
38 import java.util.concurrent.Callable;
39 import java.util.concurrent.ExecutorService;
40 import java.util.concurrent.Executors;
41 import java.util.stream.Collectors;
42
43 import org.junit.After;
44 import org.junit.AfterClass;
45 import org.junit.Before;
46 import org.junit.BeforeClass;
47 import org.junit.Test;
48 import org.junit.runner.RunWith;
49 import org.onap.aai.sparky.security.portal.UserManager;
50 import org.onap.aai.sparky.util.NodeUtils;
51 import org.openecomp.portalsdk.core.restful.domain.EcompUser;
52 import org.powermock.modules.junit4.PowerMockRunner;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 import com.google.gson.Gson;
57
58 @RunWith(PowerMockRunner.class)
59 // @PrepareForTest(RolesConfig.class)
60 public class TestUserManager {
61
62   private static final String LOGINID_3 = "3";
63   private static File noFile;
64   private static File concurrentUsers;
65   private static File concurrentEditUsers;
66
67   private static final Gson GSON = new Gson();
68   private static final String LOGINID_1 = "1";
69   private static final String LOGINID_2 = "2";
70
71   private static Logger logger = LoggerFactory.getLogger(TestUserManager.class);
72
73   enum TestData {
74     // @formatter:off
75     NO_FILE("src/test/resources/portal/no-users.config"), CONCURRENT_USERS(
76         "src/test/resources/portal/concurrent-users.config"), CONCURRENT_EDIT_USERS(
77             "src/test/resources/portal/concurrent-edit-users.config");
78     // ROLES_CONFIG_FILE ("src/test/resources/portal/roles.config");
79
80     private String filename;
81
82     TestData(String filename) {
83       this.filename = filename;
84     }
85
86     public String getFilename() {
87       return this.filename;
88     }
89     // @formatter:on
90   }
91
92   @BeforeClass
93   public static void setUpBeforeClass() throws Exception {
94     noFile = Paths.get(TestData.NO_FILE.getFilename()).toFile();
95     concurrentUsers = Paths.get(TestData.CONCURRENT_USERS.getFilename()).toFile();
96     concurrentEditUsers = Paths.get(TestData.CONCURRENT_EDIT_USERS.getFilename()).toFile();
97   }
98
99   @AfterClass
100   public static void tearDownAfterClass() throws Exception {
101     Files.deleteIfExists(concurrentUsers.toPath());
102     Files.deleteIfExists(concurrentEditUsers.toPath());
103   }
104
105   @Before
106   public void setUp() throws Exception {
107     EcompUser user1 = new EcompUser();
108     user1.setLoginId(LOGINID_1);
109
110     EcompUser user2 = new EcompUser();
111     user2.setLoginId(LOGINID_2);
112
113     List<EcompUser> users = Arrays.asList(user1, user2);
114     Files.write(concurrentEditUsers.toPath(), GSON.toJson(users).getBytes());
115
116     // Whitebox.setInternalState(RolesConfig.class, "ROLES_CONFIG_FILE",
117     // TestData.ROLES_CONFIG_FILE.getFilename());
118   }
119
120   @After
121   public void tearDown() throws Exception {
122     Files.deleteIfExists(concurrentUsers.toPath());
123     Files.deleteIfExists(concurrentEditUsers.toPath());
124   }
125
126   @Test
127   public void testGetUsersNoFile() throws Exception {
128     UserManager userManager = new UserManager(noFile);
129     List<EcompUser> users = userManager.getUsers();
130
131     assertThat(users, empty());
132   }
133
134   @Test
135   public void testConcurrentPush() throws Exception {
136     Callable<EcompUser> pushTask = () -> {
137       return pushTask(concurrentUsers, String.valueOf(NodeUtils.getRandomTxnId()));
138     };
139
140     List<Callable<EcompUser>> callables =
141         Arrays.asList(pushTask, pushTask, pushTask, pushTask, pushTask);
142
143     ExecutorService executor = Executors.newWorkStealingPool();
144     executor.invokeAll(callables).stream().map(future -> {
145       try {
146         return future.get();
147       } catch (Exception e) {
148         throw new IllegalStateException(e);
149       }
150     });
151
152     UserManager userManager = new UserManager(concurrentUsers);
153     assertThat(userManager.getUsers().size(), is(5));
154   }
155
156   /**
157    * Concurrent push/edit with sequential retry on failure.
158    *
159    * @throws Exception
160    */
161   @Test
162   public void testConcurrentPushAndEdit() throws Exception {
163     Callable<EcompUser> pushTaskRandomId = () -> {
164       return pushTask(concurrentEditUsers, String.valueOf(NodeUtils.getRandomTxnId()));
165     };
166
167     Callable<EcompUser> pushTaskId3 = () -> {
168       return pushTask(concurrentEditUsers, LOGINID_3);
169     };
170
171     Callable<EcompUser> editTaskId1 = () -> {
172       return editTask(LOGINID_1, "Bob");
173     };
174
175     Callable<EcompUser> editTaskId2 = () -> {
176       return editTask(LOGINID_2, "Jen");
177     };
178
179     Callable<EcompUser> editTaskId3 = () -> {
180       return editTask(LOGINID_3, "Amy");
181     };
182
183     List<Callable<EcompUser>> callables =
184         Arrays.asList(pushTaskRandomId, pushTaskRandomId, pushTaskId3, editTaskId1,
185             pushTaskRandomId, pushTaskRandomId, editTaskId3, editTaskId2, pushTaskRandomId);
186
187     ExecutorService executor = Executors.newWorkStealingPool();
188     List<EcompUser> userTasks = executor.invokeAll(callables).stream().map(future -> {
189       try {
190         return future.get();
191       } catch (Exception e) {
192         throw new IllegalStateException(e);
193       }
194     }).collect(Collectors.toList());
195
196     assertThat(userTasks.size(), is(9));
197
198     assertUserPushEdit(concurrentEditUsers);
199   }
200
201   /**
202    * Retry push/edit if assert fails following concurrent attempt.
203    *
204    * @param userFile
205    * @throws Exception
206    */
207   private void assertUserPushEdit(File userFile) throws Exception {
208     UserManager userManager = new UserManager(userFile);
209     try {
210       assertThat(userManager.getUsers().size(), is(8));
211     } catch (Throwable t) {
212       int size = userManager.getUsers().size();
213       logger.error("Failed to push all users. Only created: " + size + " users. " + t.getMessage());
214       pushTask(concurrentEditUsers, String.valueOf(NodeUtils.getRandomTxnId()));
215       assertThat(userManager.getUsers().size(), is(size + 1));
216     }
217
218     try {
219       assertThat(userManager.getUser(LOGINID_1).get().getFirstName(), is("Bob"));
220     } catch (Throwable t) {
221       logger.error("Failed to edit user. " + t.getMessage());
222       retryEdit(userManager, LOGINID_1, "Bob");
223     }
224
225     try {
226       assertThat(userManager.getUser(LOGINID_2).get().getFirstName(), is("Jen"));
227     } catch (Throwable t) {
228       logger.error("Failed to edit user. " + t.getMessage());
229       retryEdit(userManager, LOGINID_2, "Jen");
230     }
231
232     try {
233       assertThat(userManager.getUser(LOGINID_3).isPresent(), is(true));
234     } catch (Throwable t) {
235       logger.error("Failed to push user. " + t.getMessage());
236       pushTask(concurrentEditUsers, LOGINID_3);
237       assertThat(userManager.getUser(LOGINID_3).isPresent(), is(true));
238     }
239
240     try {
241       assertThat(userManager.getUser(LOGINID_3).get().getFirstName(), is("Amy"));
242     } catch (Throwable t) {
243       logger.error("Failed to edit user. " + t.getMessage());
244       retryEdit(userManager, LOGINID_3, "Amy");
245     }
246   }
247
248   private void retryEdit(UserManager userManager, String loginId, String firstName)
249       throws IOException {
250     editTask(loginId, firstName);
251     assertThat(userManager.getUser(loginId).get().getFirstName(), is(firstName));
252   }
253
254   private EcompUser pushTask(File fileStore, String loginId) throws IOException {
255     UserManager userManager = new UserManager(fileStore);
256     EcompUser user = new EcompUser();
257     user.setLoginId(loginId);
258     userManager.pushUser(user);
259     return user;
260   }
261
262   private EcompUser editTask(String loginId, String firstName) throws IOException {
263     UserManager userManager = new UserManager(concurrentEditUsers);
264     EcompUser user = new EcompUser();
265     user.setLoginId(loginId);
266     user.setFirstName(firstName);
267     userManager.editUser(loginId, user);
268     return user;
269   }
270
271 }