2 * This document is a part of the source code and related artifacts
3 * for CollectionSpace, an open source collections management system
4 * for museums and related institutions:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright (c)) 2009 Regents of the University of California
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
15 * https://source.collectionspace.org/collection-space/LICENSE.txt
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
23 package org.collectionspace.services.client.test;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
29 import javax.ws.rs.core.Response;
31 import org.collectionspace.services.PersonJAXBSchema;
32 import org.collectionspace.services.client.CollectionSpaceClient;
33 import org.collectionspace.services.client.PersonAuthorityClient;
34 import org.collectionspace.services.client.PersonAuthorityClientUtils;
35 import org.collectionspace.services.jaxb.AbstractCommonList;
36 import org.collectionspace.services.person.PersonsCommonList;
37 import org.jboss.resteasy.client.ClientResponse;
38 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41 import org.testng.Assert;
42 import org.testng.annotations.AfterClass;
43 import org.testng.annotations.BeforeClass;
44 import org.testng.annotations.Test;
47 * PersonAuthoritySearchTest, carries out search (e.g. partial
48 * term matching) tests against a deployed and running PersonAuthority Service.
50 * $LastChangedRevision: 753 $
51 * $LastChangedDate: 2009-09-23 11:03:36 -0700 (Wed, 23 Sep 2009) $
53 public class PersonAuthoritySearchTest extends BaseServiceTest {
55 static final Logger logger = LoggerFactory.getLogger(PersonAuthoritySearchTest.class);
57 /** The service path component. */
58 final String SERVICE_PATH_COMPONENT = "personauthorities";
60 // Test name for partial term matching: Lech Walesa
63 final String TEST_PARTIAL_TERM_FORE_NAME = "Lech";
65 // Surname (contains two non-USASCII range Unicode UTF-8 characters)
66 final String TEST_PARTIAL_TERM_SUR_NAME = "Wa" + "\u0142" + "\u0119" + "sa";
69 final String TEST_PARTIAL_TERM_DISPLAY_NAME =
70 TEST_PARTIAL_TERM_FORE_NAME + " " + TEST_PARTIAL_TERM_SUR_NAME;
72 // Non-existent partial term name (first letters of each of the words
73 // in a pangram for the English alphabet).
74 private static final String TEST_PARTIAL_TERM_NON_EXISTENT = "jlmbsoq";
76 /** The known resource id. */
77 private String knownResourceId = null;
79 /** The known resource ref name. */
80 private String knownResourceRefName = null;
82 /** The known item resource id. */
83 private String knownItemResourceId = null;
85 // The resource ID of an item resource used for partial term matching tests.
86 private String knownItemPartialTermResourceId = null;
88 private List<String> allResourceIdsCreated = new ArrayList<String>();
90 /** The all item resource ids created. */
91 private Map<String, String> allItemResourceIdsCreated =
92 new HashMap<String, String>();
94 // The number of matches expected on each partial term.
95 final int NUM_MATCHES_EXPECTED = 1;
97 // The minimum number of characters that must be included
98 // a partial term, in order to permit matching to occur.
99 final int PARTIAL_TERM_MIN_LENGTH = 1;
102 * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
105 protected CollectionSpaceClient getClientInstance() {
106 return new PersonAuthorityClient();
110 * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
113 protected AbstractCommonList getAbstractCommonList(
114 ClientResponse<AbstractCommonList> response) {
115 return response.getEntity(PersonsCommonList.class);
118 private String getPartialTerm() {
119 return TEST_PARTIAL_TERM_FORE_NAME;
122 private String getPartialTermUtf8() {
123 return TEST_PARTIAL_TERM_SUR_NAME;
126 private String getPartialTermNonExistent() {
127 return TEST_PARTIAL_TERM_NON_EXISTENT;
130 private String getPartialTermMinimumLength() {
131 String partialTerm = getPartialTerm();
132 if (partialTerm == null || partialTerm.trim().isEmpty()) {
135 if (getPartialTerm().length() > PARTIAL_TERM_MIN_LENGTH) {
136 return partialTerm.substring(0, PARTIAL_TERM_MIN_LENGTH);
143 public void setup() {
146 } catch (Exception e) {
147 Assert.fail("Could not create new Authority for search tests.", e);
150 createItemInAuthorityForPartialTermMatch(knownResourceId, knownResourceRefName);
151 } catch (Exception e) {
152 Assert.fail("Could not create new item in Authority for search tests.", e);
156 // ---------------------------------------------------------------
157 // CRUD tests : READ_LIST tests by partial term match.
158 // ---------------------------------------------------------------
163 * Reads an item list by partial term.
165 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
166 groups = {"readListByPartialTerm"})
167 public void partialTermMatch(String testName) {
168 if (logger.isDebugEnabled()) {
169 logger.debug(testBanner(testName, logger));
171 int numMatchesFound = 0;
172 String partialTerm = getPartialTerm();
173 if (logger.isDebugEnabled()) {
174 logger.debug("Attempting match on partial term '" + partialTerm + "' ...");
176 numMatchesFound = readItemListByPartialTerm(knownResourceId, partialTerm);
177 if (logger.isDebugEnabled()) {
178 logger.debug("Found " + numMatchesFound + " match(es), expected " +
179 NUM_MATCHES_EXPECTED + " match(es).");
181 Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED);
185 * Reads an item list by partial term, with a partial term that consists
186 * of an all-lowercase variation of the expected match, to test case-insensitive
189 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
190 groups = {"readListByPartialTerm"}, dependsOnMethods = {"partialTermMatch"})
191 public void partialTermMatchCaseInsensitiveLowerCase(String testName) {
192 if (logger.isDebugEnabled()) {
193 logger.debug(testBanner(testName, logger));
195 int numMatchesFound = 0;
197 final String partialTerm = getPartialTerm().toLowerCase();
198 if (logger.isDebugEnabled()) {
199 logger.debug("Attempting match on partial term '" + partialTerm + "' ...");
202 readItemListByPartialTerm(knownResourceId, partialTerm);
203 if (logger.isDebugEnabled()) {
204 logger.debug("Found " + numMatchesFound + " match(es), expected " +
205 NUM_MATCHES_EXPECTED + " match(es).");
207 Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED);
211 * Reads an item list by partial term, with a partial term that consists
212 * of an all-uppercase variation of the expected match, to test case-insensitive
215 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
216 groups = {"readListByPartialTerm"}, dependsOnMethods = {"partialTermMatch"})
217 public void partialTermMatchCaseInsensitiveUpperCase(String testName) {
218 if (logger.isDebugEnabled()) {
219 logger.debug(testBanner(testName, logger));
221 int numMatchesFound = 0;
223 final String partialTerm = getPartialTerm().toUpperCase();
224 if (logger.isDebugEnabled()) {
225 logger.debug("Attempting match on partial term '" + partialTerm + "' ...");
228 readItemListByPartialTerm(knownResourceId, partialTerm);
229 if (logger.isDebugEnabled()) {
230 logger.debug("Found " + numMatchesFound + " match(es), expected " +
231 NUM_MATCHES_EXPECTED + " match(es).");
233 Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED);
237 * Reads an item list by partial term, with a partial term that is of
238 * the minimum character length that may be expected to be matched.
240 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
241 groups = {"readListByPartialTerm"}, dependsOnMethods = {"partialTermMatch"})
242 public void partialTermMatchMinimumLength(String testName) {
243 if (logger.isDebugEnabled()) {
244 logger.debug(testBanner(testName, logger));
246 int numMatchesFound = 0;
247 String partialTerm = getPartialTermMinimumLength();
248 if (logger.isDebugEnabled()) {
249 logger.debug("Attempting match on partial term '" + partialTerm + "' ...");
251 numMatchesFound = readItemListByPartialTerm(knownResourceId, partialTerm);
252 // Zero matches are expected on a non-existent term.
253 if (logger.isDebugEnabled()) {
254 logger.debug("Found " + numMatchesFound + " match(es), expected " +
255 NUM_MATCHES_EXPECTED + " match(es).");
257 Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED);
261 * Reads an item list by partial term, with a partial term that contains
262 * at least one Unicode UTF-8 character (outside the USASCII range).
264 // FIXME: Test currently fails with a true UTF-8 String - need to investigate why.
265 // Will be commented out for now until we get this working ...
267 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
268 groups = {"readListByPartialTerm"}, dependsOnMethods = {"partialTermMatch"})
269 public void partialTermMatchUTF8(String testName) {
270 if (logger.isDebugEnabled()) {
271 logger.debug(testBanner(testName, logger));
273 int numMatchesFound = 0;
274 String partialTerm = getPartialTermUtf8();
275 if (logger.isDebugEnabled()) {
276 logger.debug("Attempting match on partial term '" + partialTerm + "' ...");
279 readItemListByPartialTerm(knownResourceId, partialTerm);
280 if (logger.isDebugEnabled()) {
281 logger.debug("Found " + numMatchesFound + " match(es), expected " +
282 NUM_MATCHES_EXPECTED + " match(es).");
284 Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED);
291 * Reads an item list by partial term, with a partial term that is not
292 * expected to be matched by any term in any resource.
294 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
295 groups = {"readListByPartialTerm"}, dependsOnMethods = {"partialTermMatch"})
296 public void partialTermMatchOnNonexistentTerm(String testName) {
297 if (logger.isDebugEnabled()) {
298 logger.debug(testBanner(testName, logger));
300 int numMatchesFound = 0;
301 int ZERO_MATCHES_EXPECTED = 0;
302 String partialTerm = getPartialTermNonExistent();
303 if (logger.isDebugEnabled()) {
304 logger.debug("Attempting match on partial term '" + partialTerm + "' ...");
306 numMatchesFound = readItemListByPartialTerm(knownResourceId, partialTerm);
307 // Zero matches are expected on a non-existent term.
308 if (logger.isDebugEnabled()) {
309 logger.debug("Found " + numMatchesFound + " match(es), expected " +
310 ZERO_MATCHES_EXPECTED + " match(es).");
312 Assert.assertEquals(numMatchesFound, ZERO_MATCHES_EXPECTED);
316 * Reads an item list by partial term, given an authority and a term.
318 * @param authorityCsid The CSID of the authority within which partial term matching
320 * @param partialTerm A partial term to match item resources.
321 * @return The number of item resources matched by the partial term.
323 private int readItemListByPartialTerm(String authorityCsid, String partialTerm) {
326 int expectedStatusCode = Response.Status.OK.getStatusCode();
327 ServiceRequestType requestType = ServiceRequestType.READ_LIST;
328 String testName = "readItemListByPartialTerm";
329 testSetup(expectedStatusCode, requestType, testName, logger);
331 // Submit the request to the service and store the response.
332 PersonAuthorityClient client = new PersonAuthorityClient();
333 ClientResponse<PersonsCommonList> res = null;
334 if (authorityCsid != null) {
335 res = client.readItemList(authorityCsid, partialTerm);
337 Assert.fail("readItemListByPartialTerm passed null csid!");
339 PersonsCommonList list = null;
341 int statusCode = res.getStatus();
343 // Check the status code of the response: does it match
344 // the expected response(s)?
345 if(logger.isDebugEnabled()){
346 logger.debug(testName + ": status = " + statusCode);
348 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
349 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
350 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
352 list = res.getEntity();
354 res.releaseConnection();
357 List<PersonsCommonList.PersonListItem> items = list.getPersonListItem();
358 int nItemsReturned = items.size();
360 return nItemsReturned;
363 // ---------------------------------------------------------------
364 // Cleanup of resources created during testing
365 // ---------------------------------------------------------------
368 * Deletes all resources created by tests, after all tests have been run.
370 * This cleanup method will always be run, even if one or more tests fail.
371 * For this reason, it attempts to remove all resources created
372 * at any point during testing, even if some of those resources
373 * may be expected to be deleted by certain tests.
375 @AfterClass(alwaysRun=true)
376 public void cleanUp() {
377 String noTest = System.getProperty("noTestCleanup");
378 if(Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
379 if (logger.isDebugEnabled()) {
380 logger.debug("Skipping Cleanup phase ...");
384 if (logger.isDebugEnabled()) {
385 logger.debug("Cleaning up temporary resources created for testing ...");
387 String parentResourceId;
388 String itemResourceId;
389 PersonAuthorityClient client = new PersonAuthorityClient();
390 parentResourceId = knownResourceId;
391 // Clean up item resources.
392 for (Map.Entry<String, String> entry : allItemResourceIdsCreated.entrySet()) {
393 itemResourceId = entry.getKey();
394 parentResourceId = entry.getValue();
395 // Note: Any non-success responses from the delete operation
396 // below are ignored and not reported.
397 ClientResponse<Response> res =
398 client.deleteItem(parentResourceId, itemResourceId);
399 res.releaseConnection();
401 // Clean up authority resources.
402 for (String resourceId : allResourceIdsCreated) {
403 // Note: Any non-success responses are ignored and not reported.
404 client.delete(resourceId).releaseConnection();
408 // ---------------------------------------------------------------
409 // Utility methods used by tests above
410 // ---------------------------------------------------------------
412 * @see org.collectionspace.services.client.test.BaseServiceTest#getServicePathComponent()
415 public String getServicePathComponent() {
416 return SERVICE_PATH_COMPONENT;
420 // ---------------------------------------------------------------
421 // Utilities: setup routines for search tests
422 // ---------------------------------------------------------------
424 public void createAuthority() throws Exception {
427 int expectedStatusCode = Response.Status.CREATED.getStatusCode();
428 ServiceRequestType requestType = ServiceRequestType.CREATE;
429 String testName = "createPersonAuthority";
430 testSetup(expectedStatusCode, requestType, testName, logger);
432 // Submit the request to the service and store the response.
433 PersonAuthorityClient client = new PersonAuthorityClient();
434 String identifier = createIdentifier();
435 String displayName = "displayName-" + identifier;
436 String baseRefName = PersonAuthorityClientUtils.createPersonAuthRefName(displayName, false);
437 String fullRefName = PersonAuthorityClientUtils.createPersonAuthRefName(displayName, true);
438 MultipartOutput multipart =
439 PersonAuthorityClientUtils.createPersonAuthorityInstance(
440 displayName, fullRefName, client.getCommonPartName());
443 ClientResponse<Response> res = client.create(multipart);
445 int statusCode = res.getStatus();
446 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
447 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
448 Assert.assertEquals(statusCode, this.EXPECTED_STATUS_CODE);
449 newID = PersonAuthorityClientUtils.extractId(res);
451 res.releaseConnection();
453 // Store the refname from the first resource created
454 // for additional tests below.
455 knownResourceRefName = baseRefName;
456 // Store the ID returned from the first resource created
457 // for additional tests below.
458 if (knownResourceId == null){
459 knownResourceId = newID;
460 knownResourceRefName = baseRefName;
463 // Store the IDs from every resource created by tests,
464 // so they can be deleted after tests have been run.
465 allResourceIdsCreated.add(newID);
469 * Creates an item in the authority, used for partial term matching tests.
471 * @param authorityCsid The CSID of the Authority in which the term will be created.
472 * @param authRefName The refName of the Authority in which the term will be created.
474 private void createItemInAuthorityForPartialTermMatch(String authorityCsid, String authRefName)
477 int expectedStatusCode = Response.Status.CREATED.getStatusCode();
478 ServiceRequestType requestType = ServiceRequestType.CREATE;
479 String testName = "createItemInAuthorityForPartialTermMatch";
480 testSetup(expectedStatusCode, requestType, testName);
482 // Submit the request to the service and store the response.
483 PersonAuthorityClient client = new PersonAuthorityClient();
484 String refName = PersonAuthorityClientUtils.createPersonRefName(authRefName,
485 TEST_PARTIAL_TERM_DISPLAY_NAME, true);
486 Map<String, String> partialTermPersonMap = new HashMap<String,String>();
488 // Fill the property map
490 partialTermPersonMap.put(PersonJAXBSchema.DISPLAY_NAME_COMPUTED, "false");
491 partialTermPersonMap.put(PersonJAXBSchema.DISPLAY_NAME, TEST_PARTIAL_TERM_DISPLAY_NAME);
492 partialTermPersonMap.put(PersonJAXBSchema.FORE_NAME, TEST_PARTIAL_TERM_FORE_NAME);
493 partialTermPersonMap.put(PersonJAXBSchema.SUR_NAME, TEST_PARTIAL_TERM_SUR_NAME);
494 partialTermPersonMap.put(PersonJAXBSchema.GENDER, "male");
495 MultipartOutput multipart =
496 PersonAuthorityClientUtils.createPersonInstance(authorityCsid, refName, partialTermPersonMap,
497 client.getItemCommonPartName() );
500 ClientResponse<Response> res = client.createItem(authorityCsid, multipart);
502 int statusCode = res.getStatus();
503 // Check the status code of the response: does it match
504 // the expected response(s)?
505 if(logger.isDebugEnabled()){
506 logger.debug(testName + ": status = " + statusCode);
508 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
509 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
510 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
512 newID = PersonAuthorityClientUtils.extractId(res);
514 res.releaseConnection();
517 // Store the ID returned from the first item resource created
518 // for additional tests below.
519 if (knownItemResourceId == null){
520 knownItemResourceId = newID;
521 if (logger.isDebugEnabled()) {
522 logger.debug(testName + ": knownItemPartialTermResourceId=" + knownItemPartialTermResourceId);
526 // Store the IDs from any item resources created
527 // by tests, along with the IDs of their parents, so these items
528 // can be deleted after all tests have been run.
529 allItemResourceIdsCreated.put(newID, authorityCsid);