/** * This work was created by participants in the DataONE project, and is * jointly copyrighted by participating institutions in DataONE. For * more information on DataONE, see our web site at http://dataone.org. * * Copyright ${year} * * Licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0 * * 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. * * $Id$ */ package org.dataone.client; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.math.BigInteger; import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.TreeSet; import java.util.concurrent.Callable; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dataone.client.exception.ClientSideException; import org.dataone.client.rest.HttpMultipartRestClient; import org.dataone.client.rest.MultipartRestClient; import org.dataone.client.v1.types.D1TypeBuilder; import org.dataone.client.v1.CNode; import org.dataone.client.v1.MNode; import org.dataone.configuration.Settings; import org.dataone.service.exceptions.BaseException; import org.dataone.service.exceptions.NotImplemented; import org.dataone.service.exceptions.ServiceFailure; import org.dataone.service.exceptions.SynchronizationFailed; import org.dataone.service.types.v1.Checksum; import org.dataone.service.types.v1.Group; import org.dataone.service.types.v1.Identifier; import org.dataone.service.types.v1.NodeReference; import org.dataone.service.types.v1.NodeState; import org.dataone.service.types.v1.NodeType; import org.dataone.service.types.v1.Permission; import org.dataone.service.types.v1.Person; import org.dataone.service.types.v1.Replica; import org.dataone.service.types.v1.ReplicationStatus; import org.dataone.service.types.v1.Subject; import org.dataone.service.types.v1.Node; import org.dataone.service.types.v1.SystemMetadata; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ErrorCollector; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; /** * This test case parses the MethodCrossReference.xls found on the dataONE architecture * site to get information about methods expected to be implemented, and then uses * introspection on the client package to get method information on the actual * implementations. It also calls out to an echo service which returns information * on the message body sent by the implementation, to compare the behavior of * the implementations versus what's expected. For example, testing whether method * parameters get properly placed in file-parts, param-parts, the URL path, or the URL * query string. *

* Current weaknesses:

* * These tests run using a Parameterized JUnit runner, and I haven't figured out * how to have eclipse run just one method, so you'll probably have to run it * at the class level. Each parameterized test tests one aspect of "conformity" * for a given method, and the set of tests is run multiple times, basically once * for each method of the api. Note however that if the signatures don't match between * documented and implementation, separate iterations will exist for both. * * * @author rnahf * */ @RunWith(value = Parameterized.class) public class V1ClientArchitectureConformityIT { private static boolean ignorePUTexceptions = false; /* configuration information for the echo service */ protected static final String TEST_SERVICE_BASE = "http://dev-testing.dataone.org/testsvc"; protected static final String ECHO_MMP = "/echomm"; protected static final String EXCEPTION_SERVICE = "/exception"; protected static String pathInfoBase; private static MultipartRestClient MRC; protected static Log log = LogFactory.getLog(V1ClientArchitectureConformityIT.class); private static String methodMatchPattern = System.getenv("test.method.match"); private static HashMap>> methodMap; /* lists of methods to hold the client interface methods */ private static HashMap clientMethodMapMN; private static HashMap clientMethodMapCN; private static List d1ExceptionList; private String currentMethodKey; private NodeType nodeType; public V1ClientArchitectureConformityIT(String methodKey) { if (methodKey.startsWith("CN.")) { this.nodeType = NodeType.CN; } else if (methodKey.startsWith("MN.")) { this.nodeType = NodeType.MN; } else { this.nodeType = null; } this.currentMethodKey = methodKey; } /** * Tests should use the error collector to handle JUnit assertions * and keep going. The check methods in this class use this errorCollector * the check methods */ @Rule public ErrorCollector errorCollector = new ErrorCollector(); @BeforeClass public static void setUp() throws IOException, ClientSideException { Settings.getConfiguration().setProperty("D1Client.useLocalCache","false"); Settings.getConfiguration().setProperty("CNode.useObjectFormatCache","false"); MRC = new HttpMultipartRestClient(); } @Parameters public static Collection setUpTestParameters() throws IOException { methodMap = ArchitectureUtils.setUpMethodDocumentationMap(ArchitectureUtils.V1_METHOD_REFERENCE_DOC); // creating a superset of methodKeys - if it exists in documentation or // implementation we're gonna test it TreeSet methodKeys = new TreeSet(getCNInterfaceMethods().keySet()); methodKeys.addAll(new TreeSet(getMNInterfaceMethods().keySet())); methodKeys.addAll(new TreeSet(methodMap.keySet())); // create the return data structure ArrayList paramList = new ArrayList(); if (methodMatchPattern != null) { for (String key : methodKeys) { if (key.matches(methodMatchPattern)) { paramList.add(new Object[] {key}); } } } else { for (String key : methodKeys) { paramList.add(new Object[] {key}); } } return paramList; } // @Test public void testHarness() { assertTrue("test", true); } /** * want to test a particularly confusing bit of logic for the path matching test * Note, (String).matches() method will only return true if the pattern includes * the entire String under test. */ // @Test public void testEscapedPattern() { String x = "/werth/rtyudfgh/xcvbg/{pid}"; String pathPattern = x.replaceAll("\\{\\w+\\}", "\\\\w+\\$"); String y = "/werth/rtyudfgh/xcvbg/testIdentifier"; assertTrue("backslash pattern in replace should find target", y.matches(pathPattern)); } /** * method to generate unique meaningful key for each method. The key includes parameters * in order to weed out non-interface methods from list of implemented methods */ private static String buildMethodListKey(Method method) { String methodString = method.toString(); // remove the class, package and return type from the beginning String qualifiedName = methodString.substring(methodString.indexOf(method.getName()+"(")); // remove the "throws" clause return qualifiedName.replaceAll("\\sthrows\\s.*", ""); } private static HashMap getCNInterfaceMethods() { if (clientMethodMapCN == null) { // build a list of interface methods for the class under test ArrayList interfaceMethodList = new ArrayList(); Class[] interfaces = CNode.class.getInterfaces(); for (Class c : interfaces) { if (c.getSimpleName().equals("D1Node")) continue; log.info("Interface under test: " + c.getName()); Method[] methods = c.getMethods(); for (Method m : methods) { log.debug(" Method from interface: " + m.getName()); interfaceMethodList.add(buildMethodListKey(m)); } } Method[] methods = CNode.class.getMethods(); // gets only public methods HashMap clientInterfaceMethods = new HashMap(); for (Method method : methods) { String methodKey = buildMethodListKey(method); if (interfaceMethodList.contains(methodKey)) { String methodMapKey = "CN." + method.getName(); clientInterfaceMethods.put(methodMapKey,method); } } clientMethodMapCN = clientInterfaceMethods; } return clientMethodMapCN; } private static HashMap getMNInterfaceMethods() { if (clientMethodMapMN == null) { // build a list of interface methods for the class under test ArrayList interfaceMethodList = new ArrayList(); Class[] interfaces = MNode.class.getInterfaces(); for (Class c : interfaces) { if (c.getSimpleName().equals("D1Node")) continue; log.info("Interface under test: " + c.getName()); Method[] methods = c.getMethods(); for (Method m : methods) { log.debug(" Method from interface: " + m.getName()); interfaceMethodList.add(buildMethodListKey(m)); } } Method[] methods = MNode.class.getMethods(); // gets only public methods HashMap clientInterfaceMethods = new HashMap(); for (Method method : methods) { log.debug(" Method from classes: " + method.getName()); String methodKey = buildMethodListKey(method); if (interfaceMethodList.contains(methodKey)) { String methodMapKey = "MN." + method.getName(); clientInterfaceMethods.put(methodMapKey,method); } } clientMethodMapMN = clientInterfaceMethods; } return clientMethodMapMN; } private static List getD1Exceptions() throws IOException, ClassNotFoundException { if (d1ExceptionList == null) { String packageName = BaseException.class.getPackage().getName(); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); assert classLoader != null; String path = packageName.replace('.', '/'); Enumeration resources = classLoader.getResources(path); List dirs = new ArrayList(); while (resources.hasMoreElements()) { URL resource = resources.nextElement(); dirs.add(new File(resource.getFile())); } ArrayList classes = new ArrayList(); for (File directory : dirs) { classes.addAll(findClasses(directory, packageName)); } classes.remove("BaseException"); d1ExceptionList = classes; } return d1ExceptionList; } /** * Recursive method used to find all classes in a given directory and subdirs. * * @param directory The base directory * @param packageName The package name for classes found inside the base directory * @return The classes * @throws ClassNotFoundException */ private static List findClasses(File directory, String packageName) throws ClassNotFoundException { List classes = new ArrayList(); if (!directory.exists()) { return classes; } File[] files = directory.listFiles(); for (File file : files) { if (file.isDirectory()) { assert !file.getName().contains("."); classes.addAll(findClasses(file, packageName + "." + file.getName())); } else if (file.getName().endsWith(".class")) { classes.add(file.getName().substring(0, file.getName().length() - 6)); } } return classes; } @Test public void testMethodIsDocumented() { checkTrue(currentMethodKey,"method should be documented.", methodMap.containsKey(currentMethodKey)); } @Test public void testMethodIsImplemented() { checkTrue(currentMethodKey,"method should be implemented.", getCNInterfaceMethods().containsKey(currentMethodKey) || getMNInterfaceMethods().containsKey(currentMethodKey) ); } @Test public void testMethodParameterAgreement() { List docParamTypes = methodMap.get(currentMethodKey).get("paramTypes"); Class[] implParamTypes = null; if (nodeType == NodeType.CN) { implParamTypes = getCNInterfaceMethods().get(currentMethodKey).getParameterTypes(); } else if (nodeType == NodeType.MN) { implParamTypes = getMNInterfaceMethods().get(currentMethodKey).getParameterTypes(); } else { handleFail(currentMethodKey,"bad nodeType value: " + nodeType.xmlValue()); } // make null equal to zero size list, to avoid null pointer exceptions if (implParamTypes == null) { implParamTypes = new Class[]{}; } if (docParamTypes == null) { docParamTypes = new ArrayList(); } // check that there are equal number of parameters // checkEquals(currentMethodKey,"number of parameters in implemented method should match " + // "number of parameters in documentation", implParamTypes.length, docParamTypes.size()); // now that we are not putting the session object in api parameters, but still // have it listed in the documentation, it's more difficult to compare the number // of parameters, so need to detect in the impl, and account for it. boolean implHasSession = false; for (Class type: implParamTypes) { if (type.getSimpleName().equals("Session")) { implHasSession = true; break; } } boolean docHasSession = false; for (String type: docParamTypes) { if (type.equals("Session")) { docHasSession = true; break; } } int sessionCorrection = 0; if (docHasSession && !implHasSession) { sessionCorrection = 1; // // need to adjust the position in the array, too // class[] tmp = new class[implparamtypes.length+1]; // tmp[0] = session.class; // for (int i = 1; i docReturnType = methodMap.get(currentMethodKey).get("returnType"); Class implReturnType = null; if (nodeType == NodeType.CN) { implReturnType = getCNInterfaceMethods().get(currentMethodKey).getReturnType(); } else if (nodeType == NodeType.MN) { implReturnType = getMNInterfaceMethods().get(currentMethodKey).getReturnType(); } else { handleFail(currentMethodKey,"bad nodeType value: " + nodeType.xmlValue()); } String expectedReturnType = currentMethodKey.endsWith("ping") ? "Date" : docReturnType.get(0); // check that types agree String returnTypeSimpleName = implReturnType.getSimpleName(); // don't have to worry about arrays checkTrue(currentMethodKey, String.format("Implemented return type (%s) should match documented type (%s)", returnTypeSimpleName, expectedReturnType), ArchitectureUtils.checkDocTypeEqualsJavaType( expectedReturnType, returnTypeSimpleName) ); } /** * Tests that the documented http verb is the one returned by the echo service. * Expect HEAD requests to return null (because they can't take message bodies); */ @Test public void testHttpVerb() { String exceptionLocation = null; try { exceptionLocation = "getEchoResponse"; String echoResponse = getEchoResponse(ECHO_MMP); exceptionLocation = "get verb from documentMap"; String docVerb = methodMap.get(currentMethodKey).get("verb").get(0); if (docVerb.equals("HEAD")) { checkEquals(currentMethodKey, "HEAD method will return 'null'", getVerb(echoResponse), null); } else { checkEquals(currentMethodKey, "method verb should agree", getVerb(echoResponse), docVerb); } } catch (Exception e) { e.printStackTrace(); handleFail(currentMethodKey,"unexpected error at '" + exceptionLocation + "' " + e.getClass().getName() + ": " + e.getMessage()); } } @Test public void testPath() { String exceptionLocation = null; // head requests don't return from the echo service, so can't test exceptions if (!methodMap.get(currentMethodKey).get("verb").get(0).equalsIgnoreCase("HEAD")) { try { // create pattern from docMap path entry to match against echo response exceptionLocation = "creating pathMatch"; String pathMatch = pathInfoBase + methodMap.get(currentMethodKey).get("path").get(0).replaceAll("\\{\\w+\\}", "\\\\w+") + "$"; log.debug("testPath() pathMatch: " + pathMatch); exceptionLocation = "getEchoResponse"; String echoResponse = getEchoResponse(ECHO_MMP); checkTrue(currentMethodKey, "path_info should be matched by " + pathMatch + ". got: " + getUrlPath(echoResponse), verifyUrlPath(pathMatch, echoResponse)); } catch (Exception e) { e.printStackTrace(); handleFail(currentMethodKey,"unexpected error at " + exceptionLocation + " " + e.getClass().getName() + ": " + e.getMessage()); } } } @Test public void testMethodParameters() { String exceptionLocation = null; // head requests don't return from the echo service, so can't test exceptions if (!methodMap.get(currentMethodKey).get("verb").get(0).equalsIgnoreCase("HEAD")) { // catch all exceptions into errorHandler try { exceptionLocation = "getEchoResponse"; String echoResponse = getEchoResponse(ECHO_MMP); if (methodMap.containsKey(currentMethodKey)) { ArrayList parameters = (ArrayList) methodMap.get(currentMethodKey).get("params"); ArrayList paramTypes = (ArrayList) methodMap.get(currentMethodKey).get("paramTypes"); ArrayList paramLocation = (ArrayList) methodMap.get(currentMethodKey).get("paramLocation"); if (parameters != null && paramTypes != null) { Pattern pat = Pattern.compile("(\\w+).*"); if (parameters.size() != paramTypes.size()) { handleFail(currentMethodKey,"documentation error: the number of params" + " and paramTypes in the documentation are not equal."); } else { int i = 0; for (String param : parameters) { if (param == null || param.trim().isEmpty()) continue; // get the corresponding type from paramType // pick out the param name from the text String paramType = null; String expectedLocation = null; if (paramTypes != null) { paramType = paramTypes.get(i); expectedLocation = paramLocation.get(i++); // session is not sent in the echo test so need to force a match if (paramType.equalsIgnoreCase("Session")) { expectedLocation = null; } } Matcher matcher = pat.matcher(param); String paramKey = null; if (matcher.find()) { paramKey = matcher.group(1); } String actualLocation = findParameterLocation(echoResponse,paramKey,"test" + paramType); // String expectedLocation = calcExpectedParamLocation(paramKey,paramType,currentMethodKey); String echoedVerb = getVerb(echoResponse); if (expectedLocation != null && (expectedLocation.equals("File") || expectedLocation.equals("Param")) && (echoedVerb.equals("PUT") || echoedVerb.equals("DELETE")) && actualLocation == null) { if (!ignorePUTexceptions) { handleFail(currentMethodKey, String.format("%s operation: parameter '%s' " + "is expected to be in a file or param part, but cannot be properly tested " + "in a %s operation against the echo service. (actual location WAS null)", echoedVerb, paramKey, echoedVerb)); } } else { checkEquals(currentMethodKey, "parameter '" + paramKey + "' is not in expected location", actualLocation, expectedLocation); } } } } } else { handleFail(currentMethodKey, "did not find method in documentation map"); } } catch (Exception e) { e.printStackTrace(); handleFail(currentMethodKey,"unexpected error at " + exceptionLocation + " " + e.getClass().getName() + ": " + e.getMessage()); } } } /** * Check the method against all D1 exceptions. If it's supposed to be thrown * according to the documentation, */ @Test public void testMethodExceptionHandling() { log.info("::::::: checkExceptionHandling vs. " + currentMethodKey); // head requests don't return from the echo service, so can't test exceptions if (!methodMap.get(currentMethodKey).get("verb").get(0).equalsIgnoreCase("HEAD")) { String exceptionName = null; try { ArrayList docExceptions = (ArrayList) methodMap.get(currentMethodKey).get("exceptions"); // ArrayList implExList = new ArrayList(); // Class[] implExceptions = null; // if (nodeType.equals(NodeType.CN)) { // implExceptions = getCNInterfaceMethods().get(currentMethodKey).getExceptionTypes(); // } else if (nodeType.equals(NodeType.MN)) { // implExceptions = getMNInterfaceMethods().get(currentMethodKey).getExceptionTypes(); // } else { // handleFail(currentMethodKey,"test misconfiguration - NodeType is " + nodeType); // } // // for (Class exceptionClass : implExceptions) { // implExList.add(exceptionClass.getClass().getSimpleName()); // } List d1ExceptionList = getD1Exceptions(); for (String d1Exception : d1ExceptionList) { if (d1Exception.equals("SynchronizationFailed")) { log.info(" : : : : : SKIPPING: " + d1Exception); continue; } log.info(" : : : : : checking: " + d1Exception); String actualException = getExceptionResponse(d1Exception); if (docExceptions.contains(d1Exception)) { checkEquals(currentMethodKey, "method should throw exception '" + d1Exception + "'", actualException, d1Exception); } else { checkEquals(currentMethodKey, "method should recast '" + d1Exception + "' to 'ServiceFailure'", actualException, "ServiceFailure"); } } } catch (Exception e) { e.printStackTrace(); handleFail(currentMethodKey,"unexpected error at " + exceptionName + " " + e.getClass().getName() + ": " + e.getMessage()); } } } private String getEchoResponse(String testResource) throws ClientSideException { String echoResponse = null; D1Node d1node = null; if (nodeType.equals(NodeType.CN)) { d1node = D1NodeFactory.buildNode(CNode.class, MRC,URI.create(TEST_SERVICE_BASE + testResource)); echoResponse = getEchoResponse(d1node,getCNInterfaceMethods().get(currentMethodKey)); } else { d1node = D1NodeFactory.buildNode(MNode.class, MRC,URI.create(TEST_SERVICE_BASE + testResource)); echoResponse = getEchoResponse(d1node,getMNInterfaceMethods().get(currentMethodKey)); } pathInfoBase = d1node.getNodeBaseServiceUrl().replaceAll(TEST_SERVICE_BASE, ""); log.info("set PATH_INFO base (prefix): " + pathInfoBase); return echoResponse; } /** * expect the echo service to return an http status in the 400s * whereupon the client exception handler will not be able to * parse the response into a d1 exception, and will instead wrap * the response text into a ServiceFailure. * * @param d1node - either a CN or MN instance intended to be called by * the passed in method. * @param method - the method object that will be invoked * @return - the response from the echo service */ private String getEchoResponse(D1Node d1node, Method method) { String echoResponse = null; try { Object[] paramObjects = buildParameterObjectInstances(method); method.invoke(d1node,paramObjects); } catch (InvocationTargetException e) { if (!(e.getCause() instanceof ServiceFailure)) { e.printStackTrace(); handleFail("","Error invoking method " + method.getName()); } else { ServiceFailure sf = (ServiceFailure) e.getCause(); echoResponse = "\ndetail code = " + sf.getDetail_code() + "\n" + sf.getDescription(); } } catch (Exception e) { log.debug("invocation class: " + d1node.getClass()); log.debug("class of method being invoked: " + method.getDeclaringClass()); e.printStackTrace(); handleFail(buildMethodListKey(method),"Error building parameters for or invoking method " + method.getName()); } log.debug("echo response: " + echoResponse); return echoResponse; } private String getExceptionResponse(String exception) throws Exception { String exceptionReturned = null; D1Node d1node = null; Method method = null; log.debug(" - - - - calling " + TEST_SERVICE_BASE + EXCEPTION_SERVICE + "/" + exception); if (nodeType.equals(NodeType.CN)) { d1node = D1NodeFactory.buildNode(org.dataone.client.v1.CNode.class, MRC,URI.create(TEST_SERVICE_BASE + EXCEPTION_SERVICE + "/" + exception)); // + "/v1/object"); method = getCNInterfaceMethods().get(currentMethodKey); } else { d1node = D1NodeFactory.buildNode(org.dataone.client.v1.MNode.class, MRC,URI.create(TEST_SERVICE_BASE + EXCEPTION_SERVICE + "/" + exception)); // + "/v1/object"); method = getMNInterfaceMethods().get(currentMethodKey); } try { Object[] paramObjects = buildParameterObjectInstances(method); method.invoke(d1node,paramObjects); } catch (InvocationTargetException e) { log.debug("exceptionReturned: " + ((BaseException)e.getCause()).getDescription()); exceptionReturned = e.getCause().getClass().getSimpleName(); } return exceptionReturned; } private Object[] buildParameterObjectInstances(Method method) throws Exception { Class[] params = method.getParameterTypes(); Object[] paramObjects = new Object[params.length]; for (int i = 0; i c) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, SecurityException, NoSuchMethodException, UnsupportedEncodingException { Object o = null; if (c.getCanonicalName().equals("java.io.InputStream")) { byte[] contentBytes = "some input for the stream".getBytes("UTF-8"); o = new ByteArrayInputStream(contentBytes); } else if (c.getCanonicalName().equals("long")) { o = 0; } else if (c.getCanonicalName().equals("java.lang.Integer")) { o = new Integer(1); } else if (c.getCanonicalName().equals("java.lang.Boolean")) { o = new Boolean(true); } else if (c.getCanonicalName().equals("java.lang.String")) { o = new String("testString"); // dataone types needing special instruction (required fields in xsd) } else if (c.getCanonicalName().endsWith("BaseException")) { o = new NotImplemented("detailCodeString","descriptionString"); } else if (c.getCanonicalName().endsWith("Event")) { o = org.dataone.service.types.v1.Event.READ; } else if (c.getCanonicalName().endsWith("Permission")) { o = Permission.READ; } else if (c.getCanonicalName().endsWith("ReplicationStatus")) { o = ReplicationStatus.COMPLETED; } else if (c.getCanonicalName().endsWith("SystemMetadata")) { Identifier id = new Identifier(); id.setValue("testIdentifier"); SystemMetadata smd = new SystemMetadata(); smd.setIdentifier(id); smd.setOriginMemberNode(D1TypeBuilder.buildNodeReference("nodeIdString")); smd.setAuthoritativeMemberNode(D1TypeBuilder.buildNodeReference("nodeIdString")); smd.setFormatId(D1TypeBuilder.buildFormatIdentifier("text/plain")); smd.setSubmitter(D1TypeBuilder.buildSubject("submitterString")); smd.setSerialVersion(BigInteger.ONE); smd.setSize(BigInteger.TEN); smd.setDateSysMetadataModified(new Date()); smd.setDateUploaded(new Date()); smd.setChecksum(new Checksum()); smd.getChecksum().setAlgorithm("MD5"); smd.getChecksum().setValue("asqweroivlksjklrwe452398opvds9fdcvoipefnwr"); smd.setRightsHolder(D1TypeBuilder.buildSubject("rightsHolderString")); o = smd; } else if (c.getCanonicalName().endsWith("SynchronizationFailed")) { o = new SynchronizationFailed("detailCodeString","descriptionString"); // } else { Constructor co = c.getConstructor(new Class[]{}); o = co.newInstance((Object[]) null); log.debug("created :" + o.getClass()); try { Method mm = c.getMethod("setValue", new Class[]{String.class}); mm.invoke(o, "test" + c.getSimpleName()); log.debug(" setValue : test" + c.getSimpleName()); } catch (NoSuchMethodException e) { // ok, object doesn't have that method... } } // post-instantiation modifications if (c.getCanonicalName().endsWith("Node")) { NodeReference nr = new NodeReference(); nr.setValue("testNodeReference"); ((Node)o).setIdentifier(nr); ((Node)o).setName("fako"); ((Node)o).setDescription("blah blah blah"); ((Node)o).setBaseURL("somewhere over the rainbow"); ((Node)o).setType(NodeType.MN); ((Node)o).setState(NodeState.UP); } else if (c.getCanonicalName().endsWith("Person")) { Subject s = new Subject(); s.setValue("testSubject"); ((Person)o).setSubject(s); ((Person)o).setGivenNameList(Arrays.asList(new String[]{"Sleepy"})); ((Person)o).setFamilyName("Dwarf"); } else if (c.getCanonicalName().endsWith("Group")) { Subject s = new Subject(); s.setValue("testSubject"); ((Group)o).setSubject(s); ((Group)o).setGroupName("testGroupName"); ((Group)o).setRightsHolderList(Arrays.asList(new Subject[]{s})); } else if (c.getCanonicalName().endsWith("Replica")) { NodeReference nf = new NodeReference(); nf.setValue("testNodeReference"); ((Replica)o).setReplicaMemberNode(nf); ((Replica)o).setReplicationStatus(ReplicationStatus.REQUESTED); ((Replica)o).setReplicaVerified(new Date()); } return o; } private String findParameterLocation(String echoText,String parameterName, String paramTestObject) { String[] textLines = echoText.split("\n"); String location = null; String pathLocation = null; for (String line : textLines) { if (line.contains(parameterName)) { if (line.startsWith("request.META[ QUERY_STRING ]")) { location = "Query"; break; } else if (line.startsWith("request.POST=() { public Object call() throws Exception { if (host != null) { assertThat("for method: " + host + ":: " + message, s1, is(s2)); } else { assertThat(message, s1, is(s2)); } return null; } }); } public void checkEquals(final String host, final String message, final int s1, final int s2) { errorCollector.checkSucceeds(new Callable() { public Object call() throws Exception { if (host != null) { assertThat("for method: " + host + ":: " + message, s1, is(s2)); } else { assertThat(message, s1, is(s2)); } return null; } }); } public void checkTrue(final String host, final String message, final boolean b) { errorCollector.checkSucceeds(new Callable() { public Object call() throws Exception { if (host != null) { assertThat("for method: " + host + ":: " + message, b, is(true)); } else { assertThat(message, b, is(true)); } return null; } }); } public void handleFail(final String host, final String message) { errorCollector.checkSucceeds(new Callable() { public Object call() throws Exception { if (host != null) { fail("for method: " + host + ":: " + message); } else { fail(message); } return null; } }); } }