]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
7ed609f177866c053c40cc62fbba290efb774801
[tmp/jakarta-migration.git] /
1 /**
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:
5  *
6  * http://www.collectionspace.org
7  * http://wiki.collectionspace.org
8  *
9  * Copyright © 2009 Regents of the University of California
10  *
11  * Licensed under the Educational Community License (ECL), Version 2.0.
12  * You may not use this file except in compliance with this License.
13  *
14  * You may obtain a copy of the ECL 2.0 License at
15  * https://source.collectionspace.org/collection-space/LICENSE.txt
16  *
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.
22  */
23 package org.collectionspace.services.client.test;
24
25 import java.util.List;
26 import javax.ws.rs.core.MediaType;
27 import javax.ws.rs.core.Response;
28
29 //import org.collectionspace.services.client.AbstractServiceClientImpl;
30 import org.collectionspace.services.client.CollectionObjectClient;
31 import org.collectionspace.services.client.CollectionObjectFactory;
32 import org.collectionspace.services.client.CollectionSpaceClient;
33 import org.collectionspace.services.collectionobject.CollectionobjectsCommon;
34 import org.collectionspace.services.collectionobject.domain.naturalhistory.CollectionobjectsNaturalhistory;
35 import org.collectionspace.services.collectionobject.CollectionobjectsCommonList;
36 import org.collectionspace.services.collectionobject.ResponsibleDepartmentList;
37 import org.collectionspace.services.jaxb.AbstractCommonList;
38
39 import org.jboss.resteasy.client.ClientResponse;
40 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
41 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
42 import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
43 import org.testng.Assert;
44 import org.testng.annotations.Test;
45
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 /**
50  * CollectionObjectServiceTest, carries out tests against a
51  * deployed and running CollectionObject Service.
52  *
53  * $LastChangedRevision$
54  * $LastChangedDate$
55  */
56 public class CollectionObjectServiceTest extends AbstractServiceTestImpl {
57
58     /** The logger. */
59     private final Logger logger =
60             LoggerFactory.getLogger(CollectionObjectServiceTest.class);
61     // Instance variables specific to this test.
62     /** The known resource id. */
63     private String knownResourceId = null;
64     
65     /** The multivalue. */
66     private boolean multivalue; //toggle
67
68     /* (non-Javadoc)
69      * @see org.collectionspace.services.client.test.BaseServiceTest#getServicePathComponent()
70      */
71     @Override
72     protected String getServicePathComponent() {
73         return new CollectionObjectClient().getServicePathComponent();
74     }
75     
76     /* (non-Javadoc)
77      * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
78      */
79     @Override
80     protected CollectionSpaceClient getClientInstance() {
81         return new CollectionObjectClient();
82     }
83     
84     /* (non-Javadoc)
85      * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
86      */
87     @Override
88         protected AbstractCommonList getAbstractCommonList(
89                         ClientResponse<AbstractCommonList> response) {
90         return response.getEntity(CollectionobjectsCommonList.class);
91     }
92  
93     // ---------------------------------------------------------------
94     // CRUD tests : CREATE tests
95     // ---------------------------------------------------------------
96     // Success outcomes
97     /* (non-Javadoc)
98      * @see org.collectionspace.services.client.test.ServiceTest#create(java.lang.String)
99      */
100     @Override
101     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
102     public void create(String testName) throws Exception {
103
104         // Perform setup, such as initializing the type of service request
105         // (e.g. CREATE, DELETE), its valid and expected status codes, and
106         // its associated HTTP method name (e.g. POST, DELETE).
107         setupCreate(testName);
108
109         // Submit the request to the service and store the response.
110         CollectionObjectClient client = new CollectionObjectClient();
111         String identifier = createIdentifier();
112         MultipartOutput multipart =
113                 createCollectionObjectInstance(client.getCommonPartName(), identifier);
114         ClientResponse<Response> res = client.create(multipart);
115         int statusCode = res.getStatus();
116
117         // Check the status code of the response: does it match
118         // the expected response(s)?
119         //
120         // Specifically:
121         // Does it fall within the set of valid status codes?
122         // Does it exactly match the expected status code?
123         if (logger.isDebugEnabled()) {
124             logger.debug(testName + ": status = " + statusCode);
125         }
126         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
127                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
128         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
129
130         // Store the ID returned from the first resource created
131         // for additional tests below.
132         if (knownResourceId == null) {
133             knownResourceId = extractId(res);
134             if (logger.isDebugEnabled()) {
135                 logger.debug(testName + ": knownResourceId=" + knownResourceId);
136             }
137         }
138
139         // Store the IDs from every resource created by tests,
140         // so they can be deleted after tests have been run.
141         allResourceIdsCreated.add(extractId(res));
142     }
143
144
145     /*
146      * Tests to diagnose and verify the fixed status of CSPACE-1026,
147      * "Whitespace at certain points in payload cause failure"
148      */
149     /**
150      * Creates the from xml cambridge.
151      *
152      * @param testName the test name
153      * @throws Exception the exception
154      */
155     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
156         dependsOnMethods = {"create", "testSubmitRequest"})
157     public void createFromXmlCambridge(String testName) throws Exception {
158         String newId =
159             createFromXmlFile(testName, "./test-data/testCambridge.xml", true);
160         testSubmitRequest(newId);
161     }
162
163     /**
164      * Creates the from xml rfw s1.
165      *
166      * @param testName the test name
167      * @throws Exception the exception
168      */
169     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
170         dependsOnMethods = {"create", "testSubmitRequest"})
171     public void createFromXmlRFWS1(String testName) throws Exception {
172         String testDataDir = System.getProperty("test-data.fileName");
173         String newId =
174             //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp1.xml", false);
175                 createFromXmlFile(testName, testDataDir + "/repfield_whitesp1.xml", false);
176         testSubmitRequest(newId);
177     }
178
179     /**
180      * Creates the from xml rfw s2.
181      *
182      * @param testName the test name
183      * @throws Exception the exception
184      */
185     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
186         dependsOnMethods = {"create", "testSubmitRequest"})
187     public void createFromXmlRFWS2(String testName) throws Exception {
188         String testDataDir = System.getProperty("test-data.fileName");
189         String newId =
190             //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp2.xml", false);
191                 createFromXmlFile(testName, testDataDir + "/repfield_whitesp2.xml", false);
192         testSubmitRequest(newId);
193     }
194
195     /**
196      * Creates the from xml rfw s3.
197      *
198      * @param testName the test name
199      * @throws Exception the exception
200      */
201     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
202         dependsOnMethods = {"create", "testSubmitRequest"})
203     public void createFromXmlRFWS3(String testName) throws Exception {
204         String testDataDir = System.getProperty("test-data.fileName");
205         String newId =
206             //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp3.xml", false);
207                 createFromXmlFile(testName, testDataDir + "/repfield_whitesp3.xml", false);
208         testSubmitRequest(newId);
209     }
210
211     /**
212      * Creates the from xml rfw s4.
213      *
214      * @param testName the test name
215      * @throws Exception the exception
216      */
217     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
218         dependsOnMethods = {"create", "testSubmitRequest"})
219     public void createFromXmlRFWS4(String testName) throws Exception {
220         String testDataDir = System.getProperty("test-data.fileName");
221         String newId =
222             createFromXmlFile(testName, testDataDir + "/repfield_whitesp4.xml", false);
223         testSubmitRequest(newId);
224     }
225
226     /*
227      * Tests to diagnose and verify the fixed status of CSPACE-1248,
228      * "Wedged records created!" (i.e. records with child repeatable
229      * fields, which contain null values, can be successfully created
230      * but an error occurs on trying to retrieve those records).
231      */
232     /**
233      * Creates the with null value repeatable field.
234      *
235      * @param testName the test name
236      * @throws Exception the exception
237      */
238     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
239         dependsOnMethods = {"create", "testSubmitRequest"})
240     public void createWithNullValueRepeatableField(String testName) throws Exception {
241         String testDataDir = System.getProperty("test-data.fileName");
242         String newId =
243             createFromXmlFile(testName, testDataDir + "/repfield_null1.xml", false);
244         if (logger.isDebugEnabled()) {
245             logger.debug("Successfully created record with null value repeatable field.");
246             logger.debug("Attempting to retrieve just-created record ...");
247         }
248         testSubmitRequest(newId);
249     }
250     
251     /* (non-Javadoc)
252      * @see org.collectionspace.services.client.test.ServiceTest#createList()
253      */
254     @Override
255     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
256     dependsOnMethods = {"create"})
257     public void createList(String testName) throws Exception {
258         this.createPaginatedList(testName, DEFAULT_LIST_SIZE);
259     }
260
261     // Failure outcomes
262     // Placeholders until the three tests below can be uncommented.
263     // See Issue CSPACE-401.
264     /* (non-Javadoc)
265      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithEmptyEntityBody(java.lang.String)
266      */
267     @Override
268     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
269     public void createWithEmptyEntityBody(String testName) throws Exception {
270         //FIXME: Should this test really be empty?
271     }
272
273    /**
274     * Test how the service handles XML that is not well formed,
275     * when sent in the payload of a Create request.
276     *
277     * @param testName  The name of this test method.  This name is supplied
278     *     automatically, via reflection, by a TestNG 'data provider' in
279     *     a base class.
280     */
281     @Override
282     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
283     public void createWithMalformedXml(String testName) throws Exception {
284         setupCreate(testName);
285     }
286
287     /* (non-Javadoc)
288      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithWrongXmlSchema(java.lang.String)
289      */
290     @Override
291     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
292     public void createWithWrongXmlSchema(String testName) throws Exception {
293         //FIXME: Should this test really be empty?
294     }
295
296
297 /*
298     @Override
299     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
300     dependsOnMethods = {"create", "testSubmitRequest"})
301     public void createWithEmptyEntityBody(String testName) throwsException {
302
303     // Perform setup.
304     setupCreateWithEmptyEntityBody(testName);
305
306     // Submit the request to the service and store the response.
307     String method = REQUEST_TYPE.httpMethodName();
308     String url = getServiceRootURL();
309     String mediaType = MediaType.APPLICATION_XML;
310     final String entity = "";
311     int statusCode = submitRequest(method, url, mediaType, entity);
312
313     // Check the status code of the response: does it match
314     // the expected response(s)?
315     if(logger.isDebugEnabled()){
316     logger.debug(testName + ": url=" + url +
317     " status=" + statusCode);
318     }
319     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
320     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
321     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
322     }
323
324     @Override
325     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
326     dependsOnMethods = {"create", "testSubmitRequest"})
327     public void createWithMalformedXml(String testName) throws Exception {
328
329     // Perform setup.
330     setupCreateWithMalformedXml(testName);
331
332     // Submit the request to the service and store the response.
333     String method = REQUEST_TYPE.httpMethodName();
334     String url = getServiceRootURL();
335     String mediaType = MediaType.APPLICATION_XML;
336     final String entity = MALFORMED_XML_DATA; // Constant from base class.
337     int statusCode = submitRequest(method, url, mediaType, entity);
338
339     // Check the status code of the response: does it match
340     // the expected response(s)?
341     if(logger.isDebugEnabled()){
342     logger.debug(testName + ": url=" + url +
343     " status=" + statusCode);
344     }
345     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
346     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
347     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
348     }
349
350     @Override
351     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
352     dependsOnMethods = {"create", "testSubmitRequest"})
353     public void createWithWrongXmlSchema(String testName) throws Exception {
354
355     // Perform setup.
356     setupCreateWithWrongXmlSchema(testName);
357
358     // Submit the request to the service and store the response.
359     String method = REQUEST_TYPE.httpMethodName();
360     String url = getServiceRootURL();
361     String mediaType = MediaType.APPLICATION_XML;
362     final String entity = WRONG_XML_SCHEMA_DATA;
363     int statusCode = submitRequest(method, url, mediaType, entity);
364
365     // Check the status code of the response: does it match
366     // the expected response(s)?
367     if(logger.isDebugEnabled()){
368     logger.debug(testName + ": url=" + url +
369     " status=" + statusCode);
370     }
371     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
372     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
373     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
374     }
375 */
376
377    /**
378     * Test how the service handles, in a Create request, payloads
379     * containing null values (or, in the case of String fields,
380     * empty String values) in one or more fields which must be
381     * present and are required to contain non-empty values.
382     *
383     * This is a test of code and/or configuration in the service's
384     * validation routine(s).
385     *
386     * @param testName  The name of this test method.  This name is supplied
387     *     automatically, via reflection, by a TestNG 'data provider' in
388     *     a base class.
389     * @throws Exception 
390     */
391     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
392     public void createWithRequiredValuesNullOrEmpty(String testName) throws Exception {
393         setupCreate(testName);
394
395         // Build a payload with invalid content, by omitting a
396         // field (objectNumber) which must be present, and in which
397         // a non-empty value is required, as enforced by the service's
398         // validation routine(s).
399         CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
400         collectionObject.setTitle("atitle");
401         collectionObject.setObjectName("some name");
402
403         // Submit the request to the service and store the response.
404         CollectionObjectClient client = new CollectionObjectClient();
405         MultipartOutput multipart =
406                 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
407         ClientResponse<Response> res = client.create(multipart);
408         int statusCode = res.getStatus();
409
410         // Read the response and verify that the create attempt failed.
411         if (logger.isDebugEnabled()) {
412             logger.debug(testName + ": status = " + statusCode);
413         }
414         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
415                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
416         Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
417
418         // FIXME: Consider splitting off the following into its own test method.
419         
420         // Build a payload with invalid content, by setting a value to the
421         // empty String, in a field that requires a non-empty value,
422         // as enforced by the service's validation routine(s).
423         collectionObject = new CollectionobjectsCommon();
424         collectionObject.setTitle("atitle");
425         collectionObject.setObjectName("some name");
426         collectionObject.setObjectNumber("");
427
428         // Submit the request to the service and store the response.
429         multipart =
430             createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
431         res = client.create(multipart);
432         statusCode = res.getStatus();
433
434         // Read the response and verify that the create attempt failed.
435         if (logger.isDebugEnabled()) {
436             logger.debug(testName + ": status = " + statusCode);
437         }
438         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
439                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
440         Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
441
442     }
443
444
445     // ---------------------------------------------------------------
446     // CRUD tests : READ tests
447     // ---------------------------------------------------------------
448     // Success outcomes
449     /* (non-Javadoc)
450      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#read(java.lang.String)
451      */
452     @Override
453     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
454     dependsOnMethods = {"create"})
455     public void read(String testName) throws Exception {
456
457         // Perform setup.
458         setupRead(testName);
459
460         // Submit the request to the service and store the response.
461         CollectionObjectClient client = new CollectionObjectClient();
462         ClientResponse<MultipartInput> res = client.read(knownResourceId);
463         int statusCode = res.getStatus();
464
465         // Check the status code of the response: does it match
466         // the expected response(s)?
467         if (logger.isDebugEnabled()) {
468             logger.debug(testName + ": status = " + statusCode);
469         }
470         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
471                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
472         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
473
474         MultipartInput input = (MultipartInput) res.getEntity();
475
476         if (logger.isDebugEnabled()) {
477             logger.debug(testName + ": Reading Common part ...");
478         }
479         CollectionobjectsCommon collectionObject =
480                 (CollectionobjectsCommon) extractPart(input,
481                 client.getCommonPartName(), CollectionobjectsCommon.class);
482         Assert.assertNotNull(collectionObject);
483
484         if (logger.isDebugEnabled()) {
485             logger.debug(testName + ": Reading Natural History part ...");
486         }
487         CollectionobjectsNaturalhistory conh =
488                 (CollectionobjectsNaturalhistory) extractPart(input,
489                 getNHPartName(), CollectionobjectsNaturalhistory.class);
490         Assert.assertNotNull(conh);
491     }
492
493     // Failure outcomes
494     /* (non-Javadoc)
495      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readNonExistent(java.lang.String)
496      */
497     @Override
498     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
499     dependsOnMethods = {"read"})
500     public void readNonExistent(String testName) throws Exception {
501
502         // Perform setup.
503         setupReadNonExistent(testName);
504
505         // Submit the request to the service and store the response.
506         CollectionObjectClient client = new CollectionObjectClient();
507         ClientResponse<MultipartInput> res = client.read(NON_EXISTENT_ID);
508         int statusCode = res.getStatus();
509
510         // Check the status code of the response: does it match
511         // the expected response(s)?
512         if (logger.isDebugEnabled()) {
513             logger.debug(testName + ": status = " + statusCode);
514         }
515         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
516                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
517         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
518     }
519
520     
521     // ---------------------------------------------------------------
522     // CRUD tests : READ_LIST tests
523     // ---------------------------------------------------------------
524     // Success outcomes
525     /* (non-Javadoc)
526      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readList(java.lang.String)
527      */
528     @Override
529     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
530     dependsOnMethods = {"createList", "read"})
531     public void readList(String testName) throws Exception {
532
533         // Perform setup.
534         setupReadList(testName);
535
536         // Submit the request to the service and store the response.
537         CollectionObjectClient client = new CollectionObjectClient();
538         ClientResponse<CollectionobjectsCommonList> res = client.readList();
539         CollectionobjectsCommonList list = res.getEntity();
540         int statusCode = res.getStatus();
541
542         // Check the status code of the response: does it match
543         // the expected response(s)?
544         if (logger.isDebugEnabled()) {
545             logger.debug(testName + ": status = " + statusCode);
546         }
547         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
548                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
549         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
550
551         // Optionally output additional data about list members for debugging.
552         boolean iterateThroughList = false;
553         if (iterateThroughList && logger.isDebugEnabled()) {
554             List<CollectionobjectsCommonList.CollectionObjectListItem> items =
555                     list.getCollectionObjectListItem();
556             int i = 0;
557
558             for (CollectionobjectsCommonList.CollectionObjectListItem item : items) {
559                 logger.debug(testName + ": list-item[" + i + "] csid="
560                         + item.getCsid());
561                 logger.debug(testName + ": list-item[" + i + "] objectNumber="
562                         + item.getObjectNumber());
563                 logger.debug(testName + ": list-item[" + i + "] URI="
564                         + item.getUri());
565                 i++;
566
567             }
568         }
569     }
570
571     // Failure outcomes
572     // None at present.
573     // ---------------------------------------------------------------
574     // CRUD tests : UPDATE tests
575     // ---------------------------------------------------------------
576     // Success outcomes
577     /* (non-Javadoc)
578      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#update(java.lang.String)
579      */
580     @Override
581     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
582     dependsOnMethods = {"read"})
583     public void update(String testName) throws Exception {
584
585         // Perform setup.
586         setupUpdate(testName);
587
588         // Read an existing resource that will be updated.
589         ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
590
591         // Extract its common part.
592         CollectionObjectClient client = new CollectionObjectClient();
593         MultipartInput input = (MultipartInput) res.getEntity();
594         CollectionobjectsCommon collectionObject =
595                 (CollectionobjectsCommon) extractPart(input,
596                 client.getCommonPartName(), CollectionobjectsCommon.class);
597         Assert.assertNotNull(collectionObject);
598
599         // Change the content of one or more fields in the common part.
600         collectionObject.setObjectNumber("updated-" + collectionObject.getObjectNumber());
601         collectionObject.setObjectName("updated-" + collectionObject.getObjectName());
602         if (logger.isDebugEnabled()) {
603             logger.debug("sparse update that will be sent in update request:");
604             logger.debug(objectAsXmlString(collectionObject,
605                     CollectionobjectsCommon.class));
606         }
607
608         // Send the changed resource to be updated.
609         res = updateSend(testName, knownResourceId, collectionObject);
610         int statusCode = res.getStatus();
611         // Check the status code of the response: does it match the expected response(s)?
612         if (logger.isDebugEnabled()) {
613             logger.debug(testName + ": status = " + statusCode);
614         }
615         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
616                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
617         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
618
619         // Read the response and verify that the resource was correctly updated.
620         input = (MultipartInput) res.getEntity();
621         CollectionobjectsCommon updatedCollectionObject =
622                 (CollectionobjectsCommon) extractPart(input,
623                 client.getCommonPartName(), CollectionobjectsCommon.class);
624         Assert.assertNotNull(updatedCollectionObject);
625         Assert.assertEquals(updatedCollectionObject.getObjectName(),
626                 collectionObject.getObjectName(),
627                 "Data in updated object did not match submitted data.");
628
629     }
630
631     /**
632      * Update retrieve.
633      *
634      * @param testName the test name
635      * @param id the id
636      * @return the client response
637      */
638     private ClientResponse<MultipartInput> updateRetrieve(String testName, String id) {
639         final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
640         CollectionObjectClient client = new CollectionObjectClient();
641         ClientResponse<MultipartInput> res = client.read(id);
642         if (logger.isDebugEnabled()) {
643             logger.debug("read in updateRetrieve for " + testName + " status = " + res.getStatus());
644         }
645         Assert.assertEquals(res.getStatus(), EXPECTED_STATUS);
646         if (logger.isDebugEnabled()) {
647             logger.debug("got object to updateRetrieve for " + testName + " with ID: " + id);
648         }
649         return res;
650     }
651
652     /**
653      * Update send.
654      *
655      * @param testName the test name
656      * @param id the id
657      * @param collectionObject the collection object
658      * @return the client response
659      */
660     private ClientResponse<MultipartInput> updateSend(String testName, String id,
661             CollectionobjectsCommon collectionObject) {
662         MultipartOutput output = new MultipartOutput();
663         OutputPart commonPart = output.addPart(collectionObject, MediaType.APPLICATION_XML_TYPE);
664         CollectionObjectClient client = new CollectionObjectClient();
665         commonPart.getHeaders().add("label", client.getCommonPartName());
666         ClientResponse<MultipartInput> res = client.update(knownResourceId, output);
667         return res;
668     }
669
670     // Failure outcomes
671     // Placeholders until the three tests below can be uncommented.
672     // See Issue CSPACE-401.
673     /* (non-Javadoc)
674      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithEmptyEntityBody(java.lang.String)
675      */
676     @Override
677     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
678     dependsOnMethods = {"read"})
679     public void updateWithEmptyEntityBody(String testName) throws Exception {
680         //FIXME: Should this test really be empty?
681     }
682
683    /**
684     * Test how the service handles XML that is not well formed,
685     * when sent in the payload of an Update request.
686     *
687     * @param testName  The name of this test method.  This name is supplied
688     *     automatically, via reflection, by a TestNG 'data provider' in
689     *     a base class.
690     */
691     @Override
692     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
693     dependsOnMethods = {"read"})
694     public void updateWithMalformedXml(String testName) throws Exception {
695         //FIXME: Should this test really be empty?
696     }
697
698     /* (non-Javadoc)
699      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithWrongXmlSchema(java.lang.String)
700      */
701     @Override
702     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
703     dependsOnMethods = {"read"})
704     public void updateWithWrongXmlSchema(String testName) throws Exception {
705         //FIXME: Should this test really be empty?
706     }
707
708 /*
709     @Override
710     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
711     dependsOnMethods = {"create", "update", "testSubmitRequest"})
712     public void updateWithEmptyEntityBody(String testName) throws Exception {
713
714     // Perform setup.
715     setupUpdateWithEmptyEntityBody(testName);
716
717     // Submit the request to the service and store the response.
718     String method = REQUEST_TYPE.httpMethodName();
719     String url = getResourceURL(knownResourceId);
720     String mediaType = MediaType.APPLICATION_XML;
721     final String entity = "";
722     int statusCode = submitRequest(method, url, mediaType, entity);
723
724     // Check the status code of the response: does it match
725     // the expected response(s)?
726     if(logger.isDebugEnabled()){
727     logger.debug(testName + ": url=" + url +
728     " status=" + statusCode);
729     }
730     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
731     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
732     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
733     }
734
735     @Override
736     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
737     dependsOnMethods = {"create", "update", "testSubmitRequest"})
738     public void updateWithMalformedXml() throws Exception {
739
740     // Perform setup.
741     setupUpdateWithMalformedXml(testName);
742
743     // Submit the request to the service and store the response.
744     String method = REQUEST_TYPE.httpMethodName();
745     String url = getResourceURL(knownResourceId);
746     final String entity = MALFORMED_XML_DATA;
747     String mediaType = MediaType.APPLICATION_XML;
748     int statusCode = submitRequest(method, url, mediaType, entity);
749
750     // Check the status code of the response: does it match
751     // the expected response(s)?
752     if(logger.isDebugEnabled()){
753     logger.debug(testName + ": url=" + url +
754     " status=" + statusCode);
755     }
756     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
757     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
758     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
759     }
760
761     @Override
762     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
763     dependsOnMethods = {"create", "update", "testSubmitRequest"})
764     public void updateWithWrongXmlSchema(String testName) throws Exception {
765
766     // Perform setup.
767     setupUpdateWithWrongXmlSchema(String testName);
768
769     // Submit the request to the service and store the response.
770     String method = REQUEST_TYPE.httpMethodName();
771     String url = getResourceURL(knownResourceId);
772     String mediaType = MediaType.APPLICATION_XML;
773     final String entity = WRONG_XML_SCHEMA_DATA;
774     int statusCode = submitRequest(method, url, mediaType, entity);
775
776     // Check the status code of the response: does it match
777     // the expected response(s)?
778     if(logger.isDebugEnabled()){
779     logger.debug(testName + ": url=" + url +
780     " status=" + statusCode);
781     }
782     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
783     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
784     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
785     }
786 */
787
788     /* (non-Javadoc)
789  * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateNonExistent(java.lang.String)
790  */
791 @Override
792     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
793     dependsOnMethods = {"update", "testSubmitRequest"})
794     public void updateNonExistent(String testName) throws Exception {
795
796         // Perform setup.
797         setupUpdateNonExistent(testName);
798
799         // Submit the request to the service and store the response.
800         //
801         // Note: The ID used in this 'create' call may be arbitrary.
802         // The only relevant ID may be the one used in updateCollectionObject(), below.
803         CollectionObjectClient client = new CollectionObjectClient();
804         MultipartOutput multipart =
805                 createCollectionObjectInstance(client.getCommonPartName(),
806                 NON_EXISTENT_ID);
807         ClientResponse<MultipartInput> res =
808                 client.update(NON_EXISTENT_ID, multipart);
809         int statusCode = res.getStatus();
810
811         // Check the status code of the response: does it match
812         // the expected response(s)?
813         if (logger.isDebugEnabled()) {
814             logger.debug(testName + ": status = " + statusCode);
815         }
816         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
817                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
818         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
819     }
820
821    /**
822     * Test how the service handles, in an Update request, payloads
823     * containing null values (or, in the case of String fields,
824     * empty String values) in one or more fields in which non-empty
825     * values are required.
826     *
827     * This is a test of code and/or configuration in the service's
828     * validation routine(s).
829     *
830     * @param testName  The name of this test method.  This name is supplied
831     *     automatically, via reflection, by a TestNG 'data provider' in
832     *     a base class.
833  * @throws Exception 
834     */
835     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
836     dependsOnMethods = {"read"})
837     public void updateWithRequiredValuesNullOrEmpty(String testName) throws Exception {
838         // Perform setup.
839         setupUpdate(testName);
840         if (logger.isDebugEnabled()) {
841             logger.debug(testName + " got object to update with ID: " + knownResourceId);
842         }
843
844         // Read an existing record for updating.
845         ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
846
847         CollectionObjectClient client = new CollectionObjectClient();
848         MultipartInput input = (MultipartInput) res.getEntity();
849         CollectionobjectsCommon collectionObject =
850                 (CollectionobjectsCommon) extractPart(input,
851                 client.getCommonPartName(), CollectionobjectsCommon.class);
852         Assert.assertNotNull(collectionObject);
853
854         // Update with invalid content, by setting a value to the
855         // empty String, in a field that requires a non-empty value,
856         // as enforced by the service's validation routine(s).
857         collectionObject.setObjectNumber("");
858
859         if (logger.isDebugEnabled()) {
860             logger.debug(testName + " updated object");
861             logger.debug(objectAsXmlString(collectionObject,
862                     CollectionobjectsCommon.class));
863         }
864
865         // Submit the request to the service and store the response.
866         res = updateSend(testName, knownResourceId, collectionObject);
867         int statusCode = res.getStatus();
868
869         // Read the response and verify that the update attempt failed.
870         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
871                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
872         Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
873
874     }
875
876     // ---------------------------------------------------------------
877     // CRUD tests : DELETE tests
878     // ---------------------------------------------------------------
879     // Success outcomes
880     /* (non-Javadoc)
881      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#delete(java.lang.String)
882      */
883     @Override
884     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
885     dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
886     public void delete(String testName) throws Exception {
887
888         // Perform setup.
889         setupDelete(testName);
890
891         // Submit the request to the service and store the response.
892         CollectionObjectClient client = new CollectionObjectClient();
893         ClientResponse<Response> res = client.delete(knownResourceId);
894         int statusCode = res.getStatus();
895
896         // Check the status code of the response: does it match
897         // the expected response(s)?
898         if (logger.isDebugEnabled()) {
899             logger.debug(testName + ": status = " + statusCode);
900         }
901         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
902                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
903         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
904     }
905
906     // Failure outcomes
907     /* (non-Javadoc)
908      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#deleteNonExistent(java.lang.String)
909      */
910     @Override
911     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
912     dependsOnMethods = {"delete"})
913     public void deleteNonExistent(String testName) throws Exception {
914
915         // Perform setup.
916         setupDeleteNonExistent(testName);
917
918         // Submit the request to the service and store the response.
919         CollectionObjectClient client = new CollectionObjectClient();
920         ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
921         int statusCode = res.getStatus();
922
923         // Check the status code of the response: does it match
924         // the expected response(s)?
925         if (logger.isDebugEnabled()) {
926             logger.debug(testName + ": status = " + statusCode);
927         }
928         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
929                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
930         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
931     }
932
933     // ---------------------------------------------------------------
934     // Utility tests : tests of code used in tests above
935     // ---------------------------------------------------------------
936     /**
937      * Tests the code for manually submitting data that is used by several
938      * of the methods above.
939      * @throws Exception 
940      */
941
942     @Test(dependsOnMethods = {"create", "read"})
943     public void testSubmitRequest() throws Exception {
944         testSubmitRequest(knownResourceId);
945     }
946
947     /**
948      * Test submit request.
949      *
950      * @param resourceId the resource id
951      * @throws Exception the exception
952      */
953     private void testSubmitRequest(String resourceId) throws Exception {
954
955         // Expected status code: 200 OK
956         final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
957
958         // Submit the request to the service and store the response.
959         String method = ServiceRequestType.READ.httpMethodName();
960         String url = getResourceURL(resourceId);
961         int statusCode = submitRequest(method, url);
962
963         // Check the status code of the response: does it match
964         // the expected response(s)?
965         if (logger.isDebugEnabled()) {
966             logger.debug("testSubmitRequest: url=" + url
967                     + " status=" + statusCode);
968         }
969         Assert.assertEquals(statusCode, EXPECTED_STATUS);
970
971     }
972
973     // ---------------------------------------------------------------
974     // Utility methods used by tests above
975     // ---------------------------------------------------------------
976     /**
977      * Creates the collection object instance.
978      *
979      * @param commonPartName the common part name
980      * @param identifier the identifier
981      * @return the multipart output
982      */
983     private MultipartOutput createCollectionObjectInstance(String commonPartName,
984             String identifier) {
985         return createCollectionObjectInstance(commonPartName,
986                 "objectNumber-" + identifier,
987                 "objectName-" + identifier);
988     }
989
990     /**
991      * Creates the collection object instance.
992      *
993      * @param commonPartName the common part name
994      * @param objectNumber the object number
995      * @param objectName the object name
996      * @return the multipart output
997      */
998     private MultipartOutput createCollectionObjectInstance(String commonPartName,
999             String objectNumber, String objectName) {
1000         CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
1001         ResponsibleDepartmentList deptList = new ResponsibleDepartmentList();
1002         List<String> depts = deptList.getResponsibleDepartment();
1003         // @TODO Use properly formatted refNames for representative departments
1004         // in this example test record. The following are mere placeholders.
1005         depts.add("urn:org.collectionspace.services.department:Registrar");
1006         if (multivalue) {
1007             depts.add("urn:org.walkerart.department:Fine Art");
1008         }
1009         multivalue = !multivalue;
1010         //FIXME: Title does not need to be set.
1011         collectionObject.setTitle("atitle");
1012         collectionObject.setResponsibleDepartments(deptList);
1013         collectionObject.setObjectNumber(objectNumber);
1014         collectionObject.setOtherNumber("urn:org.walkerart.id:123");
1015         collectionObject.setObjectName(objectName);
1016         collectionObject.setAge(""); //test for null string
1017         collectionObject.setBriefDescription("Papier mache bird cow mask with horns, "
1018                 + "painted red with black and yellow spots. "
1019                 + "Puerto Rico. ca. 8&quot; high, 6&quot; wide, projects 10&quot; (with horns).");
1020
1021         CollectionobjectsNaturalhistory conh = new CollectionobjectsNaturalhistory();
1022         conh.setNhString("test-string");
1023         conh.setNhInt(999);
1024         conh.setNhLong(9999);
1025
1026
1027         MultipartOutput multipart = createCollectionObjectInstance(commonPartName, collectionObject, conh);
1028         return multipart;
1029     }
1030
1031     /**
1032      * Creates the collection object instance.
1033      *
1034      * @param commonPartName the common part name
1035      * @param collectionObject the collection object
1036      * @param conh the conh
1037      * @return the multipart output
1038      */
1039     private MultipartOutput createCollectionObjectInstance(String commonPartName,
1040             CollectionobjectsCommon collectionObject, CollectionobjectsNaturalhistory conh) {
1041
1042         MultipartOutput multipart = CollectionObjectFactory.createCollectionObjectInstance(
1043                 commonPartName, collectionObject, getNHPartName(), conh);
1044         if (logger.isDebugEnabled()) {
1045             logger.debug("to be created, collectionobject common");
1046             logger.debug(objectAsXmlString(collectionObject,
1047                     CollectionobjectsCommon.class));
1048         }
1049
1050         if (conh != null) {
1051             if (logger.isDebugEnabled()) {
1052                 logger.debug("to be created, collectionobject nhistory");
1053                 logger.debug(objectAsXmlString(conh,
1054                         CollectionobjectsNaturalhistory.class));
1055             }
1056         }
1057         return multipart;
1058
1059     }
1060
1061     /**
1062      * createCollectionObjectInstanceFromXml uses JAXB unmarshaller to retrieve
1063      * collectionobject from given file
1064      * @param commonPartName
1065      * @param commonPartFileName
1066      * @return
1067      * @throws Exception
1068      */
1069     private MultipartOutput createCollectionObjectInstanceFromXml(String testName, String commonPartName,
1070             String commonPartFileName) throws Exception {
1071
1072         CollectionobjectsCommon collectionObject =
1073                 (CollectionobjectsCommon) getObjectFromFile(CollectionobjectsCommon.class,
1074                 commonPartFileName);
1075         MultipartOutput multipart = new MultipartOutput();
1076         OutputPart commonPart = multipart.addPart(collectionObject,
1077                 MediaType.APPLICATION_XML_TYPE);
1078         commonPart.getHeaders().add("label", commonPartName);
1079
1080         if (logger.isDebugEnabled()) {
1081             logger.debug(testName + " to be created, collectionobject common");
1082             logger.debug(objectAsXmlString(collectionObject,
1083                     CollectionobjectsCommon.class));
1084         }
1085         return multipart;
1086
1087     }
1088
1089     /**
1090      * createCollectionObjectInstanceFromRawXml uses stringified collectionobject
1091      * retrieve from given file
1092      * @param commonPartName
1093      * @param commonPartFileName
1094      * @return
1095      * @throws Exception
1096      */
1097     private MultipartOutput createCollectionObjectInstanceFromRawXml(String testName, String commonPartName,
1098             String commonPartFileName) throws Exception {
1099
1100         MultipartOutput multipart = new MultipartOutput();
1101         String stringObject = getXmlDocumentAsString(commonPartFileName);
1102         if (logger.isDebugEnabled()) {
1103             logger.debug(testName + " to be created, collectionobject common " + "\n" + stringObject);
1104         }
1105         OutputPart commonPart = multipart.addPart(stringObject,
1106                 MediaType.APPLICATION_XML_TYPE);
1107         commonPart.getHeaders().add("label", commonPartName);
1108
1109         return multipart;
1110
1111     }
1112
1113     /**
1114      * Gets the nH part name.
1115      *
1116      * @return the nH part name
1117      */
1118     private String getNHPartName() {
1119         return "collectionobjects_naturalhistory";
1120     }
1121
1122     /**
1123      * Creates the from xml file.
1124      *
1125      * @param testName the test name
1126      * @param fileName the file name
1127      * @param useJaxb the use jaxb
1128      * @return the string
1129      * @throws Exception the exception
1130      */
1131     private String createFromXmlFile(String testName, String fileName, boolean useJaxb) throws Exception {
1132         // Perform setup, such as initializing the type of service request
1133         // (e.g. CREATE, DELETE), its valid and expected status codes, and
1134         // its associated HTTP method name (e.g. POST, DELETE).
1135         setupCreate(testName);
1136
1137         MultipartOutput multipart = null;
1138
1139         CollectionObjectClient client = new CollectionObjectClient();
1140         if (useJaxb) {
1141             multipart = createCollectionObjectInstanceFromXml(testName,
1142                     client.getCommonPartName(), fileName);
1143         } else {
1144             multipart = createCollectionObjectInstanceFromRawXml(testName,
1145                     client.getCommonPartName(), fileName);
1146         }
1147         ClientResponse<Response> res = client.create(multipart);
1148         int statusCode = res.getStatus();
1149
1150         if (logger.isDebugEnabled()) {
1151             logger.debug(testName + ": status = " + statusCode);
1152         }
1153         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1154                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1155         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1156         String newId = extractId(res);
1157         allResourceIdsCreated.add(newId);
1158         return newId;
1159     }
1160 }