/** * 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.index.service.impl; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.capture; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import org.opencastproject.capture.admin.api.CaptureAgentStateService; import org.opencastproject.index.service.catalog.adapter.events.CommonEventCatalogUIAdapter; import org.opencastproject.index.service.exception.IndexServiceException; import org.opencastproject.index.service.impl.index.AbstractSearchIndex; import org.opencastproject.index.service.impl.index.event.Event; import org.opencastproject.index.service.impl.index.event.EventSearchQuery; import org.opencastproject.ingest.api.IngestException; import org.opencastproject.ingest.api.IngestService; import org.opencastproject.matterhorn.search.SearchIndexException; import org.opencastproject.matterhorn.search.SearchQuery; import org.opencastproject.matterhorn.search.SearchResult; import org.opencastproject.matterhorn.search.impl.SearchResultImpl; import org.opencastproject.matterhorn.search.impl.SearchResultItemImpl; import org.opencastproject.mediapackage.Attachment; import org.opencastproject.mediapackage.Catalog; import org.opencastproject.mediapackage.CatalogImpl; import org.opencastproject.mediapackage.MediaPackage; import org.opencastproject.mediapackage.MediaPackageElement; import org.opencastproject.mediapackage.MediaPackageElementFlavor; import org.opencastproject.mediapackage.MediaPackageException; import org.opencastproject.mediapackage.identifier.HandleException; import org.opencastproject.mediapackage.identifier.Id; import org.opencastproject.mediapackage.identifier.IdImpl; import org.opencastproject.metadata.dublincore.DublinCore; import org.opencastproject.metadata.dublincore.DublinCoreCatalog; import org.opencastproject.metadata.dublincore.MetadataCollection; import org.opencastproject.metadata.dublincore.MetadataField; import org.opencastproject.scheduler.api.SchedulerException; import org.opencastproject.scheduler.api.SchedulerService; import org.opencastproject.security.api.AccessControlList; import org.opencastproject.security.api.AclScope; import org.opencastproject.security.api.AuthorizationService; import org.opencastproject.security.api.Organization; import org.opencastproject.security.api.SecurityService; import org.opencastproject.security.api.UnauthorizedException; import org.opencastproject.security.api.User; import org.opencastproject.security.api.UserDirectoryService; import org.opencastproject.security.impl.jpa.JpaOrganization; import org.opencastproject.security.impl.jpa.JpaUser; import org.opencastproject.util.ConfigurationException; import org.opencastproject.util.IoSupport; import org.opencastproject.util.NotFoundException; import org.opencastproject.util.PropertiesUtil; import org.opencastproject.util.data.Option; import org.opencastproject.util.data.Tuple; import org.opencastproject.util.data.VCell; import org.opencastproject.workflow.api.WorkflowDatabaseException; import org.opencastproject.workflow.api.WorkflowInstance; import org.opencastproject.workspace.api.Workspace; import net.fortuna.ical4j.model.DateTime; import net.fortuna.ical4j.model.Period; import net.fortuna.ical4j.model.property.RRule; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.easymock.Capture; import org.easymock.EasyMock; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.osgi.service.component.ComponentException; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Dictionary; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TimeZone; public class IndexServiceImplTest { private static final JSONParser parser = new JSONParser(); /** * Tests for the method calculatePeriods */ private final TimeZone utc = TimeZone.getTimeZone("UTC"); private final TimeZone jst = TimeZone.getTimeZone("JST"); // Japan Standard Time (UTC +9) private final TimeZone pst = TimeZone.getTimeZone("PST"); // Alaska Standard Time (UTC -8) private final TimeZone cet = TimeZone.getTimeZone("CET"); // Alaska Standard Time (UTC +2) private JpaOrganization organization = new JpaOrganization("org-id", "Organization", null, null, null, null, null); private User user1 = new JpaUser("user1", "pass", organization, "User 1", "email1", "provider1", true); private User user2 = new JpaUser("user2", "pass", organization, "User 2", "email1", "provider1", true); private User user3 = new JpaUser("user3", "pass", organization, null, "email1", "provider1", true); private UserDirectoryService noUsersUserDirectoryService; @Before public void before() { noUsersUserDirectoryService = EasyMock.createMock(UserDirectoryService.class); EasyMock.expect(noUsersUserDirectoryService.loadUser(EasyMock.anyString())).andStubReturn(null); EasyMock.replay(noUsersUserDirectoryService); } private CaptureAgentStateService setupCaptureAgentStateService() throws NotFoundException { // Setup capture agent state service CaptureAgentStateService captureAgentStateService = EasyMock.createNiceMock(CaptureAgentStateService.class); Properties agentProperties = new Properties(); agentProperties.put("capture.device.timezone", "Europe/Zurich"); EasyMock.expect(captureAgentStateService.getAgentConfiguration(EasyMock.anyString())).andReturn(agentProperties) .anyTimes(); EasyMock.replay(captureAgentStateService); return captureAgentStateService; } private IngestService setupIngestServiceWithMediaPackage() throws IngestException, MediaPackageException, HandleException, IOException, NotFoundException { MediaPackage mediapackage = EasyMock.createNiceMock(MediaPackage.class); EasyMock.replay(mediapackage); return setupIngestService(mediapackage, Capture.<InputStream> newInstance()); } private IngestService setupIngestService(MediaPackage mediapackage, Capture<InputStream> captureInputStream) throws MediaPackageException, HandleException, IOException, IngestException, NotFoundException { // Setup ingest service. WorkflowInstance workflowInstance = createMock(WorkflowInstance.class); IngestService ingestService = createMock(IngestService.class); expect(ingestService.createMediaPackage()).andReturn(mediapackage).anyTimes(); expect(ingestService.addTrack(anyObject(InputStream.class), EasyMock.anyString(), anyObject(MediaPackageElementFlavor.class), anyObject(MediaPackage.class))).andReturn(mediapackage) .anyTimes(); expect(ingestService.addCatalog(capture(captureInputStream), anyObject(String.class), anyObject(MediaPackageElementFlavor.class), anyObject(MediaPackage.class))).andReturn(mediapackage) .anyTimes(); expect(ingestService.ingest(anyObject(MediaPackage.class), anyObject(String.class), EasyMock.<Map<String, String>> anyObject())).andReturn(workflowInstance).anyTimes(); EasyMock.replay(ingestService); return ingestService; } private SecurityService setupSecurityService(String username, String org) { // Setup Security Service, Organization and User Organization organization = EasyMock.createNiceMock(Organization.class); EasyMock.expect(organization.getId()).andReturn(org).anyTimes(); EasyMock.replay(organization); User user = EasyMock.createMock(User.class); EasyMock.expect(user.getOrganization()).andReturn(organization).anyTimes(); EasyMock.expect(user.getUsername()).andReturn(username); EasyMock.replay(user); SecurityService securityService = EasyMock.createMock(SecurityService.class); EasyMock.expect(securityService.getOrganization()).andReturn(organization).anyTimes(); EasyMock.expect(securityService.getUser()).andReturn(user); EasyMock.replay(securityService); return securityService; } private Tuple<CommonEventCatalogUIAdapter, VCell<Option<MetadataCollection>>> setupCommonCatalogUIAdapter( Workspace workspace) throws org.osgi.service.cm.ConfigurationException { // Create Common Event Catalog UI Adapter final VCell<Option<MetadataCollection>> metadataCell = VCell.ocell(); CommonEventCatalogUIAdapter commonEventCatalogUIAdapter = new CommonEventCatalogUIAdapter() { @Override public Catalog storeFields(MediaPackage mediaPackage, MetadataCollection metadata) { metadataCell.set(Option.some(metadata)); return super.storeFields(mediaPackage, metadata); } }; Properties episodeCatalogProperties = new Properties(); InputStream in = null; try { in = getClass().getResourceAsStream("/episode-catalog.properties"); episodeCatalogProperties.load(in); } catch (IOException e) { throw new ComponentException(e); } finally { IoSupport.closeQuietly(in); } commonEventCatalogUIAdapter.updated(PropertiesUtil.toDictionary(episodeCatalogProperties)); commonEventCatalogUIAdapter.setWorkspace(workspace); return Tuple.tuple(commonEventCatalogUIAdapter, metadataCell); } /** * * * Test Create Event * * */ @Test(expected = IllegalArgumentException.class) public void testCreateEventInputNullMetadataExpectsIllegalArgumentException() throws IllegalArgumentException, IndexServiceException, ConfigurationException, MediaPackageException, HandleException, IOException, IngestException, ParseException, NotFoundException, SchedulerException, UnauthorizedException { IndexServiceImpl indexServiceImpl = new IndexServiceImpl(); indexServiceImpl.setIngestService(setupIngestServiceWithMediaPackage()); indexServiceImpl.createEvent(null, null); } @Test(expected = IllegalArgumentException.class) public void testCreateEventInputEmptyJsonExpectsIllegalArgumentException() throws IllegalArgumentException, IndexServiceException, ConfigurationException, MediaPackageException, HandleException, IOException, IngestException, ParseException, NotFoundException, SchedulerException, UnauthorizedException, org.json.simple.parser.ParseException { JSONObject metadataJson = (JSONObject) parser.parse("{}"); IndexServiceImpl indexServiceImpl = new IndexServiceImpl(); indexServiceImpl.setIngestService(setupIngestServiceWithMediaPackage()); indexServiceImpl.createEvent(metadataJson, null); } @Test(expected = IllegalArgumentException.class) public void testCreateEventInputNoSourceExpectsIllegalArgumentException() throws IllegalArgumentException, IndexServiceException, ConfigurationException, MediaPackageException, HandleException, IOException, IngestException, ParseException, NotFoundException, SchedulerException, UnauthorizedException, org.json.simple.parser.ParseException { String testResourceLocation = "/events/create-event-no-source.json"; JSONObject metadataJson = (JSONObject) parser .parse(IOUtils.toString(IndexServiceImplTest.class.getResourceAsStream(testResourceLocation))); IndexServiceImpl indexServiceImpl = new IndexServiceImpl(); indexServiceImpl.setIngestService(setupIngestServiceWithMediaPackage()); indexServiceImpl.createEvent(metadataJson, null); } @Test(expected = IllegalArgumentException.class) public void testCreateEventInputNoProcessingExpectsIllegalArgumentException() throws IllegalArgumentException, IndexServiceException, ConfigurationException, MediaPackageException, HandleException, IOException, IngestException, ParseException, NotFoundException, SchedulerException, UnauthorizedException, org.json.simple.parser.ParseException { String testResourceLocation = "/events/create-event-no-processing.json"; JSONObject metadataJson = (JSONObject) parser .parse(IOUtils.toString(IndexServiceImplTest.class.getResourceAsStream(testResourceLocation))); IndexServiceImpl indexServiceImpl = new IndexServiceImpl(); indexServiceImpl.setIngestService(setupIngestServiceWithMediaPackage()); indexServiceImpl.createEvent(metadataJson, null); } @Test(expected = IllegalArgumentException.class) public void testCreateEventInputNoWorkflowExpectsIllegalArgumentException() throws IllegalArgumentException, IndexServiceException, ConfigurationException, MediaPackageException, HandleException, IOException, IngestException, ParseException, NotFoundException, SchedulerException, UnauthorizedException, org.json.simple.parser.ParseException { String testResourceLocation = "/events/create-event-no-workflow.json"; JSONObject metadataJson = (JSONObject) parser .parse(IOUtils.toString(IndexServiceImplTest.class.getResourceAsStream(testResourceLocation))); IndexServiceImpl indexServiceImpl = new IndexServiceImpl(); indexServiceImpl.setIngestService(setupIngestServiceWithMediaPackage()); indexServiceImpl.createEvent(metadataJson, null); } @Test(expected = IllegalArgumentException.class) public void testCreateEventInputNoMetadataExpectsIllegalArgumentException() throws IllegalArgumentException, IndexServiceException, ConfigurationException, MediaPackageException, HandleException, IOException, IngestException, ParseException, NotFoundException, SchedulerException, UnauthorizedException, org.json.simple.parser.ParseException { String testResourceLocation = "/events/create-event-no-metadata.json"; JSONObject metadataJson = (JSONObject) parser .parse(IOUtils.toString(IndexServiceImplTest.class.getResourceAsStream(testResourceLocation))); IndexServiceImpl indexServiceImpl = new IndexServiceImpl(); indexServiceImpl.setIngestService(setupIngestServiceWithMediaPackage()); indexServiceImpl.createEvent(metadataJson, null); } @Test public void testCreateEventInputNoWorkflowConfigurationExpectsCreatedEvent() throws Exception { String expectedTitle = "Test Event Creation"; String username = "akm220"; String org = "mh_default_org"; String[] creators = new String[] {}; Id mpId = new IdImpl("mp-id"); String testResourceLocation = "/events/create-event-no-workflow-configuration.json"; JSONObject metadataJson = (JSONObject) parser .parse(IOUtils.toString(IndexServiceImplTest.class.getResourceAsStream(testResourceLocation))); Capture<Catalog> result = EasyMock.newCapture(); Capture<String> mediapackageIdResult = EasyMock.newCapture(); Capture<String> catalogIdResult = EasyMock.newCapture(); Capture<String> filenameResult = EasyMock.newCapture(); Capture<InputStream> catalogResult = EasyMock.newCapture(); Capture<String> mediapackageTitleResult = EasyMock.newCapture(); SecurityService securityService = setupSecurityService(username, org); Workspace workspace = EasyMock.createMock(Workspace.class); EasyMock.expect(workspace.put(EasyMock.capture(mediapackageIdResult), EasyMock.capture(catalogIdResult), EasyMock.capture(filenameResult), EasyMock.capture(catalogResult))).andReturn(new URI("catalog.xml")); EasyMock.replay(workspace); CommonEventCatalogUIAdapter commonEventCatalogUIAdapter = setupCommonCatalogUIAdapter(workspace).getA(); // Setup mediapackage. MediaPackage mediapackage = EasyMock.createMock(MediaPackage.class); mediapackage.add(EasyMock.capture(result)); EasyMock.expectLastCall(); EasyMock.expect(mediapackage.getCatalogs(EasyMock.anyObject(MediaPackageElementFlavor.class))) .andReturn(new Catalog[] {}); EasyMock.expect(mediapackage.getIdentifier()).andReturn(mpId).anyTimes(); EasyMock.expect(mediapackage.getCreators()).andReturn(creators); mediapackage.addCreator(""); EasyMock.expectLastCall(); mediapackage.setTitle(EasyMock.capture(mediapackageTitleResult)); EasyMock.expectLastCall(); EasyMock.expect(mediapackage.getElements()).andReturn(new MediaPackageElement[] {}).anyTimes(); EasyMock.expect(mediapackage.getCatalogs(EasyMock.anyObject(MediaPackageElementFlavor.class))) .andReturn(new Catalog[] {}).anyTimes(); mediapackage.setSeries(EasyMock.anyString()); EasyMock.expectLastCall(); EasyMock.replay(mediapackage); IngestService ingestService = setupIngestService(mediapackage, Capture.<InputStream> newInstance()); // Run Test IndexServiceImpl indexServiceImpl = new IndexServiceImpl(); indexServiceImpl.setAuthorizationService(setupAuthorizationService(mediapackage)); indexServiceImpl.setIngestService(ingestService); indexServiceImpl.setCommonEventCatalogUIAdapter(commonEventCatalogUIAdapter); indexServiceImpl.addCatalogUIAdapter(commonEventCatalogUIAdapter); indexServiceImpl.setUserDirectoryService(noUsersUserDirectoryService); indexServiceImpl.setSecurityService(securityService); indexServiceImpl.setWorkspace(workspace); indexServiceImpl.createEvent(metadataJson, mediapackage); assertTrue("The catalog must be added to the mediapackage", result.hasCaptured()); assertEquals("The catalog should have been added to the correct mediapackage", mpId.toString(), mediapackageIdResult.getValue()); assertTrue("The catalog should have a new id", catalogIdResult.hasCaptured()); assertTrue("The catalog should have a new filename", filenameResult.hasCaptured()); assertTrue("The catalog should have been added to the input stream", catalogResult.hasCaptured()); assertTrue("The mediapackage should have had its title updated", catalogResult.hasCaptured()); assertEquals("The mediapackage title should have been updated.", expectedTitle, mediapackageTitleResult.getValue()); assertTrue("The catalog should have been created", catalogResult.hasCaptured()); } @Test public void testCreateEventInputNormalExpectsCreatedEvent() throws Exception { String expectedTitle = "Test Event Creation"; String username = "akm220"; String org = "mh_default_org"; String[] creators = new String[] {}; Id mpId = new IdImpl("mp-id"); String testResourceLocation = "/events/create-event.json"; JSONObject metadataJson = (JSONObject) parser .parse(IOUtils.toString(IndexServiceImplTest.class.getResourceAsStream(testResourceLocation))); Capture<Catalog> result = EasyMock.newCapture(); Capture<String> mediapackageIdResult = EasyMock.newCapture(); Capture<String> catalogIdResult = EasyMock.newCapture(); Capture<String> filenameResult = EasyMock.newCapture(); Capture<InputStream> catalogResult = EasyMock.newCapture(); Capture<String> mediapackageTitleResult = EasyMock.newCapture(); SecurityService securityService = setupSecurityService(username, org); Workspace workspace = EasyMock.createMock(Workspace.class); EasyMock.expect(workspace.put(EasyMock.capture(mediapackageIdResult), EasyMock.capture(catalogIdResult), EasyMock.capture(filenameResult), EasyMock.capture(catalogResult))).andReturn(new URI("catalog.xml")); EasyMock.replay(workspace); // Create Common Event Catalog UI Adapter CommonEventCatalogUIAdapter commonEventCatalogUIAdapter = setupCommonCatalogUIAdapter(workspace).getA(); // Setup mediapackage. MediaPackage mediapackage = EasyMock.createMock(MediaPackage.class); mediapackage.add(EasyMock.capture(result)); EasyMock.expectLastCall(); EasyMock.expect(mediapackage.getCatalogs(EasyMock.anyObject(MediaPackageElementFlavor.class))) .andReturn(new Catalog[] {}); EasyMock.expect(mediapackage.getIdentifier()).andReturn(mpId).anyTimes(); EasyMock.expect(mediapackage.getCreators()).andReturn(creators); mediapackage.addCreator(""); EasyMock.expectLastCall(); mediapackage.setTitle(EasyMock.capture(mediapackageTitleResult)); EasyMock.expectLastCall(); EasyMock.expect(mediapackage.getElements()).andReturn(new MediaPackageElement[] {}).anyTimes(); EasyMock.expect(mediapackage.getCatalogs(EasyMock.anyObject(MediaPackageElementFlavor.class))) .andReturn(new Catalog[] {}).anyTimes(); mediapackage.setSeries(EasyMock.anyString()); EasyMock.expectLastCall(); EasyMock.replay(mediapackage); IngestService ingestService = setupIngestService(mediapackage, Capture.<InputStream> newInstance()); // Run Test IndexServiceImpl indexServiceImpl = new IndexServiceImpl(); indexServiceImpl.setAuthorizationService(setupAuthorizationService(mediapackage)); indexServiceImpl.setIngestService(ingestService); indexServiceImpl.setCommonEventCatalogUIAdapter(commonEventCatalogUIAdapter); indexServiceImpl.addCatalogUIAdapter(commonEventCatalogUIAdapter); indexServiceImpl.setUserDirectoryService(noUsersUserDirectoryService); indexServiceImpl.setSecurityService(securityService); indexServiceImpl.setWorkspace(workspace); indexServiceImpl.createEvent(metadataJson, mediapackage); assertTrue("The catalog must be added to the mediapackage", result.hasCaptured()); assertEquals("The catalog should have been added to the correct mediapackage", mpId.toString(), mediapackageIdResult.getValue()); assertTrue("The catalog should have a new id", catalogIdResult.hasCaptured()); assertTrue("The catalog should have a new filename", filenameResult.hasCaptured()); assertTrue("The catalog should have been added to the input stream", catalogResult.hasCaptured()); assertTrue("The mediapackage should have had its title updated", catalogResult.hasCaptured()); assertEquals("The mediapackage title should have been updated.", expectedTitle, mediapackageTitleResult.getValue()); assertTrue("The catalog should have been created", catalogResult.hasCaptured()); } @Test public void testCreateEventInputNormalExpectsCreatedScheduledEvent() throws Exception { String expectedTitle = "Test Event Creation"; String username = "akm220"; String org = "mh_default_org"; String[] creators = new String[] {}; Id mpId = new IdImpl("mp-id"); String testResourceLocation = "/events/create-scheduled-event.json"; JSONObject metadataJson = (JSONObject) parser .parse(IOUtils.toString(IndexServiceImplTest.class.getResourceAsStream(testResourceLocation))); Capture<Catalog> result = EasyMock.newCapture(); Capture<String> mediapackageIdResult = EasyMock.newCapture(); Capture<String> catalogIdResult = EasyMock.newCapture(); Capture<String> filenameResult = EasyMock.newCapture(); Capture<InputStream> catalogResult = EasyMock.newCapture(); Capture<String> mediapackageTitleResult = EasyMock.newCapture(); SecurityService securityService = setupSecurityService(username, org); Workspace workspace = EasyMock.createMock(Workspace.class); EasyMock.expect(workspace.put(EasyMock.capture(mediapackageIdResult), EasyMock.capture(catalogIdResult), EasyMock.capture(filenameResult), EasyMock.capture(catalogResult))).andReturn(new URI("catalog.xml")); EasyMock.replay(workspace); // Create Common Event Catalog UI Adapter CommonEventCatalogUIAdapter commonEventCatalogUIAdapter = setupCommonCatalogUIAdapter(workspace).getA(); // Setup mediapackage. MediaPackage mediapackage = EasyMock.createMock(MediaPackage.class); mediapackage.add(EasyMock.capture(result)); EasyMock.expectLastCall(); EasyMock.expect(mediapackage.getCatalogs(EasyMock.anyObject(MediaPackageElementFlavor.class))) .andReturn(new Catalog[] {}); EasyMock.expect(mediapackage.getIdentifier()).andReturn(mpId).anyTimes(); EasyMock.expect(mediapackage.getCreators()).andReturn(creators); mediapackage.addCreator(""); EasyMock.expectLastCall(); mediapackage.setTitle(EasyMock.capture(mediapackageTitleResult)); EasyMock.expectLastCall(); EasyMock.expect(mediapackage.getElements()).andReturn(new MediaPackageElement[] {}).anyTimes(); EasyMock.expect(mediapackage.getCatalogs(EasyMock.anyObject(MediaPackageElementFlavor.class))) .andReturn(new Catalog[] {}).anyTimes(); EasyMock.expect(mediapackage.getSeries()).andReturn(null).anyTimes(); mediapackage.setSeries(EasyMock.anyString()); EasyMock.expectLastCall(); EasyMock.replay(mediapackage); IngestService ingestService = setupIngestService(mediapackage, Capture.<InputStream> newInstance()); CaptureAgentStateService captureAgentStateService = setupCaptureAgentStateService(); Capture<Date> captureStart = EasyMock.newCapture(); Capture<Date> captureEnd = EasyMock.newCapture(); SchedulerService schedulerService = EasyMock.createNiceMock(SchedulerService.class); EasyMock.expect( schedulerService.addEvent(anyObject(DublinCoreCatalog.class), EasyMock.<Map<String, String>> anyObject())) .andReturn(1L).once(); EasyMock.replay(schedulerService); // Run Test IndexServiceImpl indexServiceImpl = new IndexServiceImpl(); indexServiceImpl.setAuthorizationService(setupAuthorizationService(mediapackage)); indexServiceImpl.setIngestService(ingestService); indexServiceImpl.setCommonEventCatalogUIAdapter(commonEventCatalogUIAdapter); indexServiceImpl.addCatalogUIAdapter(commonEventCatalogUIAdapter); indexServiceImpl.setSecurityService(securityService); indexServiceImpl.setUserDirectoryService(noUsersUserDirectoryService); indexServiceImpl.setWorkspace(workspace); indexServiceImpl.setCaptureAgentStateService(captureAgentStateService); indexServiceImpl.setSchedulerService(schedulerService); String scheduledEvent = indexServiceImpl.createEvent(metadataJson, mediapackage); Assert.assertEquals(mediapackage.getIdentifier().compact(), scheduledEvent); assertTrue("The catalog must be added to the mediapackage", result.hasCaptured()); assertEquals("The catalog should have been added to the correct mediapackage", mpId.toString(), mediapackageIdResult.getValue()); assertTrue("The catalog should have a new id", catalogIdResult.hasCaptured()); assertTrue("The catalog should have a new filename", filenameResult.hasCaptured()); assertTrue("The catalog should have been added to the input stream", catalogResult.hasCaptured()); assertTrue("The mediapackage should have had its title updated", catalogResult.hasCaptured()); assertEquals("The mediapackage title should have been updated.", expectedTitle, mediapackageTitleResult.getValue()); assertTrue("The catalog should have been created", catalogResult.hasCaptured()); } private AuthorizationService setupAuthorizationService(MediaPackage mediapackage) { // Setup Authorization Service Tuple<MediaPackage, Attachment> returnValue = new Tuple<>(mediapackage, null); AuthorizationService authorizationService = EasyMock.createMock(AuthorizationService.class); EasyMock.expect(authorizationService.setAcl(EasyMock.anyObject(MediaPackage.class), EasyMock.anyObject(AclScope.class), EasyMock.anyObject(AccessControlList.class))).andReturn(returnValue) .anyTimes(); EasyMock.replay(authorizationService); return authorizationService; } @Test public void testCreateEventInputNormalExpectsCreatedRecurringEvent() throws Exception { String expectedTitle = "Test Event Creation"; String username = "akm220"; String org = "mh_default_org"; String[] creators = new String[] {}; Id mpId = new IdImpl("mp-id"); String testResourceLocation = "/events/create-recurring-event.json"; JSONObject metadataJson = (JSONObject) parser .parse(IOUtils.toString(IndexServiceImplTest.class.getResourceAsStream(testResourceLocation))); Capture<String> mediapackageIdResult = EasyMock.newCapture(); Capture<String> catalogIdResult = EasyMock.newCapture(); Capture<String> filenameResult = EasyMock.newCapture(); Capture<InputStream> catalogResult = EasyMock.newCapture(); Capture<String> mediapackageTitleResult = EasyMock.newCapture(); SecurityService securityService = setupSecurityService(username, org); Workspace workspace = EasyMock.createMock(Workspace.class); EasyMock.expect(workspace.put(EasyMock.capture(mediapackageIdResult), EasyMock.capture(catalogIdResult), EasyMock.capture(filenameResult), EasyMock.capture(catalogResult))).andReturn(new URI("catalog.xml")); EasyMock.expect(workspace.get(getClass().getResource("/dublincore.xml").toURI())) .andReturn(new File(getClass().getResource("/dublincore.xml").toURI())).anyTimes(); EasyMock.replay(workspace); // Create Common Event Catalog UI Adapter CommonEventCatalogUIAdapter commonEventCatalogUIAdapter = setupCommonCatalogUIAdapter(workspace).getA(); // Setup mediapackage. MediaPackage mediapackage = EasyMock.createMock(MediaPackage.class); EasyMock.expect(mediapackage.getSeries()).andReturn(null).anyTimes(); EasyMock.expect(mediapackage.getCatalogs(EasyMock.anyObject(MediaPackageElementFlavor.class))) .andReturn(new Catalog[] { CatalogImpl.fromURI(getClass().getResource("/dublincore.xml").toURI()) }); EasyMock.expect(mediapackage.getIdentifier()).andReturn(mpId).anyTimes(); EasyMock.expect(mediapackage.getCreators()).andReturn(creators); mediapackage.addCreator(""); EasyMock.expectLastCall(); mediapackage.setTitle(EasyMock.capture(mediapackageTitleResult)); EasyMock.expectLastCall().once(); mediapackage.setTitle(EasyMock.anyString()); EasyMock.expectLastCall().times(15); EasyMock.expect(mediapackage.getElements()).andReturn(new MediaPackageElement[] {}).anyTimes(); EasyMock.expect(mediapackage.getCatalogs(EasyMock.anyObject(MediaPackageElementFlavor.class))) .andReturn(new Catalog[] {}).anyTimes(); mediapackage.setIdentifier(EasyMock.anyObject(Id.class)); EasyMock.expectLastCall().anyTimes(); mediapackage.setSeries(EasyMock.anyString()); EasyMock.expectLastCall(); EasyMock.replay(mediapackage); CaptureAgentStateService captureAgentStateService = setupCaptureAgentStateService(); // Setup scheduler service Capture<Date> captureStart = EasyMock.newCapture(); Capture<Date> captureEnd = EasyMock.newCapture(); SchedulerService schedulerService = EasyMock.createNiceMock(SchedulerService.class); EasyMock.expect(schedulerService.addEvent(EasyMock.anyObject(DublinCoreCatalog.class), EasyMock.<Map<String, String>> anyObject())).andReturn(2L).atLeastOnce(); EasyMock.replay(schedulerService); // Run Test IndexServiceImpl indexServiceImpl = new IndexServiceImpl(); indexServiceImpl.setAuthorizationService(setupAuthorizationService(mediapackage)); indexServiceImpl.setIngestService(setupIngestService(mediapackage, Capture.<InputStream> newInstance())); indexServiceImpl.setCommonEventCatalogUIAdapter(commonEventCatalogUIAdapter); indexServiceImpl.addCatalogUIAdapter(commonEventCatalogUIAdapter); indexServiceImpl.setSecurityService(securityService); indexServiceImpl.setUserDirectoryService(noUsersUserDirectoryService); indexServiceImpl.setWorkspace(workspace); indexServiceImpl.setCaptureAgentStateService(captureAgentStateService); indexServiceImpl.setSchedulerService(schedulerService); String scheduledEvents = indexServiceImpl.createEvent(metadataJson, mediapackage); String[] ids = StringUtils.split(scheduledEvents, ","); Assert.assertTrue(ids.length > 1); assertEquals("The catalog should have been added to the correct mediapackage", mpId.toString(), mediapackageIdResult.getValue()); assertTrue("The catalog should have a new id", catalogIdResult.hasCaptured()); assertTrue("The catalog should have a new filename", filenameResult.hasCaptured()); assertTrue("The catalog should have been added to the input stream", catalogResult.hasCaptured()); assertTrue("The mediapackage should have had its title updated", catalogResult.hasCaptured()); assertEquals("The mediapackage title should have been updated.", expectedTitle, mediapackageTitleResult.getValue()); assertTrue("The catalog should have been created", catalogResult.hasCaptured()); } /** * * Test Put Event * * */ @Test(expected = NotFoundException.class) public void testUpdateEventInputNoEventExpectsNotFound() throws IOException, IllegalArgumentException, IndexServiceException, NotFoundException, UnauthorizedException, SearchIndexException, WorkflowDatabaseException { String username = "username"; String org = "org1"; String testResourceLocation = "/events/update-event.json"; String eventId = "event-1"; String metadataJson = IOUtils.toString(IndexServiceImplTest.class.getResourceAsStream(testResourceLocation)); SearchQuery query = EasyMock.createMock(SearchQuery.class); EasyMock.expect(query.getLimit()).andReturn(100); EasyMock.expect(query.getOffset()).andReturn(0); EasyMock.replay(query); SearchResult<Event> result = new SearchResultImpl<>(query, 0, 0); AbstractSearchIndex abstractIndex = EasyMock.createMock(AbstractSearchIndex.class); EasyMock.expect(abstractIndex.getByQuery(EasyMock.anyObject(EventSearchQuery.class))).andReturn(result); EasyMock.replay(abstractIndex); SecurityService securityService = setupSecurityService(username, org); IndexServiceImpl indexService = new IndexServiceImpl(); indexService.setSecurityService(securityService); indexService.updateAllEventMetadata(eventId, metadataJson, abstractIndex); } public void testUpdateEvent() throws IOException, IllegalArgumentException, IndexServiceException, NotFoundException, UnauthorizedException, SearchIndexException, WorkflowDatabaseException { String username = "username1"; String org = "org1"; String testResourceLocation = "/events/update-event.json"; String eventId = "event-1"; String metadataJson = IOUtils.toString(IndexServiceImplTest.class.getResourceAsStream(testResourceLocation)); String expectedTitle = "Updated Title"; String expectedDescription = "Unset Description"; // Setup search results SearchQuery query = EasyMock.createMock(SearchQuery.class); EasyMock.expect(query.getLimit()).andReturn(100); EasyMock.expect(query.getOffset()).andReturn(0); EasyMock.replay(query); Event event = new Event(); event.setTitle("Other Title"); event.setDescription(expectedDescription); SearchResultItemImpl<Event> searchResultItem = new SearchResultItemImpl<>(1.0, event); SearchResultImpl<Event> result = new SearchResultImpl<>(query, 0, 0); result.addResultItem(searchResultItem); AbstractSearchIndex abstractIndex = EasyMock.createMock(AbstractSearchIndex.class); EasyMock.expect(abstractIndex.getByQuery(EasyMock.anyObject(EventSearchQuery.class))).andReturn(result); EasyMock.replay(abstractIndex); SecurityService securityService = setupSecurityService(username, org); IndexServiceImpl indexServiceImpl = new IndexServiceImpl(); indexServiceImpl.setSecurityService(securityService); indexServiceImpl.updateAllEventMetadata(eventId, metadataJson, abstractIndex); Assert.assertEquals("The title should have been updated.", expectedTitle, event.getTitle()); Assert.assertEquals("The description should be the same.", expectedDescription, event.getDescription()); Assert.assertNull("The subject should still be null.", event.getSubject()); } @Test public void calculateDaysChange() throws ParseException { Calendar start; Calendar end; long durationMillis; String days; List<Period> periods; // JST start = Calendar.getInstance(jst); start.set(2016, 2, 25, 22, 0); end = Calendar.getInstance(jst); end.set(2016, 2, 29, start.get(Calendar.HOUR_OF_DAY), 5); durationMillis = (end.get(Calendar.MINUTE) - start.get(Calendar.MINUTE)) * 60 * 1000; days = "MO,TU,FR,SA,SU"; // --> Still the same day when switch to UTC (22-9) periods = generatePeriods(jst, start, end, days, durationMillis); assertEquals(5, periods.size()); // PST start = Calendar.getInstance(pst); start.set(2016, 2, 25, 22, 0); end = Calendar.getInstance(pst); end.set(2016, 2, 29, start.get(Calendar.HOUR_OF_DAY), 5); durationMillis = (end.get(Calendar.MINUTE) - start.get(Calendar.MINUTE)) * 60 * 1000; days = "MO,TU,WE,SA,SU"; // --> A day after when switching to UTC (22+8) periods = generatePeriods(pst, start, end, days, durationMillis); assertEquals(5, periods.size()); // CET start = Calendar.getInstance(cet); start.set(2016, 2, 25, 0, 5); end = Calendar.getInstance(cet); end.set(2016, 2, 29, start.get(Calendar.HOUR_OF_DAY), 10); durationMillis = (end.get(Calendar.MINUTE) - start.get(Calendar.MINUTE)) * 60 * 1000; days = "MO,TH,FR,SA,SU"; // --> A day before when switch to UCT (0-2) periods = generatePeriods(cet, start, end, days, durationMillis); assertEquals(5, periods.size()); } @Test public void calculateDSTChange() throws ParseException { Calendar start; Calendar end; long durationMillis; String days; List<Period> periods; // CET TimeZone.setDefault(cet); start = Calendar.getInstance(cet); start.set(2016, 2, 24, 0, 5); end = Calendar.getInstance(cet); end.set(2016, 2, 29, start.get(Calendar.HOUR_OF_DAY), 10); durationMillis = (end.get(Calendar.MINUTE) - start.get(Calendar.MINUTE)) * 60 * 1000; days = "MO,TH,FR,SA,SU"; periods = generatePeriods(cet, start, end, days, durationMillis); assertEquals(5, periods.size()); TimeZone.setDefault(cet); for (Period d : periods) { DateTime dEnd = d.getEnd(); Date date = new Date(dEnd.getTime()); Calendar instance = Calendar.getInstance(); instance.setTime(date); assertEquals(0, instance.get(Calendar.HOUR_OF_DAY)); } } private MetadataField<Iterable<String>> createCreatorMetadataField(Iterable<String> value) { MetadataField<Iterable<String>> creator = new MetadataField<>(); creator.setInputId(DublinCore.PROPERTY_CREATOR.getLocalName()); creator.setValue(value); return creator; } @Test public void updatePresenters() throws IOException, org.osgi.service.cm.ConfigurationException { String nonUser1 = "Non User 1"; String nonUser2 = "Non User 2"; String nonUser3 = "Non User 3"; Properties eventProperties = new Properties(); InputStream in = getClass().getResourceAsStream("/episode-catalog.properties"); eventProperties.load(in); in.close(); Dictionary<String, String> properties = PropertiesUtil.toDictionary(eventProperties); SecurityService securityService = EasyMock.createMock(SecurityService.class); EasyMock.expect(securityService.getOrganization()).andStubReturn(organization); EasyMock.replay(securityService); UserDirectoryService userDirectoryService = EasyMock.createMock(UserDirectoryService.class); EasyMock.expect(userDirectoryService.loadUser(user1.getUsername())).andStubReturn(user1); EasyMock.expect(userDirectoryService.loadUser(user2.getUsername())).andStubReturn(user2); EasyMock.expect(userDirectoryService.loadUser(user3.getUsername())).andStubReturn(user3); EasyMock.expect(userDirectoryService.loadUser(nonUser1)).andStubReturn(null); EasyMock.expect(userDirectoryService.loadUser(nonUser2)).andStubReturn(null); EasyMock.expect(userDirectoryService.loadUser(nonUser3)).andStubReturn(null); EasyMock.replay(userDirectoryService); IndexServiceImpl indexServiceImpl = new IndexServiceImpl(); CommonEventCatalogUIAdapter commonEventCatalogUIAdapter = new CommonEventCatalogUIAdapter(); commonEventCatalogUIAdapter.updated(properties); indexServiceImpl.setCommonEventCatalogUIAdapter(commonEventCatalogUIAdapter); indexServiceImpl.setUserDirectoryService(userDirectoryService); indexServiceImpl.setSecurityService(securityService); MetadataCollection metadata = commonEventCatalogUIAdapter.getRawFields(); // Possible presenter combinations MetadataField<Iterable<String>> emptyUpdatedPresenter = createCreatorMetadataField(new ArrayList<String>()); ArrayList<String> oneNonUserList = new ArrayList<>(); oneNonUserList.add(nonUser1); MetadataField<Iterable<String>> nonUserUpdatedPresenter = createCreatorMetadataField(oneNonUserList); ArrayList<String> multiNonUserList = new ArrayList<>(); multiNonUserList.add(nonUser1); multiNonUserList.add(nonUser2); multiNonUserList.add(nonUser3); MetadataField<Iterable<String>> multiNonUserUpdatedPresenter = createCreatorMetadataField(multiNonUserList); ArrayList<String> oneUserList = new ArrayList<>(); oneUserList.add(user1.getUsername()); MetadataField<Iterable<String>> userUpdatedPresenter = createCreatorMetadataField(oneUserList); ArrayList<String> multiUserList = new ArrayList<>(); multiUserList.add(user1.getUsername()); multiUserList.add(user2.getUsername()); multiUserList.add(user3.getUsername()); MetadataField<Iterable<String>> multiUserUpdatedPresenter = createCreatorMetadataField(multiUserList); ArrayList<String> mixedUserList = new ArrayList<>(); mixedUserList.add(user1.getUsername()); mixedUserList.add(nonUser1); mixedUserList.add(user2.getUsername()); mixedUserList.add(nonUser2); mixedUserList.add(nonUser3); mixedUserList.add(user3.getUsername()); MetadataField<Iterable<String>> mixedPresenters = createCreatorMetadataField(mixedUserList); ArrayList<String> userFullNames = new ArrayList<>(); userFullNames.add(user1.getName()); userFullNames.add(user2.getName()); userFullNames.add(user3.getUsername()); // Empty presenters metadata.removeField(metadata.getOutputFields().get(DublinCore.PROPERTY_CREATOR.getLocalName())); metadata.addField(emptyUpdatedPresenter); Tuple<List<String>, Set<String>> updatedPresenters = indexServiceImpl.getTechnicalPresenters(metadata); assertTrue("The presenters dublincore metadata should be empty", updatedPresenters.getA().isEmpty()); assertTrue("The technical presenters should be empty", updatedPresenters.getB().isEmpty()); // Non-user presenter metadata.removeField(metadata.getOutputFields().get(DublinCore.PROPERTY_CREATOR.getLocalName())); metadata.addField(nonUserUpdatedPresenter); updatedPresenters = indexServiceImpl.getTechnicalPresenters(metadata); assertTrue("There should be one presenter", updatedPresenters.getA().size() == 1); assertTrue("There should be no technical presenters", updatedPresenters.getB().isEmpty()); // Multi non-user presenter metadata.removeField(metadata.getOutputFields().get(DublinCore.PROPERTY_CREATOR.getLocalName())); metadata.addField(multiNonUserUpdatedPresenter); updatedPresenters = indexServiceImpl.getTechnicalPresenters(metadata); assertTrue("There should be three presenters", updatedPresenters.getA().size() == 3); assertTrue("The value for technical presenters should be empty", updatedPresenters.getB().isEmpty()); // User presenter metadata.removeField(metadata.getOutputFields().get(DublinCore.PROPERTY_CREATOR.getLocalName())); metadata.addField(userUpdatedPresenter); updatedPresenters = indexServiceImpl.getTechnicalPresenters(metadata); assertTrue("There should be one presenter", updatedPresenters.getA().size() == 1); assertEquals("The one presenter should have the user's full name", "User 1", updatedPresenters.getA().get(0)); assertTrue("The one technical presenter", updatedPresenters.getB().size() == 1); assertEquals("The one technical presenter has the correct username", "user1", updatedPresenters.getB().iterator().next()); // Multi user presenter metadata.removeField(metadata.getOutputFields().get(DublinCore.PROPERTY_CREATOR.getLocalName())); metadata.addField(multiUserUpdatedPresenter); updatedPresenters = indexServiceImpl.getTechnicalPresenters(metadata); assertTrue("There should be three presenters", updatedPresenters.getA().size() == 3); assertTrue("There should be three technical presenters", updatedPresenters.getB().size() == 3); assertTrue("The list of technical presenters should contain all of the user names", updatedPresenters.getB().containsAll(multiUserList)); // Mixed non-user and user presenters metadata.removeField(metadata.getOutputFields().get(DublinCore.PROPERTY_CREATOR.getLocalName())); metadata.addField(mixedPresenters); updatedPresenters = indexServiceImpl.getTechnicalPresenters(metadata); assertTrue("There should be six presenters", updatedPresenters.getA().size() == 6); assertTrue("There should be three technical presenters", updatedPresenters.getB().size() == 3); assertTrue("The list of presenters should contain all of the non-user names", updatedPresenters.getA().containsAll(multiNonUserList)); assertTrue("The list of presenters should contain all of the user full names", updatedPresenters.getA().containsAll(userFullNames)); assertTrue("The list of technical presenters should contain all of the usernames", updatedPresenters.getB().containsAll(multiUserList)); } private List<Period> generatePeriods(TimeZone tz, Calendar start, Calendar end, String days, Long duration) throws ParseException { Calendar utcDate = Calendar.getInstance(utc); utcDate.setTime(start.getTime()); RRule rRule = new RRule(generateRule(days, utcDate.get(Calendar.HOUR_OF_DAY), utcDate.get(Calendar.MINUTE))); IndexServiceImpl indexServiceImpl = new IndexServiceImpl(); return indexServiceImpl.calculatePeriods(start.getTime(), end.getTime(), duration, rRule, tz); } private String generateRule(String days, int hour, int minute) { return String.format("FREQ=WEEKLY;BYDAY=%s;BYHOUR=%d;BYMINUTE=%d", days, hour, minute); } }