示例#1
0
def install_queries(required_specific_queries: Dict[str, str], setup_helper: SetupHelper):
    """
    Installs the given specific queries required to in iRODS using the given iRODS setup helper.
    :param required_specific_queries: dictionary of specific queries, where the key is the alias and the value is the
    SQL query
    :param setup_helper: iRODS setup helper
    """
    for alias, query_location_relative_to_root in required_specific_queries.items():
        query_location = normpath(join(dirname(realpath(__file__)), "..", "..", "..", "..", "..",
                                       query_location_relative_to_root))
        with open(query_location) as file:
            query = file.read().replace('\n', ' ')

        setup_helper.run_icommand(["iadmin", "asq", "%s" % query, alias])
class TestBatonInstalledSpecificQueryMapper(unittest.TestCase):
    """
    Tests for `BatonSpecificQueryMapper`.
    """
    def setUp(self):
        self.test_with_baton = TestWithBaton(baton_setup=BATON_SETUP)
        self.test_with_baton.setup()
        self.setup_helper = SetupHelper(self.test_with_baton.icommands_location)

        self.mapper = BatonSpecificQueryMapper(self.test_with_baton.baton_location)

    def test_get_all(self):
        iquest_ls_response = self.setup_helper.run_icommand(["iquest", "--sql", "ls"])
        expected = TestBatonInstalledSpecificQueryMapper._parse_iquest_ls(iquest_ls_response)
        specific_queries = self.mapper.get_all()
        self.assertCountEqual(specific_queries, expected)

    @staticmethod
    def _parse_iquest_ls(iquest_ls_response: str) -> Sequence[SpecificQuery]:
        """
        Gets the installed specific queries by parsing the output returned by "iquest --sql ls".
        :param iquest_ls_response: the response returned by the iquest command
        :return: the specific queries installed on the iRODS server
        """
        iquest_ls_response_lines = iquest_ls_response.split('\n')
        assert (len(iquest_ls_response_lines) + 1) % 3 == 0

        specific_queries = []
        for i in range(int((len(iquest_ls_response_lines) + 1) / 3)):
            i3 = int(3 * i)
            alias = iquest_ls_response_lines[i3]
            sql = iquest_ls_response_lines[i3 + 1]
            specific_queries.append(SpecificQuery(alias, sql))

        return specific_queries
示例#3
0
def create_data_object(
    test_with_baton: TestWithBaton,
    name: str,
    metadata: IrodsMetadata = IrodsMetadata(),
    access_controls: Iterable[AccessControl] = None,
) -> DataObject:
    """
    Factory method to create an iRODS data object that has metadata, an ACL and replicas. Creates in current directory.
    :param test_with_baton: framework to allow testing with baton
    :param name: the name given to the created data object
    :param metadata: the metadata to give the file
    :param access_controls: access control list that the data object should have
    :return: the created iRODS file
    """
    user = test_with_baton.irods_server.users[0]
    setup_helper = SetupHelper(test_with_baton.icommands_location)

    path = setup_helper.create_data_object(name)
    setup_helper.add_metadata_to(path, metadata)
    checksum = setup_helper.get_checksum(path)
    replicas = []
    for i in range(2):
        replica_storage = setup_helper.create_replica_storage()
        setup_helper.replicate_data_object(path, replica_storage)
        replica = DataObjectReplica(i + 1, checksum, replica_storage.host, replica_storage.name, True)
        replicas.append(replica)
    setup_helper.update_checksums(path)

    # Difficult to get all the details of replica 0 using icommands so remove
    setup_helper.run_icommand(["irm", "-n", "0", path])

    if access_controls is None:
        access_controls = [AccessControl(User(user.username, user.zone), AccessControl.Level.OWN)]
    else:
        _set_access_controls(test_with_baton, path, access_controls)

    data_object = DataObject(path, access_controls, metadata, replicas)
    synchronise_timestamps(test_with_baton, data_object)

    return data_object
示例#4
0
def create_entity_tree(
    test_with_baton: TestWithBaton, root: str, node: EntityNode, access_controls: Iterable[AccessControl] = None
) -> Iterable[IrodsEntity]:
    """
    TODO
    :param test_with_baton:
    :param root:
    :param node:
    :param access_controls:
    :return:
    """
    entities = []
    setup_helper = SetupHelper(test_with_baton.icommands_location)

    if isinstance(node, DataObjectNode):
        entity = DataObject(setup_helper.create_data_object(node.name))
    else:
        entity = Collection(setup_helper.create_collection(node.name))

    _set_access_controls(test_with_baton, entity.path, access_controls)
    entity.access_controls = access_controls

    new_path = "%s/%s" % (root, entity.get_name())
    setup_helper.run_icommand(["imv", entity.path, new_path])
    entity.path = new_path
    entities.append(entity)

    if isinstance(node, CollectionNode):
        for child in node.children:
            descendants = create_entity_tree(test_with_baton, "%s/%s" % (root, node.name), child, access_controls)
            entities.extend(descendants)

    if isinstance(node, CollectionNode):
        assert len(entities) == len(list(node.get_all_descendants()) + [node])
    else:
        assert len(entities) == 1
    return entities
示例#5
0
class TestTestWithBaton(unittest.TestCase, BatonSetupContainer, metaclass=ABCMeta):
    """
    Unit tests for `TestWithBaton`.
    """
    def setUp(self):
        self.test_with_baton = TestWithBaton(self.baton_setup.value[0], self.baton_setup.value[1])
        self.test_with_baton.setup()
        self.setup_helper = SetupHelper(self.test_with_baton.icommands_location)

    def tearDown(self):
        self.test_with_baton.tear_down()

    def test_can_use_icommand_binary(self):
        user = self.test_with_baton.irods_server.users[0]
        zone = user.zone
        username = user.username
        self.assertEquals(self.setup_helper.run_icommand(["ils"]), "/%s/home/%s:" % (zone, username))

    def test_can_use_baton_binary(self):
        process = subprocess.Popen(["%s/baton" % self.test_with_baton.baton_location],
                                   stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=None)
        out, error = process.communicate()

        self.assertEqual(str.strip(out.decode("utf-8")), "{\"avus\":[]}")
        self.assertEqual(error, None)

    def test_tear_down(self):
        baton_location = self.test_with_baton.baton_location
        icommands_location = self.test_with_baton.icommands_location

        self.test_with_baton.tear_down()

        self.assertFalse(os.path.exists(baton_location))
        self.assertFalse(os.path.exists(icommands_location))
        self.assertIsNone(self.test_with_baton.baton_location)
        self.assertIsNone(self.test_with_baton.icommands_location)

    def test_cannot_setup_if_already_setup(self):
        self.assertRaises(RuntimeError, self.test_with_baton.setup)

    def test_cannot_setup_after_tear_down(self):
        self.test_with_baton.tear_down()
        self.assertRaises(RuntimeError, self.test_with_baton.setup)
class _TestBatonIrodsEntityMapper(unittest.TestCase, metaclass=ABCMeta):
    """
    Tests for subclasses of `_BatonIrodsEntityMapper`.
    """
    def setUp(self):
        self.test_with_baton = TestWithBaton(baton_setup=BATON_SETUP)
        self.test_with_baton.setup()
        self.setup_helper = SetupHelper(self.test_with_baton.icommands_location)

        self.metadata_1 = IrodsMetadata({ATTRIBUTES[0]: {"something_else", VALUES[0]}})
        self.metadata_2 = IrodsMetadata({ATTRIBUTES[1]: {VALUES[1]}})
        self.metadata_1_2 = combine_metadata([self.metadata_1, self.metadata_2])
        self.search_criterion_1 = SearchCriterion(ATTRIBUTES[0], VALUES[0], ComparisonOperator.EQUALS)
        self.search_criterion_2 = SearchCriterion(ATTRIBUTES[1], VALUES[1], ComparisonOperator.EQUALS)

    def tearDown(self):
        self.test_with_baton.tear_down()

    @abstractmethod
    def create_mapper(self) -> _BatonIrodsEntityMapper:
        """
        Creates a mapper to test with.
        :return: the created mapper
        """

    @abstractmethod
    def create_irods_entity(self, name: str, metadata: IrodsMetadata=IrodsMetadata()) -> IrodsEntity:
        """
        Creates an iRODS entity to test with
        :param name: the name of the entity to create
        :param metadata: the metadata to give to the entity
        :return: the created entity
        """

    def test_get_by_metadata_when_no_metadata(self):
        retrieved_entities = self.create_mapper().get_by_metadata(
            SearchCriterion(ATTRIBUTES[0], UNUSED_VALUE, ComparisonOperator.EQUALS))
        self.assertEqual(len(retrieved_entities), 0)

    def test_get_by_metadata_when_single_criterion_match_single_file(self):
        irods_entity_1 = self.create_irods_entity(NAMES[0], self.metadata_1)

        retrieved_entities = self.create_mapper().get_by_metadata(self.search_criterion_1)
        self.assertEqual(retrieved_entities, [irods_entity_1])

    def test_get_by_metadata_when_multiple_criterions_match_single_entity(self):
        search_criteria = [self.search_criterion_1, self.search_criterion_2]

        irods_entity_1 = self.create_irods_entity(NAMES[0], self.metadata_1_2)
        self.create_irods_entity(NAMES[1], self.metadata_1)

        retrieved_entities = self.create_mapper().get_by_metadata(search_criteria)
        self.maxDiff = None
        self.assertEqual(retrieved_entities, [irods_entity_1])

    def test_get_by_metadata_when_single_criterion_match_multiple_entities(self):
        irods_entity_1 = self.create_irods_entity(NAMES[0], self.metadata_1_2)
        irods_entity_2 = self.create_irods_entity(NAMES[1], self.metadata_1)
        self.create_irods_entity(NAMES[2], IrodsMetadata())

        retrieved_entities = self.create_mapper().get_by_metadata(self.search_criterion_1)
        self.maxDiff = None
        self.assertEqual(retrieved_entities, [irods_entity_1, irods_entity_2])

    def test_get_by_metadata_when_multiple_criterions_match_multiple_entities(self):
        search_criteria = [self.search_criterion_1, self.search_criterion_2]

        irods_entity_1 = self.create_irods_entity(NAMES[0], self.metadata_1_2)
        irods_entity_2 = self.create_irods_entity(NAMES[1], self.metadata_1_2)
        self.create_irods_entity(NAMES[2], IrodsMetadata())

        retrieved_entities = self.create_mapper().get_by_metadata(search_criteria)
        self.maxDiff = None
        self.assertEqual(retrieved_entities, [irods_entity_1, irods_entity_2])

    def test_get_by_metadata_when_metadata_not_required_for_entities(self):
        irods_entity_1 = self.create_irods_entity(NAMES[0], self.metadata_1)

        retrieved_entities = self.create_mapper().get_by_metadata(self.search_criterion_1, load_metadata=False)

        self.assertIsNone(retrieved_entities[0].metadata)
        irods_entity_1.metadata = None
        self.assertEqual(retrieved_entities[0], irods_entity_1)

    @unittest.skip("Unable to setup a new zone in iRODS")
    def test_get_by_metadata_when_zone_restricted(self):
        new_zone = "newZone"
        self.setup_helper.run_icommand(["iadmin", "mkzone %s remote" % new_zone])

        irods_entity_1 = self.create_irods_entity(NAMES[0], self.metadata_1)
        irods_entity_2 = self.create_irods_entity(NAMES[1], self.metadata_1)

        self.setup_helper.run_icommand(["icp", "-r", "%s /%s" % (irods_entity_2.path, new_zone)])
        irods_entity_3 = deepcopy(irods_entity_2)
        irods_entity_3.path = "/%s/%s" % (new_zone, irods_entity_2.path.split("/")[-1])

        mapper = self.create_mapper()
        # Check gets both without specifying zone
        self.assertEqual(mapper.get_by_metadata(self.search_criterion_1), [irods_entity_1, irods_entity_2])
        # Check can zone restrict
        self.assertEqual(mapper.get_by_metadata(self.search_criterion_1, zone=new_zone), [irods_entity_3])

    def test_get_by_path_when_no_paths_given(self):
        retrieved_entities = self.create_mapper().get_by_path([])
        self.assertEqual(len(retrieved_entities), 0)

    def test_get_by_path_when_entity_does_not_exist(self):
        self.assertRaises(FileNotFoundError, self.create_mapper().get_by_path, "/invalid/name")

    def test_get_by_path_with_single_entity(self):
        irods_entity_1 = self.create_irods_entity(NAMES[0], self.metadata_1)

        retrieved_entity = self.create_mapper().get_by_path(irods_entity_1.path)
        self.assertEqual(retrieved_entity, irods_entity_1)

    def test_get_by_path_with_multiple_entities(self):
        irods_entities = [
            self.create_irods_entity(NAMES[i], self.metadata_1) for i in range(len(NAMES))]
        paths = [irods_entity.path for irods_entity in irods_entities]

        retrieved_entities = self.create_mapper().get_by_path(paths)
        self.assertEqual(retrieved_entities, irods_entities)

    def test_get_by_path_with_multiple_files_when_some_do_not_exist(self):
        irods_entities = [
            self.create_irods_entity(NAMES[i], self.metadata_1) for i in range(len(NAMES))]
        paths = [irods_entity.path for irods_entity in irods_entities]

        self.assertRaises(
            FileNotFoundError, self.create_mapper().get_by_path, paths + ["/invalid/name"])

    def test_get_by_path_when_metadata_not_required(self):
        irods_entity_1 = self.create_irods_entity(NAMES[0], self.metadata_1)

        retrieved_entity = self.create_mapper().get_by_path(irods_entity_1.path, load_metadata=False)

        self.assertIsNone(retrieved_entity.metadata)
        irods_entity_1.metadata = None
        self.assertEqual(retrieved_entity, irods_entity_1)

    def test_get_all_in_collection_when_collection_does_not_exist(self):
        self.assertRaises(FileNotFoundError, self.create_mapper().get_all_in_collection, "/invalid")

    def test_get_all_in_collection_when_one_of_multiple_collections_does_not_exist(self):
        collection_paths = [self.setup_helper.create_collection("collection"), "/invalid"]
        self.assertRaises(FileNotFoundError, self.create_mapper().get_all_in_collection, collection_paths)

    def test_get_all_in_collection_when_no_paths_given(self):
        retrieved = self.create_mapper().get_all_in_collection([])
        self.assertEqual(len(retrieved), 0)

    def test_get_all_in_collection_with_single_collection_containing_one_entity(self):
        entity = self.create_irods_entity(NAMES[0], self.metadata_1)

        retrieved_entities = self.create_mapper().get_all_in_collection(entity.get_collection_path())
        self.assertEqual(retrieved_entities, [entity])

    def test_get_all_in_collection_with_single_collection_containing_multiple_entities(self):
        entity_1 = self.create_irods_entity(NAMES[0], self.metadata_1)
        entity_2 = self.create_irods_entity(NAMES[1], self.metadata_2)
        assert entity_1.get_collection_path() == entity_2.get_collection_path()

        retrieved_entities = self.create_mapper().get_all_in_collection(entity_1.get_collection_path())
        self.assertEqual(retrieved_entities, [entity_1, entity_2])

    def test_get_all_in_collection_with_multiple_collections(self):
        collections = []
        entities = []

        for i in range(3):
            collection = self.setup_helper.create_collection("collection_%d" % i)

            for j in range(len(NAMES)):
                entity = self.create_irods_entity(NAMES[j], self.metadata_1)
                moved_path = "%s/%s" % (collection, entity.get_name())
                self.setup_helper.run_icommand(["imv", entity.path, moved_path])
                entity.path = moved_path
                synchronise_timestamps(self.test_with_baton, entity)
                entities.append(entity)

            collections.append(collection)

        retrieved_entities = self.create_mapper().get_all_in_collection(collections)
        self.assertEqual(retrieved_entities, entities)

    def test_get_all_in_collection_when_metadata_not_required(self):
        entity = self.create_irods_entity(NAMES[0], self.metadata_1)
        self.create_irods_entity(NAMES[1], self.metadata_1)

        retrieved_entities = self.create_mapper().get_all_in_collection(
            entity.get_collection_path(), load_metadata=False)

        self.assertIsNone(retrieved_entities[0].metadata)
        entity.metadata = None
        self.assertEqual(retrieved_entities[0], entity)

    def test_get_all_in_collection_when_collection_contains_data_objects_and_collections(self):
        data_object = create_data_object(self.test_with_baton, NAMES[0], self.metadata_1)
        create_collection(self.test_with_baton, NAMES[1], self.metadata_2)

        retrieved_entities = self.create_mapper().get_all_in_collection(data_object.get_collection_path())

        self.assertEqual(len(retrieved_entities), 1)
        self.assertIsInstance(retrieved_entities[0], type(self.create_irods_entity(NAMES[2])))

    def test_access_control_property(self):
        self.assertIsInstance(self.create_mapper().access_control, AccessControlMapper)