]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
729af0e51e2f3faa6cc74de4f4e39be49f6b12d2
[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.text.DateFormat;
26 import java.text.SimpleDateFormat;
27 import java.util.Calendar;
28 import java.util.Date;
29 import java.util.List;
30 import java.util.TimeZone;
31 import javax.ws.rs.core.MediaType;
32 import javax.ws.rs.core.Response;
33
34 import org.collectionspace.services.common.datetime.GregorianCalendarDateTimeUtils;
35 import org.collectionspace.services.client.CollectionSpaceClient;
36 import org.collectionspace.services.client.MovementClient;
37 import org.collectionspace.services.jaxb.AbstractCommonList;
38 import org.collectionspace.services.movement.MovementsCommon;
39 import org.collectionspace.services.movement.MovementsCommonList;
40 import org.collectionspace.services.movement.MovementMethodsList;
41
42 import org.jboss.resteasy.client.ClientResponse;
43
44 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
45 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
46 import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
47 import org.testng.Assert;
48 import org.testng.annotations.Test;
49
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 /**
54  * MovementServiceTest, carries out tests against a
55  * deployed and running Movement Service.
56  *
57  * $LastChangedRevision$
58  * $LastChangedDate$
59  */
60 public class MovementServiceTest extends AbstractServiceTestImpl {
61
62    /** The logger. */
63     private final String CLASS_NAME = MovementServiceTest.class.getName();
64     private final Logger logger = LoggerFactory.getLogger(CLASS_NAME);
65
66     // Instance variables specific to this test.
67     /** The service path component. */
68     final String SERVICE_PATH_COMPONENT = "movements";
69     
70     /** The known resource id. */
71     private String knownResourceId = null;
72
73     private final static String TIMESTAMP_UTC = GregorianCalendarDateTimeUtils.timestampUTC();
74     
75     /* (non-Javadoc)
76      * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
77      */
78     @Override
79     protected CollectionSpaceClient getClientInstance() {
80         return new MovementClient();
81     }
82     
83     /* (non-Javadoc)
84      * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
85      */
86     @Override
87         protected AbstractCommonList getAbstractCommonList(
88                         ClientResponse<AbstractCommonList> response) {
89         return response.getEntity(MovementsCommonList.class);
90     }
91  
92     // ---------------------------------------------------------------
93     // CRUD tests : CREATE tests
94     // ---------------------------------------------------------------
95     // Success outcomes
96     /* (non-Javadoc)
97      * @see org.collectionspace.services.client.test.ServiceTest#create(java.lang.String)
98      */
99     @Override
100     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class)
101     public void create(String testName) throws Exception {
102
103         if (logger.isDebugEnabled()) {
104             logger.debug(testBanner(testName, CLASS_NAME));
105         }
106         // Perform setup, such as initializing the type of service request
107         // (e.g. CREATE, DELETE), its valid and expected status codes, and
108         // its associated HTTP method name (e.g. POST, DELETE).
109         setupCreate();
110
111         // Submit the request to the service and store the response.
112         MovementClient client = new MovementClient();
113         String identifier = createIdentifier();
114         MultipartOutput multipart = createMovementInstance(identifier);
115         ClientResponse<Response> res = client.create(multipart);
116
117         int statusCode = res.getStatus();
118
119         // Check the status code of the response: does it match
120         // the expected response(s)?
121         //
122         // Specifically:
123         // Does it fall within the set of valid status codes?
124         // Does it exactly match the expected status code?
125         if(logger.isDebugEnabled()){
126             logger.debug(testName + ": status = " + statusCode);
127         }
128         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
129                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
130         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
131
132         // Store the ID returned from the first resource created
133         // for additional tests below.
134         if (knownResourceId == null){
135             knownResourceId = extractId(res);
136             if (logger.isDebugEnabled()) {
137                 logger.debug(testName + ": knownResourceId=" + knownResourceId);
138             }
139         }
140         
141         // Store the IDs from every resource created by tests,
142         // so they can be deleted after tests have been run.
143         allResourceIdsCreated.add(extractId(res));
144     }
145
146     /* (non-Javadoc)
147      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createList(java.lang.String)
148      */
149     @Override
150     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
151         dependsOnMethods = {"create"})
152     public void createList(String testName) throws Exception {
153         for(int i = 0; i < 3; i++){
154             create(testName);
155         }
156     }
157
158     // Failure outcomes
159     // Placeholders until the three tests below can be uncommented.
160     // See Issue CSPACE-401.
161     /* (non-Javadoc)
162      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithEmptyEntityBody(java.lang.String)
163      */
164     @Override
165     public void createWithEmptyEntityBody(String testName) throws Exception {
166         //Should this really be empty?
167     }
168
169     /* (non-Javadoc)
170      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithMalformedXml(java.lang.String)
171      */
172     @Override
173     public void createWithMalformedXml(String testName) throws Exception {
174         //Should this really be empty?
175     }
176
177     /* (non-Javadoc)
178      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithWrongXmlSchema(java.lang.String)
179      */
180     @Override
181     public void createWithWrongXmlSchema(String testName) throws Exception {
182         //Should this really be empty?
183     }
184
185     /*
186     @Override
187     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
188         dependsOnMethods = {"create", "testSubmitRequest"})
189     public void createWithEmptyEntityBody(String testName) throws Exception {
190
191         if (logger.isDebugEnabled()) {
192             logger.debug(testBanner(testName, CLASS_NAME));
193         }
194         // Perform setup.
195         setupCreateWithEmptyEntityBody();
196
197         // Submit the request to the service and store the response.
198         String method = REQUEST_TYPE.httpMethodName();
199         String url = getServiceRootURL();
200         String mediaType = MediaType.APPLICATION_XML;
201         final String entity = "";
202         int statusCode = submitRequest(method, url, mediaType, entity);
203
204         // Check the status code of the response: does it match
205         // the expected response(s)?
206         if(logger.isDebugEnabled()){
207             logger.debug("createWithEmptyEntityBody url=" + url +
208                 " status=" + statusCode);
209          }
210         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
211         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
212         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
213     }
214
215     @Override
216     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
217         dependsOnMethods = {"create", "testSubmitRequest"})
218     public void createWithMalformedXml(String testName) throws Exception {
219
220         if (logger.isDebugEnabled()) {
221             logger.debug(testBanner(testName, CLASS_NAME));
222         }
223         // Perform setup.
224         setupCreateWithMalformedXml();
225
226         // Submit the request to the service and store the response.
227         String method = REQUEST_TYPE.httpMethodName();
228         String url = getServiceRootURL();
229         String mediaType = MediaType.APPLICATION_XML;
230         final String entity = MALFORMED_XML_DATA; // Constant from base class.
231         int statusCode = submitRequest(method, url, mediaType, entity);
232
233         // Check the status code of the response: does it match
234         // the expected response(s)?
235         if(logger.isDebugEnabled()){
236             logger.debug(testName + ": url=" + url +
237                 " status=" + statusCode);
238          }
239         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
240         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
241         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
242     }
243
244     @Override
245     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
246         dependsOnMethods = {"create", "testSubmitRequest"})
247     public void createWithWrongXmlSchema(String testName) throws Exception {
248
249         if (logger.isDebugEnabled()) {
250             logger.debug(testBanner(testName, CLASS_NAME));
251         }
252         // Perform setup.
253         setupCreateWithWrongXmlSchema();
254
255         // Submit the request to the service and store the response.
256         String method = REQUEST_TYPE.httpMethodName();
257         String url = getServiceRootURL();
258         String mediaType = MediaType.APPLICATION_XML;
259         final String entity = WRONG_XML_SCHEMA_DATA;
260         int statusCode = submitRequest(method, url, mediaType, entity);
261
262         // Check the status code of the response: does it match
263         // the expected response(s)?
264         if(logger.isDebugEnabled()){
265             logger.debug(testName + ": url=" + url +
266                 " status=" + statusCode);
267          }
268         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
269         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
270         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
271     }
272      */
273
274     // ---------------------------------------------------------------
275     // CRUD tests : READ tests
276     // ---------------------------------------------------------------
277     // Success outcomes
278     /* (non-Javadoc)
279      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#read(java.lang.String)
280      */
281     @Override
282     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
283         dependsOnMethods = {"create"})
284     public void read(String testName) throws Exception {
285
286         if (logger.isDebugEnabled()) {
287             logger.debug(testBanner(testName, CLASS_NAME));
288         }
289         // Perform setup.
290         setupRead();
291
292         // Submit the request to the service and store the response.
293         MovementClient client = new MovementClient();
294         ClientResponse<MultipartInput> res = client.read(knownResourceId);
295         int statusCode = res.getStatus();
296
297         // Check the status code of the response: does it match
298         // the expected response(s)?
299         if(logger.isDebugEnabled()){
300             logger.debug(testName + ": status = " + statusCode);
301         }
302         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
303                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
304         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
305
306         MultipartInput input = (MultipartInput) res.getEntity();
307         MovementsCommon movement = (MovementsCommon) extractPart(input,
308                 client.getCommonPartName(), MovementsCommon.class);
309         Assert.assertNotNull(movement);
310
311         // Check the values of one or more date/time fields
312         if (logger.isDebugEnabled()) {
313             logger.debug("locationDate=" + movement.getLocationDate());
314             logger.debug("TIMESTAMP_UTC=" + TIMESTAMP_UTC);
315         }
316         Assert.assertTrue(movement.getLocationDate().equals(TIMESTAMP_UTC));
317         Assert.assertTrue(movement.getPlannedRemovalDate().equals(TIMESTAMP_UTC));
318         Assert.assertNull(movement.getRemovalDate());
319     }
320
321     // Failure outcomes
322     /* (non-Javadoc)
323      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readNonExistent(java.lang.String)
324      */
325     @Override
326     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
327         dependsOnMethods = {"read"})
328     public void readNonExistent(String testName) throws Exception {
329
330         if (logger.isDebugEnabled()) {
331             logger.debug(testBanner(testName, CLASS_NAME));
332         }
333         // Perform setup.
334         setupReadNonExistent();
335
336         // Submit the request to the service and store the response.
337         MovementClient client = new MovementClient();
338         ClientResponse<MultipartInput> res = client.read(NON_EXISTENT_ID);
339         int statusCode = res.getStatus();
340
341         // Check the status code of the response: does it match
342         // the expected response(s)?
343         if(logger.isDebugEnabled()){
344             logger.debug(testName + ": status = " + statusCode);
345         }
346         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
347                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
348         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
349     }
350
351     // ---------------------------------------------------------------
352     // CRUD tests : READ_LIST tests
353     // ---------------------------------------------------------------
354     // Success outcomes
355     /* (non-Javadoc)
356      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readList(java.lang.String)
357      */
358     @Override
359     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
360         dependsOnMethods = {"createList", "read"})
361     public void readList(String testName) throws Exception {
362
363         if (logger.isDebugEnabled()) {
364             logger.debug(testBanner(testName, CLASS_NAME));
365         }
366         // Perform setup.
367         setupReadList();
368
369         // Submit the request to the service and store the response.
370         MovementClient client = new MovementClient();
371         ClientResponse<MovementsCommonList> res = client.readList();
372         MovementsCommonList list = res.getEntity();
373         int statusCode = res.getStatus();
374
375         // Check the status code of the response: does it match
376         // the expected response(s)?
377         if(logger.isDebugEnabled()){
378             logger.debug(testName + ": status = " + statusCode);
379         }
380         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
381                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
382         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
383
384         // Optionally output additional data about list members for debugging.
385         boolean iterateThroughList = true;
386         if(iterateThroughList && logger.isDebugEnabled()){
387             List<MovementsCommonList.MovementListItem> items =
388                     list.getMovementListItem();
389             int i = 0;
390             for(MovementsCommonList.MovementListItem item : items){
391                 logger.debug(testName + ": list-item[" + i + "] csid=" +
392                         item.getCsid());
393                 logger.debug(testName + ": list-item[" + i + "] movementReferenceNumber=" +
394                         item.getMovementReferenceNumber());
395                 logger.debug(testName + ": list-item[" + i + "] locationDate=" +
396                         item.getLocationDate());
397                 logger.debug(testName + ": list-item[" + i + "] URI=" +
398                         item.getUri());
399                 i++;
400             }
401         }
402
403     }
404
405     // Failure outcomes
406     // None at present.
407     // ---------------------------------------------------------------
408     // CRUD tests : UPDATE tests
409     // ---------------------------------------------------------------
410     // Success outcomes
411     /* (non-Javadoc)
412      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#update(java.lang.String)
413      */
414     @Override
415     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
416         dependsOnMethods = {"read"})
417     public void update(String testName) throws Exception {
418
419         if (logger.isDebugEnabled()) {
420             logger.debug(testBanner(testName, CLASS_NAME));
421         }
422         // Perform setup.
423         setupUpdate();
424
425         // Retrieve the contents of a resource to update.
426         MovementClient client = new MovementClient();
427         ClientResponse<MultipartInput> res =
428                 client.read(knownResourceId);
429         if(logger.isDebugEnabled()){
430             logger.debug(testName + ": read status = " + res.getStatus());
431         }
432         Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
433
434         if(logger.isDebugEnabled()){
435             logger.debug("got object to update with ID: " + knownResourceId);
436         }
437         MultipartInput input = (MultipartInput) res.getEntity();
438         MovementsCommon movement = (MovementsCommon) extractPart(input,
439                 client.getCommonPartName(), MovementsCommon.class);
440         Assert.assertNotNull(movement);
441
442         // Update the content of this resource.
443         movement.setMovementReferenceNumber("updated-" + movement.getMovementReferenceNumber());
444         movement.setMovementNote("updated movement note-" + movement.getMovementNote());
445         movement.setNormalLocation(""); // Test deletion of existing string value
446
447         String currentTimestamp = GregorianCalendarDateTimeUtils.timestampUTC();
448         movement.setPlannedRemovalDate(""); // Test deletion of existing date or date/time value
449         movement.setRemovalDate(currentTimestamp);
450
451         if(logger.isDebugEnabled()){
452             logger.debug("to be updated object");
453             logger.debug(objectAsXmlString(movement, MovementsCommon.class));
454         }
455
456         // Submit the request to the service and store the response.
457         MultipartOutput output = new MultipartOutput();
458         OutputPart commonPart = output.addPart(movement, MediaType.APPLICATION_XML_TYPE);
459         commonPart.getHeaders().add("label", client.getCommonPartName());
460
461         res = client.update(knownResourceId, output);
462         int statusCode = res.getStatus();
463         // Check the status code of the response: does it match the expected response(s)?
464         if(logger.isDebugEnabled()){
465             logger.debug(testName + ": status = " + statusCode);
466         }
467         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
468                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
469         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
470
471         input = (MultipartInput) res.getEntity();
472         MovementsCommon updatedMovement =
473                 (MovementsCommon) extractPart(input,
474                         client.getCommonPartName(), MovementsCommon.class);
475         Assert.assertNotNull(updatedMovement);
476
477         if(logger.isDebugEnabled()){
478             logger.debug("updated object");
479             logger.debug(objectAsXmlString(movement, MovementsCommon.class));
480         }
481
482         Assert.assertEquals(updatedMovement.getNormalLocation(),
483             movement.getNormalLocation(), "Data in updated object did not match submitted data.");
484         if(logger.isDebugEnabled()){
485             logger.debug("Normal location after update=|" + updatedMovement.getNormalLocation() + "|");
486         }
487
488         Assert.assertEquals(updatedMovement.getMovementReferenceNumber(),
489             movement.getMovementReferenceNumber(),
490             "Data in updated object did not match submitted data.");
491         Assert.assertEquals(updatedMovement.getMovementNote(),
492             movement.getMovementNote(),
493             "Data in updated object did not match submitted data.");
494         Assert.assertNull(updatedMovement.getPlannedRemovalDate());
495         Assert.assertEquals(updatedMovement.getRemovalDate(),
496             movement.getRemovalDate(),
497             "Data in updated object did not match submitted data.");
498
499     }
500
501     // Failure outcomes
502     // Placeholders until the three tests below can be uncommented.
503     // See Issue CSPACE-401.
504     /* (non-Javadoc)
505      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithEmptyEntityBody(java.lang.String)
506      */
507     @Override
508     public void updateWithEmptyEntityBody(String testName) throws Exception{
509         //Should this really be empty?
510     }
511     
512     /* (non-Javadoc)
513      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithMalformedXml(java.lang.String)
514      */
515     @Override
516     public void updateWithMalformedXml(String testName) throws Exception {
517         //Should this really be empty?
518     }
519     
520     /* (non-Javadoc)
521      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithWrongXmlSchema(java.lang.String)
522      */
523     @Override
524     public void updateWithWrongXmlSchema(String testName) throws Exception {
525         //Should this really be empty?
526     }
527
528     /*
529     @Override
530     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
531         dependsOnMethods = {"create", "update", "testSubmitRequest"})
532     public void updateWithEmptyEntityBody(String testName) throws Exception {
533
534         if (logger.isDebugEnabled()) {
535             logger.debug(testBanner(testName, CLASS_NAME));
536         }
537         // Perform setup.
538         setupUpdateWithEmptyEntityBody();
539
540         // Submit the request to the service and store the response.
541         String method = REQUEST_TYPE.httpMethodName();
542         String url = getResourceURL(knownResourceId);
543         String mediaType = MediaType.APPLICATION_XML;
544         final String entity = "";
545         int statusCode = submitRequest(method, url, mediaType, entity);
546
547         // Check the status code of the response: does it match
548         // the expected response(s)?
549         if(logger.isDebugEnabled()){
550             logger.debug(testName + ": url=" + url +
551                 " status=" + statusCode);
552          }
553         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
554         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
555         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
556     }
557
558     @Override
559     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
560         dependsOnMethods = {"create", "update", "testSubmitRequest"})
561     public void updateWithMalformedXml(String testName) throws Exception {
562
563         if (logger.isDebugEnabled()) {
564             logger.debug(testBanner(testName, CLASS_NAME));
565         }
566         // Perform setup.
567         setupUpdateWithMalformedXml();
568
569         // Submit the request to the service and store the response.
570         String method = REQUEST_TYPE.httpMethodName();
571         String url = getResourceURL(knownResourceId);
572         String mediaType = MediaType.APPLICATION_XML;
573         final String entity = MALFORMED_XML_DATA;
574         int statusCode = submitRequest(method, url, mediaType, entity);
575
576         // Check the status code of the response: does it match
577         // the expected response(s)?
578         if(logger.isDebugEnabled()){
579             logger.debug(testName + ": url=" + url +
580              " status=" + statusCode);
581          }
582         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
583         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
584         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
585     }
586
587     @Override
588     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
589         dependsOnMethods = {"create", "update", "testSubmitRequest"})
590     public void updateWithWrongXmlSchema(String testName) throws Exception {
591
592         if (logger.isDebugEnabled()) {
593             logger.debug(testBanner(testName, CLASS_NAME));
594         }
595         // Perform setup.
596         setupUpdateWithWrongXmlSchema();
597
598         // Submit the request to the service and store the response.
599         String method = REQUEST_TYPE.httpMethodName();
600         String url = getResourceURL(knownResourceId);
601         String mediaType = MediaType.APPLICATION_XML;
602         final String entity = WRONG_XML_SCHEMA_DATA;
603         int statusCode = submitRequest(method, url, mediaType, entity);
604
605         // Check the status code of the response: does it match
606         // the expected response(s)?
607         if(logger.isDebugEnabled()){
608             logger.debug(testName + ": url=" + url +
609             " status=" + statusCode);
610          }
611         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
612         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
613         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
614     }
615      */
616
617     /* (non-Javadoc)
618      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateNonExistent(java.lang.String)
619      */
620     @Override
621     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
622         dependsOnMethods = {"update", "testSubmitRequest"})
623     public void updateNonExistent(String testName) throws Exception {
624
625         if (logger.isDebugEnabled()) {
626             logger.debug(testBanner(testName, CLASS_NAME));
627         }
628         // Perform setup.
629         setupUpdateNonExistent();
630
631         // Submit the request to the service and store the response.
632         // Note: The ID used in this 'create' call may be arbitrary.
633         // The only relevant ID may be the one used in update(), below.
634         MovementClient client = new MovementClient();
635         MultipartOutput multipart = createMovementInstance(NON_EXISTENT_ID);
636         ClientResponse<MultipartInput> res =
637                 client.update(NON_EXISTENT_ID, multipart);
638         int statusCode = res.getStatus();
639
640         // Check the status code of the response: does it match
641         // the expected response(s)?
642         if(logger.isDebugEnabled()){
643             logger.debug(testName + ": status = " + statusCode);
644         }
645         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
646                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
647         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
648     }
649
650     // ---------------------------------------------------------------
651     // CRUD tests : DELETE tests
652     // ---------------------------------------------------------------
653     // Success outcomes
654     /* (non-Javadoc)
655      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#delete(java.lang.String)
656      */
657
658     @Override
659     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
660         dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
661     public void delete(String testName) throws Exception {
662
663         if (logger.isDebugEnabled()) {
664             logger.debug(testBanner(testName, CLASS_NAME));
665         }
666         /*
667         // Perform setup.
668         setupDelete();
669
670         // Submit the request to the service and store the response.
671         MovementClient client = new MovementClient();
672         ClientResponse<Response> res = client.delete(knownResourceId);
673         int statusCode = res.getStatus();
674
675         // Check the status code of the response: does it match
676         // the expected response(s)?
677         if(logger.isDebugEnabled()){
678             logger.debug(testName + ": status = " + statusCode);
679         }
680         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
681                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
682         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
683      *
684      */
685     }
686
687
688     // Failure outcomes
689     /* (non-Javadoc)
690      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#deleteNonExistent(java.lang.String)
691      */
692     @Override
693     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
694         dependsOnMethods = {"delete"})
695     public void deleteNonExistent(String testName) throws Exception {
696
697         if (logger.isDebugEnabled()) {
698             logger.debug(testBanner(testName, CLASS_NAME));
699         }
700         // Perform setup.
701         setupDeleteNonExistent();
702
703         // Submit the request to the service and store the response.
704         MovementClient client = new MovementClient();
705         ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
706         int statusCode = res.getStatus();
707
708         // Check the status code of the response: does it match
709         // the expected response(s)?
710         if(logger.isDebugEnabled()){
711             logger.debug(testName + ": status = " + statusCode);
712         }
713         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
714                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
715         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
716     }
717
718     // ---------------------------------------------------------------
719     // Utility tests : tests of code used in tests above
720     // ---------------------------------------------------------------
721     /**
722      * Tests the code for manually submitting data that is used by several
723      * of the methods above.
724      */
725     @Test(dependsOnMethods = {"create", "read"})
726     public void testSubmitRequest() {
727
728         // Expected status code: 200 OK
729         final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
730
731         // Submit the request to the service and store the response.
732         String method = ServiceRequestType.READ.httpMethodName();
733         String url = getResourceURL(knownResourceId);
734         int statusCode = submitRequest(method, url);
735
736         // Check the status code of the response: does it match
737         // the expected response(s)?
738         if(logger.isDebugEnabled()){
739             logger.debug("testSubmitRequest: url=" + url +
740                 " status=" + statusCode);
741         }
742         Assert.assertEquals(statusCode, EXPECTED_STATUS);
743
744     }
745
746     // ---------------------------------------------------------------
747     // Utility methods used by tests above
748     // ---------------------------------------------------------------
749     /* (non-Javadoc)
750      * @see org.collectionspace.services.client.test.BaseServiceTest#getServicePathComponent()
751      */
752     @Override
753     public String getServicePathComponent() {
754         return SERVICE_PATH_COMPONENT;
755     }
756
757     /**
758      * Creates the movement instance.
759      *
760      * @param identifier the identifier
761      * @return the multipart output
762      */
763     private MultipartOutput createMovementInstance(String identifier) {
764         return createInstance("movementReferenceNumber-" + identifier);
765     }
766
767     /**
768      * Creates an instance of a Movement record for testing.
769      *
770      * @param movementReferenceNumber A movement reference number.
771      * @return Multipart output suitable for use as a payload
772      *     in a create or update request.
773      */
774     private MultipartOutput createInstance(String movementReferenceNumber) {
775         MovementsCommon movement = new MovementsCommon();
776         // FIXME: Values of currentLocation, normalLocation,
777         // and movementContact should be refNames.
778         movement.setCurrentLocation("currentLocation value");
779         movement.setCurrentLocationFitness("currentLocationFitness value");
780         movement.setCurrentLocationNote("currentLocationNote value");
781         movement.setLocationDate(TIMESTAMP_UTC);
782         movement.setNormalLocation("normalLocation value");
783         movement.setMovementContact("movementContact value");
784         MovementMethodsList movementMethodsList = new MovementMethodsList();
785         List<String> methods = movementMethodsList.getMovementMethod();
786         // @TODO Use properly formatted refNames for representative movement
787         // methods in this example record. The values below are placeholders.
788         String identifier = createIdentifier();
789         methods.add("First Movement Method-" + identifier);
790         methods.add("Second Movement Method-" + identifier);
791         movement.setMovementMethods(movementMethodsList);
792         movement.setMovementNote("movementNote value");
793         movement.setMovementReferenceNumber(movementReferenceNumber);
794         movement.setPlannedRemovalDate(TIMESTAMP_UTC);
795         movement.setRemovalDate(""); // Test empty date value
796         movement.setReasonForMove("reasonForMove value");
797         MultipartOutput multipart = new MultipartOutput();
798         OutputPart commonPart =
799             multipart.addPart(movement, MediaType.APPLICATION_XML_TYPE);
800         commonPart.getHeaders().add("label", new MovementClient().getCommonPartName());
801
802         if(logger.isDebugEnabled()){
803             logger.debug("to be created, movement common");
804             logger.debug(objectAsXmlString(movement, MovementsCommon.class));
805         }
806
807         return multipart;
808     }
809
810     // FIXME Should be moved to a common class, as these are general utilities.
811     // FIXME Should be refactored to become a convenience variant of a
812     // general method to return a current datestamp or timestamp in any
813     // provided time zone.
814
815    /**
816     * Returns an ISO 8601 formatted timestamp of the
817     * current time instance in the UTC time zone.
818     */
819     public String datestampUTC() {
820         final String ISO_8601_DATE_FORMAT_PATTERN = "yyyy-MM-dd";
821         final DateFormat ISO_8601_DATE_FORMAT =
822             new SimpleDateFormat(ISO_8601_DATE_FORMAT_PATTERN);
823
824         final String UTC_TIMEZONE_IDENTIFIER = "UTC";
825         final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone(UTC_TIMEZONE_IDENTIFIER);
826
827         Date timestamp = new Date();
828         return formatDate(timestamp, UTC_TIMEZONE, ISO_8601_DATE_FORMAT);
829     }
830
831    /**
832     * Returns an ISO 8601 formatted timestamp of the
833     * current time instance in the UTC time zone.
834     */
835     public String timestampUTC() {
836         final String ISO_8601_FORMAT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'";
837         final DateFormat ISO_8601_FORMAT =
838             new SimpleDateFormat(ISO_8601_FORMAT_PATTERN);
839
840         final String UTC_TIMEZONE_IDENTIFIER = "UTC";
841         final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone(UTC_TIMEZONE_IDENTIFIER);
842
843         Date timestamp = new Date();
844         return formatDate(timestamp, UTC_TIMEZONE, ISO_8601_FORMAT);
845     }
846
847    /**
848     * Formats a provided date using a provided date formatter,
849     * in the default system time zone.
850     *
851     * @param date  A date to format.
852     * @param df    A date formatter to apply.
853     * @return      A formatted date string.
854     */
855     public String formatDate(Date date, DateFormat df) {
856         return formatDate(date, TimeZone.getDefault(), df);
857     }
858
859     // FIXME Add error handling.
860
861    /**
862     * Formats a provided date using a provided date formatter,
863     * in a provided time zone.
864     *
865     * @param date  A date to format.
866     * @param tz    The time zone qualifier for the date to format.
867     * @param df    A date formatter to apply.
868     *
869     * @return      A formatted date string.
870     */
871     public String formatDate(Date date, TimeZone tz, DateFormat df) {
872         df.setTimeZone(tz);
873         return df.format(date);
874     }
875
876 }