/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.course.assessment.manager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.Assert;
import org.junit.Test;
import org.olat.core.commons.persistence.DB;
import org.olat.core.id.Identity;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.course.ICourse;
import org.olat.course.assessment.UserCourseInformations;
import org.olat.resource.OLATResource;
import org.olat.restapi.repository.course.CoursesWebService;
import org.olat.test.JunitTestHelper;
import org.olat.test.OlatTestCase;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 03.09.2013<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class UserCourseInformationsManagerTest extends OlatTestCase {
private static final OLog log = Tracing.createLoggerFor(UserCourseInformationsManagerTest.class);
@Autowired
private DB dbInstance;
@Autowired
private UserCourseInformationsManager userCourseInformationsManager;
@Test
public void createUpdateCourseInfos_create() {
Identity user = JunitTestHelper.createAndPersistIdentityAsUser("user-launch-1-" + UUID.randomUUID().toString());
ICourse course = CoursesWebService.createEmptyCourse(user, "course-launch-dates", "course long name", null);
dbInstance.commitAndCloseSession();
OLATResource courseResource = course.getCourseEnvironment().getCourseGroupManager().getCourseResource();
userCourseInformationsManager.updateUserCourseInformations(courseResource, user);
dbInstance.commitAndCloseSession();
UserCourseInformations infos = userCourseInformationsManager.getUserCourseInformations(courseResource, user);
Assert.assertNotNull(infos);
Assert.assertNotNull(infos.getIdentity());
Assert.assertNotNull(infos.getResource());
Assert.assertNotNull(infos.getInitialLaunch());
Assert.assertNotNull(infos.getRecentLaunch());
Assert.assertEquals(1, infos.getVisit());
Assert.assertEquals(infos.getIdentity(), user);
Assert.assertEquals(course.getResourceableId(), infos.getResource().getResourceableId());
Assert.assertEquals(course.getResourceableTypeName(), infos.getResource().getResourceableTypeName());
}
@Test
public void createUpdateCourseInfos_updateToo() {
Identity user = JunitTestHelper.createAndPersistIdentityAsUser("user-launch-1-" + UUID.randomUUID().toString());
ICourse course = CoursesWebService.createEmptyCourse(user, "course-launch-dates", "course long name", null);
dbInstance.commitAndCloseSession();
OLATResource courseResource = course.getCourseEnvironment().getCourseGroupManager().getCourseResource();
userCourseInformationsManager.updateUserCourseInformations(courseResource, user);
dbInstance.commitAndCloseSession();
userCourseInformationsManager.updateUserCourseInformations(courseResource, user);
dbInstance.commitAndCloseSession();
UserCourseInformations infos = userCourseInformationsManager.getUserCourseInformations(courseResource, user);
Assert.assertNotNull(infos);
Assert.assertNotNull(infos.getIdentity());
Assert.assertEquals(2, infos.getVisit());
}
/**
* Check the low level update statement, it's the critical part of the
* method which update the user course informations.
*/
@Test
public void createUpdateCourseInfos_updateToo_implementationDetails() {
Identity user = JunitTestHelper.createAndPersistIdentityAsUser("user-launch-1-" + UUID.randomUUID().toString());
ICourse course = CoursesWebService.createEmptyCourse(user, "course-launch-dates", "course long name", null);
dbInstance.commitAndCloseSession();
OLATResource courseResource = course.getCourseEnvironment().getCourseGroupManager().getCourseResource();
userCourseInformationsManager.updateUserCourseInformations(courseResource, user);
dbInstance.commitAndCloseSession();
int updated1 = ((UserCourseInformationsManagerImpl)userCourseInformationsManager).lowLevelUpdate(courseResource, user);
dbInstance.commitAndCloseSession();
Assert.assertEquals(1, updated1);
int updated2 = ((UserCourseInformationsManagerImpl)userCourseInformationsManager).lowLevelUpdate(courseResource, user);
dbInstance.commitAndCloseSession();
Assert.assertEquals(1, updated2);
UserCourseInformations infos = userCourseInformationsManager.getUserCourseInformations(courseResource, user);
Assert.assertNotNull(infos);
Assert.assertNotNull(infos.getIdentity());
Assert.assertEquals(3, infos.getVisit());
}
@Test
public void getRecentLaunchDate() {
Identity user = JunitTestHelper.createAndPersistIdentityAsUser("user-launch-7-" + UUID.randomUUID().toString());
ICourse course = CoursesWebService.createEmptyCourse(user, "course-launch-dates", "course long name", null);
dbInstance.commitAndCloseSession();
OLATResource courseResource = course.getCourseEnvironment().getCourseGroupManager().getCourseResource();
userCourseInformationsManager.updateUserCourseInformations(courseResource, user);
dbInstance.commitAndCloseSession();
Date launchDate = userCourseInformationsManager.getRecentLaunchDate(courseResource, user);
Assert.assertNotNull(launchDate);
}
@Test
public void getInitialLaunchDate() {
Identity user = JunitTestHelper.createAndPersistIdentityAsUser("user-launch-2-" + UUID.randomUUID().toString());
ICourse course = CoursesWebService.createEmptyCourse(user, "course-launch-dates", "course long name", null);
dbInstance.commitAndCloseSession();
OLATResource courseResource = course.getCourseEnvironment().getCourseGroupManager().getCourseResource();
userCourseInformationsManager.updateUserCourseInformations(courseResource, user);
dbInstance.commitAndCloseSession();
Date launchDate = userCourseInformationsManager.getInitialLaunchDate(courseResource, user);
Assert.assertNotNull(launchDate);
}
@Test
public void getInitialLaunchDates() {
Identity user1 = JunitTestHelper.createAndPersistIdentityAsUser("user-launch-3-" + UUID.randomUUID().toString());
Identity user2 = JunitTestHelper.createAndPersistIdentityAsUser("user-launch-4-" + UUID.randomUUID().toString());
ICourse course = CoursesWebService.createEmptyCourse(user1, "course-launch-dates", "course long name", null);
dbInstance.commitAndCloseSession();
OLATResource courseResource = course.getCourseEnvironment().getCourseGroupManager().getCourseResource();
userCourseInformationsManager.updateUserCourseInformations(courseResource, user1);
userCourseInformationsManager.updateUserCourseInformations(courseResource, user2);
dbInstance.commitAndCloseSession();
List<Identity> users = new ArrayList<Identity>();
users.add(user1);
users.add(user2);
Map<Long,Date> launchDates = userCourseInformationsManager.getInitialLaunchDates(courseResource, users);
Assert.assertNotNull(launchDates);
Assert.assertEquals(2, launchDates.size());
Assert.assertTrue(launchDates.containsKey(user1.getKey()));
Assert.assertNotNull(launchDates.get(user1.getKey()));
Assert.assertTrue(launchDates.containsKey(user2.getKey()));
Assert.assertNotNull(launchDates.get(user2.getKey()));
}
@Test
public void getInitialLaunchDates_noIdentites() {
Identity user1 = JunitTestHelper.createAndPersistIdentityAsRndUser("user-launch-7-");
Identity user2 = JunitTestHelper.createAndPersistIdentityAsRndUser("user-launch-8-");
Identity user3 = JunitTestHelper.createAndPersistIdentityAsRndUser("user-launch-9-");
ICourse course = CoursesWebService.createEmptyCourse(user1, "course-launch-dates", "course long name", null);
dbInstance.commitAndCloseSession();
OLATResource courseResource = course.getCourseEnvironment().getCourseGroupManager().getCourseResource();
userCourseInformationsManager.updateUserCourseInformations(courseResource, user1);
userCourseInformationsManager.updateUserCourseInformations(courseResource, user2);
userCourseInformationsManager.updateUserCourseInformations(courseResource, user3);
dbInstance.commitAndCloseSession();
//get all launch dates
Map<Long,Date> launchDates = userCourseInformationsManager.getInitialLaunchDates(course.getResourceableId());
Assert.assertNotNull(launchDates);
Assert.assertEquals(3, launchDates.size());
Assert.assertTrue(launchDates.containsKey(user1.getKey()));
Assert.assertNotNull(launchDates.get(user1.getKey()));
Assert.assertTrue(launchDates.containsKey(user2.getKey()));
Assert.assertNotNull(launchDates.get(user2.getKey()));
Assert.assertTrue(launchDates.containsKey(user3.getKey()));
Assert.assertNotNull(launchDates.get(user3.getKey()));
}
/**
* This test is to analyze a red screen
*/
@Test
public void updateInitialLaunchDates_loop() {
Identity user = JunitTestHelper.createAndPersistIdentityAsUser("user-launch-5-" + UUID.randomUUID().toString());
ICourse course = CoursesWebService.createEmptyCourse(user, "course-launch-dates", "course long name", null);
dbInstance.commitAndCloseSession();
for(int i=0; i<10; i++) {
OLATResource courseResource = course.getCourseEnvironment().getCourseGroupManager().getCourseResource();
userCourseInformationsManager.updateUserCourseInformations(courseResource, user);
}
dbInstance.commitAndCloseSession();
List<Identity> users = Collections.singletonList(user);
OLATResource courseResource = course.getCourseEnvironment().getCourseGroupManager().getCourseResource();
Map<Long,Date> launchDates = userCourseInformationsManager.getInitialLaunchDates(courseResource, users);
Assert.assertNotNull(launchDates);
Assert.assertEquals(1, launchDates.size());
Assert.assertTrue(launchDates.containsKey(user.getKey()));
Assert.assertNotNull(launchDates.get(user.getKey()));
}
/**
* This test is to analyze a red screen
*/
@Test
public void updateInitialLaunchDates_concurrent() {
Identity user = JunitTestHelper.createAndPersistIdentityAsUser("user-launch-concurrent-6-" + UUID.randomUUID().toString());
ICourse course = CoursesWebService.createEmptyCourse(user, "course-concurrent-launch-dates", "course long name", null);
dbInstance.commitAndCloseSession();
final int numThreads = 20;
CountDownLatch latch = new CountDownLatch(numThreads);
UpdateThread[] threads = new UpdateThread[numThreads];
for(int i=0; i<threads.length;i++) {
OLATResource courseResource = course.getCourseEnvironment().getCourseGroupManager().getCourseResource();
threads[i] = new UpdateThread(user, courseResource, userCourseInformationsManager, latch, dbInstance);
}
for(int i=0; i<threads.length;i++) {
threads[i].start();
}
try {
latch.await(120, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Assert.fail("Takes too long (more than 120sec)");
}
int countErrors = 0;
for(int i=0; i<threads.length;i++) {
countErrors += threads[i].getErrors();
}
Assert.assertEquals(0, countErrors);
}
/* Needed to generate a lot of datas
@Test
public void testHeavyLoads() {
List<Identity> loadIdentities = CoreSpringFactory.getImpl(BaseSecurity.class)
.getVisibleIdentitiesByPowerSearch(null, null, false, null, null, null, null, null, 1000, 20000);
SearchRepositoryEntryParameters params = new SearchRepositoryEntryParameters();
params.setRoles(new Roles(true, false, false, false, false, false, false));
params.setResourceTypes(Collections.singletonList("CourseModule"));
List<RepositoryEntry> loadOres = RepositoryManager.getInstance().genericANDQueryWithRolesRestriction(params, 0, -1, false);
for(Identity identity:loadIdentities) {
double r = Math.random() * loadOres.size();
int pos = (int)Math.round(r) - 1;
if(pos < 40) {
pos = 40;
}
List<RepositoryEntry> subEntries = loadOres.subList(pos - 30, pos);
for(RepositoryEntry entry:subEntries) {
OLATResource resource = entry.getOlatResource();
userCourseInformationsManager.updateUserCourseInformations(resource.getResourceableId(), identity, true);
}
dbInstance.commitAndCloseSession();
}
}
*/
private static class UpdateThread extends Thread {
private final DB db;
private final CountDownLatch latch;
private final UserCourseInformationsManager uciManager;
private final OLATResource courseResource;
private final Identity user;
private int errors = 0;
public UpdateThread(Identity user, OLATResource courseResource,
UserCourseInformationsManager uciManager, CountDownLatch latch, DB db) {
this.user = user;
this.courseResource = courseResource;
this.uciManager = uciManager;
this.latch = latch;
this.db = db;
}
public int getErrors() {
return errors;
}
@Override
public void run() {
try {
Thread.sleep(10);
for(int i=0; i<25;i++) {
uciManager.updateUserCourseInformations(courseResource, user);
uciManager.getUserCourseInformations(courseResource, user);
uciManager.updateUserCourseInformations(courseResource, user);
db.commitAndCloseSession();
}
} catch (Exception e) {
log.error("", e);
errors++;
} finally {
latch.countDown();
}
}
}
}