|
1 | 1 | #! /usr/bin/env python |
2 | 2 | from __future__ import absolute_import |
| 3 | +from datetime import datetime |
3 | 4 | import os |
4 | 5 | import sys |
5 | 6 | import socket |
|
15 | 16 | from irods.test.helpers import my_function_name, unique_name |
16 | 17 | from irods.collection import iRODSCollection |
17 | 18 |
|
| 19 | +RODSUSER = 'nonadmin' |
18 | 20 |
|
19 | 21 | class TestCollection(unittest.TestCase): |
20 | 22 |
|
| 23 | + class WrongUserType(RuntimeError): pass |
| 24 | + |
| 25 | + @classmethod |
| 26 | + def setUpClass(cls): |
| 27 | + adm = helpers.make_session() |
| 28 | + if adm.users.get(adm.username).type != 'rodsadmin': |
| 29 | + raise cls.WrongUserType('Must be an iRODS admin to run tests in class {0.__name__}'.format(cls)) |
| 30 | + cls.logins = helpers.iRODSUserLogins(adm) |
| 31 | + cls.logins.create_user(RODSUSER, 'abc123') |
| 32 | + |
| 33 | + |
| 34 | + @classmethod |
| 35 | + def tearDownClass(cls): |
| 36 | + # TODO(#553): Skipping this will result in an interpreter seg fault for Py3.6 but not 3.11; why? |
| 37 | + del cls.logins |
| 38 | + |
| 39 | + |
21 | 40 | def setUp(self): |
22 | 41 | self.sess = helpers.make_session() |
23 | | - self.test_coll_path = '/{}/home/{}/test_dir'.format(self.sess.zone, self.sess.username) |
24 | 42 |
|
| 43 | + self.test_coll_path = '/{}/home/{}/test_dir'.format(self.sess.zone, self.sess.username) |
25 | 44 | self.test_coll = self.sess.collections.create(self.test_coll_path) |
26 | 45 |
|
27 | 46 |
|
@@ -380,6 +399,96 @@ def test_object_paths_with_dot_and_dotdot__323(self): |
380 | 399 | home2 = normalize('/zone','holmes','..','home','public','..','user') |
381 | 400 | self.assertEqual(home2, '/zone/home/user') |
382 | 401 |
|
| 402 | + def test_update_mtime_of_collection_using_touch_operation_as_non_admin__525(self): |
| 403 | + user_session = self.logins.session_for_user(RODSUSER) |
| 404 | + |
| 405 | + # Capture mtime of the home collection. |
| 406 | + home_collection_path = helpers.home_collection(user_session) |
| 407 | + collection = user_session.collections.get(home_collection_path) |
| 408 | + old_mtime = collection.modify_time |
| 409 | + |
| 410 | + # Set the mtime to an earlier time. |
| 411 | + new_mtime = 1400000000 |
| 412 | + user_session.collections.touch(home_collection_path, seconds_since_epoch=new_mtime) |
| 413 | + |
| 414 | + # Compare mtimes for correctness. |
| 415 | + collection = user_session.collections.get(home_collection_path) |
| 416 | + self.assertEqual(datetime.utcfromtimestamp(new_mtime), collection.modify_time) |
| 417 | + self.assertGreater(old_mtime, collection.modify_time) |
| 418 | + |
| 419 | + def test_touch_operation_does_not_create_new_collections__525(self): |
| 420 | + user_session = self.logins.session_for_user(RODSUSER) |
| 421 | + |
| 422 | + # The collection should not exist. |
| 423 | + collection_path = f'{helpers.home_collection(user_session)}/test_touch_operation_does_not_create_new_collections__525' |
| 424 | + with self.assertRaises(CollectionDoesNotExist): |
| 425 | + user_session.collections.get(collection_path) |
| 426 | + |
| 427 | + # Show the touch operation throws an exception if the target collection |
| 428 | + # does not exist. |
| 429 | + with self.assertRaises(CollectionDoesNotExist): |
| 430 | + user_session.collections.touch(collection_path) |
| 431 | + |
| 432 | + # Show the touch operation did not create a new collection. |
| 433 | + with self.assertRaises(CollectionDoesNotExist): |
| 434 | + user_session.collections.get(collection_path) |
| 435 | + |
| 436 | + def test_touch_operation_does_not_work_when_given_a_data_object__525(self): |
| 437 | + try: |
| 438 | + user_session = self.logins.session_for_user(RODSUSER) |
| 439 | + |
| 440 | + # Create a data object. |
| 441 | + data_object_path = f'{helpers.home_collection(user_session)}/test_touch_operation_does_not_work_when_given_a_data_object__525.txt' |
| 442 | + self.assertFalse(user_session.data_objects.exists(data_object_path)) |
| 443 | + user_session.data_objects.touch(data_object_path) |
| 444 | + self.assertTrue(user_session.data_objects.exists(data_object_path)) |
| 445 | + |
| 446 | + # Show the touch operation for collections throws an exception when |
| 447 | + # given a path pointing to a data object. |
| 448 | + with self.assertRaises(CollectionDoesNotExist): |
| 449 | + user_session.collections.touch(data_object_path) |
| 450 | + |
| 451 | + finally: |
| 452 | + user_session.data_objects.unlink(data_object_path, force=True) |
| 453 | + |
| 454 | + def test_touch_operation_ignores_unsupported_options__525(self): |
| 455 | + user_session = self.logins.session_for_user(RODSUSER) |
| 456 | + path = f'{helpers.home_collection(user_session)}/test_touch_operation_ignores_unsupported_options__525' |
| 457 | + |
| 458 | + try: |
| 459 | + # Capture mtime of the home collection. |
| 460 | + collection = user_session.collections.create(path) |
| 461 | + old_mtime = collection.modify_time |
| 462 | + |
| 463 | + # Capture the current time. |
| 464 | + time.sleep(2) # Guarantees the mtime is different. |
| 465 | + new_mtime = int(time.time()) |
| 466 | + |
| 467 | + # The touch API for the iRODS server will attempt to create a new data object |
| 468 | + # if the "no_create" option is set to false. The PRC's collection interface will |
| 469 | + # ignore that option if passed. |
| 470 | + # |
| 471 | + # The following arguments don't make sense for collections and will also be ignored. |
| 472 | + # |
| 473 | + # - replica_number |
| 474 | + # - leaf_resource_name |
| 475 | + # |
| 476 | + # They are included to prove the PRC handles them appropriately (i.e. unsupported |
| 477 | + # parameters are removed from the request). |
| 478 | + user_session.collections.touch(path, |
| 479 | + no_create=False, |
| 480 | + replica_number=525, |
| 481 | + seconds_since_epoch=new_mtime, |
| 482 | + leaf_resource_name='ufs525') |
| 483 | + |
| 484 | + # Compare mtimes for correctness. |
| 485 | + collection = user_session.collections.get(path) |
| 486 | + self.assertEqual(datetime.utcfromtimestamp(int(new_mtime)), collection.modify_time) |
| 487 | + |
| 488 | + finally: |
| 489 | + if collection: |
| 490 | + user_session.collections.remove(path, recurse=True, force=True) |
| 491 | + |
383 | 492 |
|
384 | 493 | if __name__ == "__main__": |
385 | 494 | # let the tests find the parent irods lib |
|
0 commit comments