package org.dataone.integration.it.testImplementations; import static org.junit.Assert.assertTrue; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.commons.collections.IteratorUtils; import org.apache.commons.io.IOUtils; import org.dataone.client.v1.types.D1TypeBuilder; import org.dataone.integration.ContextAwareTestCaseDataone; import org.dataone.integration.adapters.CNCallAdapter; import org.dataone.integration.adapters.MNCallAdapter; import org.dataone.integration.webTest.WebTestDescription; import org.dataone.integration.webTest.WebTestName; import org.dataone.service.exceptions.NotAuthorized; import org.dataone.service.types.v1.AccessRule; import org.dataone.service.types.v1.Identifier; import org.dataone.service.types.v1.Node; import org.dataone.service.types.v1.NodeType; import org.dataone.service.types.v1.Permission; import org.dataone.service.types.v1.Service; import org.dataone.service.types.v2.Log; import org.dataone.service.types.v2.LogEntry; import org.dataone.service.types.v2.SystemMetadata; import org.dataone.service.util.Constants; public class LogAggregationFunctionalTestImplementations extends ContextAwareTestCaseDataone { private CNCallAdapter cn; private List mns; private List v1mns; private List v2mns; private List v1v2mns; private static final long LOG_AGG_WAIT = 4 * 60000; // 5 minutes @Override protected String getTestDescription() { return "Runs create/read/etc methods agains MNs in the environment and verifies " + "that the corresponding logs end up on a CN."; } public void setup(Iterator cnIter) { mns = new ArrayList(); v1mns = new ArrayList(); v2mns = new ArrayList(); v1v2mns = new ArrayList(); List cnList = IteratorUtils.toList(cnIter); assertTrue("Test requires at least one CN, but got zero CNs.", cnList.size() != 0); log.info("Using CN " + cnList.get(0).getBaseURL() + " for tests"); cn = new CNCallAdapter(getSession(cnSubmitter), cnList.get(0), "v2"); List mnList = new ArrayList(); try { for(Node n : cn.listNodes().getNodeList()) if(n.getType() == NodeType.MN) mnList.add(n); } catch (Exception e) { throw new AssertionError("Unable to fetch node list from CN: " + cn.getNodeBaseServiceUrl(), e); } for (Node mNode : mnList) { MNCallAdapter v1mn = new MNCallAdapter(getSession(cnSubmitter), mNode, "v1"); MNCallAdapter v2mn = new MNCallAdapter(getSession(cnSubmitter), mNode, "v2"); Node v1capabilities = null; Node v2capabilities = null; try { v1mn.ping(); Node cap = v1mn.getCapabilities(); List serviceList = cap.getServices().getServiceList(); for (Service service : serviceList) { if ("MNCore".equals(service.getName()) // getLogRecords && "v1".equals(service.getVersion()) && service.getAvailable()) { v1capabilities = cap; break; } } } catch (Exception e1) { log.info("Unable to assess v1 capabilities for MN: " + v1mn.getNodeBaseServiceUrl() + " : " + e1.getClass().getSimpleName() + " : " + e1.getMessage()); } try { v2mn.ping(); Node cap = v2mn.getCapabilities(); List serviceList = cap.getServices().getServiceList(); for (Service service : serviceList) { if ("MNCore".equals(service.getName()) // getLogRecords && "v2".equals(service.getVersion()) && service.getAvailable()) { v2capabilities = cap; break; } } } catch (Exception e1) { log.info("Unable to assess v2 capabilities for MN: " + v1mn.getNodeBaseServiceUrl() + " : " + e1.getClass().getSimpleName() + " : " + e1.getMessage()); } if (v1capabilities != null && v2capabilities != null) { mns.add(v2capabilities); v1v2mns.add(v2capabilities); } else if (v1capabilities != null) { mns.add(v1capabilities); v1mns.add(v1capabilities); } else if (v2capabilities != null) { mns.add(v2capabilities); v2mns.add(v2capabilities); } } log.info("MNs available: " + mns.size()); for (Node n : mns) log.info("MN: " + n.getBaseURL()); assertTrue("Test requires that the environment has at least one MN to work with that " + "supports logging for CN log aggregation. Found: " + mns.size(), mns.size() >= 1); } /** * Helper method to return an {@link MNCallAdapter} for either a v1 or v2 MN in the system. * Will preferentially return one for an MN that supports v1 AND v2 APIs (which will call the v2 API), * followed by just v2, followed by just v1. */ private MNCallAdapter getMNCallAdapter(String certificateFilename) { if (v1v2mns.size() > 0) return new MNCallAdapter(getSession(certificateFilename), v1v2mns.get(0), "v2"); if (v2mns.size() > 0) return new MNCallAdapter(getSession(certificateFilename), v2mns.get(0), "v2"); if (v1mns.size() > 0) { log.warn("only v1 MN available for use! (" + v1mns.get(0).getBaseURL() + ") " + "libclient used by tests calls the /v1/log and /v2/log endpoint with the" + "idFilter parameter. The v1 MN may still be using the pidFilter parameter!"); return new MNCallAdapter(getSession(certificateFilename), v1mns.get(0), "v1"); } throw new AssertionError("Not enough (responsive) MNs to test with in this environment."); } @WebTestName("getLogRecords() user-based access") @WebTestDescription("Tests that an authenticated user may only view their own records " + "or public records, and that a CN caller may view all records. Note: allowing " + "access to more than the CN is optional for an MN, so authentication failures for " + "non-CN subjects are ignored.") public void testMnGetLogRecords_Access() { MNCallAdapter mnCnCaller = getMNCallAdapter(cnSubmitter); MNCallAdapter mnPublicCaller = getMNCallAdapter(Constants.SUBJECT_PUBLIC); MNCallAdapter mnTestPersonCaller = getMNCallAdapter("testPerson"); MNCallAdapter mnTestRightsHolderCaller = getMNCallAdapter("testRightsHolder"); AccessRule publicAccessRule = new AccessRule(); publicAccessRule.addSubject(D1TypeBuilder.buildSubject(Constants.SUBJECT_PUBLIC)); publicAccessRule.addPermission(Permission.CHANGE_PERMISSION); AccessRule testPersonAccessRule = new AccessRule(); getSession("testPerson"); testPersonAccessRule.addSubject(getSubject("testPerson")); testPersonAccessRule.addPermission(Permission.CHANGE_PERMISSION); AccessRule testRightsHolderAccessRule = new AccessRule(); getSession("testRightsHolder"); testRightsHolderAccessRule.addSubject(getSubject("testRightsHolder")); testRightsHolderAccessRule.addPermission(Permission.CHANGE_PERMISSION); Identifier publicPid = D1TypeBuilder.buildIdentifier("testMnGetLogRecords_Access_public");//_" + ExampleUtilities.generateIdentifier()); Identifier testPersonPid = D1TypeBuilder.buildIdentifier("testMnGetLogRecords_Access_testPerson");//_" + ExampleUtilities.generateIdentifier()); Identifier testRightsHolderPid = D1TypeBuilder.buildIdentifier("testMnGetLogRecords_Access_testRightsHolder");//_" + ExampleUtilities.generateIdentifier()); InputStream is = null; try { publicPid = procureTestObject(mnCnCaller, publicAccessRule, publicPid); is = mnCnCaller.get(null, publicPid); // create read log record } catch (Exception e) { throw new AssertionError("testMnGetLogRecords_Access: Unable to get or create a test object " + "with pid: " + publicPid.getValue() + ", " + e.getClass().getSimpleName() + " : " + e.getMessage(), e); } finally { IOUtils.closeQuietly(is); } try { testPersonPid = procureTestObject(mnCnCaller, testPersonAccessRule, testPersonPid); is = mnCnCaller.get(null, testPersonPid); // create read log record } catch (Exception e) { throw new AssertionError("testMnGetLogRecords_Access: Unable to get or create a test object " + "with pid: " + testPersonPid.getValue() + ", " + e.getClass().getSimpleName() + " : " + e.getMessage(), e); } finally { IOUtils.closeQuietly(is); } try { testRightsHolderPid = procureTestObject(mnCnCaller, testRightsHolderAccessRule, testRightsHolderPid); is = mnCnCaller.get(null, testRightsHolderPid); // create read log record } catch (Exception e) { throw new AssertionError("testMnGetLogRecords_Access: Unable to get or create a test object " + "with pid: " + testRightsHolderPid.getValue() + ", " + e.getClass().getSimpleName() + " : " + e.getMessage(), e); } finally { IOUtils.closeQuietly(is); } try { Thread.sleep(5000); // asynchronous actions on MN? } catch (InterruptedException e1) { ; } ArrayList errors = new ArrayList(); Log publicLog = null; try { publicLog = mnPublicCaller.getLogRecords(null, null, null, null, publicPid.getValue(), null, null); } catch (NotAuthorized nf) { // expected } catch (Exception e) { log.warn(mnPublicCaller.getLatestRequestUrl() + " Unable to fetch Log records for public subject. " + "Expected a NotAuthorized (only CN or MN admin should have access) but got exception: " + e.getClass().getSimpleName() + " : " + e.getMessage(), e); } Log testPersonLog = null; try { testPersonLog = mnTestPersonCaller.getLogRecords(null, null, null, null, testPersonPid.getValue(), null, null); } catch (NotAuthorized nf) { // expected } catch (Exception e) { log.warn(mnTestPersonCaller.getLatestRequestUrl() + " Unable to fetch Log records for testPerson subject. " + "Expected a NotAuthorized (only CN or MN admin should have access) but got exception: " + e.getClass().getSimpleName() + " : " + e.getMessage(), e); } Log testRightsHolderLog = null; try { testRightsHolderLog = mnTestRightsHolderCaller.getLogRecords(null, null, null, null, testRightsHolderPid.getValue(), null, null); } catch (NotAuthorized nf) { // expected } catch (Exception e) { log.warn(mnTestRightsHolderCaller.getLatestRequestUrl() + " Unable to fetch Log records for testRightsHolder subject. " + "Expected a NotAuthorized (only CN or MN admin should have access) but got exception: " + e.getClass().getSimpleName() + " : " + e.getMessage(), e); } Log cnLogPublicPid = null; Log cnLogTestPersonPid = null; Log cnLogTestRightsHolderPid = null; try { cnLogPublicPid = mnCnCaller.getLogRecords(null, null, null, null, publicPid.getValue(), null, null); } catch (Exception e) { throw new AssertionError(mnCnCaller.getLatestRequestUrl() + " Unable to fetch Log records for CN subject. " + "Got exception: " + e.getClass().getSimpleName() + " : " + e.getMessage(), e); } try { cnLogTestPersonPid = mnCnCaller.getLogRecords(null, null, null, null, testPersonPid.getValue(), null, null); } catch (Exception e) { throw new AssertionError(mnCnCaller.getLatestRequestUrl() + " Unable to fetch Log records for CN subject. " + "Got exception: " + e.getClass().getSimpleName() + " : " + e.getMessage(), e); } try { cnLogTestRightsHolderPid = mnCnCaller.getLogRecords(null, null, null, null, testRightsHolderPid.getValue(), null, null); } catch (Exception e) { throw new AssertionError(mnCnCaller.getLatestRequestUrl() + " Unable to fetch Log records for CN subject. " + "Got exception: " + e.getClass().getSimpleName() + " : " + e.getMessage(), e); } if (publicLog != null) { boolean publicPidFound = false; boolean testPersonPidFound = false; boolean testRightsHolderPidFound = false; for (LogEntry logEntry : publicLog.getLogEntryList()) { if (logEntry.getIdentifier().equals(publicPid)) publicPidFound = true; if (logEntry.getIdentifier().equals(testPersonPid)) testPersonPidFound = true; if (logEntry.getIdentifier().equals(testRightsHolderPid)) testRightsHolderPidFound = true; } if (!publicPidFound) errors.add("Public subject should have access to public-accessible object we created."); if (testPersonPidFound) errors.add("Public subject should NOT have access to testPerson-accessible object we created."); if (testRightsHolderPidFound) errors.add("Public subject should NOT have access to testRightsHolder-accessible object we created."); } if (testPersonLog != null) { boolean publicPidFound = false; boolean testPersonPidFound = false; boolean testRightsHolderPidFound = false; for (LogEntry logEntry : testPersonLog.getLogEntryList()) { if (logEntry.getIdentifier().equals(publicPid)) publicPidFound = true; if (logEntry.getIdentifier().equals(testPersonPid)) testPersonPidFound = true; if (logEntry.getIdentifier().equals(testRightsHolderPid)) testRightsHolderPidFound = true; } if (!publicPidFound) errors.add("testPerson subject should have access to public-accessible object we created."); if (testPersonPidFound) errors.add("testPerson subject should have access to testPerson-accessible object we created."); if (testRightsHolderPidFound) errors.add("testPerson subject should NOT have access to testRightsHolder-accessible object we created."); } if (testRightsHolderLog != null) { boolean publicPidFound = false; boolean testPersonPidFound = false; boolean testRightsHolderPidFound = false; for (LogEntry logEntry : testRightsHolderLog.getLogEntryList()) { if (logEntry.getIdentifier().equals(publicPid)) publicPidFound = true; if (logEntry.getIdentifier().equals(testPersonPid)) testPersonPidFound = true; if (logEntry.getIdentifier().equals(testRightsHolderPid)) testRightsHolderPidFound = true; } if (!publicPidFound) errors.add("testRightsHolder subject should have access to public-accessible object we created."); if (!testPersonPidFound) errors.add("testRightsHolder subject should NOT have access to testPerson-accessible object we created."); if (!testRightsHolderPidFound) errors.add("testRightsHolder subject should have access to testRightsHolder-accessible object we created."); } boolean publicPidFound = false; if (cnLogPublicPid != null && cnLogPublicPid.getLogEntryList() != null) { for (LogEntry logEntry : cnLogPublicPid.getLogEntryList()) if (logEntry.getIdentifier().equals(publicPid)) publicPidFound = true; } if (!publicPidFound) errors.add("CN subject (" + getSubject(cnSubmitter).getValue() + ") should have access to public-accessible object we created on " + mnCnCaller.getNodeBaseServiceUrl() + "." + " pid: " + publicPid.getValue()); boolean testPersonPidFound = false; if (cnLogTestPersonPid != null && cnLogTestPersonPid.getLogEntryList() != null) { for (LogEntry logEntry : cnLogTestPersonPid.getLogEntryList()) if (logEntry.getIdentifier().equals(testPersonPid)) testPersonPidFound = true; } if (!testPersonPidFound) errors.add("CN subject (" + getSubject(cnSubmitter).getValue() + ") should have access to testPerson-accessible object we created on " + mnCnCaller.getNodeBaseServiceUrl() + "." + " pid: " + testPersonPid.getValue()); boolean testRightsHolderPidFound = false; if (cnLogTestRightsHolderPid != null && cnLogTestRightsHolderPid.getLogEntryList() != null) { for (LogEntry logEntry : cnLogTestRightsHolderPid.getLogEntryList()) if (logEntry.getIdentifier().equals(testRightsHolderPid)) testRightsHolderPidFound = true; } if (!testRightsHolderPidFound) errors.add("CN subject (" + getSubject(cnSubmitter).getValue() + ") should have access to testRightsHolder-accessible object we created on " + mnCnCaller.getNodeBaseServiceUrl() + "." + " pid: " + testRightsHolderPid.getValue()); if (errors.size() > 0) { String errorString = ""; for (String err : errors) errorString += err + "\n"; throw new AssertionError("testMnGetLogRecords_Access ran into " + errors.size() + " errors:\n" + errorString); } } @WebTestName("query() user-based access") @WebTestDescription("Tests that an authenticated user may only view their own records " + "or public records, and that a CN caller may view all records.") public void testMnQuery_Access() { MNCallAdapter mnCnCaller = getMNCallAdapter(cnSubmitter); MNCallAdapter mnPublicCaller = getMNCallAdapter(Constants.SUBJECT_PUBLIC); MNCallAdapter mnTestPersonCaller = getMNCallAdapter("testPerson"); MNCallAdapter mnTestRightsHolderCaller = getMNCallAdapter("testRightsHolder"); AccessRule publicAccessRule = new AccessRule(); publicAccessRule.addSubject(D1TypeBuilder.buildSubject(Constants.SUBJECT_PUBLIC)); publicAccessRule.addPermission(Permission.CHANGE_PERMISSION); AccessRule testPersonAccessRule = new AccessRule(); getSession("testPerson"); testPersonAccessRule.addSubject(getSubject("testPerson")); testPersonAccessRule.addPermission(Permission.CHANGE_PERMISSION); AccessRule testRightsHolderAccessRule = new AccessRule(); getSession("testRightsHolder"); testRightsHolderAccessRule.addSubject(getSubject("testRightsHolder")); testRightsHolderAccessRule.addPermission(Permission.CHANGE_PERMISSION); Identifier publicPid = D1TypeBuilder.buildIdentifier("testMnQuery_Access_public_"); Identifier testPersonPid = D1TypeBuilder.buildIdentifier("testMnQuery_Access_testPerson_"); Identifier testRightsHolderPid = D1TypeBuilder.buildIdentifier("testMnQuery_Access_testRightsHolder_"); try { publicPid = procureTestObject(mnCnCaller, publicAccessRule, publicPid, cnSubmitter, "public", null); log.info("procured test object: " + publicPid.getValue() + " on " + mnCnCaller.getNodeId().getValue()); } catch (Exception e) { throw new AssertionError("testMnQuery_Access: Unable to get or create a test object " + "with pid: " + publicPid.getValue() + ", " + e.getClass().getSimpleName() + " : " + e.getMessage(), e); } try { getSession("testPerson"); testPersonPid = procureTestObject(mnCnCaller, testPersonAccessRule, testPersonPid, cnSubmitter, getSubject("testPerson").getValue(), null); log.info("procured test object: " + testPersonPid.getValue() + " on " + mnCnCaller.getNodeId().getValue()); } catch (Exception e) { throw new AssertionError("testMnQuery_Access: Unable to get or create a test object " + "with pid: " + testPersonPid.getValue() + ", " + e.getClass().getSimpleName() + " : " + e.getMessage(), e); } try { getSession("testRightsHolder"); testRightsHolderPid = procureTestObject(mnCnCaller, testRightsHolderAccessRule, testRightsHolderPid, cnSubmitter, getSubject("testRightsHolder").getValue(), null); log.info("procured test object: " + testRightsHolderPid.getValue() + " on " + mnCnCaller.getNodeId().getValue()); } catch (Exception e) { throw new AssertionError("testMnQuery_Access: Unable to get or create a test object " + "with pid: " + testRightsHolderPid.getValue() + ", " + e.getClass().getSimpleName() + " : " + e.getMessage(), e); } // sysmeta for debug purposes: SystemMetadata sysmetaPublicObj = null; SystemMetadata sysmetaTestPersonObj = null; SystemMetadata sysmetaTestRightsHolderObj = null; try { sysmetaPublicObj = mnCnCaller.getSystemMetadata(null, publicPid); sysmetaTestPersonObj = mnCnCaller.getSystemMetadata(null, testPersonPid); sysmetaTestRightsHolderObj = mnCnCaller.getSystemMetadata(null, testRightsHolderPid); } catch (Exception e) { log.warn("failed to fetch sysmeta", e); } String publicPidEncoded = null; String testPersonPidEncoded = null; String testRightsHolderPidEncoded = null; try { publicPidEncoded = URLEncoder.encode(publicPid.getValue(), "UTF-8"); testPersonPidEncoded = URLEncoder.encode(testPersonPid.getValue(), "UTF-8"); testRightsHolderPidEncoded = URLEncoder.encode(testRightsHolderPid.getValue(), "UTF-8"); } catch (UnsupportedEncodingException e1) { throw new AssertionError("testMnQuery_Access() unable to encode identifiers using UTF-8", e1); } ArrayList errors = new ArrayList(); InputStream publicQueryPublicObj = null; InputStream publicQueryPersonObj = null; InputStream publicQueryRightsHolderObj = null; LogContents publicObjContents = null; LogContents personObjContents = null; LogContents rightsHolderObjContents = null; try { publicQueryPublicObj = mnPublicCaller.query(null, "solr", "q=identifier:" + publicPidEncoded); publicObjContents = ContextAwareTestCaseDataone.getNumQueryContents(publicQueryPublicObj); publicQueryPersonObj = mnPublicCaller.query(null, "solr", "q=identifier:" + testPersonPidEncoded); personObjContents = ContextAwareTestCaseDataone.getNumQueryContents(publicQueryPersonObj); publicQueryRightsHolderObj = mnPublicCaller.query(null, "solr", "q=identifier:" + testRightsHolderPidEncoded); rightsHolderObjContents = ContextAwareTestCaseDataone.getNumQueryContents(publicQueryRightsHolderObj); } catch (Exception e) { throw new AssertionError(mnPublicCaller.getLatestRequestUrl() + ", Unable to run solr query for public subject. " + "Got exception: " + e.getClass().getSimpleName() + " : " + e.getMessage()); } // check result count if ( publicObjContents.existingLogs == 0 ) errors.add("Query run by public subject should retrieve a positive result count for public-created object. For MN " + mnPublicCaller.getNodeBaseServiceUrl() + ". " + "pid: " + publicPid.getValue()); if ( personObjContents.existingLogs != 0 ) errors.add("Query run by public subject should retrieve a zero result count for testPerson-created object. For MN " + mnPublicCaller.getNodeBaseServiceUrl() + ". " + "pid: " + testPersonPid.getValue()); if ( rightsHolderObjContents.existingLogs != 0 ) errors.add("Query run by public subject should retrieve a zero result count for testRightsHolder-created object. For MN " + mnPublicCaller.getNodeBaseServiceUrl() + ". " + "pid: " + testRightsHolderPid.getValue()); // check result docs if ( publicObjContents.docsReturned == 0 ) errors.add("Query run by public subject should retrieve result docs for public-created object. For MN " + mnPublicCaller.getNodeBaseServiceUrl() + ". " + "pid: " + publicPid.getValue()); if ( personObjContents.docsReturned != 0 ) errors.add("Query run by public subject should NOT retrieve result docs for testPerson-created object. For MN " + mnPublicCaller.getNodeBaseServiceUrl() + ". " + "pid: " + testPersonPid.getValue()); if ( rightsHolderObjContents.docsReturned != 0 ) errors.add("Query run by public subject should NOT retrieve result docs for testRightsHolder-created object. For MN " + mnPublicCaller.getNodeBaseServiceUrl() + ". " + "pid: " + testRightsHolderPid.getValue()); InputStream testPersonQueryPublicObj = null; InputStream testPersonQueryPersonObj = null; InputStream testPersonQueryRightsHolderObj = null; try { testPersonQueryPublicObj = mnTestPersonCaller.query(null, "solr", "q=identifier:" + publicPidEncoded); publicObjContents = ContextAwareTestCaseDataone.getNumQueryContents(testPersonQueryPublicObj); testPersonQueryPersonObj = mnTestPersonCaller.query(null, "solr", "q=identifier:" + testPersonPidEncoded); personObjContents = ContextAwareTestCaseDataone.getNumQueryContents(testPersonQueryPersonObj); testPersonQueryRightsHolderObj = mnTestPersonCaller.query(null, "solr", "q=identifier:" + testRightsHolderPidEncoded); rightsHolderObjContents = ContextAwareTestCaseDataone.getNumQueryContents(testPersonQueryRightsHolderObj); } catch (Exception e) { throw new AssertionError(mnTestPersonCaller.getLatestRequestUrl() + ", Unable to run solr query for testPerson subject. " + "Got exception: " + e.getClass().getSimpleName() + " : " + e.getMessage()); } // check result count if ( publicObjContents.existingLogs == 0 ) errors.add("Query run by testPerson subject should retrieve a positive result count for public-created object. For MN " + mnTestPersonCaller.getNodeBaseServiceUrl() + ". " + "pid: " + publicPid.getValue()); if ( personObjContents.existingLogs == 0 ) errors.add("Query run by testPerson subject should retrieve a positive result count for testPerson-created object. For MN " + mnTestPersonCaller.getNodeBaseServiceUrl() + ". " + "pid: " + testPersonPid.getValue()); if ( rightsHolderObjContents.existingLogs != 0 ) errors.add("Query run by testPerson subject should retrieve a zero result count for testRightsHolder-created object. For MN " + mnTestPersonCaller.getNodeBaseServiceUrl() + ". " + "pid: " + testRightsHolderPid.getValue()); // check result docs if ( publicObjContents.docsReturned == 0 ) errors.add("Query run by testPerson subject should retrieve result docs for public-created object. For MN " + mnTestPersonCaller.getNodeBaseServiceUrl() + ". " + "pid: " + publicPid.getValue()); if ( personObjContents.docsReturned == 0 ) errors.add("Query run by testPerson subject should retrieve result docs for testPerson-created object. For MN " + mnTestPersonCaller.getNodeBaseServiceUrl() + ". " + "pid: " + testPersonPid.getValue()); if ( rightsHolderObjContents.docsReturned != 0 ) errors.add("Query run by testPerson subject should NOT retrieve result docs for testRightsHolder-created object. For MN " + mnTestPersonCaller.getNodeBaseServiceUrl() + ". " + "pid: " + testRightsHolderPid.getValue()); InputStream testRightsHolderQueryPublicObj = null; InputStream testRightsHolderQueryPersonObj = null; InputStream testRightsHolderQueryRightsHolderObj = null; try { testRightsHolderQueryPublicObj = mnTestRightsHolderCaller.query(null, "solr", "q=identifier:" + publicPidEncoded); publicObjContents = ContextAwareTestCaseDataone.getNumQueryContents(testRightsHolderQueryPublicObj); testRightsHolderQueryPersonObj = mnTestRightsHolderCaller.query(null, "solr", "q=identifier:" + testPersonPidEncoded); personObjContents = ContextAwareTestCaseDataone.getNumQueryContents(testRightsHolderQueryPersonObj); testRightsHolderQueryRightsHolderObj = mnTestRightsHolderCaller.query(null, "solr", "q=identifier:" + testRightsHolderPidEncoded); rightsHolderObjContents = ContextAwareTestCaseDataone.getNumQueryContents(testRightsHolderQueryRightsHolderObj); } catch (Exception e) { throw new AssertionError(mnTestRightsHolderCaller.getLatestRequestUrl() + ", Unable to run solr query for testRightsHolder subject. " + "Got exception: " + e.getClass().getSimpleName() + " : " + e.getMessage()); } // check result count if ( publicObjContents.existingLogs == 0 ) errors.add("Query run by testRightsHolder subject should retrieve a positive result count for public-created object. For MN " + mnTestRightsHolderCaller.getNodeBaseServiceUrl() + ". " + "pid: " + publicPid.getValue()); if ( personObjContents.existingLogs != 0 ) errors.add("Query run by testRightsHolder subject should NOT retrieve a positive result count for testPerson-created object. For MN " + mnTestRightsHolderCaller.getNodeBaseServiceUrl() + ". " + "pid: " + testPersonPid.getValue()); if ( rightsHolderObjContents.existingLogs == 0 ) errors.add("Query run by testRightsHolder subject should retrieve a positive result count for testRightsHolder-created object. For MN " + mnTestRightsHolderCaller.getNodeBaseServiceUrl() + ". " + "pid: " + testRightsHolderPid.getValue()); // check result docs if ( publicObjContents.docsReturned == 0 ) errors.add("Query run by testRightsHolder subject should retrieve result docs for public-created object. For MN " + mnTestRightsHolderCaller.getNodeBaseServiceUrl() + ". " + "pid: " + publicPid.getValue()); if ( personObjContents.docsReturned != 0 ) errors.add("Query run by testRightsHolder subject should NOT retrieve result docs for testPerson-created object. For MN " + mnTestRightsHolderCaller.getNodeBaseServiceUrl() + ". " + "pid: " + testPersonPid.getValue()); if ( rightsHolderObjContents.docsReturned == 0 ) errors.add("Query run by testRightsHolder subject should retrieve result docs for testRightsHolder-created object. For MN " + mnTestRightsHolderCaller.getNodeBaseServiceUrl() + ". " + "pid: " + testRightsHolderPid.getValue()); InputStream cnQueryPublicObj = null; InputStream cnQueryPersonObj = null; InputStream cnQueryRightsHolderObj = null; try { cnQueryPublicObj = mnCnCaller.query(null, "solr", "q=identifier:" + publicPidEncoded); publicObjContents = ContextAwareTestCaseDataone.getNumQueryContents(cnQueryPublicObj); cnQueryPersonObj = mnCnCaller.query(null, "solr", "q=identifier:" + testPersonPidEncoded); personObjContents = ContextAwareTestCaseDataone.getNumQueryContents(cnQueryPersonObj); cnQueryRightsHolderObj = mnCnCaller.query(null, "solr", "q=identifier:" + testRightsHolderPidEncoded); rightsHolderObjContents = ContextAwareTestCaseDataone.getNumQueryContents(cnQueryRightsHolderObj); } catch (Exception e) { handleFail(mnCnCaller.getLatestRequestUrl(), "Unable to run solr query for testRightsHolder subject."); } // check result count if ( publicObjContents.existingLogs == 0 ) errors.add("Query run by CN subject (" + getSubject(cnSubmitter).getValue() + ") should retrieve a positive result count for public-created object on " + mnCnCaller.getNodeBaseServiceUrl() + ". " + "pid: " + publicPid.getValue()); // FIXME the below were commented out because MN.query() doesn't currently support this // it makes sense that this would be supported in the future, so leaving tests commented for now // if ( personObjContents.existingLogs == 0 ) // errors.add("Query run by CN subject (" + getSubject(cnSubmitter).getValue() + ") should retrieve a positive result count for testPerson-created object on " + mnCnCaller.getNodeBaseServiceUrl() + ". " // + "pid: " + testPersonPid.getValue()); // if ( rightsHolderObjContents.existingLogs == 0 ) // errors.add("Query run by CN subject (" + getSubject(cnSubmitter).getValue() + ") should retrieve a positive result count for testRightsHolder-created object on " + mnCnCaller.getNodeBaseServiceUrl() + ". " // + "pid: " + testRightsHolderPid.getValue()); // check result docs if ( publicObjContents.docsReturned == 0 ) errors.add("Query run by CN subject (" + getSubject(cnSubmitter).getValue() + ") should retrieve result docs for public-created object on " + mnCnCaller.getNodeBaseServiceUrl() + ". " + "pid: " + publicPid.getValue()); // if ( personObjContents.docsReturned == 0 ) // errors.add("Query run by CN subject (" + getSubject(cnSubmitter).getValue() + ") should retrieve result docs for testPerson-created object on " + mnCnCaller.getNodeBaseServiceUrl() + ". " // + "pid: " + testPersonPid.getValue()); // if ( rightsHolderObjContents.docsReturned == 0 ) // errors.add("Query run by CN subject (" + getSubject(cnSubmitter).getValue() + ") should retrieve result docs for testRightsHolder-created object on " + mnCnCaller.getNodeBaseServiceUrl() + ". " // + "pid: " + testRightsHolderPid.getValue()); if (errors.size() > 0) { String errorString = ""; for (String err : errors) errorString += err + "\n"; throw new AssertionError("testMnQuery_Access ran into " + errors.size() + " errors:\n" + errorString); } } @WebTestName("getLogRecords() create on MN read on CN") @WebTestDescription("Tests the getLogRecords() call. After creating objects on MNs " + "and waiting, verifies that logs are aggregated on the CN.") public void testCnGetLogRecords_Aggregating() { int numMNs = this.mns.size(); ArrayList skippedMNs = new ArrayList(); ArrayList mnCallAdapters = new ArrayList(numMNs); for (Node n : this.mns) { if (v1v2mns.contains(n) || v2mns.contains(n)) // if v2 node mnCallAdapters.add(new MNCallAdapter(getSession(cnSubmitter), n, "v2")); else mnCallAdapters.add(new MNCallAdapter(getSession(cnSubmitter), n, "v1")); } AccessRule publicAccessRule = new AccessRule(); publicAccessRule.addSubject(D1TypeBuilder.buildSubject(Constants.SUBJECT_PUBLIC)); publicAccessRule.addPermission(Permission.CHANGE_PERMISSION); ArrayList pids = new ArrayList(numMNs); // create objects for (int i=0; i 0); } catch (Exception e) { log.info("pid: " + pid); log.info("call adapter: " + mnCallAdapters.get(i)); throw new AssertionError("testCnGetLogRecords_Aggregating: Unable to get record for pid: " + pid.getValue() + " on originating mn " + mnCallAdapters.get(i).getNodeBaseServiceUrl(), e); } } try { log.info("testCnGetLogRecords_Aggregating: " + "waiting for log aggregation: (" + ((double)LOG_AGG_WAIT / 60000) + " minutes)"); Thread.sleep(LOG_AGG_WAIT); } catch (InterruptedException e) { // no time for a sandwich :( } ArrayList errors = new ArrayList(); // check for logs on CN for (int i=0; i 0) { String errorString = ""; for (String err : errors) errorString += err + "\n"; throw new AssertionError("testCnGetLogRecords_Aggregating ran into " + errors.size() + " errors:\n" + errorString); } } @WebTestName("query() parameters") @WebTestDescription("Tests the query() call with different parameters - " + "verifies that a handful of parameters work for filtering down on the created object.") public void testQuery_Params() { MNCallAdapter mnCnCaller = getMNCallAdapter(cnSubmitter); AccessRule publicAccessRule = new AccessRule(); publicAccessRule.addSubject(D1TypeBuilder.buildSubject(Constants.SUBJECT_PUBLIC)); publicAccessRule.addPermission(Permission.CHANGE_PERMISSION); Identifier pid = D1TypeBuilder.buildIdentifier("testQuery_Params"); try { procureTestObject(mnCnCaller, publicAccessRule, pid); } catch (Exception e) { throw new AssertionError("testQuery_Params: Unable to get or create a test object " + "with pid: " + pid.getValue() + ", " + e.getClass().getSimpleName() + " : " + e.getMessage(), e); } String pidEncoded = null; String title = "\"PISCO: Physical Oceanography: moored temperature data: Terrace Point, California, USA (TPT001)\""; String titleEncoded = null; String author = "\"Margaret McManus\""; String authorEncoded = null; try { pidEncoded = URLEncoder.encode(pid.getValue(), "UTF-8"); titleEncoded = URLEncoder.encode(title, "UTF-8"); authorEncoded = URLEncoder.encode(author, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new AssertionError("testQuery_Params() unable to encode parameters", e); } //----------------------------------------------------------------------------------- DEBUG CODE // try { // SystemMetadata sysmeta = mnCnCaller.getSystemMetadata(null, pid); // } catch (Exception e) { // throw new AssertionError("getSysmeta() failed", e); // } // InputStream is = null; // FileOutputStream os = null; // try { // is = mnCnCaller.query(null, "solr", "q=identifier:" + pidEncoded); // os = new FileOutputStream(new File("C:\\Users\\Andrei\\stuff\\solrQuery.txt")); // IOUtils.copy(is, os); // } catch (Exception e) { // handleFail(mnCnCaller.getLatestRequestUrl(), "Unable to run solr query with params: identifier. " // + "Got exception: " + e.getClass().getSimpleName() + " : " + e.getMessage()); // } finally { // IOUtils.closeQuietly(is); // IOUtils.closeQuietly(os); // } //---------------------------------------------------------------------------------------------- ArrayList errors = new ArrayList(); InputStream queryResult_id = null; try { queryResult_id = mnCnCaller.query(null, "solr", "q=identifier:" + pidEncoded); LogContents queryContents = ContextAwareTestCaseDataone.getNumQueryContents(queryResult_id); if (queryContents.existingLogs == 0) errors.add("query made by as CN should return some results when filtering on pid for " + mnCnCaller.getLatestRequestUrl()); } catch (Exception e) { errors.add(mnCnCaller.getLatestRequestUrl() + " Unable to run solr query with params: identifier. " + "Got exception: " + e.getClass().getSimpleName() + " : " + e.getMessage()); } finally { IOUtils.closeQuietly(queryResult_id); } InputStream queryResult_title = null; try { queryResult_title = mnCnCaller.query(null, "solr", "q=title:" + titleEncoded); LogContents queryContents = ContextAwareTestCaseDataone.getNumQueryContents(queryResult_title); if (queryContents.existingLogs == 0) errors.add("query made by as CN should return some results when filtering on title for " + mnCnCaller.getLatestRequestUrl()); } catch (Exception e) { errors.add(mnCnCaller.getLatestRequestUrl() + " Unable to run solr query with params: title. " + "Got exception: " + e.getClass().getSimpleName() + " : " + e.getMessage()); } finally { IOUtils.closeQuietly(queryResult_title); } InputStream queryResult_author = null; try { queryResult_author = mnCnCaller.query(null, "solr", "q=author:" + authorEncoded); LogContents queryContents = ContextAwareTestCaseDataone.getNumQueryContents(queryResult_author); if (queryContents.existingLogs == 0) errors.add("query made by as CN should return some results when filtering on author for " + mnCnCaller.getLatestRequestUrl()); } catch (Exception e) { errors.add(mnCnCaller.getLatestRequestUrl() + " Unable to run solr query with params: author. " + "Got exception: " + e.getClass().getSimpleName() + " : " + e.getMessage()); } finally { IOUtils.closeQuietly(queryResult_author); } // test data created: // identifier testQuery_ParamOrder // author Margaret McManus // title PISCO: Physical Oceanography: moored temperature data: Terrace Point, California, USA (TPT001) // formatType METADATA // formatId eml://ecoinformatics.org/eml-2.0.1 // submitter ....cn....? (in this case CN=urn:node:cnDevUCSB2,DC=dataone,DC=org) // rightsHolder CN=testRightsHolder,DC=dataone,DC=org // authoritativeMN mn created on (MN Identifier: in this case urn:node:mnDevUCSB2) // author* // text PISCO moored temperature, TPT001 PISCO: Physical Oceanography:... InputStream queryResult_pidTitleAuthor = null; try { queryResult_pidTitleAuthor = mnCnCaller.query(null, "solr", "q=identifier:" + pidEncoded + "&q=title:" + titleEncoded + "&q=author:" + authorEncoded); LogContents queryContents = ContextAwareTestCaseDataone.getNumQueryContents(queryResult_pidTitleAuthor); if (queryContents.existingLogs == 0) errors.add("query made by as CN should return some results when filtering on identifier, title, and author for " + mnCnCaller.getLatestRequestUrl()); } catch (Exception e) { errors.add(mnCnCaller.getLatestRequestUrl() + " Unable to run solr query with params: identifier, title, author. " + "Got exception: " + e.getClass().getSimpleName() + " : " + e.getMessage()); } finally { IOUtils.closeQuietly(queryResult_pidTitleAuthor); } // TODO to be continued... if (errors.size() > 0) { String errorString = ""; for (String err : errors) errorString += err + "\n"; throw new AssertionError("testQuery_Params ran into " + errors.size() + " errors:\n" + errorString); } } @WebTestName("getLogRecords() create on MN test access on CN") @WebTestDescription("Tests the getLogRecords() call. Assumes that aggregation works, so" + "the testCnGetLogRecords_Aggregating test should be working. After creating objects on MNs " + "and waiting, verifies that logs returned are based on the identity of the caller.") public void testCnGetLogRecords_Access() { int numMNs = this.mns.size(); ArrayList mnIds = new ArrayList(numMNs); ArrayList mnCallAdapters = new ArrayList(numMNs); ArrayList skippedMNs = new ArrayList(); for (Node n : this.mns) { mnCallAdapters.add(new MNCallAdapter(getSession(cnSubmitter), n, "v1")); mnIds.add(n.getIdentifier().getValue().replaceAll(":", "")); } AccessRule publicAccessRule = new AccessRule(); publicAccessRule.addSubject(D1TypeBuilder.buildSubject(Constants.SUBJECT_PUBLIC)); publicAccessRule.addPermission(Permission.CHANGE_PERMISSION); AccessRule testPersonAccessRule = new AccessRule(); getSession("testPerson"); testPersonAccessRule.addSubject(getSubject("testPerson")); testPersonAccessRule.addPermission(Permission.CHANGE_PERMISSION); AccessRule testRightsHolderAccessRule = new AccessRule(); getSession("testRightsHolder"); testRightsHolderAccessRule.addSubject(getSubject("testRightsHolder")); testRightsHolderAccessRule.addPermission(Permission.CHANGE_PERMISSION); for (int i=0; i errors = new ArrayList(); for (int i=0; i 0) { String errorString = ""; for (String err : errors) errorString += err + "\n"; throw new AssertionError("testCnGetLogRecords_Access ran into " + errors.size() + " errors:\n" + errorString); } } }