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 © 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.List;
27 import javax.ws.rs.core.MediaType;
28 import javax.ws.rs.core.Response;
30 import org.collectionspace.services.client.CollectionSpaceClient;
31 import org.collectionspace.services.client.RelationClient;
32 import org.collectionspace.services.jaxb.AbstractCommonList;
33 import org.collectionspace.services.relation.RelationsCommon;
34 import org.collectionspace.services.relation.RelationsCommonList;
35 import org.collectionspace.services.relation.RelationshipType;
37 import org.jboss.resteasy.client.ClientResponse;
39 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
40 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
41 import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
42 import org.testng.Assert;
43 import org.testng.annotations.AfterClass;
44 import org.testng.annotations.Test;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
50 * RelationServiceTest, carries out tests against a
51 * deployed and running Relation Service.
53 * $LastChangedRevision$
56 public class RelationServiceTest extends AbstractServiceTestImpl {
58 private final Logger logger =
59 LoggerFactory.getLogger(RelationServiceTest.class);
61 final String SERVICE_PATH_COMPONENT = "relations";
62 private String knownResourceId = null;
63 private List<String> allResourceIdsCreated = new ArrayList<String>();
66 * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
69 protected CollectionSpaceClient getClientInstance() {
70 return new RelationClient();
74 * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
77 protected AbstractCommonList getAbstractCommonList(
78 ClientResponse<AbstractCommonList> response) {
79 return response.getEntity(RelationsCommonList.class);
82 // ---------------------------------------------------------------
83 // CRUD tests : CREATE tests
84 // ---------------------------------------------------------------
86 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class)
88 public void create(String testName) throws Exception {
90 // Perform setup, such as initializing the type of service request
91 // (e.g. CREATE, DELETE), its valid and expected status codes, and
92 // its associated HTTP method name (e.g. POST, DELETE).
93 setupCreate(testName);
95 // Submit the request to the service and store the response.
96 RelationClient client = new RelationClient();
97 String identifier = createIdentifier();
98 MultipartOutput multipart = createRelationInstance(identifier);
99 ClientResponse<Response> res = client.create(multipart);
100 int statusCode = res.getStatus();
102 // Check the status code of the response: does it match
103 // the expected response(s)?
105 // Does it fall within the set of valid status codes?
106 // Does it exactly match the expected status code?
107 if(logger.isDebugEnabled()){
108 logger.debug(testName + ": status = " + statusCode);
110 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
111 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
112 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
114 // Store the ID returned from the first resource created
115 // for additional tests below.
116 if (knownResourceId == null){
117 knownResourceId = extractId(res);
118 if (logger.isDebugEnabled()) {
119 logger.debug(testName + ": knownResourceId=" + knownResourceId);
123 // Store the IDs from every resource created by tests,
124 // so they can be deleted after tests have been run.
125 allResourceIdsCreated.add(extractId(res));
129 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
130 dependsOnMethods = {"create"})
131 public void createList(String testName) throws Exception {
132 for(int i = 0; i < 3; i++){
138 // Placeholders until the three tests below can be uncommented.
139 // See Issue CSPACE-401.
140 public void createWithEmptyEntityBody(String testName) throws Exception {
143 public void createWithMalformedXml(String testName) throws Exception {
146 public void createWithWrongXmlSchema(String testName) throws Exception {
151 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
152 dependsOnMethods = {"create", "testSubmitRequest"})
153 public void createWithEmptyEntityBody(String testName) throws Exception {
156 setupCreateWithEmptyEntityBody(testName);
158 // Submit the request to the service and store the response.
159 String method = REQUEST_TYPE.httpMethodName();
160 String url = getServiceRootURL();
161 String mediaType = MediaType.APPLICATION_XML;
162 final String entity = "";
163 int statusCode = submitRequest(method, url, mediaType, entity);
165 // Check the status code of the response: does it match
166 // the expected response(s)?
167 if(logger.isDebugEnabled()){
168 logger.debug(testName + ": url=" + url +
169 " status=" + statusCode);
171 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
172 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
173 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
177 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
178 dependsOnMethods = {"create", "testSubmitRequest"})
179 public void createWithMalformedXml(String testName) throws Exception {
182 setupCreateWithMalformedXml(testName);
184 // Submit the request to the service and store the response.
185 String method = REQUEST_TYPE.httpMethodName();
186 String url = getServiceRootURL();
187 String mediaType = MediaType.APPLICATION_XML;
188 final String entity = MALFORMED_XML_DATA; // Constant from base class.
189 int statusCode = submitRequest(method, url, mediaType, entity);
191 // Check the status code of the response: does it match
192 // the expected response(s)?
193 if(logger.isDebugEnabled()){
194 logger.debug(testName + ": url=" + url +
195 " status=" + statusCode);
197 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
198 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
199 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
203 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
204 dependsOnMethods = {"create", "testSubmitRequest"})
205 public void createWithWrongXmlSchema(String testName) throws Exception {
208 setupCreateWithWrongXmlSchema(testName);
210 // Submit the request to the service and store the response.
211 String method = REQUEST_TYPE.httpMethodName();
212 String url = getServiceRootURL();
213 String mediaType = MediaType.APPLICATION_XML;
214 final String entity = WRONG_XML_SCHEMA_DATA;
215 int statusCode = submitRequest(method, url, mediaType, entity);
217 // Check the status code of the response: does it match
218 // the expected response(s)?
219 if(logger.isDebugEnabled()){
220 logger.debug(testName + ": url=" + url +
221 " status=" + statusCode);
223 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
224 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
225 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
229 // ---------------------------------------------------------------
230 // CRUD tests : READ tests
231 // ---------------------------------------------------------------
234 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
235 dependsOnMethods = {"create"})
236 public void read(String testName) throws Exception {
241 // Submit the request to the service and store the response.
242 RelationClient client = new RelationClient();
243 ClientResponse<MultipartInput> res = client.read(knownResourceId);
244 int statusCode = res.getStatus();
246 // Check the status code of the response: does it match
247 // the expected response(s)?
248 if(logger.isDebugEnabled()){
249 logger.debug(testName + ": status = " + statusCode);
251 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
252 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
253 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
255 // Verify that the resource identifier ...
256 MultipartInput input = (MultipartInput) res.getEntity();
257 RelationsCommon relation = (RelationsCommon) extractPart(input,
258 client.getCommonPartName(), RelationsCommon.class);
259 Assert.assertNotNull(relation);
265 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
266 dependsOnMethods = {"read"})
267 public void readNonExistent(String testName) throws Exception {
270 setupReadNonExistent(testName);
272 // Submit the request to the service and store the response.
273 RelationClient client = new RelationClient();
274 ClientResponse<MultipartInput> res = client.read(NON_EXISTENT_ID);
275 int statusCode = res.getStatus();
277 // Check the status code of the response: does it match
278 // the expected response(s)?
279 if(logger.isDebugEnabled()){
280 logger.debug(testName + ": status = " + statusCode);
282 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
283 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
284 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
287 // ---------------------------------------------------------------
288 // CRUD tests : READ_LIST tests
289 // ---------------------------------------------------------------
292 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
293 dependsOnMethods = {"createList", "read"})
294 public void readList(String testName) throws Exception {
297 setupReadList(testName);
299 // Submit the request to the service and store the response.
300 RelationClient client = new RelationClient();
301 ClientResponse<RelationsCommonList> res = client.readList();
302 RelationsCommonList list = res.getEntity();
303 int statusCode = res.getStatus();
305 // Check the status code of the response: does it match
306 // the expected response(s)?
307 if(logger.isDebugEnabled()){
308 logger.debug(testName + ": status = " + statusCode);
310 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
311 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
312 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
314 // Optionally output additional data about list members for debugging.
315 boolean iterateThroughList = false;
316 if(iterateThroughList && logger.isDebugEnabled()){
317 List<RelationsCommonList.RelationListItem> items =
318 list.getRelationListItem();
320 for(RelationsCommonList.RelationListItem item : items){
321 logger.debug(testName + ": list-item[" + i + "] csid=" +
323 logger.debug(testName + ": list-item[" + i + "] URI=" +
334 // ---------------------------------------------------------------
335 // CRUD tests : UPDATE tests
336 // ---------------------------------------------------------------
340 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
341 dependsOnMethods = {"read"})
342 public void update(String testName) throws Exception {
345 setupUpdate(testName);
347 // Retrieve an existing resource that we can update.
348 RelationClient client = new RelationClient();
349 ClientResponse<MultipartInput> res =
350 client.read(knownResourceId);
351 if(logger.isDebugEnabled()){
352 logger.debug(testName + ": read status = " + res.getStatus());
354 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
355 if(logger.isDebugEnabled()){
356 logger.debug("Got object to update with ID: " + knownResourceId);
358 MultipartInput input = (MultipartInput) res.getEntity();
359 RelationsCommon relation = (RelationsCommon) extractPart(input,
360 client.getCommonPartName(), RelationsCommon.class);
361 Assert.assertNotNull(relation);
363 // Update the content of this resource.
364 relation.setDocumentId1("updated-" + relation.getDocumentId1());
365 relation.setDocumentType1("updated-" + relation.getDocumentType1());
366 relation.setDocumentId2("updated-" + relation.getDocumentId2());
367 relation.setDocumentType2("updated-" + relation.getDocumentType2());
368 if(logger.isDebugEnabled()){
369 logger.debug("updated object");
370 logger.debug(objectAsXmlString(relation, RelationsCommon.class));
373 // Submit the request to the service and store the response.
374 MultipartOutput output = new MultipartOutput();
375 OutputPart commonPart = output.addPart(relation, MediaType.APPLICATION_XML_TYPE);
376 commonPart.getHeaders().add("label", client.getCommonPartName());
377 res = client.update(knownResourceId, output);
378 int statusCode = res.getStatus();
380 // Check the status code of the response: does it match the expected response(s)?
381 if(logger.isDebugEnabled()){
382 logger.debug(testName + ": status = " + statusCode);
384 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
385 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
386 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
388 input = (MultipartInput) res.getEntity();
389 RelationsCommon updatedObject = (RelationsCommon) extractPart(
390 input, client.getCommonPartName(),
391 RelationsCommon.class);
392 Assert.assertNotNull(updatedObject);
395 "Data in updated object did not match submitted data.";
397 updatedObject.getDocumentId1(), relation.getDocumentId1(), msg);
399 updatedObject.getDocumentType1(), relation.getDocumentType1(), msg);
401 updatedObject.getDocumentId2(), relation.getDocumentId2(), msg);
403 updatedObject.getDocumentType2(), relation.getDocumentType2(), msg);
408 // Placeholders until the three tests below can be uncommented.
409 // See Issue CSPACE-401.
410 public void updateWithEmptyEntityBody(String testName) throws Exception {
413 public void updateWithMalformedXml(String testName) throws Exception {
416 public void updateWithWrongXmlSchema(String testName) throws Exception {
421 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
422 dependsOnMethods = {"create", "update", "testSubmitRequest"})
423 public void updateWithEmptyEntityBody(String testName) throws Exception {
426 setupUpdateWithEmptyEntityBody(testName);
428 // Submit the request to the service and store the response.
429 String method = REQUEST_TYPE.httpMethodName();
430 String url = getResourceURL(knownResourceId);
431 String mediaType = MediaType.APPLICATION_XML;
432 final String entity = "";
433 int statusCode = submitRequest(method, url, mediaType, entity);
435 // Check the status code of the response: does it match
436 // the expected response(s)?
437 if(logger.isDebugEnabled()){
438 logger.debug(testName + ": url=" + url +
439 " status=" + statusCode);
441 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
442 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
443 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
447 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
448 dependsOnMethods = {"create", "update", "testSubmitRequest"})
449 public void updateWithMalformedXml(String testName) throws Exception {
452 setupUpdateWithMalformedXml(testName);
454 // Submit the request to the service and store the response.
455 String method = REQUEST_TYPE.httpMethodName();
456 String url = getResourceURL(knownResourceId);
457 String mediaType = MediaType.APPLICATION_XML;
458 final String entity = MALFORMED_XML_DATA; // Constant from abstract base class.
459 int statusCode = submitRequest(method, url, mediaType, entity);
461 // Check the status code of the response: does it match
462 // the expected response(s)?
463 if(logger.isDebugEnabled()){
464 logger.debug(testName + ": url=" + url +
465 " status=" + statusCode);
467 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
468 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
469 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
473 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
474 dependsOnMethods = {"create", "update", "testSubmitRequest"})
475 public void updateWithWrongXmlSchema(String testName) throws Exception {
478 setupUpdateWithWrongXmlSchema(testName);
480 // Submit the request to the service and store the response.
481 String method = REQUEST_TYPE.httpMethodName();
482 String url = getResourceURL(knownResourceId);
483 String mediaType = MediaType.APPLICATION_XML;
484 final String entity = WRONG_XML_SCHEMA_DATA; // Constant from abstract base class.
485 int statusCode = submitRequest(method, url, mediaType, entity);
487 // Check the status code of the response: does it match
488 // the expected response(s)?
489 if(logger.isDebugEnabled()){
490 logger.debug(testName + ": url=" + url +
491 " status=" + statusCode);
493 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
494 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
495 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
500 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
501 dependsOnMethods = {"update", "testSubmitRequest"})
502 public void updateNonExistent(String testName) throws Exception {
505 setupUpdateNonExistent(testName);
507 // Submit the request to the service and store the response.
508 // Note: The ID used in this 'create' call may be arbitrary.
509 // The only relevant ID may be the one used in update(), below.
510 RelationClient client = new RelationClient();
511 MultipartOutput multipart = createRelationInstance(NON_EXISTENT_ID);
512 ClientResponse<MultipartInput> res =
513 client.update(NON_EXISTENT_ID, multipart);
514 int statusCode = res.getStatus();
516 // Check the status code of the response: does it match
517 // the expected response(s)?
518 if(logger.isDebugEnabled()){
519 logger.debug(testName + ": status = " + statusCode);
521 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
522 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
523 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
526 // ---------------------------------------------------------------
527 // CRUD tests : DELETE tests
528 // ---------------------------------------------------------------
531 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
532 dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
533 public void delete(String testName) throws Exception {
536 setupDelete(testName);
538 // Submit the request to the service and store the response.
539 RelationClient client = new RelationClient();
540 ClientResponse<Response> res = client.delete(knownResourceId);
541 int statusCode = res.getStatus();
543 // Check the status code of the response: does it match
544 // the expected response(s)?
545 if(logger.isDebugEnabled()){
546 logger.debug(testName + ": status = " + statusCode);
548 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
549 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
550 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
555 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
556 dependsOnMethods = {"delete"})
557 public void deleteNonExistent(String testName) throws Exception {
560 setupDeleteNonExistent(testName);
562 // Submit the request to the service and store the response.
563 RelationClient client = new RelationClient();
564 ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
565 int statusCode = res.getStatus();
567 // Check the status code of the response: does it match
568 // the expected response(s)?
569 if(logger.isDebugEnabled()){
570 logger.debug(testName + ": status = " + statusCode);
572 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
573 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
574 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
577 // ---------------------------------------------------------------
578 // RELATE_OBJECT tests
579 // ---------------------------------------------------------------
580 @Test(dependsOnMethods = {"create"})
581 public void relateObjects() {
584 // ---------------------------------------------------------------
585 // Utility tests : tests of code used in tests above
586 // ---------------------------------------------------------------
588 * Tests the code for manually submitting data that is used by several
589 * of the methods above.
591 @Test(dependsOnMethods = {"create", "read"})
592 public void testSubmitRequest() {
594 // Expected status code: 200 OK
595 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
597 // Submit the request to the service and store the response.
598 String method = ServiceRequestType.READ.httpMethodName();
599 String url = getResourceURL(knownResourceId);
600 int statusCode = submitRequest(method, url);
602 // Check the status code of the response: does it match
603 // the expected response(s)?
604 if(logger.isDebugEnabled()){
605 logger.debug("testSubmitRequest: url=" + url +
606 " status=" + statusCode);
608 Assert.assertEquals(statusCode, EXPECTED_STATUS);
612 // ---------------------------------------------------------------
613 // Cleanup of resources created during testing
614 // ---------------------------------------------------------------
617 * Deletes all resources created by tests, after all tests have been run.
619 * This cleanup method will always be run, even if one or more tests fail.
620 * For this reason, it attempts to remove all resources created
621 * at any point during testing, even if some of those resources
622 * may be expected to be deleted by certain tests.
624 @AfterClass(alwaysRun=true)
625 public void cleanUp() {
626 String noTest = System.getProperty("noTestCleanup");
627 if(Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
628 if (logger.isDebugEnabled()) {
629 logger.debug("Skipping Cleanup phase ...");
633 if (logger.isDebugEnabled()) {
634 logger.debug("Cleaning up temporary resources created for testing ...");
636 RelationClient client = new RelationClient();
637 for (String resourceId : allResourceIdsCreated) {
638 // Note: Any non-success responses are ignored and not reported.
639 ClientResponse<Response> res = client.delete(resourceId);
643 // ---------------------------------------------------------------
644 // Utility methods used by tests above
645 // ---------------------------------------------------------------
647 public String getServicePathComponent() {
648 return SERVICE_PATH_COMPONENT;
651 private MultipartOutput createRelationInstance(String identifier) {
652 RelationsCommon relation = new RelationsCommon();
653 fillRelation(relation, identifier);
655 MultipartOutput multipart = new MultipartOutput();
656 OutputPart commonPart =
657 multipart.addPart(relation, MediaType.APPLICATION_XML_TYPE);
658 commonPart.getHeaders().add("label", new RelationClient().getCommonPartName());
659 if(logger.isDebugEnabled()){
660 logger.debug("to be created, relation common");
661 logger.debug(objectAsXmlString(relation, RelationsCommon.class));
667 * Fills the relation.
669 * @param identifier the identifier
671 * @return the relation
673 private void fillRelation(RelationsCommon relation, String identifier) {
674 fillRelation(relation, "Subject-" + identifier,
675 "SubjectType-" + identifier + "-type",
676 "Object-" + identifier,
677 "ObjectType-" + identifier + "-type",
678 RelationshipType.COLLECTIONOBJECT_INTAKE);
682 * Fills the relation.
684 * @param documentId1 the document id1
685 * @param documentType1 the document type1
686 * @param documentId2 the document id2
687 * @param documentType2 the document type2
690 * @return the relation
692 private void fillRelation(RelationsCommon relation,
693 String documentId1, String documentType1,
694 String documentId2, String documentType2,
695 RelationshipType rt) {
696 relation.setDocumentId1(documentId1);
697 relation.setDocumentType1(documentType1);
698 relation.setDocumentId2(documentId2);
699 relation.setDocumentType2(documentType2);
701 relation.setRelationshipType(rt);