From a667c2f40e9139d05b23d41d31a9d7ea8e9f827d Mon Sep 17 00:00:00 2001 From: Aron Roberts Date: Mon, 14 Jun 2010 20:44:06 +0000 Subject: [PATCH] CSPACE-2128: Added initial (albeit minimal) prototype client test of keyword / full text search to the CollectionObject service. --- .../client/test/ServiceRequestType.java | 33 ++ .../client/CollectionObjectProxy.java | 3 +- .../test/CollectionObjectSearchTest.java | 282 ++++++++++++++++++ 3 files changed, 316 insertions(+), 2 deletions(-) create mode 100644 services/collectionobject/client/src/test/java/org/collectionspace/services/client/test/CollectionObjectSearchTest.java diff --git a/services/client/src/main/java/org/collectionspace/services/client/test/ServiceRequestType.java b/services/client/src/main/java/org/collectionspace/services/client/test/ServiceRequestType.java index 92de8f039..b5a80b567 100644 --- a/services/client/src/main/java/org/collectionspace/services/client/test/ServiceRequestType.java +++ b/services/client/src/main/java/org/collectionspace/services/client/test/ServiceRequestType.java @@ -214,6 +214,39 @@ public enum ServiceRequestType { return javax.ws.rs.HttpMethod.DELETE; } }, + SEARCH { + + @Override + public int[] validStatusCodes() { + final int[] STATUS_CODES = { + Response.Status.OK.getStatusCode(), + Response.Status.UNAUTHORIZED.getStatusCode(), + Response.Status.FORBIDDEN.getStatusCode(), + Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() + }; + Arrays.sort(STATUS_CODES); + return STATUS_CODES; + } + + @Override + public boolean isValidStatusCode(int statusCode) { + if (Arrays.binarySearch(SEARCH.validStatusCodes(), statusCode) >= 0) { + return true; + } else { + return false; + } + } + + @Override + public String validStatusCodesAsString() { + return Arrays.toString(SEARCH.validStatusCodes()); + } + + @Override + public String httpMethodName() { + return javax.ws.rs.HttpMethod.GET; + } + }, // Used by guard code. NON_EXISTENT { diff --git a/services/collectionobject/client/src/main/java/org/collectionspace/services/client/CollectionObjectProxy.java b/services/collectionobject/client/src/main/java/org/collectionspace/services/client/CollectionObjectProxy.java index b6e2941b0..23ff39381 100644 --- a/services/collectionobject/client/src/main/java/org/collectionspace/services/client/CollectionObjectProxy.java +++ b/services/collectionobject/client/src/main/java/org/collectionspace/services/client/CollectionObjectProxy.java @@ -101,10 +101,9 @@ public interface CollectionObjectProxy extends CollectionSpaceProxy { * @return the client response */ @GET - @Path("/search") @Produces({"application/xml"}) ClientResponse keywordSearch( - @QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS) String keywords); + @QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_KW) String keywords); //(C)reate /** diff --git a/services/collectionobject/client/src/test/java/org/collectionspace/services/client/test/CollectionObjectSearchTest.java b/services/collectionobject/client/src/test/java/org/collectionspace/services/client/test/CollectionObjectSearchTest.java new file mode 100644 index 000000000..008bae5a8 --- /dev/null +++ b/services/collectionobject/client/src/test/java/org/collectionspace/services/client/test/CollectionObjectSearchTest.java @@ -0,0 +1,282 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + * + * http://www.collectionspace.org + * http://wiki.collectionspace.org + * + * Copyright © 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * 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. + */ +package org.collectionspace.services.client.test; + +import java.util.ArrayList; +import java.util.List; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.collectionspace.services.client.CollectionObjectClient; +import org.collectionspace.services.client.CollectionSpaceClient; +import org.collectionspace.services.collectionobject.CollectionobjectsCommon; +import org.collectionspace.services.collectionobject.CollectionobjectsCommonList; +import org.collectionspace.services.jaxb.AbstractCommonList; +import org.jboss.resteasy.client.ClientResponse; +import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput; +import org.jboss.resteasy.plugins.providers.multipart.OutputPart; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * CollectionObjectAuthRefsTest, carries out tests against a + * deployed and running CollectionObject Service. + * + * $LastChangedRevision: 1327 $ + * $LastChangedDate: 2010-02-12 10:35:11 -0800 (Fri, 12 Feb 2010) $ + */ +public class CollectionObjectSearchTest extends BaseServiceTest { + + /** The logger. */ + private final String CLASS_NAME = CollectionObjectSearchTest.class.getName(); + private final Logger logger = LoggerFactory.getLogger(CLASS_NAME); + + final static String KEYWORD = "Tsolyani"; + // final static String[] TWO_KEYWORDS = {"Cheggarra", "Ahoggya"}; + final static String NOISE_WORD = "Mihalli"; + final static String NON_EXISTENT_KEYWORD = "jlmbsoqjlmbsoq"; + + /* Use this to keep track of resources to delete */ + private List allResourceIdsCreated = new ArrayList(); + + /* (non-Javadoc) + * @see org.collectionspace.services.client.test.BaseServiceTest#getServicePathComponent() + */ + @Override + protected String getServicePathComponent() { + return new CollectionObjectClient().getServicePathComponent(); + } + + /* (non-Javadoc) + * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance() + */ + @Override + protected CollectionSpaceClient getClientInstance() { + return new CollectionObjectClient(); + } + + /* (non-Javadoc) + * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse) + */ + @Override + protected AbstractCommonList getAbstractCommonList(ClientResponse response) { + return response.getEntity(CollectionobjectsCommonList.class); + } + + /** + * Creates one or more resources containing a "noise" keyword, + * which should NOT be retrieved by keyword searches. + */ + @BeforeClass(alwaysRun=true) + public void setup() { + long numNoiseWordResources = 2; + if (logger.isDebugEnabled()) { + logger.debug("Creating " + numNoiseWordResources + + " 'noise word' resources ..."); + } + createCollectionObjects(numNoiseWordResources, NOISE_WORD); + } + + + // --------------------------------------------------------------- + // Search tests + // --------------------------------------------------------------- + + // Success outcomes + + @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class) + public void keywordSearchOneWord(String testName) throws Exception { + + if (logger.isDebugEnabled()) { + logger.debug(testBanner(testName, CLASS_NAME)); + } + + // Create one or more keyword retrievable resources, each containing + // a specified keyword. + long numKeywordRetrievableResources = 3; + if (logger.isDebugEnabled()) { + logger.debug("Creating " + numKeywordRetrievableResources + + " keyword-retrievable resources ..."); + } + createCollectionObjects(numKeywordRetrievableResources, KEYWORD); + + testSetup(STATUS_OK, ServiceRequestType.SEARCH); + if (logger.isDebugEnabled()) { + logger.debug("Searching on keyword(s): " + KEYWORD + " ..."); + } + CollectionObjectClient client = new CollectionObjectClient(); + ClientResponse res = + client.keywordSearch(KEYWORD); + int statusCode = res.getStatus(); + + // Check the status code of the response: does it match + // the expected response(s)? + if (logger.isDebugEnabled()) { + logger.debug(testName + ": status = " + statusCode); + } + Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode), + invalidStatusCodeMessage(REQUEST_TYPE, statusCode)); + + CollectionobjectsCommonList list = (CollectionobjectsCommonList) + res.getEntity(CollectionobjectsCommonList.class); + long numMatched = list.getTotalItems(); + + if (logger.isDebugEnabled()) { + logger.debug("Keyword search matched " + numMatched + + " resources, expected to match " + numKeywordRetrievableResources); + } + + // Optionally output additional data about list members for debugging. + boolean iterateThroughList = false; + if (iterateThroughList && logger.isDebugEnabled()) { + itemizeListItems(list); + } + + Assert.assertEquals(numMatched, numKeywordRetrievableResources); + + } + + // @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class) + public void keywordSearchRepeatableScalarField(String testName) throws Exception { + } + + private void createCollectionObjects(long numToCreate, String keywords) { + testSetup(STATUS_CREATED, ServiceRequestType.CREATE); + CollectionObjectClient client = new CollectionObjectClient(); + for (long i = 0; i < numToCreate; i++) { + MultipartOutput multipart = createCollectionObjectInstance(keywords); + ClientResponse res = client.create(multipart); + try { + int statusCode = res.getStatus(); + Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE); + allResourceIdsCreated.add(extractId(res)); + } finally { + res.releaseConnection(); + } + } + } + + private MultipartOutput createCollectionObjectInstance(String keywords) { + CollectionobjectsCommon collectionObject = new CollectionobjectsCommon(); + collectionObject.setObjectNumber(createIdentifier()); + collectionObject.setTitle(keywords); + MultipartOutput multipart = new MultipartOutput(); + OutputPart commonPart = multipart.addPart(collectionObject, + MediaType.APPLICATION_XML_TYPE); + commonPart.getHeaders().add("label", new CollectionObjectClient().getCommonPartName()); + return multipart; + } + + // Failure outcomes + + @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class) + public void keywordSearchNonExistentKeyword(String testName) throws Exception { + + if (logger.isDebugEnabled()) { + logger.debug(testBanner(testName, CLASS_NAME)); + } + + final long NUM_MATCHES_EXPECTED = 0; + + testSetup(STATUS_OK, ServiceRequestType.SEARCH); + if (logger.isDebugEnabled()) { + logger.debug("Searching on keyword(s): " + NON_EXISTENT_KEYWORD + " ..."); + } + CollectionObjectClient client = new CollectionObjectClient(); + ClientResponse res = + client.keywordSearch(NON_EXISTENT_KEYWORD); + int statusCode = res.getStatus(); + + // Check the status code of the response: does it match + // the expected response(s)? + if (logger.isDebugEnabled()) { + logger.debug(testName + ": status = " + statusCode); + } + Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode), + invalidStatusCodeMessage(REQUEST_TYPE, statusCode)); + + CollectionobjectsCommonList list = (CollectionobjectsCommonList) + res.getEntity(CollectionobjectsCommonList.class); + long numMatched = list.getTotalItems(); + + if (logger.isDebugEnabled()) { + logger.debug("Keyword search matched " + numMatched + + " resources, expected to match " + NUM_MATCHES_EXPECTED); + } + + Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED); + + } + + // --------------------------------------------------------------- + // Cleanup of resources created during testing + // --------------------------------------------------------------- + + /** + * Deletes all resources created by tests, after all tests have been run. + * + * This cleanup method will always be run, even if one or more tests fail. + * For this reason, it attempts to remove all resources created + * at any point during testing, even if some of those resources + * may be expected to be deleted by certain tests. + */ + @AfterClass(alwaysRun=true) + public void cleanUp() { + String noTest = System.getProperty("noTestCleanup"); + if(Boolean.TRUE.toString().equalsIgnoreCase(noTest)) { + if (logger.isDebugEnabled()) { + logger.debug("Skipping Cleanup phase ..."); + } + return; + } + if (logger.isDebugEnabled()) { + logger.debug("Cleaning up temporary resources created for testing ..."); + } + CollectionObjectClient collectionObjectClient = new CollectionObjectClient(); + for (String resourceId : allResourceIdsCreated) { + // Note: Any non-success responses are ignored and not reported. + collectionObjectClient.delete(resourceId).releaseConnection(); + } + } + + // --------------------------------------------------------------- + // Utility methods used by tests above + // --------------------------------------------------------------- + + private void itemizeListItems(CollectionobjectsCommonList list) { + List items = + list.getCollectionObjectListItem(); + int i = 0; + for (CollectionobjectsCommonList.CollectionObjectListItem item : items) { + logger.debug("list-item[" + i + "] title=" + + item.getTitle()); + logger.debug("list-item[" + i + "] URI=" + + item.getUri()); + i++; + } + } + +} -- 2.47.3