package org.dataone.integration.it.functional; import static org.junit.Assert.assertFalse; import static org.junit.Assert.fail; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.apache.commons.collections.CollectionUtils; import org.dataone.client.v1.CNode; import org.dataone.client.v1.MNode; import org.dataone.configuration.Settings; import org.dataone.integration.APITestUtils; import org.dataone.integration.ContextAwareTestCaseDataone; import org.dataone.service.exceptions.BaseException; import org.dataone.service.exceptions.NotFound; import org.dataone.service.exceptions.NotImplemented; import org.dataone.service.exceptions.ServiceFailure; import org.dataone.service.types.v1.ChecksumAlgorithmList; import org.dataone.service.types.v1.Identifier; import org.dataone.service.types.v1.Node; import org.dataone.service.types.v1.ObjectFormatIdentifier; import org.dataone.service.types.v1.ObjectInfo; import org.dataone.service.types.v1.ObjectList; import org.junit.Before; import org.junit.Test; public class PreRegNodeContentCheck extends ContextAwareTestCaseDataone { ObjectList objectList = null; @Before public void fetchMnObjectList() { if (objectList == null) { Iterator it = this.getMemberNodeIterator(); MNode mn = new MNode(it.next().getBaseURL()); try { objectList = APITestUtils.pagedListObjects(mn, null, null, null, null, null, null); } catch (BaseException e) { System.out.println(e.getClass() + ": " + e.getDescription()); } } } // @Test public void checkNodeNotRegisteredElsewhere() { // loop through the various environments looking for the nodeId } @Test public void checkFormatsRegistered() { Set formats = new TreeSet(); try { String cnUrl = getReferenceContextCnUrl(); CNode cn = new CNode(cnUrl); // ObjectFormatCache.setCNode(cn); if (objectList != null && objectList.getCount() > 0) { for (ObjectInfo oi : objectList.getObjectInfoList()) { formats.add(oi.getFormatId()); } } String[] unregistered = new String[formats.size()]; int i = 0; boolean hasUnregistered = false; Settings.getConfiguration().setProperty("CNode.useObjectFormatCache", "false"); for (ObjectFormatIdentifier formatId : formats) { System.out.println("checking " + formatId.getValue()); try { cn.getFormat(formatId); } catch (NotFound nfe) { hasUnregistered = true; unregistered[i++] = formatId.getValue(); } } System.out.println("Unregistered Formats:"); for (String f : unregistered) { if (f != null) System.out.println(" " + f); } assertFalse("All formats should be registered in the reference environment", hasUnregistered); } catch (BaseException e) { System.out.println(e.getClass() + ": " + e.getDescription()); fail(e.getClass() + ": " + e.getDescription()); } catch (Exception e) { System.out.println(e.getClass() + ": " + e.getMessage()); fail(e.getClass() + ": " + e.getMessage()); } } @Test public void checkRequiredChecksumsUsed() throws ServiceFailure, NotImplemented { Set chAlgSet = new TreeSet(); try { String cnUrl = getReferenceContextCnUrl(); CNode cn = new CNode(cnUrl); ChecksumAlgorithmList cnAlgs = cn.listChecksumAlgorithms(); if (objectList != null && objectList.getCount() > 0) { for (ObjectInfo oi : objectList.getObjectInfoList()) { chAlgSet.add(oi.getChecksum().getAlgorithm()); } } String[] unregistered = new String[chAlgSet.size()]; int i = 0; boolean hasUnregistered = false; for (String alg : chAlgSet) { System.out.println("checking " + alg); if (!cnAlgs.getAlgorithmList().contains(alg)) { hasUnregistered = true; unregistered[i++] = alg; } } System.out.println("Unregistered Algorithms:"); for (String f : unregistered) { System.out.println(" " + f); } assertFalse("All checksums algorithms used by MN objects should be in the reference environment", hasUnregistered); } catch (BaseException e) { System.out.println(e.getClass() + ": " + e.getDescription()); fail(e.getClass() + ": " + e.getDescription()); } catch (Exception e) { System.out.println(e.getClass() + ": " + e.getMessage()); fail(e.getClass() + ": " + e.getMessage()); } } private Set buildSerializedObjectInfoSet(ObjectList ol) { Set oiSet = new HashSet(ol.getTotal(),1); for (ObjectInfo oi: ol.getObjectInfoList()) { oiSet.add( String.format("%s\t%s\t%d\t%s\t%s", oi.getIdentifier().getValue(), oi.getFormatId().getValue(), oi.getSize(), oi.getChecksum().getAlgorithm(), oi.getChecksum().getValue()) ); } return oiSet; } /** * This looks for identifiers in the potential membernode that might already be * taken in DataONE. If it's already there, it checks the size and checksum * to see if the associated object is the same or not. This could happen when * multiple nodes that may already hold copies of each other's data come online. * * Implementation note: This test doesn't hold the entire CN objectList in memory and/or a hashmap, * so should be resistant to the size of the cn objectlist. */ @Test public void checkIdentifierCollisions() { String cnUrl = getReferenceContextCnUrl(); CNode cn = new CNode(cnUrl); try { HashMap mnOiMap = new HashMap(objectList.getObjectInfoList().size()); for (ObjectInfo oi: objectList.getObjectInfoList()) { mnOiMap.put(oi.getIdentifier(), oi); } int runningTotal = 0; int olTotal = 0; while (runningTotal < olTotal || olTotal == 0) { ObjectList ol = cn.listObjects(null, null, null, null, runningTotal, 1000); olTotal = ol.getTotal(); runningTotal += ol.getObjectInfoList().size(); for (ObjectInfo oi : ol.getObjectInfoList()) { if (mnOiMap.containsKey(oi.getIdentifier())) { if ( oi.getSize().equals( mnOiMap.get(oi.getIdentifier()).getSize() ) && oi.getChecksum().getValue().equals( mnOiMap.get(oi.getIdentifier()).getChecksum().getValue())) { System.out.println("Identifier " + oi.getIdentifier().getValue() + " is already registered, yet appears to be the same object"); } else { System.out.println("Identifier " + oi.getIdentifier().getValue() + " is already registered:"); System.out.println(String.format(" cn: %s %d %s %s", oi.getIdentifier().getValue(), oi.getSize(), oi.getChecksum().getAlgorithm(), oi.getChecksum().getValue())); System.out.println(String.format(" mn: %s %d %s %s", oi.getIdentifier().getValue(), mnOiMap.get(oi.getIdentifier()).getSize(), mnOiMap.get(oi.getIdentifier()).getChecksum().getAlgorithm(), mnOiMap.get(oi.getIdentifier()).getChecksum().getValue())); } } } } } catch (BaseException be) { be.printStackTrace(); } } private Map buildObjectIdentifierMap(ObjectList ol) { Map oiMap = new HashMap(89); int i = 0; for (ObjectInfo oi: ol.getObjectInfoList()) { if (++i % 3000 == 0) { System.out.println(i); } oiMap.put(oi.getIdentifier().getValue(), String.format("%s\t%s\t%d\t%s\t%s", oi.getIdentifier().getValue(), oi.getFormatId().getValue(), oi.getSize(), oi.getChecksum().getAlgorithm(), oi.getChecksum().getValue()) ); } return oiMap; } /** * Identifiers in the potential MN should not already be registered in dataONE, * but if they do, they should have the same objectInfo (checksum, size, formatId) * NOTE: This test is sensitive to large cn objectLists * @throws ServiceFailure * @throws NotImplemented */ //@Test // this test is sensitive to large cn objectlists public void checkIdentifierCollision() throws ServiceFailure, NotImplemented { // must be cn admin to get around access restrictions on cn.describe try { String cnUrl = getReferenceContextCnUrl(); CNode cn = new CNode(cnUrl); ObjectList cnOL = APITestUtils.pagedListObjects(cn, null, null, null, null, null, null); Map cnOISet = buildObjectIdentifierMap(cnOL); Map mnOISet = buildObjectIdentifierMap(objectList); Collection collisions = CollectionUtils.intersection(mnOISet.keySet(), cnOISet.keySet()); if (! collisions.isEmpty()) { for (String pid : collisions) { if (!mnOISet.get(pid).equals(cnOISet.get(pid))) { System.out.println(String.format("%s already registered and is different:", pid)); System.out.println(" mn: " + mnOISet.get(pid)); System.out.println(" cn: " + cnOISet.get(pid)); } else { System.out.println(String.format("%s already registered but is same**",pid)); } } } } catch (BaseException be) { fail("problem getting an ObjectList from the cn. " + be.getClass() + ": " + be.getDescription()); } } @Override protected String getTestDescription() { // TODO Auto-generated method stub return null; } }