/**
* 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.v2.CNode;
import org.dataone.client.v2.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.v2.Node;
import org.dataone.service.types.v2.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:
* Similarly, HEAD requests don't return message bodies, so "describe" will fail miserably, too.
* the parameter key for the implementation is deduced from the parameter type,
* which for the most part works, but not always. After a couple times, it's easy
* to spot the real failures from the fake, but eventually, the tests should account
* for these parameter naming exceptions.
* Our current implementation of the echo service has been specially configured
* to handle http PUT methods, so the following is just for awareness. However, by default
* a django echo server doesn't return message body information from http PUTs.
* In this case, methods using PUT would return more errors than
* they should. In that case, manual inspection of the code is needed for validating
* the method. To help the tester, there's a static property "ignorePUTexceptions"
* that can be set to true after doing those manual checks.
* Overridden methods may not be properly mapped.
*
*
* 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 ClientArchitectureConformityIT {
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(ClientArchitectureConformityIT.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 ClientArchitectureConformityIT(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.V2_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(CNode.class,
MRC,URI.create(TEST_SERVICE_BASE + EXCEPTION_SERVICE +
"/" + exception)); // + "/v1/object");
method = getCNInterfaceMethods().get(currentMethodKey);
} else {
d1node = D1NodeFactory.buildNode(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;
}
});
}
}