[AAI-2531] | Update springboot to 2.1.12.RELEASE
[aai/sparky-be.git] / sparkybe-onap-service / 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.onap.aai.sparky.security.portal.UserManager;
49 import org.onap.aai.sparky.util.NodeUtils;
50 import org.onap.portalsdk.core.restful.domain.EcompUser;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 import com.google.gson.Gson;
55
56
57 // @PrepareForTest(RolesConfig.class)
58 public class TestUserManager {
59
60   private static final String LOGINID_3 = "3";
61   private static File noFile;
62   private static File concurrentUsers;
63   private static File concurrentEditUsers;
64
65   private static final Gson GSON = new Gson();
66   private static final String LOGINID_1 = "1";
67   private static final String LOGINID_2 = "2";
68
69   private static Logger logger = LoggerFactory.getLogger(TestUserManager.class);
70
71   enum TestData {
72     // @formatter:off
73     NO_FILE("src/test/resources/portal/no-users.config"), CONCURRENT_USERS(
74         "src/test/resources/portal/concurrent-users.config"), CONCURRENT_EDIT_USERS(
75             "src/test/resources/portal/concurrent-edit-users.config");
76     // ROLES_CONFIG_FILE ("src/test/resources/portal/roles.config");
77
78     private String filename;
79
80     TestData(String filename) {
81       this.filename = filename;
82     }
83
84     public String getFilename() {
85       return this.filename;
86     }
87     // @formatter:on
88   }
89
90   @BeforeClass
91   public static void setUpBeforeClass() throws Exception {
92     noFile = Paths.get(TestData.NO_FILE.getFilename()).toFile();
93     concurrentUsers = Paths.get(TestData.CONCURRENT_USERS.getFilename()).toFile();
94     concurrentEditUsers = Paths.get(TestData.CONCURRENT_EDIT_USERS.getFilename()).toFile();
95   }
96
97   @AfterClass
98   public static void tearDownAfterClass() throws Exception {
99     Files.deleteIfExists(concurrentUsers.toPath());
100     Files.deleteIfExists(concurrentEditUsers.toPath());
101   }
102
103   @Before
104   public void setUp() throws Exception {
105     EcompUser user1 = new EcompUser();
106     user1.setLoginId(LOGINID_1);
107
108     EcompUser user2 = new EcompUser();
109     user2.setLoginId(LOGINID_2);
110
111     List<EcompUser> users = Arrays.asList(user1, user2);
112     Files.write(concurrentEditUsers.toPath(), GSON.toJson(users).getBytes());
113
114     // Whitebox.setInternalState(RolesConfig.class, "ROLES_CONFIG_FILE",
115     // TestData.ROLES_CONFIG_FILE.getFilename());
116   }
117
118   @After
119   public void tearDown() throws Exception {
120     Files.deleteIfExists(concurrentUsers.toPath());
121     Files.deleteIfExists(concurrentEditUsers.toPath());
122   }
123
124   @Test
125   public void testGetUsersNoFile() throws Exception {
126     UserManager userManager = new UserManager(noFile);
127     List<EcompUser> users = userManager.getUsers();
128
129     assertThat(users, empty());
130   }
131
132   @Test
133   public void testConcurrentPush() throws Exception {
134     Callable<EcompUser> pushTask = () -> {
135       return pushTask(concurrentUsers, String.valueOf(NodeUtils.getRandomTxnId()));
136     };
137
138     List<Callable<EcompUser>> callables =
139         Arrays.asList(pushTask, pushTask, pushTask, pushTask, pushTask);
140
141     ExecutorService executor = Executors.newWorkStealingPool();
142     executor.invokeAll(callables).stream().map(future -> {
143       try {
144         return future.get();
145       } catch (Exception e) {
146         throw new IllegalStateException(e);
147       }
148     });
149
150     UserManager userManager = new UserManager(concurrentUsers);
151     assertThat(userManager.getUsers().size(), is(5));
152   }
153
154   /**
155    * Concurrent push/edit with sequential retry on failure.
156    *
157    * @throws Exception
158    */
159   @Test
160   public void testConcurrentPushAndEdit() throws Exception {
161     Callable<EcompUser> pushTaskRandomId = () -> {
162       return pushTask(concurrentEditUsers, String.valueOf(NodeUtils.getRandomTxnId()));
163     };
164
165     Callable<EcompUser> pushTaskId3 = () -> {
166       return pushTask(concurrentEditUsers, LOGINID_3);
167     };
168
169     Callable<EcompUser> editTaskId1 = () -> {
170       return editTask(LOGINID_1, "Bob");
171     };
172
173     Callable<EcompUser> editTaskId2 = () -> {
174       return editTask(LOGINID_2, "Jen");
175     };
176
177     Callable<EcompUser> editTaskId3 = () -> {
178       return editTask(LOGINID_3, "Amy");
179     };
180
181     List<Callable<EcompUser>> callables =
182         Arrays.asList(pushTaskRandomId, pushTaskRandomId, pushTaskId3, editTaskId1,
183             pushTaskRandomId, pushTaskRandomId, editTaskId3, editTaskId2, pushTaskRandomId);
184
185     ExecutorService executor = Executors.newWorkStealingPool();
186     List<EcompUser> userTasks = executor.invokeAll(callables).stream().map(future -> {
187       try {
188         return future.get();
189       } catch (Exception e) {
190         throw new IllegalStateException(e);
191       }
192     }).collect(Collectors.toList());
193
194     assertThat(userTasks.size(), is(9));
195
196     assertUserPushEdit(concurrentEditUsers);
197   }
198
199   /**
200    * Retry push/edit if assert fails following concurrent attempt.
201    *
202    * @param userFile
203    * @throws Exception
204    */
205   private void assertUserPushEdit(File userFile) throws Exception {
206     UserManager userManager = new UserManager(userFile);
207     try {
208       assertThat(userManager.getUsers().size(), is(8));
209     } catch (Throwable t) {
210       int size = userManager.getUsers().size();
211       logger.error("Failed to push all users. Only created: " + size + " users. " + t.getMessage());
212       pushTask(concurrentEditUsers, String.valueOf(NodeUtils.getRandomTxnId()));
213       assertThat(userManager.getUsers().size(), is(size + 1));
214     }
215
216     try {
217       assertThat(userManager.getUser(LOGINID_1).get().getFirstName(), is("Bob"));
218     } catch (Throwable t) {
219       logger.error("Failed to edit user. " + t.getMessage());
220       retryEdit(userManager, LOGINID_1, "Bob");
221     }
222
223     try {
224       assertThat(userManager.getUser(LOGINID_2).get().getFirstName(), is("Jen"));
225     } catch (Throwable t) {
226       logger.error("Failed to edit user. " + t.getMessage());
227       retryEdit(userManager, LOGINID_2, "Jen");
228     }
229
230     try {
231       assertThat(userManager.getUser(LOGINID_3).isPresent(), is(true));
232     } catch (Throwable t) {
233       logger.error("Failed to push user. " + t.getMessage());
234       pushTask(concurrentEditUsers, LOGINID_3);
235       assertThat(userManager.getUser(LOGINID_3).isPresent(), is(true));
236     }
237
238     try {
239       assertThat(userManager.getUser(LOGINID_3).get().getFirstName(), is("Amy"));
240     } catch (Throwable t) {
241       logger.error("Failed to edit user. " + t.getMessage());
242       retryEdit(userManager, LOGINID_3, "Amy");
243     }
244   }
245
246   private void retryEdit(UserManager userManager, String loginId, String firstName)
247       throws IOException {
248     editTask(loginId, firstName);
249     assertThat(userManager.getUser(loginId).get().getFirstName(), is(firstName));
250   }
251
252   private EcompUser pushTask(File fileStore, String loginId) throws IOException {
253     UserManager userManager = new UserManager(fileStore);
254     EcompUser user = new EcompUser();
255     user.setLoginId(loginId);
256     userManager.pushUser(user);
257     return user;
258   }
259
260   private EcompUser editTask(String loginId, String firstName) throws IOException {
261     UserManager userManager = new UserManager(concurrentEditUsers);
262     EcompUser user = new EcompUser();
263     user.setLoginId(loginId);
264     user.setFirstName(firstName);
265     userManager.editUser(loginId, user);
266     return user;
267   }
268
269 }