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