/*
* RHQ Management Platform
* Copyright 2013, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.enterprise.server.scheduler.jobs;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;
import org.testng.annotations.Test;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Role;
import org.rhq.core.domain.criteria.SavedSearchCriteria;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.search.SavedSearch;
import org.rhq.core.domain.search.SearchSubsystem;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.authz.RoleManagerLocal;
import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.scheduler.SchedulerLocal;
import org.rhq.enterprise.server.search.SavedSearchManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.test.TransactionCallback;
import org.rhq.enterprise.server.test.TransactionCallbackReturnable;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.util.ResourceTreeHelper;
import org.rhq.enterprise.server.util.SessionTestHelper;
/**
* @author Thomas Segismont
*/
public class SavedSearchResultCountRecalculationJobTest extends AbstractEJB3Test {
private SavedSearchManagerLocal savedSearchManager;
private SubjectManagerLocal subjectManager;
private RoleManagerLocal roleManager;
private ResourceGroupManagerLocal resourceGroupManager;
private SchedulerLocal scheduler;
private TestData testData;
@Override
protected void beforeMethod() throws Exception {
savedSearchManager = LookupUtil.getSavedSearchManager();
subjectManager = LookupUtil.getSubjectManager();
roleManager = LookupUtil.getRoleManager();
resourceGroupManager = LookupUtil.getResourceGroupManager();
scheduler = LookupUtil.getSchedulerBean();
createTestData();
prepareScheduler();
}
private void createTestData() {
testData = executeInTransaction(false, new TransactionCallbackReturnable<TestData>() {
@Override
public TestData execute() throws Exception {
Subject searchesOwner = SessionTestHelper.createNewSubject(em, "fake subject");
Role searchesOwnerRole = SessionTestHelper.createNewRoleForSubject(em, searchesOwner, "fake role");
ResourceType resourceType = SessionTestHelper.createNewResourceType(em);
Set<Resource> resources = new HashSet<Resource>();
Set<ResourceGroup> resourceGroups = new HashSet<ResourceGroup>();
Set<SavedSearch> savedSearches = new HashSet<SavedSearch>();
for (int i = 0; i < 50; i++) {
String iStr = i > 9 ? String.valueOf(i) : "0" + String.valueOf(i);
if (i < 25) {
resources.add(SessionTestHelper.createNewResource(em, "resource-" + iStr, resourceType));
SavedSearch savedSearch = new SavedSearch(SearchSubsystem.RESOURCE, "search-" + iStr,
"resource-" + iStr, searchesOwner);
savedSearchManager.createSavedSearch(searchesOwner, savedSearch);
savedSearches.add(savedSearch);
} else {
resourceGroups.add(SessionTestHelper.createNewCompatibleGroupForRole(em, searchesOwnerRole,
"group-" + iStr, resourceType));
SavedSearch savedSearch = new SavedSearch(SearchSubsystem.GROUP, "search-" + iStr, "group-"
+ iStr, searchesOwner);
savedSearchManager.createSavedSearch(searchesOwner, savedSearch);
savedSearches.add(savedSearch);
}
}
return new TestData(searchesOwner, searchesOwnerRole, resourceType, resources, resourceGroups,
savedSearches);
}
});
}
@Override
protected void afterMethod() throws Exception {
try {
deleteTestData();
} finally {
unprepareScheduler();
}
}
private void deleteTestData() {
if (testData != null) {
final TestData testDataToDelete = testData;
testData = null;
executeInTransaction(false, new TransactionCallback() {
@Override
public void execute() throws Exception {
for (SavedSearch savedSearch : testDataToDelete.getSavedSearches()) {
savedSearchManager.deleteSavedSearch(savedSearch.getSubject(), savedSearch.getId());
}
for (ResourceGroup resourceGroup : testDataToDelete.getResourceGroups()) {
resourceGroupManager.deleteResourceGroup(subjectManager.getOverlord(), resourceGroup.getId());
}
for (Resource resource : testDataToDelete.getResources()) {
ResourceTreeHelper.deleteResource(em, em.find(Resource.class, resource.getId()));
}
em.remove(em.find(ResourceType.class, testDataToDelete.getResourceType().getId()));
subjectManager.deleteSubjects(subjectManager.getOverlord(), new int[] { testDataToDelete
.getSearchesOwner().getId() });
roleManager.deleteRoles(subjectManager.getOverlord(), new int[] { testDataToDelete
.getSearchesOwnerRole().getId() });
}
});
}
}
@Test
public void testSavedSearchResultCountRecalculation() throws Exception {
runJobSynchronously();
executeInTransaction(new TransactionCallback() {
@Override
public void execute() throws Exception {
SavedSearchCriteria criteria = new SavedSearchCriteria();
criteria.clearPaging();
criteria.addFilterSubjectId(testData.getSearchesOwner().getId());
PageList<SavedSearch> foundSavedSearches = savedSearchManager.findSavedSearchesByCriteria(
testData.getSearchesOwner(), criteria);
assertEquals(testData.getSavedSearches().size(), foundSavedSearches.size());
for (SavedSearch savedSearch : foundSavedSearches) {
assertTrue(savedSearch.toString() + " should have been computed",
savedSearch.getLastComputeTime() > 0);
assertEquals(Long.valueOf(1), savedSearch.getResultCount());
}
}
});
}
private void runJobSynchronously() throws Exception {
final CountDownLatch countDownLatch = new CountDownLatch(1);
final String jobName = SavedSearchResultCountRecalculationJob.class.getSimpleName();
final String jobGroup = SavedSearchResultCountRecalculationJobTest.class.getSimpleName();
scheduler.addGlobalJobListener(new JobListener() {
@Override
public String getName() {
return SavedSearchResultCountRecalculationJobTest.class.getSimpleName();
}
@Override
public void jobToBeExecuted(JobExecutionContext context) {
}
@Override
public void jobExecutionVetoed(JobExecutionContext context) {
}
@Override
public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
if (context.getJobDetail().getGroup().equals(jobGroup)) {
countDownLatch.countDown();
}
}
});
scheduler.addJob(new JobDetail(jobName, jobGroup, SavedSearchResultCountRecalculationJob.class), true);
scheduler.triggerJob(jobName, jobGroup);
try {
countDownLatch.await(60, TimeUnit.SECONDS);
} finally {
scheduler.deleteJob(jobName, jobGroup);
}
}
private static final class TestData {
private final Subject searchesOwner;
private final Role searchesOwnerRole;
private final ResourceType resourceType;
private final Set<Resource> resources;
private final Set<ResourceGroup> resourceGroups;
private final Set<SavedSearch> savedSearches;
private TestData(Subject searchesOwner, Role searchesOwnerRole, ResourceType resourceType,
Set<Resource> resources, Set<ResourceGroup> resourceGroups, Set<SavedSearch> savedSearches) {
this.searchesOwner = searchesOwner;
this.searchesOwnerRole = searchesOwnerRole;
this.resourceType = resourceType;
this.resources = resources;
this.resourceGroups = resourceGroups;
this.savedSearches = savedSearches;
}
public Subject getSearchesOwner() {
return searchesOwner;
}
public Role getSearchesOwnerRole() {
return searchesOwnerRole;
}
public ResourceType getResourceType() {
return resourceType;
}
public Set<Resource> getResources() {
return resources;
}
public Set<ResourceGroup> getResourceGroups() {
return resourceGroups;
}
public Set<SavedSearch> getSavedSearches() {
return savedSearches;
}
}
}