/** * Licensed to The Apereo Foundation under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * * The Apereo Foundation licenses this file to you 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://opensource.org/licenses/ecl2.txt * * 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.opencastproject.workflow.impl; import static org.opencastproject.workflow.impl.SecurityServiceStub.DEFAULT_ORG_ADMIN; import org.opencastproject.mediapackage.DefaultMediaPackageSerializerImpl; import org.opencastproject.mediapackage.MediaPackage; import org.opencastproject.mediapackage.MediaPackageBuilder; import org.opencastproject.mediapackage.MediaPackageBuilderFactory; import org.opencastproject.message.broker.api.MessageSender; import org.opencastproject.metadata.api.MediaPackageMetadataService; import org.opencastproject.security.api.AccessControlList; import org.opencastproject.security.api.AclScope; import org.opencastproject.security.api.AuthorizationService; import org.opencastproject.security.api.DefaultOrganization; import org.opencastproject.security.api.Organization; import org.opencastproject.security.api.OrganizationDirectoryService; import org.opencastproject.security.api.SecurityService; import org.opencastproject.security.api.UserDirectoryService; import org.opencastproject.serviceregistry.api.IncidentService; import org.opencastproject.serviceregistry.api.ServiceRegistryInMemoryImpl; import org.opencastproject.util.data.Tuple; import org.opencastproject.workflow.api.WorkflowDefinition; import org.opencastproject.workflow.api.WorkflowInstance; import org.opencastproject.workflow.api.WorkflowInstance.WorkflowState; import org.opencastproject.workflow.api.WorkflowParser; import org.opencastproject.workflow.api.WorkflowStateListener; import org.opencastproject.workflow.impl.WorkflowServiceImpl.HandlerRegistration; import org.opencastproject.workspace.api.Workspace; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.easymock.EasyMock; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import junit.framework.Assert; public class PauseWorkflowTest { private WorkflowServiceImpl service = null; private WorkflowDefinitionScanner scanner = null; private WorkflowDefinition def = null; private WorkflowInstance workflow = null; private MediaPackage mp = null; private WorkflowServiceSolrIndex dao = null; private Workspace workspace = null; private SecurityService securityService = null; private ResumableTestWorkflowOperationHandler firstHandler = null; private ResumableTestWorkflowOperationHandler secondHandler = null; private File sRoot = null; private AccessControlList acl = new AccessControlList(); protected static final String getStorageRoot() { return "." + File.separator + "target" + File.separator + System.currentTimeMillis(); } @Before public void setUp() throws Exception { // always start with a fresh solr root directory sRoot = new File(getStorageRoot()); try { FileUtils.deleteDirectory(sRoot); FileUtils.forceMkdir(sRoot); } catch (IOException e) { Assert.fail(e.getMessage()); } MediaPackageBuilder mediaPackageBuilder = MediaPackageBuilderFactory.newInstance().newMediaPackageBuilder(); mediaPackageBuilder.setSerializer(new DefaultMediaPackageSerializerImpl(new File("target/test-classes"))); InputStream is = PauseWorkflowTest.class.getResourceAsStream("/mediapackage-1.xml"); mp = mediaPackageBuilder.loadFromXml(is); IOUtils.closeQuietly(is); // create operation handlers for our workflows final Set<HandlerRegistration> handlerRegistrations = new HashSet<HandlerRegistration>(); firstHandler = new ResumableTestWorkflowOperationHandler(); secondHandler = new ResumableTestWorkflowOperationHandler(); handlerRegistrations.add(new HandlerRegistration("op1", firstHandler)); handlerRegistrations.add(new HandlerRegistration("op2", secondHandler)); // instantiate a service implementation and its DAO, overriding the methods that depend on the osgi runtime service = new WorkflowServiceImpl() { @Override public Set<HandlerRegistration> getRegisteredHandlers() { return handlerRegistrations; } }; scanner = new WorkflowDefinitionScanner(); service.addWorkflowDefinitionScanner(scanner); // security service DefaultOrganization organization = new DefaultOrganization(); securityService = EasyMock.createNiceMock(SecurityService.class); EasyMock.expect(securityService.getUser()).andReturn(SecurityServiceStub.DEFAULT_ORG_ADMIN).anyTimes(); EasyMock.expect(securityService.getOrganization()).andReturn(organization).anyTimes(); EasyMock.replay(securityService); service.setSecurityService(securityService); AuthorizationService authzService = EasyMock.createNiceMock(AuthorizationService.class); EasyMock.expect(authzService.getActiveAcl((MediaPackage) EasyMock.anyObject())) .andReturn(Tuple.tuple(acl, AclScope.Series)).anyTimes(); EasyMock.replay(authzService); service.setAuthorizationService(authzService); UserDirectoryService userDirectoryService = EasyMock.createMock(UserDirectoryService.class); EasyMock.expect(userDirectoryService.loadUser((String) EasyMock.anyObject())).andReturn(DEFAULT_ORG_ADMIN) .anyTimes(); EasyMock.replay(userDirectoryService); service.setUserDirectoryService(userDirectoryService); MediaPackageMetadataService mds = EasyMock.createNiceMock(MediaPackageMetadataService.class); EasyMock.replay(mds); service.addMetadataService(mds); List<Organization> organizationList = new ArrayList<Organization>(); organizationList.add(organization); OrganizationDirectoryService organizationDirectoryService = EasyMock.createMock(OrganizationDirectoryService.class); EasyMock.expect(organizationDirectoryService.getOrganizations()).andReturn(organizationList).anyTimes(); EasyMock.expect(organizationDirectoryService.getOrganization((String) EasyMock.anyObject())) .andReturn(securityService.getOrganization()).anyTimes(); EasyMock.replay(organizationDirectoryService); service.setOrganizationDirectoryService(organizationDirectoryService); ServiceRegistryInMemoryImpl serviceRegistry = new ServiceRegistryInMemoryImpl(service, securityService, userDirectoryService, organizationDirectoryService, EasyMock.createNiceMock(IncidentService.class)); workspace = EasyMock.createNiceMock(Workspace.class); EasyMock.expect(workspace.getCollectionContents((String) EasyMock.anyObject())).andReturn(new URI[0]); EasyMock.replay(workspace); MessageSender messageSender = EasyMock.createNiceMock(MessageSender.class); EasyMock.replay(messageSender); dao = new WorkflowServiceSolrIndex(); dao.setServiceRegistry(serviceRegistry); dao.setAuthorizationService(authzService); dao.solrRoot = sRoot + File.separator + "solr"; dao.setSecurityService(securityService); dao.setOrgDirectory(organizationDirectoryService); dao.activate("System Admin"); service.setDao(dao); service.setServiceRegistry(serviceRegistry); service.setMessageSender(messageSender); service.activate(null); is = PauseWorkflowTest.class.getResourceAsStream("/workflow-definition-pause.xml"); def = WorkflowParser.parseWorkflowDefinition(is); IOUtils.closeQuietly(is); service.registerWorkflowDefinition(def); } @After public void tearDown() throws Exception { dao.deactivate(); service.deactivate(); } @Test public void testHoldAndResume() throws Exception { // Start a new workflow WorkflowStateListener pauseListener = new WorkflowStateListener(WorkflowState.PAUSED); service.addWorkflowListener(pauseListener); synchronized (pauseListener) { workflow = service.start(def, mp, null); pauseListener.wait(); } // Ensure that the first operation handler was called, but not the second Assert.assertTrue(firstHandler.isStarted()); Assert.assertTrue(!secondHandler.isStarted()); // The workflow should be in the paused state Assert.assertEquals(WorkflowState.PAUSED, service.getWorkflowById(workflow.getId()).getState()); // Resume the workflow with some properties Map<String, String> properties = new HashMap<String, String>(); properties.put("key", "value"); service.addWorkflowListener(pauseListener); synchronized (pauseListener) { service.resume(workflow.getId(), properties); pauseListener.wait(); } service.removeWorkflowListener(pauseListener); // The handler should have picked up the properties Assert.assertEquals(properties, firstHandler.getProperties()); } }