package dk.statsbiblioteket.medieplatform.autonomous; import dk.statsbiblioteket.doms.central.connectors.EnhancedFedora; import dk.statsbiblioteket.doms.central.connectors.fedora.ChecksumType; import dk.statsbiblioteket.doms.central.connectors.fedora.structures.ObjectProfile; import org.mockito.ArgumentCaptor; import org.mockito.Matchers; import org.mockito.Mockito; import org.testng.Assert; import org.testng.annotations.Test; import javax.xml.bind.JAXBException; import java.util.ArrayList; import java.util.ConcurrentModificationException; import java.util.Date; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; public class NewspaperDomsEventStorageTest { public static final String BATCH_ID = "400022028241"; public static final int ROUND_TRIP_NUMBER = 1; @Test public void testAddEventToBatch3() throws Exception { ArrayList<String> log = new ArrayList<>(); FedoraMockupEmpty fedora = new FedoraMockupEmpty(log); DomsEventStorage<Batch> doms = new NewspaperDomsEventStorage(fedora, PremisManipulatorFactory.TYPE, NewspaperDomsEventStorageFactory.BATCH_TEMPLATE, NewspaperDomsEventStorageFactory.ROUND_TRIP_TEMPLATE, NewspaperDomsEventStorageFactory.HAS_PART, DomsEventStorageFactory.EVENTS, new BatchItemFactory()); doms.appendEventToItem(new Batch(BATCH_ID, ROUND_TRIP_NUMBER + 1), "agent", new Date(0), "Details here", "Data_Received", true); Assert.assertEquals(8, log.size()); for (String s : log) { Assert.assertNotSame(s, AbstractFedoraMockup.UNEXPECTED_METHOD); System.out.println(s); } } @Test public void testAddEventToBatch1() throws Exception { ArrayList<String> log = new ArrayList<>(); FedoraMockupEmpty fedora = new FedoraMockupEmpty(log); DomsEventStorage<Batch> doms = new NewspaperDomsEventStorage(fedora, PremisManipulatorFactory.TYPE, NewspaperDomsEventStorageFactory.BATCH_TEMPLATE, NewspaperDomsEventStorageFactory.ROUND_TRIP_TEMPLATE, NewspaperDomsEventStorageFactory.HAS_PART, DomsEventStorageFactory.EVENTS, new BatchItemFactory()); doms.appendEventToItem(new Batch(BATCH_ID, ROUND_TRIP_NUMBER), "agent", new Date(0), "Details here", "Data_Received", true); Assert.assertEquals(8, log.size()); for (String s : log) { Assert.assertNotSame(s, AbstractFedoraMockup.UNEXPECTED_METHOD); System.out.println(s); } } @Test public void testAddEventToBatch2() throws Exception { ArrayList<String> log = new ArrayList<>(); FedoraMockupEmpty fedora = new FedoraMockupBatchNoRoundTripObject(log); DomsEventStorage<Batch> doms = new NewspaperDomsEventStorage(fedora, PremisManipulatorFactory.TYPE, NewspaperDomsEventStorageFactory.BATCH_TEMPLATE, NewspaperDomsEventStorageFactory.ROUND_TRIP_TEMPLATE, NewspaperDomsEventStorageFactory.HAS_PART, DomsEventStorageFactory.EVENTS, new BatchItemFactory()); doms.appendEventToItem(new Batch(BATCH_ID, ROUND_TRIP_NUMBER), "agent", new Date(0), "Details here", "Data_Received", true); Assert.assertEquals(log.size(), 3); for (String s : log) { Assert.assertNotSame(s, AbstractFedoraMockup.UNEXPECTED_METHOD); System.out.println(s); } } @Test public void testCreateBatchRoundTrip() throws Exception { ArrayList<String> log = new ArrayList<>(); FedoraMockupEmpty fedora = new FedoraMockupEmpty(log); NewspaperDomsEventStorage doms = new NewspaperDomsEventStorage(fedora, PremisManipulatorFactory.TYPE, NewspaperDomsEventStorageFactory.BATCH_TEMPLATE, NewspaperDomsEventStorageFactory.ROUND_TRIP_TEMPLATE, NewspaperDomsEventStorageFactory.HAS_PART, DomsEventStorageFactory.EVENTS, new BatchItemFactory()); doms.createBatchRoundTrip(new Batch(BATCH_ID, ROUND_TRIP_NUMBER).getFullID()); Assert.assertEquals(log.size(), 6); for (String s : log) { Assert.assertNotSame(s, AbstractFedoraMockup.UNEXPECTED_METHOD); System.out.println(s); } } /** * Tests the case where we remove all events after the first error. * * @throws Exception */ @Test public void testTriggerWorkflowRestartFromError() throws Exception { EnhancedFedora enhancedFedora = Mockito.mock(EnhancedFedora.class); ObjectProfile objectProfile = new ObjectProfile(); objectProfile.setObjectLastModifiedDate(new Date()); Mockito.when(enhancedFedora.getObjectProfile(Matchers.anyString(), Matchers.anyLong())) .thenReturn(objectProfile); PremisManipulator manipulator = getPremisManipulator(); Mockito.when(enhancedFedora.getXMLDatastreamContents(Matchers.anyString(), Matchers.anyString(), Matchers.anyLong())) .thenReturn(manipulator.toXML()); ArrayList<String> pids = new ArrayList<>(); pids.add("uuid:thepid"); Mockito.when(enhancedFedora.findObjectFromDCIdentifier(Matchers.anyString())).thenReturn(pids); Mockito.doReturn(new Date()) .when(enhancedFedora) .modifyDatastreamByValue(Matchers.anyString(), Matchers.anyString(), Matchers.any(ChecksumType.class), Matchers.anyString(), Matchers.any(byte[].class), Matchers.anyListOf(String.class), Matchers.anyString(), Matchers.anyString(), Matchers.anyLong()); DomsEventStorage<Batch> doms = new DomsEventStorage<>(enhancedFedora, PremisManipulatorFactory.TYPE, DomsEventStorageFactory.EVENTS, new BatchItemFactory()); //Make the call int eventsRemoved = doms.triggerWorkflowRestartFromFirstFailure(new Batch("foo", 3)); assertEquals(eventsRemoved, 6); //The captor is used to capture the modified datastream so it can be examined to see if it has been //correctly modfied ArgumentCaptor<byte[]> captor = ArgumentCaptor.forClass(byte[].class); //There should be two calls to each of these methods, once for each attempt Mockito.verify(enhancedFedora) .modifyDatastreamByValue(Matchers.anyString(), Matchers.anyString(), Matchers.any(ChecksumType.class), Matchers.anyString(), captor.capture(), Matchers.anyListOf(String.class), Matchers.anyString(), Matchers.anyString(), Matchers.anyLong()); //The failed events should have been stripped from the xml String newXml = new String(captor.getValue()); assertTrue(newXml.contains("e1")); assertTrue(newXml.contains("e2")); assertFalse(newXml.contains("e3")); assertFalse(newXml.contains("e4")); assertFalse(newXml.contains("e5")); assertFalse(newXml.contains("e6")); assertFalse(newXml.contains("e7")); assertFalse(newXml.contains("e8")); } /** * Tests the case where we remove all events after a given event. * * @throws Exception */ @Test public void testTriggerWorkflowRestartFromNamedEvent() throws Exception { EnhancedFedora enhancedFedora = Mockito.mock(EnhancedFedora.class); ObjectProfile objectProfile = new ObjectProfile(); objectProfile.setObjectLastModifiedDate(new Date()); Mockito.when(enhancedFedora.getObjectProfile(Matchers.anyString(), Matchers.anyLong())) .thenReturn(objectProfile); PremisManipulator manipulator = getPremisManipulator(); Mockito.when(enhancedFedora.getXMLDatastreamContents(Matchers.anyString(), Matchers.anyString(), Matchers.anyLong())) .thenReturn(manipulator.toXML()); ArrayList<String> pids = new ArrayList<>(); pids.add("uuid:thepid"); Mockito.when(enhancedFedora.findObjectFromDCIdentifier(Matchers.anyString())).thenReturn(pids); Mockito.doReturn(new Date()) .when(enhancedFedora) .modifyDatastreamByValue(Matchers.anyString(), Matchers.anyString(), Matchers.any(ChecksumType.class), Matchers.anyString(), Matchers.any(byte[].class), Matchers.anyListOf(String.class), Matchers.anyString(), Matchers.anyString(), Matchers.anyLong()); DomsEventStorage<Batch> doms = new DomsEventStorage<>(enhancedFedora, PremisManipulatorFactory.TYPE, DomsEventStorageFactory.EVENTS, new BatchItemFactory()); //Make the call int eventsRemoved = doms.triggerWorkflowRestartFromFirstFailure(new Batch("foo", 3), "e5"); assertEquals(eventsRemoved, 4); //The captor is used to capture the modified datastream so it can be examined to see if it has been //correctly modfied ArgumentCaptor<byte[]> captor = ArgumentCaptor.forClass(byte[].class); //There should be two calls to each of these methods, once for each attempt Mockito.verify(enhancedFedora) .modifyDatastreamByValue(Matchers.anyString(), Matchers.anyString(), Matchers.any(ChecksumType.class), Matchers.anyString(), captor.capture(), Matchers.anyListOf(String.class), Matchers.anyString(), Matchers.anyString(), Matchers.anyLong()); //The failed events should have been stripped from the xml String newXml = new String(captor.getValue()); assertTrue(newXml.contains("e1")); assertTrue(newXml.contains("e2")); assertTrue(newXml.contains("e3")); assertTrue(newXml.contains("e4")); assertFalse(newXml.contains("e5")); assertFalse(newXml.contains("e6")); assertFalse(newXml.contains("e7")); assertFalse(newXml.contains("e8")); } /** * This tests that if the attempt to modify the EVENTS datastream keeps failing then the code will give up after * the specified number of attempts. * * @throws Exception */ @Test public void testTriggerWorkflowRestartFails() throws Exception { EnhancedFedora enhancedFedora = Mockito.mock(EnhancedFedora.class); ObjectProfile objectProfile = new ObjectProfile(); objectProfile.setObjectLastModifiedDate(new Date()); Mockito.when(enhancedFedora.getObjectProfile(Matchers.anyString(), Matchers.anyLong())) .thenReturn(objectProfile); PremisManipulator manipulator = getPremisManipulator(); Mockito.when(enhancedFedora.getXMLDatastreamContents(Matchers.anyString(), Matchers.anyString(), Matchers.anyLong())) .thenReturn(manipulator.toXML()); ArrayList<String> pids = new ArrayList<>(); pids.add("uuid:thepid"); Mockito.when(enhancedFedora.findObjectFromDCIdentifier(Matchers.anyString())).thenReturn(pids); //This ensure that the call always throws the exception Mockito.doThrow(new ConcurrentModificationException()) .when(enhancedFedora) .modifyDatastreamByValue(Matchers.anyString(), Matchers.anyString(), Matchers.any(ChecksumType.class), Matchers.anyString(), Matchers.any(byte[].class), Matchers.anyListOf(String.class), Matchers.anyString(), Matchers.anyString(), Matchers.anyLong()); DomsEventStorage<Batch> doms = new DomsEventStorage<>(enhancedFedora, PremisManipulatorFactory.TYPE, DomsEventStorageFactory.EVENTS, new BatchItemFactory()); int eventsRemoved = doms.triggerWorkflowRestartFromFirstFailure(new Batch("foo", 3)); assertEquals(-1,eventsRemoved); Mockito.verify(enhancedFedora) .modifyDatastreamByValue(Matchers.anyString(), Matchers.anyString(), Matchers.any(ChecksumType.class), Matchers.anyString(), Matchers.any(byte[].class), Matchers.anyListOf(String.class), Matchers.anyString(), Matchers.anyString(), Matchers.anyLong()); } /** * Get a Premis object with some successful and some failed events. * * @throws JAXBException */ private PremisManipulator getPremisManipulator() throws JAXBException { PremisManipulatorFactory<Batch> factory = new PremisManipulatorFactory<>(PremisManipulatorFactory.TYPE, new BatchItemFactory()); PremisManipulator manipulator = factory.createInitialPremisBlob(Batch.formatFullID(BATCH_ID, ROUND_TRIP_NUMBER)); manipulator = manipulator.appendEvent("me", new Date(100), "details here", "e1", true); manipulator = manipulator.appendEvent("me", new Date(200), "details here", "e2", true); manipulator = manipulator.appendEvent("me", new Date(300), "details here", "e3", false); manipulator = manipulator.appendEvent("me", new Date(400), "details here", "e4", true); manipulator = manipulator.appendEvent("me", new Date(500), "details here", "e5", true); manipulator = manipulator.appendEvent("me", new Date(600), "details here", "e6", false); manipulator = manipulator.appendEvent("me", new Date(700), "details here", "e7", true); manipulator = manipulator.appendEvent("me", new Date(800), "details here", "e8", true); return manipulator; } }