Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2010 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *  Purpose: To test the Access Controls in metacat by JUnit
6
 *
7
 *   '$Author:$'
8
 *     '$Date:$'
9
 * '$Revision:$'
10
 *
11
 * This program is free software; you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation; either version 2 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program; if not, write to the Free Software
23
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24
 */
25

    
26
package edu.ucsb.nceas.metacat.dataone;
27

    
28

    
29
import gov.loc.repository.bagit.Bag;
30
import gov.loc.repository.bagit.BagFactory;
31
import gov.loc.repository.bagit.BagFile;
32
import gov.loc.repository.bagit.Manifest;
33

    
34
import java.io.ByteArrayInputStream;
35
import java.io.ByteArrayOutputStream;
36
import java.io.File;
37
import java.io.FileOutputStream;
38
import java.io.IOException;
39
import java.io.InputStream;
40
import java.io.UnsupportedEncodingException;
41
import java.text.SimpleDateFormat;
42
import java.util.ArrayList;
43
import java.util.Calendar;
44
import java.util.Date;
45
import java.util.HashMap;
46
import java.util.Iterator;
47
import java.util.List;
48
import java.util.Map;
49

    
50
import junit.framework.Test;
51
import junit.framework.TestSuite;
52

    
53
import org.apache.commons.io.IOUtils;
54
import org.dataone.client.ObjectFormatCache;
55
import org.dataone.configuration.Settings;
56
import org.dataone.ore.ResourceMapFactory;
57
import org.dataone.service.util.TypeMarshaller;
58
import org.dataone.service.exceptions.IdentifierNotUnique;
59
import org.dataone.service.exceptions.InsufficientResources;
60
import org.dataone.service.exceptions.InvalidRequest;
61
import org.dataone.service.exceptions.InvalidSystemMetadata;
62
import org.dataone.service.exceptions.InvalidToken;
63
import org.dataone.service.exceptions.NotAuthorized;
64
import org.dataone.service.exceptions.NotFound;
65
import org.dataone.service.exceptions.NotImplemented;
66
import org.dataone.service.exceptions.ServiceFailure;
67
import org.dataone.service.exceptions.SynchronizationFailed;
68
import org.dataone.service.exceptions.UnsupportedType;
69
import org.dataone.service.types.v1.AccessPolicy;
70
import org.dataone.service.types.v1.AccessRule;
71
import org.dataone.service.types.v1.Checksum;
72
import org.dataone.service.types.v1.DescribeResponse;
73
import org.dataone.service.types.v1.Event;
74
import org.dataone.service.types.v1.Identifier;
75
import org.dataone.service.types.v1.Log;
76
import org.dataone.service.types.v1.MonitorList;
77
import org.dataone.service.types.v1.Node;
78
import org.dataone.service.types.v1.NodeReference;
79
import org.dataone.service.types.v1.ObjectFormatIdentifier;
80
import org.dataone.service.types.v1.ObjectList;
81
import org.dataone.service.types.v1.Permission;
82
import org.dataone.service.types.v1.Person;
83
import org.dataone.service.types.v1.Session;
84
import org.dataone.service.types.v1.Subject;
85
import org.dataone.service.types.v1.SubjectInfo;
86
import org.dataone.service.types.v1.SystemMetadata;
87
import org.dspace.foresite.ResourceMap;
88
import org.jibx.runtime.JiBXException;
89
import org.junit.After;
90
import org.junit.Before;
91

    
92
/**
93
 * A JUnit test to exercise the Metacat Member Node service implementation.
94
 * This also tests a few of the D1NodeService superclass methods
95
 * 
96
 * @author cjones
97
 *
98
 */
99
public class MNodeServiceTest extends D1NodeServiceTest {
100

    
101
  /**
102
   * Set up the test fixtures
103
   * 
104
   * @throws Exception
105
   */
106
  @Before
107
  public void setUp() throws Exception {
108
    super.setUp();
109
    // set up the configuration for d1client
110
    Settings.getConfiguration().setProperty("D1Client.cnClassName", MockCNode.class.getName());
111
  }
112

    
113
  /**
114
   * Remove the test fixtures
115
   */
116
  @After
117
  public void tearDown() {
118
  }
119
  
120
  /**
121
   * Build the test suite
122
   * @return
123
   */
124
  public static Test suite() {
125
    
126
    TestSuite suite = new TestSuite();
127
    suite.addTest(new MNodeServiceTest("initialize"));
128
    // MNStorage tests
129
    suite.addTest(new MNodeServiceTest("testCreate"));
130
    suite.addTest(new MNodeServiceTest("testCreateInvalidIdentifier"));
131
    suite.addTest(new MNodeServiceTest("testUpdate"));
132
    // this requires MN certificate
133
    suite.addTest(new MNodeServiceTest("testDelete"));
134
    
135
    // MNRead tests
136
    suite.addTest(new MNodeServiceTest("testGet"));
137
    suite.addTest(new MNodeServiceTest("testGetChecksum"));
138
    suite.addTest(new MNodeServiceTest("testGetSystemMetadata"));
139
    suite.addTest(new MNodeServiceTest("testDescribe"));
140
    suite.addTest(new MNodeServiceTest("testListObjects"));
141
    // this requires CN certificate
142
    suite.addTest(new MNodeServiceTest("testSynchronizationFailed"));
143
    
144
    // MNCore tests
145
    suite.addTest(new MNodeServiceTest("testPing"));
146
    suite.addTest(new MNodeServiceTest("testGetLogRecords"));
147
    suite.addTest(new MNodeServiceTest("testGetOperationStatistics"));
148
    suite.addTest(new MNodeServiceTest("testGetCapabilities"));
149
    // include these when they are part of the MN interface definitions
150
    // suite.addTest(new MNodeServiceTest("testGetObjectStatistics"));
151
    // suite.addTest(new MNodeServiceTest("testGetStatus"));
152
    // MNAuthorization tests
153
    suite.addTest(new MNodeServiceTest("testIsAuthorized"));
154
    suite.addTest(new MNodeServiceTest("testIsEquivIdentityAuthorized"));
155
    suite.addTest(new MNodeServiceTest("testSetAccessPolicy"));
156
    // MNreplication tests
157
    suite.addTest(new MNodeServiceTest("testReplicate"));
158
    // MN packaging tests
159
    suite.addTest(new MNodeServiceTest("testGetPackage"));
160
    suite.addTest(new MNodeServiceTest("testGetOREPackage"));
161
    
162
    
163
    return suite;
164
    
165
  }
166
  
167
  /**
168
   * Constructor for the tests
169
   * 
170
   * @param name - the name of the test
171
   */
172
  public MNodeServiceTest(String name) {
173
    super(name);
174
    
175
  }
176

    
177
  /**
178
   * Initial blank test
179
   */
180
  public void initialize() {
181
    assertTrue(1 == 1);
182
    
183
  }
184
  
185
  /**
186
   * Test getting a known object
187
   */
188
  public void testGet() {
189
    printTestHeader("testGet");
190

    
191
    try {
192
      Session session = getTestSession();
193
      Identifier guid = new Identifier();
194
      guid.setValue("testGet." + System.currentTimeMillis());
195
      InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
196
      SystemMetadata sysmeta = createSystemMetadata(guid, session.getSubject(), object);
197
      Identifier pid = MNodeService.getInstance(request).create(session, guid, object, sysmeta);
198
      InputStream result = MNodeService.getInstance(request).get(session, guid);
199
      // go back to beginning of original stream
200
      object.reset();
201
      // check
202
      assertTrue(object.available() > 0);
203
      assertTrue(result.available() > 0);
204
      assertTrue(IOUtils.contentEquals(result, object));
205
      
206
    } catch (UnsupportedEncodingException e) {
207
      e.printStackTrace();
208
      fail("Unexpected error: " + e.getMessage());
209

    
210
    } catch (InvalidToken e) {
211
      e.printStackTrace();
212
      fail("Unexpected error: " + e.getMessage());
213
      
214
    } catch (ServiceFailure e) {
215
      e.printStackTrace();
216
      fail("Unexpected error: " + e.getMessage());
217
      
218
    } catch (NotAuthorized e) {
219
      e.printStackTrace();
220
      fail("Unexpected error: " + e.getMessage());
221
      
222
    } catch (IdentifierNotUnique e) {
223
      e.printStackTrace();
224
      fail("Unexpected error: " + e.getMessage());
225
      
226
    } catch (UnsupportedType e) {
227
      e.printStackTrace();
228
      fail("Unexpected error: " + e.getMessage());
229
      
230
    } catch (InsufficientResources e) {
231
      e.printStackTrace();
232
      fail("Unexpected error: " + e.getMessage());
233
      
234
    } catch (InvalidSystemMetadata e) {
235
      e.printStackTrace();
236
      fail("Unexpected error: " + e.getMessage());
237
      
238
    } catch (NotImplemented e) {
239
      e.printStackTrace();
240
      fail("Unexpected error: " + e.getMessage());
241
      
242
    } catch (InvalidRequest e) {
243
      e.printStackTrace();
244
      fail("Unexpected error: " + e.getMessage());
245
      
246
    } catch (NotFound e) {
247
      e.printStackTrace();
248
      fail("Unexpected error: " + e.getMessage());
249
      
250
    } catch (Exception e) {
251
      e.printStackTrace();
252
      fail("Unexpected error: " + e.getMessage());
253
      
254
    }
255

    
256
  }
257

    
258
  /**
259
   * Test getting the system metadata of an object
260
   */
261
  public void testGetSystemMetadata() {    
262
    printTestHeader("testGetSystemMetadata");
263

    
264
    try {
265
      Session session = getTestSession();
266
      Identifier guid = new Identifier();
267
      guid.setValue("testGetSystemMetadata." + System.currentTimeMillis());
268
      InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
269
      SystemMetadata sysmeta = createSystemMetadata(guid, session.getSubject(), object);
270
      Identifier pid = MNodeService.getInstance(request).create(session, guid, object, sysmeta);
271
      SystemMetadata newsysmeta = MNodeService.getInstance(request).getSystemMetadata(session, pid);
272
      assertEquals(newsysmeta.getIdentifier().getValue(), sysmeta.getIdentifier().getValue());
273
      
274
    } catch (UnsupportedEncodingException e) {
275
      e.printStackTrace();
276
      fail("Unexpected error: " + e.getMessage());
277

    
278
    } catch (InvalidToken e) {
279
      e.printStackTrace();      
280
      fail("Unexpected error: " + e.getMessage());
281

    
282
    } catch (ServiceFailure e) {
283
      e.printStackTrace();
284
      fail("Unexpected error: " + e.getMessage());
285

    
286
    } catch (NotAuthorized e) {
287
      e.printStackTrace();
288
      fail("Unexpected error: " + e.getMessage());
289

    
290
    } catch (IdentifierNotUnique e) {
291
      e.printStackTrace();
292
      fail("Unexpected error: " + e.getMessage());
293
      
294
    } catch (UnsupportedType e) {
295
      e.printStackTrace();
296
      fail("Unexpected error: " + e.getMessage());
297

    
298
    } catch (InsufficientResources e) {
299
      e.printStackTrace();
300
      fail("Unexpected error: " + e.getMessage());
301

    
302
    } catch (InvalidSystemMetadata e) {
303
      e.printStackTrace();
304
      fail("Unexpected error: " + e.getMessage());
305

    
306
    } catch (NotImplemented e) {
307
      e.printStackTrace();
308
      fail("Unexpected error: " + e.getMessage());
309

    
310
    } catch (InvalidRequest e) {
311
      e.printStackTrace();
312
      fail("Unexpected error: " + e.getMessage());
313

    
314
    } catch (NotFound e) {
315
      e.printStackTrace();
316
      fail("Unexpected error: " + e.getMessage());
317

    
318
    } catch (Exception e) {
319
      e.printStackTrace();
320
      fail("Unexpected error: " + e.getMessage());
321

    
322
    }
323
    
324
  }
325

    
326
  /**
327
   * Test object creation
328
   */
329
  public void testCreate() {
330
    printTestHeader("testCreate");
331
    
332
    try {
333
      Session session = getTestSession();
334
      Identifier guid = new Identifier();
335
      guid.setValue("testCreate." + System.currentTimeMillis());
336
      InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
337
      SystemMetadata sysmeta = createSystemMetadata(guid, session.getSubject(), object);
338
      Identifier pid = MNodeService.getInstance(request).create(session, guid, object, sysmeta);
339
      assertEquals(guid.getValue(), pid.getValue());
340
    } catch (UnsupportedEncodingException e) {
341
      e.printStackTrace();
342
      fail("Unexpected error: " + e.getMessage());
343

    
344
    } catch (InvalidToken e) {
345
      e.printStackTrace();
346
      fail("Unexpected error: " + e.getMessage());
347

    
348
    } catch (ServiceFailure e) {
349
      e.printStackTrace();
350
      fail("Unexpected error: " + e.getMessage());
351

    
352
    } catch (NotAuthorized e) {
353
      e.printStackTrace();
354
      fail("Unexpected error: " + e.getMessage());
355

    
356
    } catch (IdentifierNotUnique e) {
357
      e.printStackTrace();
358
      fail("Unexpected error: " + e.getMessage());
359

    
360
    } catch (UnsupportedType e) {
361
      e.printStackTrace();
362
      fail("Unexpected error: " + e.getMessage());
363

    
364
    } catch (InsufficientResources e) {
365
      e.printStackTrace();
366
      fail("Unexpected error: " + e.getMessage());
367

    
368
    } catch (InvalidSystemMetadata e) {
369
      e.printStackTrace();
370
      fail("Unexpected error: " + e.getMessage());
371

    
372
    } catch (NotImplemented e) {
373
      e.printStackTrace();
374
      fail("Unexpected error: " + e.getMessage());
375

    
376
    } catch (InvalidRequest e) {
377
      e.printStackTrace();
378
      fail("Unexpected error: " + e.getMessage());
379

    
380
    } catch (Exception e) {
381
      e.printStackTrace();
382
      fail("Unexpected error: " + e.getMessage());
383

    
384
    }
385
      
386
  }
387

    
388
  /**
389
   * test object deletion
390
   */
391
  public void testDelete() {
392
    printTestHeader("testDelete");
393

    
394
    try {
395
      Session session = getTestSession();
396
      Identifier guid = new Identifier();
397
      guid.setValue("testDelete." + System.currentTimeMillis());
398
      InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
399
      SystemMetadata sysmeta = createSystemMetadata(guid, session.getSubject(), object);
400
      Identifier pid = MNodeService.getInstance(request).create(session, guid, object, sysmeta);
401
      
402
      // use MN admin to delete
403
      session = getMNSession();
404
      Identifier deletedPid = MNodeService.getInstance(request).delete(session, pid);
405
      assertEquals(pid.getValue(), deletedPid.getValue());
406
      // check that we cannot get the object
407
      session = getTestSession();
408
      InputStream deletedObject = null;
409
      try {
410
    	  deletedObject = MNodeService.getInstance(request).get(session, deletedPid);
411
      } catch (NotFound nf) {
412
    	  // this is expected
413
      }
414
	  assertNull(deletedObject);
415
      
416
    } catch (UnsupportedEncodingException e) {
417
      e.printStackTrace();
418
      
419
    } catch (Exception e) {
420
      e.printStackTrace();
421
      fail("Unexpected error: " + e.getMessage());
422

    
423
    } 
424

    
425
  }
426

    
427
  /**
428
   * Test object updating
429
   */
430
  public void testUpdate() {
431
    printTestHeader("testUpdate");
432
    
433
    try {
434
      Session session = getTestSession();
435
      Identifier guid = new Identifier();
436
      guid.setValue("testUpdate." + System.currentTimeMillis());
437
      InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
438
      SystemMetadata sysmeta = createSystemMetadata(guid, session.getSubject(), object);
439
      Identifier newPid = new Identifier();
440
      newPid.setValue("testUpdate." + (System.currentTimeMillis() + 1)); // ensure it is different from original
441
      Identifier pid = 
442
        MNodeService.getInstance(request).create(session, guid, object, sysmeta);
443
      
444
      SystemMetadata newSysMeta = createSystemMetadata(newPid, session.getSubject(), object);
445
            
446
      // do the update
447
      Identifier updatedPid = 
448
        MNodeService.getInstance(request).update(session, pid, object, newPid, newSysMeta);
449
      
450
      // get the updated system metadata
451
      SystemMetadata updatedSysMeta = 
452
        MNodeService.getInstance(request).getSystemMetadata(session, updatedPid);
453

    
454
      assertEquals(updatedPid.getValue(), newPid.getValue());
455
//      assertTrue(updatedSysMeta.getObsolete(0).getValue().equals(pid.getValue()));
456
//      assertTrue(updatedSysMeta.getDerivedFrom(0).getValue().equals(pid.getValue()));        
457
      
458
    } catch (UnsupportedEncodingException e) {
459
      e.printStackTrace();
460
      fail("Unexpected error: " + e.getMessage());
461

    
462
    } catch (InvalidToken e) {
463
      e.printStackTrace();
464
      fail("Unexpected error: " + e.getMessage());
465

    
466
    } catch (ServiceFailure e) {
467
      e.printStackTrace();
468
      fail("Unexpected error: " + e.getMessage());
469

    
470
    } catch (NotAuthorized e) {
471
      e.printStackTrace();
472
      fail("Unexpected error: " + e.getMessage());
473

    
474
    } catch (IdentifierNotUnique e) {
475
      e.printStackTrace();
476
      fail("Unexpected error: " + e.getMessage());
477

    
478
    } catch (UnsupportedType e) {
479
      e.printStackTrace();
480
      fail("Unexpected error: " + e.getMessage());
481

    
482
    } catch (InsufficientResources e) {
483
      e.printStackTrace();
484
      fail("Unexpected error: " + e.getMessage());
485

    
486
    } catch (InvalidSystemMetadata e) {
487
      e.printStackTrace();
488
      fail("Unexpected error: " + e.getMessage());
489

    
490
    } catch (NotImplemented e) {
491
      e.printStackTrace();
492
      fail("Unexpected error: " + e.getMessage());
493

    
494
    } catch (InvalidRequest e) {
495
      e.printStackTrace();
496
      fail("Unexpected error: " + e.getMessage());
497

    
498
    } catch (Exception e) {
499
      e.printStackTrace();
500
      fail("Unexpected error: " + e.getMessage());
501

    
502
    }
503
  }
504

    
505
  /**
506
   * We currently expect this unit test to fail because it should rely on a different member node
507
   * to retrieve the object from. Currently it gets the object from itself and throws 
508
   * and expected error for duplicate entry.
509
   * 
510
   */
511
  public void testReplicate() {
512
      printTestHeader("testReplicate");
513
      try {
514
        Session session = getTestSession();
515
        Identifier guid = new Identifier();
516
        guid.setValue("testReplicate." + System.currentTimeMillis());
517
        InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
518
        SystemMetadata sysmeta = createSystemMetadata(guid, session.getSubject(), object);
519
        // save locally
520
        Identifier pid = MNodeService.getInstance(request).create(session, guid, object, sysmeta);
521
        // get our node reference (attempting to replicate with self)
522
        NodeReference sourceNode = MNodeService.getInstance(request).getCapabilities().getIdentifier();
523
        // attempt to replicate with ourselves -- this should fail!
524
      boolean result = false;
525
      try {
526
        result = MNodeService.getInstance(request).replicate(session, sysmeta, sourceNode);
527
      } catch (Exception inu) {
528
        // we are expecting this to fail since we already have the doc
529
        result = true;
530
      }
531
      assertTrue(result);
532
      } catch (Exception e) {
533
        e.printStackTrace();
534
      fail("Probably not yet implemented: " + e.getMessage());
535
    }
536
  }
537

    
538
  /**
539
   * Test describing an object
540
   */
541
  public void testDescribe() {
542
    printTestHeader("testDescribe");
543

    
544
    try {
545
      Session session = getTestSession();
546
      Identifier guid = new Identifier();
547
      guid.setValue("testGetSystemMetadata." + System.currentTimeMillis());
548
      InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
549
      SystemMetadata sysmeta = createSystemMetadata(guid, session.getSubject(), object);
550
      Identifier pid = MNodeService.getInstance(request).create(session, guid, object, sysmeta);
551
      DescribeResponse describeResponse = MNodeService.getInstance(request).describe(session, pid);
552
      assertEquals(describeResponse.getDataONE_Checksum().getValue(), sysmeta.getChecksum().getValue());
553
      assertEquals(describeResponse.getDataONE_ObjectFormatIdentifier().getValue(), sysmeta.getFormatId().getValue());
554
      
555
    } catch (UnsupportedEncodingException e) {
556
      e.printStackTrace();
557
      fail("Unexpected error: " + e.getMessage());
558

    
559
    } catch (InvalidToken e) {
560
      e.printStackTrace();      
561
      fail("Unexpected error: " + e.getMessage());
562

    
563
    } catch (ServiceFailure e) {
564
      e.printStackTrace();
565
      fail("Unexpected error: " + e.getMessage());
566

    
567
    } catch (NotAuthorized e) {
568
      e.printStackTrace();
569
      fail("Unexpected error: " + e.getMessage());
570

    
571
    } catch (IdentifierNotUnique e) {
572
      e.printStackTrace();
573
      fail("Unexpected error: " + e.getMessage());
574
      
575
    } catch (UnsupportedType e) {
576
      e.printStackTrace();
577
      fail("Unexpected error: " + e.getMessage());
578

    
579
    } catch (InsufficientResources e) {
580
      e.printStackTrace();
581
      fail("Unexpected error: " + e.getMessage());
582

    
583
    } catch (InvalidSystemMetadata e) {
584
      e.printStackTrace();
585
      fail("Unexpected error: " + e.getMessage());
586

    
587
    } catch (NotImplemented e) {
588
      e.printStackTrace();
589
      fail("Unexpected error: " + e.getMessage());
590

    
591
    } catch (InvalidRequest e) {
592
      e.printStackTrace();
593
      fail("Unexpected error: " + e.getMessage());
594

    
595
    } catch (NotFound e) {
596
      e.printStackTrace();
597
      fail("Unexpected error: " + e.getMessage());
598

    
599
    } catch (Exception e) {
600
      e.printStackTrace();
601
      fail("Unexpected error: " + e.getMessage());
602

    
603
    }
604
  }
605

    
606
  /**
607
   * Test getting the checksum of an object
608
   */
609
  public void testGetChecksum() {
610
    printTestHeader("testGetChecksum");
611

    
612
    try {
613
      Session session = getTestSession();
614
      Identifier guid = new Identifier();
615
      guid.setValue("testGetChecksum." + System.currentTimeMillis());
616
      InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
617
      SystemMetadata sysmeta = createSystemMetadata(guid, session.getSubject(), object);
618
      Identifier pid = MNodeService.getInstance(request).create(session, guid, object, sysmeta);
619
      Checksum checksum = MNodeService.getInstance(request).getChecksum(session, pid, "MD5");
620
      assertEquals(checksum.getValue(), sysmeta.getChecksum().getValue());
621
    
622
    } catch (UnsupportedEncodingException e) {
623
      e.printStackTrace();
624
      fail("Unexpected error: " + e.getMessage());
625

    
626
    } catch (InvalidToken e) {
627
      e.printStackTrace();
628
      fail("Unexpected error: " + e.getMessage());
629

    
630
    } catch (ServiceFailure e) {
631
      e.printStackTrace();
632
      fail("Unexpected error: " + e.getMessage());
633

    
634
    } catch (NotAuthorized e) {
635
      e.printStackTrace();
636
      fail("Unexpected error: " + e.getMessage());
637

    
638
    } catch (IdentifierNotUnique e) {
639
      e.printStackTrace();
640
      fail("Unexpected error: " + e.getMessage());
641

    
642
    } catch (UnsupportedType e) {
643
      e.printStackTrace();
644
      fail("Unexpected error: " + e.getMessage());
645

    
646
    } catch (InsufficientResources e) {
647
      e.printStackTrace();
648
      fail("Unexpected error: " + e.getMessage());
649

    
650
    } catch (InvalidSystemMetadata e) {
651
      e.printStackTrace();
652
      fail("Unexpected error: " + e.getMessage());
653

    
654
    } catch (NotImplemented e) {
655
      e.printStackTrace();
656
      fail("Unexpected error: " + e.getMessage());
657

    
658
    } catch (InvalidRequest e) {
659
      e.printStackTrace();
660
      fail("Unexpected error: " + e.getMessage());
661

    
662
    } catch (NotFound e) {
663
      e.printStackTrace();
664
      fail("Unexpected error: " + e.getMessage());
665

    
666
    } catch (Exception e) {
667
      e.printStackTrace();
668
      fail("Unexpected error: " + e.getMessage());
669

    
670
    }
671
    
672
  }
673

    
674
  /**
675
   * Testing listing objects on the Member Node
676
   */
677
  public void testListObjects() {
678
      printTestHeader("testListObjects");
679
  
680
      try {
681
  
682
        Session session = getTestSession();
683
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
684
        Date startTime = sdf.parse("2010-01-01");
685
        Date endTime = new Date();
686
        ObjectFormatIdentifier objectFormatId = null;
687
        boolean replicaStatus = false;
688
        int start = 0;
689
        int count = 1;
690
      
691
        // insert at least one object 
692
        testCreate();
693
        // now check that we have at least one
694
        ObjectList objectList = 
695
          MNodeService.getInstance(request).listObjects(session, startTime, endTime, 
696
              objectFormatId, replicaStatus, start, count);
697
        assertNotNull(objectList);
698
        assertTrue(objectList.getCount() == count);
699
        assertTrue(objectList.getStart() == 0);
700
        assertTrue(objectList.getTotal() > 1);
701
        
702
      } catch (Exception e) {
703
        e.printStackTrace();
704
        fail("Unexpected error: " + e.getMessage());
705
  
706
      }
707
  }
708

    
709
  public void testGetCapabilities() {
710
      printTestHeader("testGetCapabilities");
711
    try {
712
      Node node = MNodeService.getInstance(request).getCapabilities();
713
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
714
      TypeMarshaller.marshalTypeToOutputStream(node, baos);
715
      assertNotNull(node);
716
      // TODO: should probably test other parts of the node information
717
      
718
    } catch (JiBXException e) {
719
        e.printStackTrace();
720
        fail("The node instance couldn't be parsed correctly:" + e.getMessage());
721
        
722
    } catch (IOException e) {
723
        e.printStackTrace();
724
        fail("The node instance couldn't be read correctly:" + e.getMessage());
725
        
726
    } catch (Exception e) {
727
        e.printStackTrace();
728
        fail("Probably not yet implemented: " + e.getMessage());
729
        
730
    }
731
    
732
  }
733

    
734
  public void testGetOperationStatistics() {
735
      printTestHeader("testGetOperationStatistics");
736
    try {
737
      Session session = getCNSession();
738
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
739
        Date startTime = sdf.parse("2010-01-01");
740
        Date endTime = new Date();
741
      MonitorList monitorList = 
742
        MNodeService.getInstance(request).getOperationStatistics(
743
            session, 
744
            startTime, 
745
            endTime, 
746
            session.getSubject(), 
747
            Event.CREATE, 
748
            null //formatId
749
            );
750
      
751
      assertNotNull(monitorList);
752
      // TODO: should probably test other parts of the information
753
    } catch (Exception e) {
754
      e.printStackTrace();
755
      fail("Probably not yet implemented: " + e.getMessage());
756
    }
757
  }
758

    
759
  public void testPing() {
760

    
761
    try {
762
      Date mnDate = MNodeService.getInstance(request).ping();
763
      assertTrue(mnDate != null);
764
      
765
    } catch (NotImplemented e) {
766
      e.printStackTrace();
767
      fail("Unexpected error: " + e.getMessage());
768

    
769
    } catch (ServiceFailure e) {
770
      e.printStackTrace();
771
      fail("Unexpected error: " + e.getMessage());
772

    
773
    }  catch (InsufficientResources e) {
774
      e.printStackTrace();
775
      fail("Unexpected error: " + e.getMessage());
776

    
777
    }
778
    
779
  }
780

    
781
  public void testSynchronizationFailed() {
782
    printTestHeader("testSynchronizationFailed");
783
    try {
784
        Session session = getTestSession();
785
        
786
        // create the object
787
        Identifier pid = new Identifier();
788
        pid.setValue("testSynchronizationFailed." + System.currentTimeMillis());
789
        InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
790
        SystemMetadata sysmeta = createSystemMetadata(pid, session.getSubject(), object);
791
        Identifier retPid = MNodeService.getInstance(request).create(session, pid, object, sysmeta);
792
        assertEquals(retPid.getValue(), pid.getValue());
793
        
794
        // pretend the sync failed, act as CN
795
      SynchronizationFailed syncFailed = 
796
        new SynchronizationFailed("0000", "Testing Synch Failure");
797
      syncFailed.setPid(pid.getValue());
798
      session = getCNSession();
799
      MNodeService.getInstance(request).synchronizationFailed(session, syncFailed );
800
    } catch (Exception e) {
801
      e.printStackTrace();
802
        fail("Unexpected error: " + e.getMessage());
803
    }
804

    
805
  }
806

    
807
  public void testSystemMetadataChanged() {
808
      printTestHeader("testSystemMetadataChanged");
809
      try {
810
          Session session = getTestSession();
811
          
812
          // create the object
813
          Identifier pid = new Identifier();
814
          pid.setValue("testSystemMetadataChanged." + System.currentTimeMillis());
815
          InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
816
          SystemMetadata sysmeta = createSystemMetadata(pid, session.getSubject(), object);
817
          Identifier retPid = MNodeService.getInstance(request).create(session, pid, object, sysmeta);
818
          assertEquals(retPid.getValue(), pid.getValue());
819
          
820
          // pretend the system metadata changed on the CN
821
          MNodeService.getInstance(request).systemMetadataChanged(session, 
822
                  retPid, 5000L, Calendar.getInstance().getTime());
823
          
824
      } catch (Exception e) {
825
          if (e instanceof NotAuthorized) {
826
              // only CN subjects can call this
827
              // TODO: use a CN certificate in the tests
828
          } else {
829
              fail("Unexpected error: " + e.getMessage());
830
              
831
          }
832
      }
833

    
834
    }
835

    
836
  public void testGetLogRecords() {
837
    printTestHeader("testLogRecords");
838

    
839
    try {
840
	    Log log = null;
841
	    Session session = getCNSession();
842
	    Date fromDate = new Date();
843
	    Calendar calendar = Calendar.getInstance();
844
	    calendar.setTime(fromDate);
845
	    calendar.roll(Calendar.YEAR, false);
846
	    fromDate = calendar.getTime();
847
	    Date toDate = new Date();
848
	    Event event = Event.CREATE;
849
	    int start = 0;
850
	    int count = 1;
851
    
852
      log = MNodeService.getInstance(request).getLogRecords(session, fromDate, toDate, 
853
        event, null, start, count);
854
      
855
      assertNotNull(log);      
856
      assertTrue(log.getCount() == count);
857
      assertTrue(log.getStart() == start);
858
      assertTrue(log.getTotal() >= 1);
859
        
860
    } catch (Exception e) {
861
      e.printStackTrace();
862
      fail("Unexpected error: " + e.getMessage());
863

    
864
    }
865
  }
866

    
867
  /**
868
   * Testing setting access on a known object
869
   */
870
  public void testSetAccessPolicy() {
871
    printTestHeader("testSetAccess");
872
    
873
    //boolean accessWasSet = false;
874
    //
875
    //try {
876
    //  // create an object to set access on
877
    //  Session session = getTestSession();
878
    //  Identifier guid = new Identifier();
879
    //  guid.setValue("testSetAccess." + System.currentTimeMillis());
880
    //  InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
881
    //  SystemMetadata sysmeta = createSystemMetadata(guid, session.getSubject(), object);
882
    //  Identifier pid = 
883
    //    MNodeService.getInstance(request).create(session, guid, object, sysmeta);
884
    //  // set the access
885
    //  AccessPolicy accessPolicy = new AccessPolicy();
886
    //  AccessRule allow = new AccessRule();
887
    //  allow.addPermission(Permission.WRITE);
888
    //  Subject publicSubject = new Subject();
889
    //  publicSubject.setValue(Constants.SUBJECT_PUBLIC);
890
    //  allow.addSubject(publicSubject);
891
    //  accessPolicy.addAllow(allow);
892
    //  
893
    //  accessWasSet = 
894
    //    MNodeService.getInstance(request).setAccessPolicy(session, pid, accessPolicy);
895
    //  assertTrue(accessWasSet);
896
    //  // test that it is enforced
897
    //  session.setSubject(publicSubject);
898
    //  boolean isAuthorized = MNodeService.getInstance(request).isAuthorized(session, pid, Permission.WRITE);
899
    //  assertTrue(isAuthorized);
900
    //
901
    //} catch (UnsupportedEncodingException e) {
902
    //  e.printStackTrace();
903
    //  
904
    //} catch (InvalidToken e) {
905
    //  e.printStackTrace();
906
    //  fail("Unexpected error: " + e.getMessage());
907
    //  
908
    //} catch (ServiceFailure e) {
909
    //  e.printStackTrace();
910
    //  fail("Unexpected error: " + e.getMessage());
911
    //  
912
    //} catch (NotAuthorized e) {
913
    //  e.printStackTrace();
914
    //  fail("Unexpected error: " + e.getMessage());
915
    //  
916
    //} catch (IdentifierNotUnique e) {
917
    //  e.printStackTrace();
918
    //  fail("Unexpected error: " + e.getMessage());
919
    //  
920
    //} catch (UnsupportedType e) {
921
    //  e.printStackTrace();
922
    //  fail("Unexpected error: " + e.getMessage());
923
    //  
924
    //} catch (InsufficientResources e) {
925
    //  e.printStackTrace();
926
    //  fail("Unexpected error: " + e.getMessage());
927
    //  
928
    //} catch (InvalidSystemMetadata e) {
929
    //  e.printStackTrace();
930
    //  fail("Unexpected error: " + e.getMessage());
931
    //  
932
    //} catch (NotImplemented e) {
933
    //  e.printStackTrace();
934
    //  fail("Unexpected error: " + e.getMessage());
935
    //  
936
    //} catch (InvalidRequest e) {
937
    //  e.printStackTrace();
938
    //  fail("Unexpected error: " + e.getMessage());
939
    //  
940
    //} catch (NotFound e) {
941
    //  e.printStackTrace();
942
    //  fail("Unexpected error: " + e.getMessage());
943
    //  
944
    //} catch (Exception e) {
945
    //  e.printStackTrace();
946
    //  fail("Unexpected error: " + e.getMessage());
947
    //  
948
    //}
949
      
950
  }
951

    
952
  /**
953
   * Test if a subject is authorized to read a known object
954
   */
955
  public void testIsAuthorized() {
956
    printTestHeader("testIsAuthorized");
957
    
958
    try {
959
      Session session = getTestSession();
960
      Identifier guid = new Identifier();
961
      guid.setValue("testIsAuthorized." + System.currentTimeMillis());
962
      InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
963
      SystemMetadata sysmeta = createSystemMetadata(guid, session.getSubject(), object);
964
      Identifier pid = 
965
        MNodeService.getInstance(request).create(session, guid, object, sysmeta);
966
      boolean isAuthorized = 
967
        MNodeService.getInstance(request).isAuthorized(session, pid, Permission.READ);
968
      assertEquals(isAuthorized, true);
969
      
970
    } catch (UnsupportedEncodingException e) {
971
      e.printStackTrace();
972
      fail("Unexpected error: " + e.getMessage());
973

    
974
    } catch (InvalidToken e) {
975
      e.printStackTrace();
976
      fail("Unexpected error: " + e.getMessage());
977

    
978
    } catch (ServiceFailure e) {
979
      e.printStackTrace();
980
      fail("Unexpected error: " + e.getMessage());
981

    
982
    } catch (NotAuthorized e) {
983
      e.printStackTrace();
984
      fail("Unexpected error: " + e.getMessage());
985

    
986
    } catch (IdentifierNotUnique e) {
987
      e.printStackTrace();
988
      fail("Unexpected error: " + e.getMessage());
989

    
990
    } catch (UnsupportedType e) {
991
      e.printStackTrace();
992
      fail("Unexpected error: " + e.getMessage());
993

    
994
    } catch (InsufficientResources e) {
995
      e.printStackTrace();
996
      fail("Unexpected error: " + e.getMessage());
997

    
998
    } catch (InvalidSystemMetadata e) {
999
      e.printStackTrace();
1000
      fail("Unexpected error: " + e.getMessage());
1001

    
1002
    } catch (NotImplemented e) {
1003
      e.printStackTrace();
1004
      fail("Unexpected error: " + e.getMessage());
1005

    
1006
    } catch (InvalidRequest e) {
1007
      e.printStackTrace();
1008
      fail("Unexpected error: " + e.getMessage());
1009

    
1010
    } catch (Exception e) {
1011
      e.printStackTrace();
1012
      fail("Unexpected error: " + e.getMessage());
1013

    
1014
    }
1015
  }
1016

    
1017
  
1018
  public void testIsEquivIdentityAuthorized() {
1019
      printTestHeader("testIsEquivIdentityAuthorized");
1020

    
1021
      try {
1022
          Session session = new Session();
1023
          Subject s = new Subject();
1024
          s.setValue("cn=test,dc=dataone,dc=org");
1025
          session.setSubject(s);
1026
          
1027
          Identifier pid = new Identifier();
1028
          pid.setValue("testIsEquivIdentityAuthorized." + System.currentTimeMillis());
1029
          InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
1030
          SystemMetadata sysmeta = createSystemMetadata(pid, session.getSubject(), object);
1031
          
1032
          // reset the access policy to only allow 'self' read (no public)
1033
          AccessPolicy ap = new AccessPolicy();
1034
          AccessRule ar = new AccessRule();
1035
          List<Subject> sList = new ArrayList<Subject>();
1036
          sList.add(session.getSubject());
1037
          ar.setSubjectList(sList);
1038
          List<Permission> permList = new ArrayList<Permission>();
1039
          permList.add(Permission.CHANGE_PERMISSION);
1040
          ar.setPermissionList(permList);
1041
          ap.addAllow(ar);
1042
          sysmeta.setAccessPolicy(ap);
1043
          
1044
          // save it
1045
          Identifier retPid = CNodeService.getInstance(request).registerSystemMetadata(session, pid, sysmeta);
1046
          assertEquals(pid.getValue(), retPid.getValue());
1047
          
1048
          //check it against an equivalent identity not listed in the access policy
1049
          session.getSubject().setValue("cn=newSubject,dc=dataone,dc=org");
1050
          SubjectInfo subjectInfo = new SubjectInfo();
1051
          Person person = new Person();
1052
          person.setSubject(session.getSubject());
1053
          List<String> givenNames = new ArrayList<String>();
1054
          givenNames.add("New");
1055
          person.setGivenNameList(givenNames);
1056
          person.setFamilyName("Subject");
1057
          
1058
          // add equivalent identities
1059
          List<Subject> equivIdentities = new ArrayList<Subject>();
1060
          Subject mappedSubject2 = new Subject();
1061
          mappedSubject2.setValue("cn=test2,dc=dataone,dc=org");
1062
          equivIdentities.add(mappedSubject2);
1063
          
1064
          Subject mappedSubject = new Subject();
1065
          mappedSubject.setValue("cn=test,dc=dataone,dc=org");
1066
          equivIdentities.add(mappedSubject);          
1067
          
1068
          person.setEquivalentIdentityList(equivIdentities);
1069
          
1070
          List<Person> personList = new ArrayList<Person>();
1071
          personList.add(person);
1072
          subjectInfo.setPersonList(personList);
1073
          
1074
          // update the session to include subject info with a mapped identity
1075
          session.setSubjectInfo(subjectInfo);
1076
          boolean result = CNodeService.getInstance(request).isAuthorized(session, pid, Permission.READ);
1077
          assertTrue(result);
1078
        
1079
    } catch (Exception e) {
1080
        e.printStackTrace();
1081
        
1082
    }
1083
    
1084
  }
1085

    
1086
/**
1087
   * Test object creation failure when there is a space in the identifier
1088
   */
1089
  public void testCreateInvalidIdentifier() {
1090
    printTestHeader("testCreateInvalidIdentifier");
1091
    
1092
    try {
1093
      Session session = getTestSession();
1094
      Identifier guid = new Identifier();
1095
      guid.setValue("testCreate withspace." + System.currentTimeMillis());
1096
      InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
1097
      SystemMetadata sysmeta = createSystemMetadata(guid, session.getSubject(), object);
1098
      Identifier pid = MNodeService.getInstance(request).create(session, guid, object, sysmeta);
1099
      fail("Should not be able to create with whitespace in indentifier");
1100
    } catch (InvalidRequest e) {
1101
    	// expect that this request fails
1102
        assertTrue(true);
1103
    } catch (Exception e) {
1104
      e.printStackTrace();
1105
      fail("Unexpected error: " + e.getMessage());
1106
    }
1107
      
1108
  }
1109
  
1110
	/**
1111
	 * Test getting a known object
1112
	 */
1113
	public void testGetPackage() {
1114
		printTestHeader("testGetPackage");
1115

    
1116
		try {
1117
			Session session = getTestSession();
1118
			Identifier guid = new Identifier();
1119
			guid.setValue("testGetPackage." + System.currentTimeMillis());
1120
			InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
1121
			SystemMetadata sysmeta = createSystemMetadata(guid, session.getSubject(), object);
1122
			Identifier pid = MNodeService.getInstance(request).create(session, guid, object, sysmeta);
1123
			InputStream bagStream = MNodeService.getInstance(request).getPackage(session, pid);
1124
			File bagFile = File.createTempFile("bagit.", ".zip");
1125
			IOUtils.copy(bagStream, new FileOutputStream(bagFile));
1126
			BagFactory bagFactory = new BagFactory();
1127
			Bag bag = bagFactory.createBag(bagFile);
1128
			InputStream result = bag.getPayload().iterator().next().newInputStream();
1129
			
1130
			// go back to beginning of original stream
1131
			object.reset();
1132
			// check
1133
			assertTrue(object.available() > 0);
1134
			assertTrue(result.available() > 0);
1135
			assertTrue(IOUtils.contentEquals(result, object));
1136
			
1137
			// clean up
1138
			bagFile.delete();
1139

    
1140
		} catch (Exception e) {
1141
			e.printStackTrace();
1142
			fail("Unexpected error: " + e.getMessage());
1143
		}
1144
	}
1145
	
1146
	
1147
	/**
1148
	 * Test getting a known object
1149
	 */
1150
	public void testGetOREPackage() {
1151
		printTestHeader("testGetOREPackage");
1152

    
1153
		try {
1154
			
1155
			// construct the ORE package
1156
			Identifier resourceMapId = new Identifier();
1157
			//resourceMapId.setValue("doi://1234/AA/map.1.1");
1158
			resourceMapId.setValue("testGetOREPackage." + System.currentTimeMillis());
1159
			Identifier metadataId = new Identifier();
1160
			metadataId.setValue("doi://1234/AA/meta.1." + + System.currentTimeMillis());
1161
			List<Identifier> dataIds = new ArrayList<Identifier>();
1162
			Identifier dataId = new Identifier();
1163
			dataId.setValue("doi://1234/AA/data.1." + System.currentTimeMillis());
1164
			Identifier dataId2 = new Identifier();
1165
			dataId2.setValue("doi://1234/AA/data.2." + System.currentTimeMillis());
1166
			dataIds.add(dataId);
1167
			dataIds.add(dataId2);
1168
			Map<Identifier, List<Identifier>> idMap = new HashMap<Identifier, List<Identifier>>();
1169
			idMap.put(metadataId, dataIds);
1170
			ResourceMapFactory rmf = ResourceMapFactory.getInstance();
1171
			ResourceMap resourceMap = rmf.createResourceMap(resourceMapId, idMap);
1172
			assertNotNull(resourceMap);
1173
			String rdfXml = ResourceMapFactory.getInstance().serializeResourceMap(resourceMap);
1174
			assertNotNull(rdfXml);
1175
			
1176
			Session session = getTestSession();
1177
			InputStream object = null;
1178
			SystemMetadata sysmeta = null;
1179
			
1180
			// save the data objects (data just contains their ID)
1181
			InputStream dataObject1 = new ByteArrayInputStream(dataId.getValue().getBytes("UTF-8"));
1182
			sysmeta = createSystemMetadata(dataId, session.getSubject(), dataObject1);
1183
			MNodeService.getInstance(request).create(session, dataId, dataObject1, sysmeta);
1184
			// second data file
1185
			InputStream dataObject2 = new ByteArrayInputStream(dataId2.getValue().getBytes("UTF-8"));
1186
			sysmeta = createSystemMetadata(dataId2, session.getSubject(), dataObject2);
1187
			MNodeService.getInstance(request).create(session, dataId2, dataObject2, sysmeta);
1188
			// metadata file
1189
			InputStream metadataObject = new ByteArrayInputStream(metadataId.getValue().getBytes("UTF-8"));
1190
			sysmeta = createSystemMetadata(metadataId, session.getSubject(), metadataObject);
1191
			MNodeService.getInstance(request).create(session, metadataId, metadataObject, sysmeta);
1192
						
1193
			// save the ORE object
1194
			object = new ByteArrayInputStream(rdfXml.getBytes("UTF-8"));
1195
			sysmeta = createSystemMetadata(resourceMapId, session.getSubject(), object);
1196
			sysmeta.setFormatId(ObjectFormatCache.getInstance().getFormat("http://www.openarchives.org/ore/terms").getFormatId());
1197
			Identifier pid = MNodeService.getInstance(request).create(session, resourceMapId, object, sysmeta);
1198
			
1199
			// get the package we uploaded
1200
			InputStream bagStream = MNodeService.getInstance(request).getPackage(session, pid);
1201
			File bagFile = File.createTempFile("bagit.", ".zip");
1202
			IOUtils.copy(bagStream, new FileOutputStream(bagFile));
1203
			BagFactory bagFactory = new BagFactory();
1204
			Bag bag = bagFactory.createBag(bagFile);
1205
			Iterator<Manifest> manifestIter = bag.getTagManifests().iterator();
1206
			while (manifestIter.hasNext()) {
1207
				String filepath = manifestIter.next().getFilepath();
1208
				BagFile entryFile = bag.getBagFile(filepath);
1209
				InputStream result = entryFile.newInputStream();
1210
				// check ORE
1211
				if (filepath.contains(resourceMapId.getValue())) {
1212
					object.reset();
1213
					assertTrue(object.available() > 0);
1214
					assertTrue(result.available() > 0);
1215
					assertTrue(IOUtils.contentEquals(result, object));
1216
				}
1217
				// check metadata
1218
				if (filepath.contains(metadataId.getValue())) {
1219
					metadataObject.reset();
1220
					assertTrue(metadataObject.available() > 0);
1221
					assertTrue(result.available() > 0);
1222
					assertTrue(IOUtils.contentEquals(result, metadataObject));
1223
				}
1224
				if (filepath.contains(dataId.getValue())) {
1225
					dataObject1.reset();
1226
					assertTrue(dataObject1.available() > 0);
1227
					assertTrue(result.available() > 0);
1228
					assertTrue(IOUtils.contentEquals(result, dataObject1));
1229
				}
1230
				if (filepath.contains(dataId2.getValue())) {
1231
					dataObject2.reset();
1232
					assertTrue(dataObject2.available() > 0);
1233
					assertTrue(result.available() > 0);
1234
					assertTrue(IOUtils.contentEquals(result, dataObject2));
1235
				}
1236
				
1237
				
1238
			}
1239
			
1240
			// clean up
1241
			bagFile.delete();
1242

    
1243
		} catch (Exception e) {
1244
			e.printStackTrace();
1245
			fail("Unexpected error: " + e.getMessage());
1246
		}
1247
	}
1248
	
1249
  
1250
}
(3-3/6)