/*******************************************************************************
* Copyright (c) 2010-2014 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.skalli.core.validation;
import static org.easymock.EasyMock.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.UUID;
import org.eclipse.skalli.commons.CollectionUtils;
import org.eclipse.skalli.core.validation.ValidationComponent.QueueAllRunnable;
import org.eclipse.skalli.core.validation.ValidationComponent.QueueRunnable;
import org.eclipse.skalli.core.validation.ValidationComponent.ValidateAllRunnable;
import org.eclipse.skalli.core.validation.ValidationComponent.ValidateRunnable;
import org.eclipse.skalli.model.EntityBase;
import org.eclipse.skalli.model.Issue;
import org.eclipse.skalli.model.Severity;
import org.eclipse.skalli.services.configuration.ConfigurationService;
import org.eclipse.skalli.services.entity.EntityService;
import org.eclipse.skalli.services.issues.Issues;
import org.eclipse.skalli.services.issues.IssuesService;
import org.eclipse.skalli.services.scheduler.RunnableSchedule;
import org.eclipse.skalli.services.scheduler.Schedule;
import org.eclipse.skalli.services.scheduler.SchedulerService;
import org.eclipse.skalli.services.scheduler.Task;
import org.eclipse.skalli.services.validation.Validation;
import org.eclipse.skalli.testutil.AssertUtils;
import org.eclipse.skalli.testutil.BundleManager;
import org.eclipse.skalli.testutil.TestEntityBase1;
import org.eclipse.skalli.testutil.TestEntityBase2;
import org.eclipse.skalli.testutil.TestEntityService;
import org.eclipse.skalli.testutil.TestUUIDs;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.osgi.framework.ServiceRegistration;
@SuppressWarnings("nls")
public class ValidationComponentTest {
private static final String USERID = "hugo";
private static final String USERID1 = "foobar";
private static final SortedSet<Issue> ISSUES1 = CollectionUtils.asSortedSet(
new Issue(Severity.ERROR, TestEntityService.class, TestUUIDs.TEST_UUIDS[0]),
new Issue(Severity.WARNING, TestEntityService.class, TestUUIDs.TEST_UUIDS[0]));
private static final Map<UUID,SortedSet<Issue>> ISSUES_MAP = new HashMap<UUID,SortedSet<Issue>>();
static {
for (int i = 0; i < TestUUIDs.TEST_UUIDS.length; ++i) {
ISSUES_MAP.put(TestUUIDs.TEST_UUIDS[i], ISSUES1);
}
}
private List<ServiceRegistration<?>> serviceRegistrations = new ArrayList<ServiceRegistration<?>>();
private IssuesService mockISS;
private TestEntityService<TestEntityBase1> mockES1;
private TestEntityService<TestEntityBase2> mockES2;
private ConfigurationService mockCS;
private SchedulerService mockSS;
private Object[] mocks;
private ArrayList<TestEntityBase1> entities1;
private ArrayList<Issues> issues1;
private ArrayList<TestEntityBase2> entities2;
private ArrayList<Issues> issues2;
private ValidationConfig[] configs;
private ValidationsConfig config;
private static class TestValidationService extends ValidationComponent {
public TestValidationService(IssuesService issuesService, ConfigurationService configService,
SchedulerService schedulerService) {
bindConfigurationService(configService);
bindIssuesService(issuesService);
bindSchedulerService(schedulerService);
}
}
private static class TestRunnableSchedule extends RunnableSchedule {
protected TestRunnableSchedule(String daysOfWeek, String hours, String minutes) {
super(new Schedule(daysOfWeek, hours, minutes), "Test");
}
@Override
public void run() {
}
}
@Before
public void setup() throws Exception {
entities1 = new ArrayList<TestEntityBase1>();
issues1 = new ArrayList<Issues>();
for (int i = 0; i < TestUUIDs.TEST_UUIDS.length; ++i) {
entities1.add(new TestEntityBase1(TestUUIDs.TEST_UUIDS[i]));
issues1.add(new Issues(TestUUIDs.TEST_UUIDS[i]));
}
issues2 = new ArrayList<Issues>();
entities2 = new ArrayList<TestEntityBase2>();
for (int i = 0; i < TestUUIDs.TEST_UUIDS.length; ++i) {
entities2.add(new TestEntityBase2(TestUUIDs.TEST_UUIDS[i]));
issues2.add(new Issues(TestUUIDs.TEST_UUIDS[i]));
}
configs = new ValidationConfig[4];
ValidationConfig c = new ValidationConfig();
c.setSchedule(new TestRunnableSchedule("*", "*/2", "0,30"));
c.setAction(ValidationAction.QUEUE);
c.setEntityType(TestEntityBase1.class.getName());
c.setMinSeverity(Severity.ERROR);
c.setUserId("homer");
configs[0] = c;
c = new ValidationConfig();
c.setSchedule(new TestRunnableSchedule("Monday", "0", "0"));
c.setAction(ValidationAction.QUEUE_ALL);
c.setMinSeverity(Severity.INFO);
c.setUserId("homer");
configs[1] = c;
c = new ValidationConfig();
c.setSchedule(new TestRunnableSchedule("*", "*", "*"));
c.setAction(ValidationAction.VALIDATE);
c.setEntityType(TestEntityBase2.class.getSimpleName());
c.setMinSeverity(Severity.ERROR);
c.setUserId("homer");
configs[2] = c;
c = new ValidationConfig();
c.setSchedule(new TestRunnableSchedule("*/2", "*", "*"));
c.setAction(ValidationAction.VALIDATE_ALL);
c.setMinSeverity(Severity.ERROR);
c.setUserId("homer");
configs[3] = c;
config = new ValidationsConfig(Arrays.asList(configs));
mockISS = createNiceMock(IssuesService.class);
mockES1 = new TestEntityService<TestEntityBase1>(TestEntityBase1.class, entities1, ISSUES_MAP);
serviceRegistrations.add(BundleManager.registerService(EntityService.class, mockES1, null));
mockES2 = new TestEntityService<TestEntityBase2>(TestEntityBase2.class, entities2);
serviceRegistrations.add(BundleManager.registerService(EntityService.class, mockES2, null));
mockSS = createNiceMock(SchedulerService.class);
mockCS = createNiceMock(ConfigurationService.class);
mocks = new Object[] { mockISS, mockCS, mockSS };
}
@After
public void tearDown() {
for (ServiceRegistration<?> serviceRegistration : serviceRegistrations) {
serviceRegistration.unregister();
}
}
private void initQueueMocks() throws Exception {
mockISS.getByUUID(eq(TestUUIDs.TEST_UUIDS[0]));
expectLastCall().andReturn(issues1.get(0)).anyTimes();
mockISS.getByUUID(eq(TestUUIDs.TEST_UUIDS[1]));
expectLastCall().andReturn(issues1.get(1)).anyTimes();
mockISS.getByUUID(eq(TestUUIDs.TEST_UUIDS[2]));
expectLastCall().andReturn(issues2.get(2)).anyTimes();
mockISS.persist(eq(issues1.get(0)), eq(USERID));
expectLastCall().times(1);
mockISS.persist(eq(issues1.get(1)), eq(USERID));
expectLastCall().times(1);
mockISS.persist(eq(issues2.get(2)), eq(USERID1));
expectLastCall().times(1);
}
private void initQueueAllMocks() throws Exception {
for (int i = 0; i < TestUUIDs.TEST_UUIDS.length; ++i) {
mockISS.getByUUID(eq(TestUUIDs.TEST_UUIDS[i]));
expectLastCall().andReturn(issues1.get(i)).anyTimes();
mockISS.persist(eq(issues1.get(i)), eq(USERID));
expectLastCall().times(1);
}
}
private void initValidateMocks() throws Exception {
mockISS.getByUUID(eq(TestUUIDs.TEST_UUIDS[0]));
expectLastCall().andReturn(issues1.get(0)).anyTimes();
mockISS.persist(eq(TestUUIDs.TEST_UUIDS[0]), eq(ISSUES1), eq(USERID));
expectLastCall().times(1);
}
private void initValidateAllMocks() throws Exception {
for (int i = 0; i < TestUUIDs.TEST_UUIDS.length; ++i) {
mockISS.getByUUID(eq(TestUUIDs.TEST_UUIDS[i]));
expectLastCall().andReturn(issues1.get(i)).anyTimes();
mockISS.persist(eq(TestUUIDs.TEST_UUIDS[i]), eq(ISSUES1), eq(USERID));
expectLastCall().times(1);
}
}
private void initConfigurationServiceMock() {
mockCS.readConfiguration(eq(ValidationsConfig.class));
expectLastCall().andReturn(config).anyTimes();
}
private void initSchedulerServiceMock() {
mockSS.registerSchedule(eq((TestRunnableSchedule) configs[0].getSchedule()));
expectLastCall().andReturn(TestUUIDs.TEST_UUIDS[0]).anyTimes();
mockSS.registerSchedule(eq((TestRunnableSchedule) configs[1].getSchedule()));
expectLastCall().andReturn(TestUUIDs.TEST_UUIDS[1]).anyTimes();
mockSS.registerSchedule(eq((TestRunnableSchedule) configs[2].getSchedule()));
expectLastCall().andReturn(TestUUIDs.TEST_UUIDS[2]).anyTimes();
mockSS.registerSchedule(eq((TestRunnableSchedule) configs[3].getSchedule()));
expectLastCall().andReturn(TestUUIDs.TEST_UUIDS[3]).anyTimes();
mockSS.unregisterSchedule(eq(TestUUIDs.TEST_UUIDS[0]));
expectLastCall().andReturn((TestRunnableSchedule) configs[0].getSchedule()).anyTimes();
mockSS.unregisterSchedule(eq(TestUUIDs.TEST_UUIDS[1]));
expectLastCall().andReturn((TestRunnableSchedule) configs[1].getSchedule()).anyTimes();
mockSS.unregisterSchedule(eq(TestUUIDs.TEST_UUIDS[2]));
expectLastCall().andReturn((TestRunnableSchedule) configs[2].getSchedule()).anyTimes();
mockSS.unregisterSchedule(eq(TestUUIDs.TEST_UUIDS[3]));
expectLastCall().andReturn((TestRunnableSchedule) configs[3].getSchedule()).anyTimes();
mockSS.registerTask(isA(Task.class));
expectLastCall().andReturn(TestUUIDs.TEST_UUIDS[3]).anyTimes();
}
@Test
public void testQueue() throws Exception {
reset(mocks);
initQueueMocks();
replay(mocks);
TestValidationService validationService = new TestValidationService(mockISS, mockCS, mockSS);
Validation<TestEntityBase1> validation1 = new Validation<TestEntityBase1>(
TestEntityBase1.class, TestUUIDs.TEST_UUIDS[0], Severity.WARNING, USERID);
Validation<TestEntityBase2> validation2 = new Validation<TestEntityBase2>(
TestEntityBase2.class, TestUUIDs.TEST_UUIDS[2], Severity.INFO, USERID1);
Validation<TestEntityBase1> validation3 = new Validation<TestEntityBase1>(
TestEntityBase1.class, TestUUIDs.TEST_UUIDS[1], Severity.ERROR, USERID);
Validation<TestEntityBase1> validation4 = new Validation<TestEntityBase1>(
TestEntityBase1.class, TestUUIDs.TEST_UUIDS[0], Severity.INFO, USERID1); // same as but with different severity/userId
validationService.queue(validation1);
validationService.queue(validation2);
validationService.queue(validation3);
validationService.queue(validation4);
Assert.assertTrue(validationService.isQueued(entities1.get(0)));
Assert.assertTrue(validationService.isQueued(entities1.get(1)));
Assert.assertTrue(validationService.isQueued(entities2.get(2)));
Assert.assertEquals(validation2, validationService.pollNextQueueEntry());
Assert.assertEquals(validation3, validationService.pollNextQueueEntry());
Assert.assertEquals(validation1, validationService.pollNextQueueEntry());
Assert.assertNull(validationService.pollNextQueueEntry());
verify(mocks);
}
@Test
public void testQueueAll() throws Exception {
reset(mocks);
initQueueAllMocks();
replay(mocks);
TestValidationService validationService = new TestValidationService(mockISS, mockCS, mockSS);
validationService.queueAll(TestEntityBase1.class, Severity.ERROR, USERID);
for (int i = 0; i < TestUUIDs.TEST_UUIDS.length; ++i) {
Assert.assertTrue(validationService.isQueued(entities1.get(i)));
}
ArrayList<Validation<? extends EntityBase>> queued = new ArrayList<Validation<? extends EntityBase>>();
ArrayList<Validation<? extends EntityBase>> expected = new ArrayList<Validation<? extends EntityBase>>();
for (int i = 0; i < TestUUIDs.TEST_UUIDS.length; ++i) {
queued.add(validationService.pollNextQueueEntry());
expected.add(new Validation<TestEntityBase1>(
TestEntityBase1.class, TestUUIDs.TEST_UUIDS[i], Severity.ERROR, USERID));
}
Assert.assertNull(validationService.pollNextQueueEntry());
AssertUtils.assertEqualsAnyOrder("all", expected, queued);
verify(mocks);
}
@Test
public void testValidate() throws Exception {
reset(mocks);
initValidateMocks();
replay(mocks);
TestValidationService validationService = new TestValidationService(mockISS, mockCS, mockSS);
validationService.validate(TestEntityBase1.class, TestUUIDs.TEST_UUIDS[0], Severity.WARNING, USERID);
verify(mocks);
}
@Test
public void testValidateAll() throws Exception {
reset(mocks);
initValidateAllMocks();
replay(mocks);
TestValidationService validationService = new TestValidationService(mockISS, mockCS, mockSS);
validationService.validateAll(TestEntityBase1.class, Severity.WARNING, USERID);
verify(mocks);
}
@Test
public void testStartValidationTasks() {
reset(mocks);
initConfigurationServiceMock();
initSchedulerServiceMock();
replay(mocks);
TestValidationService validationService = new TestValidationService(mockISS, mockCS, mockSS);
Assert.assertEquals(configs.length, validationService.getRegisteredSchedules().size());
Assert.assertEquals(TestUUIDs.TEST_UUIDS[3], validationService.getTaskIdQueueValidator());
validationService.stopAllTasks();
Assert.assertEquals(0, validationService.getRegisteredSchedules().size());
Assert.assertNull(validationService.getTaskIdQueueValidator());
verify(mocks);
}
@Test
public void testBindUnbindConfigService() {
reset(mocks);
initConfigurationServiceMock();
initSchedulerServiceMock();
replay(mocks);
TestValidationService validationService = new TestValidationService(mockISS, mockCS, mockSS);
Assert.assertEquals(configs.length, validationService.getRegisteredSchedules().size());
validationService.unbindConfigurationService(mockCS);
Assert.assertEquals(0, validationService.getRegisteredSchedules().size()); // default nightly schedule!
validationService.bindConfigurationService(mockCS);
Assert.assertEquals(configs.length, validationService.getRegisteredSchedules().size());
verify(mocks);
}
@Test
public void testBindUnbindSchedulerService() {
reset(mocks);
initConfigurationServiceMock();
initSchedulerServiceMock();
replay(mocks);
TestValidationService validationService = new TestValidationService(mockISS, mockCS, mockSS);
Assert.assertEquals(configs.length, validationService.getRegisteredSchedules().size());
validationService.unbindSchedulerService(mockSS);
Assert.assertEquals(0, validationService.getRegisteredSchedules().size());
validationService.bindSchedulerService(mockSS);
Assert.assertEquals(configs.length, validationService.getRegisteredSchedules().size());
verify(mocks);
}
@Test
public void testGetRunnableFromConfig() throws Exception {
reset(mocks);
replay(mocks);
TestValidationService validationService = new TestValidationService(mockISS, mockCS, mockSS);
Runnable runnable = validationService.getRunnableFromConfig(configs[0]);
Assert.assertEquals(QueueRunnable.class, runnable.getClass());
runnable.run();
assertQueueEntries(validationService, 0, TestEntityBase1.class, null);
runnable = validationService.getRunnableFromConfig(configs[1]);
Assert.assertEquals(QueueAllRunnable.class, runnable.getClass());
runnable.run();
assertQueueEntries(validationService, 1, TestEntityBase1.class, TestEntityBase2.class);
runnable = validationService.getRunnableFromConfig(configs[2]);
Assert.assertEquals(ValidateRunnable.class, runnable.getClass());
runnable = validationService.getRunnableFromConfig(configs[3]);
Assert.assertEquals(ValidateAllRunnable.class, runnable.getClass());
verify(mocks);
}
private void assertQueueEntries(TestValidationService validationService, int config,
Class<? extends EntityBase> entityClass1, Class<? extends EntityBase> entityClass2) {
Set<UUID> uuids1 = CollectionUtils.asSet(TestUUIDs.TEST_UUIDS);
Set<UUID> uuids2 = CollectionUtils.asSet(TestUUIDs.TEST_UUIDS);
Validation<? extends EntityBase> next = validationService.pollNextQueueEntry();
while (next != null) {
Assert.assertNotNull(next.getEntityClass());
if (next.getEntityClass().equals(entityClass1)) {
Assert.assertTrue(uuids1.remove(next.getEntityId()));
} else if (next.getEntityClass().equals(entityClass2)) {
Assert.assertTrue(uuids2.remove(next.getEntityId()));
}
Assert.assertEquals(configs[config].getMinSeverity(), next.getMinSeverity());
Assert.assertEquals(configs[config].getUserId(), next.getUserId());
next = validationService.pollNextQueueEntry();
}
if (entityClass1 != null) {
Assert.assertTrue(uuids1.isEmpty());
} else {
Assert.assertEquals(uuids1.size(), TestUUIDs.TEST_UUIDS.length);
}
if (entityClass2 != null) {
Assert.assertTrue(uuids2.isEmpty());
} else {
Assert.assertEquals(uuids2.size(), TestUUIDs.TEST_UUIDS.length);
}
}
}