/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/kernel/trunk/kernel-impl/src/test/java/org/sakaiproject/site/impl/test/SiteAliasCleanupNotificationActionTest.java $ * $Id: SiteAliasCleanupNotificationActionTest.java 105077 2012-02-24 22:54:29Z ottenhoff@longsight.com $ *********************************************************************************** * * Copyright (c) 2003, 2004, 2005, 2006 Sakai Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * **********************************************************************************/ package org.sakaiproject.site.impl.test; import java.lang.reflect.Field; import org.apache.commons.logging.Log; import org.jmock.Expectations; import org.jmock.integration.junit3.MockObjectTestCase; import org.sakaiproject.alias.api.AliasService; import org.sakaiproject.event.api.Event; import org.sakaiproject.event.api.Notification; import org.sakaiproject.event.api.NotificationEdit; import org.sakaiproject.event.api.NotificationService; import org.sakaiproject.exception.PermissionException; import org.sakaiproject.site.api.SiteService; import org.sakaiproject.site.impl.SiteAliasCleanupNotificationAction; /** * Verifies event-driven cleanup of site aliases. * * @author dmccallum * */ public class SiteAliasCleanupNotificationActionTest extends MockObjectTestCase { private SiteAliasCleanupNotificationAction cleanupAction; private NotificationEdit cleanupActionWrappingNotificationEdit; private Notification inboundNotification; private Event inboundEvent; private AliasService aliasService; private NotificationService notificationService; private Log log; protected void setUp() throws Exception { aliasService = mock(AliasService.class); notificationService = mock(NotificationService.class); cleanupActionWrappingNotificationEdit = mock(NotificationEdit.class); inboundNotification = mock(Notification.class); inboundEvent = mock(Event.class); log = mock(Log.class); cleanupAction = new SiteAliasCleanupNotificationAction(); cleanupAction.setAliasService(aliasService); cleanupAction.setNotificationService(notificationService); setField("log", SiteAliasCleanupNotificationAction.class, null, log); super.setUp(); } public void testDeletesAliasesTargetingEventResourceIfEnabled() throws PermissionException { expectInit(); checking(new Expectations() {{ final String resourceId = "/entity/id"; // allowing() makes test more resilient to changes in logging code, // and it is unlikely the object under test is hard-coded to // remove aliases for "/entity/id" allowing(inboundEvent).getResource(); will(returnValue(resourceId)); one(aliasService).removeTargetAliases(resourceId); }}); // implicitly tests that alias deletion is enabled by default cleanupAction.init(); cleanupAction.notify(inboundNotification, inboundEvent); } public void testIgnoresNotificationsIfDisabled() { cleanupAction.setEnabled(false); expectInit(); cleanupAction.init(); cleanupAction.notify(inboundNotification, inboundEvent); } public void testLogsAndSwallowsUncheckedExceptionsByDefault() throws PermissionException { expectInit(); checking(new Expectations() {{ final String resourceId = "/entity/id"; RuntimeException failure = new RuntimeException("this is a simulated failure"); allowing(inboundEvent).getResource(); will(returnValue(resourceId)); one(aliasService).removeTargetAliases(resourceId); will(throwException(failure)); one(log).warn(with(any(String.class)), with(same(failure))); }}); cleanupAction.init(); cleanupAction.notify(inboundNotification, inboundEvent); } public void testLogsAndSwallowsCheckedExceptionsByDefault() throws PermissionException { expectInit(); checking(new Expectations() {{ final String resourceId = "/entity/id"; PermissionException failure = new PermissionException("user-123", SiteService.SECURE_REMOVE_SITE, resourceId); allowing(inboundEvent).getResource(); will(returnValue(resourceId)); one(aliasService).removeTargetAliases(resourceId); will(throwException(failure)); one(log).warn(with(any(String.class)), with(same(failure))); }}); cleanupAction.init(); cleanupAction.notify(inboundNotification, inboundEvent); } public void testRaisesUncheckedExceptionsIfSoConfigured() throws PermissionException { cleanupAction.setPropagateExceptions(true); expectInit(); final RuntimeException failure = new RuntimeException("this is a simulated failure"); checking(new Expectations() {{ final String resourceId = "/entity/id"; allowing(inboundEvent).getResource(); will(returnValue(resourceId)); one(aliasService).removeTargetAliases(resourceId); will(throwException(failure)); }}); cleanupAction.init(); try { cleanupAction.notify(inboundNotification, inboundEvent); fail("Should have raised the unchecked exception representing the failure to delete aliases"); } catch ( RuntimeException e ) { assertSame("Threw the wrong exception", failure, e); } } public void testRaisesCheckedExceptionsInUncheckedExceptionsIfSoConfigured() throws PermissionException { cleanupAction.setPropagateExceptions(true); expectInit(); final String resourceId = "/entity/id"; final PermissionException failure = new PermissionException("user-123", SiteService.SECURE_REMOVE_SITE, resourceId); checking(new Expectations() {{ allowing(inboundEvent).getResource(); will(returnValue(resourceId)); one(aliasService).removeTargetAliases(resourceId); will(throwException(failure)); }}); cleanupAction.init(); try { cleanupAction.notify(inboundNotification, inboundEvent); fail("Should have raised an unchecked exception wrapping the checked exception indicating failure to delete aliases"); } catch ( RuntimeException e ) { assertSame("Didn't wrap exception representing failure to delete aliases", failure, e.getCause()); } } public void testCloneCopiesInstanceMembers() { // ensure we're not getting false positives b/c of defaulting cleanupAction.setEnabled(!(cleanupAction.isEnabled())); cleanupAction.setPropagateExceptions(!(cleanupAction.isPropagateExceptions())); SiteAliasCleanupNotificationAction clone = (SiteAliasCleanupNotificationAction) cleanupAction.getClone(); assertEquals("Failed to copy the \"enabled\" property", cleanupAction.isEnabled(), clone.isEnabled()); assertEquals("Failed to copy the \"propagateExceptions\" property", cleanupAction.isPropagateExceptions(), clone.isPropagateExceptions()); assertSame("Failed to copy the \"aliasService\" property", cleanupAction.getAliasService(), clone.getAliasService()); assertSame("Failed to copy the \"notificationService\" property", cleanupAction.getNotificationService(), clone.getNotificationService()); } private void expectInit() { checking(new Expectations() {{ one(notificationService).addTransientNotification(); will(returnValue(cleanupActionWrappingNotificationEdit)); one(cleanupActionWrappingNotificationEdit).setFunction(SiteService.SECURE_REMOVE_SITE); one(cleanupActionWrappingNotificationEdit).setResourceFilter(SiteService.REFERENCE_ROOT); one(cleanupActionWrappingNotificationEdit).setAction(cleanupAction); }}); } private void setField(String fieldName, Class<?> clazz, Object onInstance, Object fieldValue) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Field field = clazz.getDeclaredField(fieldName); field.setAccessible(true); field.set(onInstance, fieldValue); } }