def test_patch_layer_style(client):
    with app.app_context():
        workspace = 'testuser1'
        layername = 'ne_110m_admin_0_countries'
        rest_path = url_for('rest_workspace_layer.patch', workspace=workspace, layername=layername)
        sld_path = 'sample/style/generic-blue_sld.xml'
        assert os.path.isfile(sld_path)
        response = client.patch(rest_path, data={
            'style': (open(sld_path, 'rb'), os.path.basename(sld_path)),
            'title': 'countries in blue'
        })
        assert response.status_code == 200

        # last_task = util._get_layer_task(workspace, layername)

        # Time to generate testing thumbnail is probably shorter than getting & parsing WMS/WFS capabilities documents
        # so it's finished before PATCH request is completed
        #
        # assert last_task is not None and not util._is_task_ready(last_task)
        # resp_json = rv.get_json()
        # keys_to_check = ['thumbnail']
        # for key_to_check in keys_to_check:
        #         assert 'status' in resp_json[key_to_check]
        flask_client.wait_till_layer_ready(workspace, layername)
        # last_task['last'].get()

        resp_json = response.get_json()
        assert resp_json['title'] == "countries in blue"

        wms_url = geoserver_wms.get_wms_url(workspace)
        wms = wms_proxy(wms_url)
        assert layername in wms.contents
        assert wms[layername].title == 'countries in blue'
        assert wms[layername].styles[
            workspace + '_wms:' + layername]['title'] == 'Generic Blue'

        uuid.check_redis_consistency(expected_publ_num_by_type={
            f'{LAYER_TYPE}': publication_counter.get()
        })

        expected_md_values = {
            'abstract': "and new description",
            'extent': [-180.0, -85.60903859383285, 180.0, 83.64513109859944],
            'graphic_url': url_for_external('rest_workspace_layer_thumbnail.get', workspace=workspace, layername=layername),
            'identifier': {
                'identifier': url_for_external('rest_workspace_layer.get', workspace=workspace, layername=layername),
                'label': 'ne_110m_admin_0_countries'
            },
            'language': ['eng'],
            'layer_endpoint': url_for_external('rest_workspace_layer.get', workspace=workspace, layername=layername),
            'organisation_name': None,
            'publication_date': TODAY_DATE,
            'reference_system': EXP_REFERENCE_SYSTEMS,
            'revision_date': TODAY_DATE,
            'spatial_resolution': {
                'scale_denominator': 100000000,
            },
            'title': 'countries in blue',
        }
    check_metadata(client, workspace, layername, METADATA_PROPERTIES_EQUAL, expected_md_values)
def test_patch_layer_title(client):
    with app.app_context():
        workspace = 'testuser1'
        layername = 'ne_110m_admin_0_countries'
        rest_path = url_for('rest_workspace_layer.patch', workspace=workspace, layername=layername)
        new_title = "New Title of Countries"
        new_description = "and new description"
        response = client.patch(rest_path, data={
            'title': new_title,
            'description': new_description,
        })
        assert response.status_code == 200, response.get_json()

        chain_info = util.get_layer_chain(workspace, layername)
        assert chain_info is not None and celery_util.is_chain_ready(chain_info)

        resp_json = response.get_json()
        assert resp_json['title'] == new_title
        assert resp_json['description'] == new_description

    with app.app_context():
        expected_md_values = {
            'abstract': "and new description",
            'extent': [-180.0, -85.60903859383285, 180.0, 83.64513109859944],
            'graphic_url': url_for_external('rest_workspace_layer_thumbnail.get', workspace=workspace, layername=layername),
            'identifier': {
                'identifier': url_for_external('rest_workspace_layer.get', workspace=workspace, layername=layername),
                'label': 'ne_110m_admin_0_countries'
            },
            'language': ['eng'],
            'layer_endpoint': url_for_external('rest_workspace_layer.get', workspace=workspace, layername=layername),
            'organisation_name': None,
            'publication_date': TODAY_DATE,
            'reference_system': EXP_REFERENCE_SYSTEMS,
            'revision_date': TODAY_DATE,
            'spatial_resolution': {
                'scale_denominator': 100000000,
            },
            'title': "New Title of Countries",
        }
        check_metadata(client, workspace, layername, METADATA_PROPERTIES_EQUAL, expected_md_values)

        uuid.check_redis_consistency(expected_publ_num_by_type={
            f'{LAYER_TYPE}': publication_counter.get()
        })
def test_patch_layer_data(client):
    with app.app_context():
        workspace = 'testuser2'
        layername = 'countries'
        rest_path = url_for('rest_workspace_layer.patch', workspace=workspace, layername=layername)
        file_paths = [
            'tmp/naturalearth/110m/cultural/ne_110m_populated_places.geojson',
        ]
        for file_path in file_paths:
            assert os.path.isfile(file_path)
        files = []
        try:
            files = [(open(fp, 'rb'), os.path.basename(fp)) for fp in
                     file_paths]
            response = client.patch(rest_path, data={
                'file': files,
                'title': 'populated places'
            })
            assert response.status_code == 200
        finally:
            for file_path in files:
                file_path[0].close()

        chain_info = util.get_layer_chain(workspace, layername)
        assert chain_info is not None and not celery_util.is_chain_ready(chain_info)
        resp_json = response.get_json()
        keys_to_check = ['db_table', 'wms', 'wfs', 'thumbnail', 'metadata']
        for key_to_check in keys_to_check:
            assert 'status' in resp_json[key_to_check]
        flask_client.wait_till_layer_ready(workspace, layername)
        # last_task['last'].get()

    with app.app_context():
        rest_path = url_for('rest_workspace_layer.get', workspace=workspace, layername=layername)
        response = client.get(rest_path)
        assert 200 <= response.status_code < 300

        resp_json = response.get_json()
        assert resp_json['title'] == "populated places"
        feature_type = get_feature_type(workspace, 'postgresql', layername)
        attributes = feature_type['attributes']['attribute']
        assert next((
            a for a in attributes if a['name'] == 'sovereignt'
        ), None) is None
        assert next((
            a for a in attributes if a['name'] == 'adm0cap'
        ), None) is not None

        uuid.check_redis_consistency(expected_publ_num_by_type={
            f'{LAYER_TYPE}': publication_counter.get()
        })

    with app.app_context():
        expected_md_values = {
            'abstract': "popis st\u00e1t\u016f",
            'extent': [-175.22056435043098, -41.29999116752133, 179.21664802661394, 64.15002486626597],
            'graphic_url': url_for_external('rest_workspace_layer_thumbnail.get', workspace=workspace, layername=layername),
            'identifier': {
                'identifier': url_for_external('rest_workspace_layer.get', workspace=workspace, layername=layername),
                "label": "countries"
            },
            'language': ["eng", 'chi', 'rus'],
            'layer_endpoint': url_for_external('rest_workspace_layer.get', workspace=workspace, layername=layername),
            'organisation_name': None,
            'publication_date': TODAY_DATE,
            'reference_system': EXP_REFERENCE_SYSTEMS,
            'revision_date': TODAY_DATE,
            'spatial_resolution': None,  # it's point data now and we can't guess scale from point data
            'title': 'populated places',
        }
    check_metadata(client, workspace, layername, METADATA_PROPERTIES_EQUAL, expected_md_values)
def test_post_layers_complex(client):
    with app.app_context():
        workspace = 'testuser2'
        rest_path = url_for('rest_workspace_layers.post', workspace=workspace)
        file_paths = [
            'tmp/naturalearth/110m/cultural/ne_110m_admin_0_countries.geojson',
        ]
        for file_path in file_paths:
            assert os.path.isfile(file_path)
        files = []
        sld_path = 'sample/style/generic-blue_sld.xml'
        assert os.path.isfile(sld_path)
        layername = ''
        try:
            files = [(open(fp, 'rb'), os.path.basename(fp)) for fp in file_paths]
            response = client.post(rest_path, data={
                'file': files,
                'name': 'countries',
                'title': 'staty',
                'description': 'popis států',
                'style': (open(sld_path, 'rb'), os.path.basename(sld_path)),
            })
            assert response.status_code == 200
            resp_json = response.get_json()
            # print(resp_json)
            layername = resp_json[0]['name']
        finally:
            for file_path in files:
                file_path[0].close()

        chain_info = util.get_layer_chain(workspace, layername)
        assert chain_info is not None and not celery_util.is_chain_ready(chain_info)
        flask_client.wait_till_layer_ready(workspace, layername)
        # last_task['last'].get()
        assert celery_util.is_chain_ready(chain_info)

        wms_url = geoserver_wms.get_wms_url(workspace)
        wms = wms_proxy(wms_url)
        assert 'countries' in wms.contents
        assert wms['countries'].title == 'staty'
        assert wms['countries'].abstract == 'popis států'
        assert wms['countries'].styles[workspace + '_wms:countries']['title'] == 'Generic Blue'

        assert layername != ''
        rest_path = url_for('rest_workspace_layer.get', workspace=workspace, layername=layername)
        response = client.get(rest_path)
        assert 200 <= response.status_code < 300
        resp_json = response.get_json()
        # print(resp_json)
        assert resp_json['title'] == 'staty'
        assert resp_json['description'] == 'popis států'
        for source in [
            'wms',
            'wfs',
            'thumbnail',
            'file',
            'db_table',
            'metadata',
        ]:
            assert 'status' not in resp_json[source]

        style_url = geoserver_sld.get_workspace_style_url(workspace, layername)
        response = requests.get(style_url + '.sld',
                                auth=settings.LAYMAN_GS_AUTH
                                )
        response.raise_for_status()
        sld_file = io.BytesIO(response.content)
        tree = ET.parse(sld_file)
        root = tree.getroot()
        assert root.attrib['version'] == '1.0.0'

        feature_type = get_feature_type(workspace, 'postgresql', layername)
        attributes = feature_type['attributes']['attribute']
        assert next((
            a for a in attributes if a['name'] == 'sovereignt'
        ), None) is not None

        publication_counter.increase()
        uuid.check_redis_consistency(expected_publ_num_by_type={
            f'{LAYER_TYPE}': publication_counter.get()
        })

    with app.app_context():
        expected_md_values = {
            'abstract': "popis st\u00e1t\u016f",
            'extent': [-180.0, -85.60903859383285, 180.0, 83.64513109859944],
            'graphic_url': url_for_external('rest_workspace_layer_thumbnail.get', workspace=workspace, layername=layername),
            'identifier': {
                "identifier": url_for_external('rest_workspace_layer.get', workspace=workspace, layername=layername),
                "label": "countries"
            },
            'language': ["eng"],
            'layer_endpoint': url_for_external('rest_workspace_layer.get', workspace=workspace, layername=layername),
            'organisation_name': None,
            'publication_date': TODAY_DATE,
            'reference_system': EXP_REFERENCE_SYSTEMS,
            'revision_date': None,
            'spatial_resolution': {
                'scale_denominator': 100000000,
            },
            'title': "staty",
        }
    check_metadata(client, workspace, layername, METADATA_PROPERTIES_EQUAL, expected_md_values)
def test_post_layers_simple(client):
    with app.app_context():
        workspace = 'testuser1'

        rest_path = url_for('rest_workspace_layers.post', workspace=workspace)
        file_paths = [
            'tmp/naturalearth/110m/cultural/ne_110m_admin_0_countries.geojson',
        ]
        for file_path in file_paths:
            assert os.path.isfile(file_path)
        files = []
        try:
            files = [(open(fp, 'rb'), os.path.basename(fp)) for fp in file_paths]
            response = client.post(rest_path, data={
                'file': files,
            })
            assert response.status_code == 200
        finally:
            for file_path in files:
                file_path[0].close()

        layername = 'ne_110m_admin_0_countries'

        chain_info = util.get_layer_chain(workspace, layername)
        assert chain_info is not None and not celery_util.is_chain_ready(chain_info)
        layer_info = util.get_layer_info(workspace, layername)
        keys_to_check = ['db_table', 'wms', 'wfs', 'thumbnail', 'metadata']
        for key_to_check in keys_to_check:
            assert 'status' in layer_info[key_to_check]

        # For some reason this hangs forever on get() if run (either with src/layman/authz/read_everyone_write_owner_auth2_test.py::test_authn_map_access_rights or src/layman/authn/oauth2_test.py::test_patch_current_user_without_username) and with src/layman/common/metadata/util.csw_insert
        # last_task['last'].get()
        # e.g. python3 -m pytest -W ignore::DeprecationWarning -xsvv src/layman/authn/oauth2_test.py::test_patch_current_user_without_username src/layman/layer/rest_workspace_test.py::test_post_layers_simple
        # this can badly affect also .get(propagate=False) in layman.celery.abort_task_chain
        # but hopefully this is only related to magic flask&celery test suite
        flask_client.wait_till_layer_ready(workspace, layername)

        layer_info = util.get_layer_info(workspace, layername)
        for key_to_check in keys_to_check:
            assert isinstance(layer_info[key_to_check], str) \
                or 'status' not in layer_info[key_to_check]

        wms_url = geoserver_wms.get_wms_url(workspace)
        wms = wms_proxy(wms_url)
        assert layername in wms.contents

        from layman.layer import get_layer_type_def
        from layman.common.filesystem import uuid as common_uuid
        uuid_filename = common_uuid.get_publication_uuid_file(
            get_layer_type_def()['type'], workspace, layername)
        assert os.path.isfile(uuid_filename)
        uuid_str = None
        with open(uuid_filename, "r") as file:
            uuid_str = file.read().strip()
        assert uuid.is_valid_uuid(uuid_str)
        assert settings.LAYMAN_REDIS.sismember(uuid.UUID_SET_KEY, uuid_str)
        assert settings.LAYMAN_REDIS.exists(uuid.get_uuid_metadata_key(uuid_str))
        assert settings.LAYMAN_REDIS.hexists(
            uuid.get_workspace_type_names_key(workspace, '.'.join(__name__.split('.')[:-1])),
            layername
        )

        layer_info = client.get(url_for('rest_workspace_layer.get', workspace=workspace, layername=layername)).get_json()
        assert set(layer_info['metadata'].keys()) == {'identifier', 'csw_url', 'record_url', 'comparison_url'}
        assert layer_info['metadata']['identifier'] == f"m-{uuid_str}"
        assert layer_info['metadata']['csw_url'] == settings.CSW_PROXY_URL
        md_record_url = f"http://micka:80/record/basic/m-{uuid_str}"
        assert layer_info['metadata']['record_url'].replace("http://localhost:3080", "http://micka:80") == md_record_url
        assert layer_info['metadata']['comparison_url'] == url_for_external('rest_workspace_layer_metadata_comparison.get',
                                                                            workspace=workspace, layername=layername)
        assert 'id' not in layer_info.keys()
        assert 'type' not in layer_info.keys()

        response = requests.get(md_record_url, auth=settings.CSW_BASIC_AUTHN)
        response.raise_for_status()
        assert layername in response.text

        publication_counter.increase()
        uuid.check_redis_consistency(expected_publ_num_by_type={
            f'{LAYER_TYPE}': publication_counter.get()
        })

    with app.app_context():
        expected_md_values = {
            'abstract': None,
            'extent': [-180.0, -85.60903859383285, 180.0, 83.64513109859944],
            'graphic_url': url_for_external('rest_workspace_layer_thumbnail.get', workspace=workspace, layername=layername),
            'identifier': {
                'identifier': url_for_external('rest_workspace_layer.get', workspace=workspace, layername=layername),
                'label': 'ne_110m_admin_0_countries'
            },
            'language': ['eng'],
            'layer_endpoint': url_for_external('rest_workspace_layer.get', workspace=workspace, layername=layername),
            'organisation_name': None,
            'publication_date': TODAY_DATE,
            'reference_system': EXP_REFERENCE_SYSTEMS,
            'revision_date': None,
            'spatial_resolution': {
                'scale_denominator': 100000000,
            },
            'title': 'ne_110m_admin_0_countries',
        }
    check_metadata(client, workspace, layername, METADATA_PROPERTIES_EQUAL, expected_md_values)
def test_map_composed_from_local_layers(client):
    with app.app_context():
        workspace = 'testuser1'
        rest_path = url_for('rest_workspace_layers.post', workspace=workspace)

        layername1 = 'mista'
        relative_file_paths = [
            'tmp/naturalearth/110m/cultural/ne_110m_populated_places.cpg',
            'tmp/naturalearth/110m/cultural/ne_110m_populated_places.dbf',
            'tmp/naturalearth/110m/cultural/ne_110m_populated_places.prj',
            'tmp/naturalearth/110m/cultural/ne_110m_populated_places.shp',
            'tmp/naturalearth/110m/cultural/ne_110m_populated_places.shx',
        ]
        file_paths = [
            os.path.join(os.getcwd(), fp) for fp in relative_file_paths
        ]
        for file in file_paths:
            assert os.path.isfile(file)
        files = []
        try:
            files = [(open(fp, 'rb'), os.path.basename(fp))
                     for fp in file_paths]
            response = client.post(rest_path,
                                   data={
                                       'file': files,
                                       'name': layername1,
                                   })
            assert response.status_code == 200
            layer1uuid = response.get_json()[0]['uuid']
        finally:
            for file in files:
                file[0].close()

    # If no sleep, Micka throws 500
    # [2020-03-26 09-54-11] Dibi\UniqueConstraintViolationException: duplicate key value violates unique constraint "edit_md_pkey" DETAIL:  Key (recno)=(17) already exists. SCHEMA NAME:  public TABLE NAME:  edit_md CONSTRAINT NAME:  edit_md_pkey LOCATION:  _bt_check_unique, nbtinsert.c:434 #23505 in /var/www/html/Micka/php/vendor/dibi/dibi/src/Dibi/Drivers/PostgreDriver.php:150  @  http://localhost:3080/csw  @@  exception--2020-03-26--09-54--3f034f5a61.html
    # in /var/www/html/Micka/php/app/model/RecordModel.php, line 197 setEditMd2Md INSERT INTO ...
    # probably problem with concurrent CSW insert
    # so report bug to Micka
    time.sleep(0.3)

    with app.app_context():
        layername2 = 'hranice'
        pattern = os.path.join(
            os.getcwd(),
            'tmp/naturalearth/110m/cultural/ne_110m_admin_0_boundary_lines_land.*'
        )
        file_paths = glob.glob(pattern)
        assert len(file_paths) > 0
        for file in file_paths:
            assert os.path.isfile(file)
        files = []
        try:
            files = [(open(fp, 'rb'), os.path.basename(fp))
                     for fp in file_paths]
            response = client.post(rest_path,
                                   data={
                                       'file': files,
                                       'name': layername2,
                                   })
            assert response.status_code == 200
            layer2uuid = response.get_json()[0]['uuid']
        finally:
            for file in files:
                file[0].close()

    with app.app_context():
        keys_to_check = ['db_table', 'wms', 'wfs', 'thumbnail', 'metadata']
        layer_info = client.get(
            url_for('rest_workspace_layer.get',
                    workspace=workspace,
                    layername=layername1)).get_json()
        max_attempts = 100
        num_attempts = 1
    while num_attempts < max_attempts and any(
        ('status' in layer_info[key] for key in keys_to_check)):
        time.sleep(0.1)
        # print('layer_info1', layer_info)
        with app.app_context():
            layer_info = client.get(
                url_for('rest_workspace_layer.get',
                        workspace=workspace,
                        layername=layername1)).get_json()
        num_attempts += 1
    assert num_attempts < max_attempts, f"Max attempts reached, layer1info={layer_info}"
    wms_url1 = layer_info['wms']['url']

    with app.app_context():
        layer_info = client.get(
            url_for('rest_workspace_layer.get',
                    workspace=workspace,
                    layername=layername2)).get_json()
        num_attempts = 1
    while any(('status' in layer_info[key] for key in keys_to_check)):
        time.sleep(0.1)
        # print('layer_info2', layer_info)
        with app.app_context():
            layer_info = client.get(
                url_for('rest_workspace_layer.get',
                        workspace=workspace,
                        layername=layername2)).get_json()
        num_attempts += 1
    assert num_attempts < max_attempts, f"Max attempts reached, layer2info={layer_info}"
    wms_url2 = layer_info['wms']['url']

    expected_url = 'http://localhost:8000/geoserver/testuser1_wms/ows'
    assert wms_url1 == expected_url
    assert wms_url2 == expected_url

    with app.app_context():
        mapname = 'svet'
        rest_path = url_for('rest_workspace_maps.post', workspace=workspace)
        file_paths = [
            'sample/layman.map/internal_url.json',
        ]
        for file in file_paths:
            assert os.path.isfile(file)
        files = []
        try:
            files = [(open(fp, 'rb'), os.path.basename(fp))
                     for fp in file_paths]
            response = client.post(rest_path,
                                   data={
                                       'file': files,
                                       'name': mapname,
                                   })
            assert response.status_code == 200
            resp_json = response.get_json()
            # print('resp_json', resp_json)
            assert len(resp_json) == 1
            assert resp_json[0]['name'] == mapname
        finally:
            for file_path in files:
                file_path[0].close()

    with app.app_context():
        map_info = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname)).get_json()
        thumbnail = map_info['thumbnail']
        assert 'status' in thumbnail
        assert thumbnail['status'] in ['PENDING', 'STARTED']

    with app.app_context():
        map_info = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname)).get_json()
    while 'status' in map_info['thumbnail'] and map_info['thumbnail'][
            'status'] in ['PENDING', 'STARTED', 'SUCCESS']:
        time.sleep(0.1)
        with app.app_context():
            map_info = client.get(
                url_for('rest_workspace_map.get',
                        workspace=workspace,
                        mapname=mapname)).get_json()

    with app.app_context():
        response = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname))
        assert response.status_code == 200
        resp_json = response.get_json()
        thumbnail = resp_json['thumbnail']
        assert 'status' not in thumbnail
        assert 'path' in thumbnail
        assert thumbnail['url'] == url_for_external(
            'rest_workspace_map_thumbnail.get',
            workspace=workspace,
            mapname=mapname)

        # uuid.check_redis_consistency(expected_publ_num_by_type={
        #     f'{MAP_TYPE}': num_maps_before_test + 2
        # })

    with app.app_context():
        map_info = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname)).get_json()
    while 'status' in map_info['metadata'] and map_info['metadata'][
            'status'] in ['PENDING', 'STARTED']:
        time.sleep(0.1)
        with app.app_context():
            map_info = client.get(
                url_for('rest_workspace_map.get',
                        workspace=workspace,
                        mapname=mapname)).get_json()

    with app.app_context():
        # assert metadata file is the same as filled template except for UUID and dates
        template_path, prop_values = csw.get_template_path_and_values(
            workspace, mapname, http_method='post')
        xml_file_object = micka_common_util.fill_xml_template_as_pretty_file_object(
            template_path, prop_values, csw.METADATA_PROPERTIES)
        expected_path = 'src/layman/map/rest_test_filled_template.xml'
        with open(expected_path) as file:
            expected_lines = file.readlines()
        diff_lines = list(
            difflib.unified_diff(
                [line.decode('utf-8') for line in xml_file_object.readlines()],
                expected_lines))
        assert len(diff_lines) == 40, ''.join(diff_lines)
        plus_lines = [line for line in diff_lines if line.startswith('+ ')]
        assert len(plus_lines) == 5
        minus_lines = [line for line in diff_lines if line.startswith('- ')]
        assert len(minus_lines) == 5

        plus_line = plus_lines[0]
        assert plus_line == '+    <gco:CharacterString>m-91147a27-1ff4-4242-ba6d-faffb92224c6</gco:CharacterString>\n'
        minus_line = minus_lines[0]
        assert minus_line.startswith(
            '-    <gco:CharacterString>m') and minus_line.endswith(
                '</gco:CharacterString>\n')

        plus_line = plus_lines[1]
        assert plus_line == '+    <gco:Date>2007-05-25</gco:Date>\n'
        minus_line = minus_lines[1]
        assert minus_line.startswith(
            '-    <gco:Date>') and minus_line.endswith('</gco:Date>\n')

        plus_line = plus_lines[2]
        assert plus_line == '+                <gco:Date>2007-05-25</gco:Date>\n'
        minus_line = minus_lines[2]
        assert minus_line.startswith('-                <gco:Date>'
                                     ) and minus_line.endswith('</gco:Date>\n')

        plus_line = plus_lines[3]
        assert plus_line.startswith(
            '+      <srv:operatesOn xlink:href="http://localhost:3080/csw?SERVICE=CSW&amp;VERSION=2.0.2&amp;REQUEST=GetRecordById&amp;OUTPUTSCHEMA=http://www.isotc211.org/2005/gmd&amp;ID='
        ) and plus_line.endswith(
            '" xlink:title="hranice" xlink:type="simple"/>\n'), plus_line
        minus_line = minus_lines[3]
        assert minus_line.startswith(
            '-      <srv:operatesOn xlink:href="http://localhost:3080/csw?SERVICE=CSW&amp;VERSION=2.0.2&amp;REQUEST=GetRecordById&amp;OUTPUTSCHEMA=http://www.isotc211.org/2005/gmd&amp;ID='
        ) and minus_line.endswith(
            '" xlink:title="hranice" xlink:type="simple"/>\n'), minus_line

        plus_line = plus_lines[4]
        assert plus_line.startswith(
            '+      <srv:operatesOn xlink:href="http://localhost:3080/csw?SERVICE=CSW&amp;VERSION=2.0.2&amp;REQUEST=GetRecordById&amp;OUTPUTSCHEMA=http://www.isotc211.org/2005/gmd&amp;ID='
        ) and plus_line.endswith(
            '" xlink:title="mista" xlink:type="simple"/>\n'), plus_line
        minus_line = minus_lines[4]
        assert minus_line.startswith(
            '-      <srv:operatesOn xlink:href="http://localhost:3080/csw?SERVICE=CSW&amp;VERSION=2.0.2&amp;REQUEST=GetRecordById&amp;OUTPUTSCHEMA=http://www.isotc211.org/2005/gmd&amp;ID='
        ) and minus_line.endswith(
            '" xlink:title="mista" xlink:type="simple"/>\n'), minus_line

    with app.app_context():
        expected_md_values = {
            'abstract':
            "World places and boundaries abstract",
            'extent': [-35.0, -48.5, 179.0, 81.5],
            'graphic_url':
            url_for_external('rest_workspace_map_thumbnail.get',
                             workspace=workspace,
                             mapname=mapname),
            'identifier': {
                "identifier":
                url_for_external('rest_workspace_map.get',
                                 workspace=workspace,
                                 mapname=mapname),
                "label":
                "svet"
            },
            'map_endpoint':
            url_for_external('rest_workspace_map.get',
                             workspace=workspace,
                             mapname=mapname),
            'map_file_endpoint':
            url_for_external('rest_workspace_map_file.get',
                             workspace=workspace,
                             mapname=mapname),
            'operates_on': [{
                "xlink:href":
                f"http://localhost:3080/csw?SERVICE=CSW&VERSION=2.0.2&REQUEST=GetRecordById&OUTPUTSCHEMA=http://www.isotc211.org/2005/gmd&ID=m-{layer2uuid}#_m-{layer2uuid}",
                "xlink:title": "hranice"
            }, {
                "xlink:href":
                f"http://localhost:3080/csw?SERVICE=CSW&VERSION=2.0.2&REQUEST=GetRecordById&OUTPUTSCHEMA=http://www.isotc211.org/2005/gmd&ID=m-{layer1uuid}#_m-{layer1uuid}",
                "xlink:title": "mista"
            }],
            'organisation_name':
            None,
            'publication_date':
            TODAY_DATE,
            'reference_system': ['EPSG:3857'],
            'revision_date':
            None,
            'title':
            "World places and boundaries",
        }
    check_metadata(client, workspace, mapname, METADATA_PROPERTIES_EQUAL,
                   expected_md_values)
def test_patch_map(client):
    with app.app_context():
        workspace = 'testuser1'
        mapname = 'administrativni_cleneni_libereckeho_kraje'
        uuid_str = map_uuid.get_map_uuid(workspace, mapname)
        rest_path = url_for('rest_workspace_map.patch',
                            workspace=workspace,
                            mapname=mapname)

        file_paths = [
            'sample/layman.map/full2.json',
        ]
        for file in file_paths:
            assert os.path.isfile(file)
        files = []
        try:
            files = [(open(fp, 'rb'), os.path.basename(fp))
                     for fp in file_paths]
            response = client.patch(rest_path, data={
                'file': files,
            })
            assert response.status_code == 200
            resp_json = response.get_json()
            # print('resp_json', resp_json)
        finally:
            for file in files:
                file[0].close()

        uuid.check_redis_consistency(expected_publ_num_by_type={
            f'{MAP_TYPE}': publication_counter.get()
        })

        assert resp_json['uuid'] == uuid_str
        assert resp_json['url'] == url_for_external('rest_workspace_map.get',
                                                    workspace=workspace,
                                                    mapname=mapname)
        assert resp_json[
            'title'] == "Jiné administrativn\u00ed \u010dlen\u011bn\u00ed Libereck\u00e9ho kraje"
        assert resp_json['description'] == "Jiný popis"
        map_file = resp_json['file']
        assert 'status' not in map_file
        assert 'path' in map_file
        assert map_file['url'] == url_for_external(
            'rest_workspace_map_file.get',
            workspace=workspace,
            mapname=mapname)
        thumbnail = resp_json['thumbnail']
        assert 'status' in thumbnail
        assert thumbnail['status'] in ['PENDING', 'STARTED']

    with app.app_context():
        map_info = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname)).get_json()
    while 'status' in map_info['thumbnail'] and map_info['thumbnail'][
            'status'] in ['PENDING', 'STARTED']:
        time.sleep(0.1)
        with app.app_context():
            map_info = client.get(
                url_for('rest_workspace_map.get',
                        workspace=workspace,
                        mapname=mapname)).get_json()

    with app.app_context():
        response = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname))
        assert response.status_code == 200
        resp_json = response.get_json()
        thumbnail = resp_json['thumbnail']
        assert 'status' not in thumbnail
        assert 'path' in thumbnail
        assert thumbnail['url'] == url_for_external(
            'rest_workspace_map_thumbnail.get',
            workspace=workspace,
            mapname=mapname)

    with app.app_context():
        response = client.get(
            url_for('rest_workspace_map_file.get',
                    workspace=workspace,
                    mapname=mapname))
        assert response.status_code == 200
        resp_json = response.get_json()
        assert resp_json['name'] == mapname
        assert resp_json[
            'title'] == "Jiné administrativn\u00ed \u010dlen\u011bn\u00ed Libereck\u00e9ho kraje"
        assert resp_json['abstract'] == "Jiný popis"
        user_json = resp_json['user']
        assert user_json['name'] == workspace
        assert user_json['email'] == ''
        assert len(user_json) == 2
        assert 'groups' not in resp_json

    with app.app_context():
        map_info = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname)).get_json()
    while 'status' in map_info['metadata'] and map_info['metadata'][
            'status'] in ['PENDING', 'STARTED']:
        time.sleep(0.1)
        with app.app_context():
            map_info = client.get(
                url_for('rest_workspace_map.get',
                        workspace=workspace,
                        mapname=mapname)).get_json()

    with app.app_context():
        title = 'Nový název'
        response = client.patch(rest_path, data={
            'title': title,
        })
        assert response.status_code == 200, response.get_json()
        resp_json = response.get_json()
        assert resp_json['title'] == "Nový název"
        assert resp_json['description'] == "Jiný popis"

    with app.app_context():
        description = 'Nový popis'
        response = client.patch(rest_path, data={
            'description': description,
        })
        assert response.status_code == 200
        resp_json = response.get_json()
        assert resp_json['title'] == "Nový název"
        assert resp_json['description'] == "Nový popis"

        uuid.check_redis_consistency(expected_publ_num_by_type={
            f'{MAP_TYPE}': publication_counter.get()
        })

    with app.app_context():
        expected_md_values = {
            'abstract':
            "Nov\u00fd popis",
            'extent': [14.623, 50.58, 15.42, 50.82],
            'graphic_url':
            url_for_external('rest_workspace_map_thumbnail.get',
                             workspace=workspace,
                             mapname=mapname),
            'identifier': {
                "identifier":
                url_for_external('rest_workspace_map.get',
                                 workspace=workspace,
                                 mapname=mapname),
                "label":
                "administrativni_cleneni_libereckeho_kraje"
            },
            'map_endpoint':
            url_for_external('rest_workspace_map.get',
                             workspace=workspace,
                             mapname=mapname),
            'map_file_endpoint':
            url_for_external('rest_workspace_map_file.get',
                             workspace=workspace,
                             mapname=mapname),
            'operates_on': [],
            'organisation_name':
            None,
            'publication_date':
            TODAY_DATE,
            'reference_system': ['EPSG:3857'],
            'revision_date':
            TODAY_DATE,
            'title':
            "Nov\u00fd n\u00e1zev",
        }
    check_metadata(client, workspace, mapname, METADATA_PROPERTIES_EQUAL,
                   expected_md_values)
def test_post_maps_complex(client):
    with app.app_context():
        workspace = 'testuser1'
        mapname = 'libe'
        title = 'Liberecký kraj: Administrativní členění'
        description = 'Libovolný popis'
        rest_path = url_for('rest_workspace_maps.post', workspace=workspace)
        file_paths = [
            'sample/layman.map/full.json',
        ]
        for file_path in file_paths:
            assert os.path.isfile(file_path)
        files = []
        try:
            files = [(open(fp, 'rb'), os.path.basename(fp))
                     for fp in file_paths]
            response = client.post(rest_path,
                                   data={
                                       'file': files,
                                       'name': mapname,
                                       'title': title,
                                       'description': description,
                                   })
            assert response.status_code == 200
            resp_json = response.get_json()
            # print('resp_json', resp_json)
            assert len(resp_json) == 1
            assert resp_json[0]['name'] == mapname
            uuid_str = resp_json[0]['uuid']
        finally:
            for file_path in files:
                file_path[0].close()

        publication_counter.increase()
        uuid.check_redis_consistency(expected_publ_num_by_type={
            f'{MAP_TYPE}': publication_counter.get()
        })

    with app.app_context():
        response = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname))
        assert response.status_code == 200
        resp_json = response.get_json()
        assert resp_json['name'] == mapname
        assert resp_json['uuid'] == uuid_str
        assert resp_json['url'] == url_for_external('rest_workspace_map.get',
                                                    workspace=workspace,
                                                    mapname=mapname)
        assert resp_json['title'] == title
        assert resp_json['description'] == description
        map_file = resp_json['file']
        assert 'status' not in map_file
        assert 'path' in map_file
        assert map_file['url'] == url_for_external(
            'rest_workspace_map_file.get',
            workspace=workspace,
            mapname=mapname)
        thumbnail = resp_json['thumbnail']
        assert 'status' in thumbnail
        assert thumbnail['status'] in ['PENDING', 'STARTED']

    with app.app_context():
        # assert another PATCH is not possible now
        response = client.patch(url_for('rest_workspace_map.patch',
                                        workspace=workspace,
                                        mapname=mapname),
                                data={
                                    'title': 'abcd',
                                })
        assert response.status_code == 400
        resp_json = response.get_json()
        assert resp_json['code'] == 49

    # continue with thumbnail assertion
    with app.app_context():
        map_info = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname)).get_json()
    while 'status' in map_info['thumbnail'] and map_info['thumbnail'][
            'status'] in ['PENDING', 'STARTED']:
        time.sleep(0.1)
        with app.app_context():
            map_info = client.get(
                url_for('rest_workspace_map.get',
                        workspace=workspace,
                        mapname=mapname)).get_json()

    with app.app_context():
        response = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname))
        assert response.status_code == 200
        resp_json = response.get_json()
        thumbnail = resp_json['thumbnail']
        assert 'status' not in thumbnail
        assert 'path' in thumbnail
        assert thumbnail['url'] == url_for_external(
            'rest_workspace_map_thumbnail.get',
            workspace=workspace,
            mapname=mapname)

    with app.app_context():
        response = client.get(
            url_for('rest_workspace_map_file.get',
                    workspace=workspace,
                    mapname=mapname))
        assert response.status_code == 200
        resp_json = response.get_json()
        assert resp_json['name'] == mapname
        assert resp_json['title'] == title
        assert resp_json['abstract'] == description
        user_json = resp_json['user']
        assert user_json['name'] == workspace
        assert user_json['email'] == ''
        assert len(user_json) == 2
        assert 'groups' not in resp_json

    # continue with metadata assertion
    with app.app_context():
        map_info = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname)).get_json()
    while 'status' in map_info['metadata'] and map_info['metadata'][
            'status'] in ['PENDING', 'STARTED']:
        time.sleep(0.1)
        with app.app_context():
            map_info = client.get(
                url_for('rest_workspace_map.get',
                        workspace=workspace,
                        mapname=mapname)).get_json()

    with app.app_context():
        expected_md_values = {
            'abstract':
            "Libovoln\u00fd popis",
            'extent': [14.62, 50.58, 15.42, 50.82],
            'graphic_url':
            url_for_external('rest_workspace_map_thumbnail.get',
                             workspace=workspace,
                             mapname=mapname),
            'identifier': {
                "identifier":
                url_for_external('rest_workspace_map.get',
                                 workspace=workspace,
                                 mapname=mapname),
                "label":
                "libe"
            },
            'map_endpoint':
            url_for_external('rest_workspace_map.get',
                             workspace=workspace,
                             mapname=mapname),
            'map_file_endpoint':
            url_for_external('rest_workspace_map_file.get',
                             workspace=workspace,
                             mapname=mapname),
            'operates_on': [],
            'organisation_name':
            None,
            'publication_date':
            TODAY_DATE,
            'reference_system': ['EPSG:3857'],
            'revision_date':
            None,
            'title':
            "Libereck\u00fd kraj: Administrativn\u00ed \u010dlen\u011bn\u00ed",
        }
    check_metadata(client, workspace, mapname, METADATA_PROPERTIES_EQUAL,
                   expected_md_values)
def test_post_maps_simple(client):
    with app.app_context():
        workspace = 'testuser1'
        mapname = None
        expected_mapname = 'administrativni_cleneni_libereckeho_kraje'
        rest_path = url_for('rest_workspace_maps.post', workspace=workspace)
        file_paths = [
            'sample/layman.map/full.json',
        ]
        for file_path in file_paths:
            assert os.path.isfile(file_path)
        files = []
        try:
            files = [(open(fp, 'rb'), os.path.basename(fp))
                     for fp in file_paths]
            response = client.post(rest_path, data={
                'file': files,
            })
            assert response.status_code == 200
            resp_json = response.get_json()
            # print('resp_json', resp_json)
            assert len(resp_json) == 1
            assert resp_json[0]['name'] == expected_mapname
            mapname = resp_json[0]['name']
            uuid_str = resp_json[0]['uuid']
        finally:
            for file_path in files:
                file_path[0].close()

        assert uuid.is_valid_uuid(uuid_str)

        publication_counter.increase()
        uuid.check_redis_consistency(expected_publ_num_by_type={
            f'{MAP_TYPE}': publication_counter.get()
        })

    with app.app_context():
        response = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname))
        assert response.status_code == 200
        resp_json = response.get_json()
        assert resp_json['name'] == mapname
        assert resp_json['uuid'] == uuid_str
        assert resp_json['url'] == url_for_external('rest_workspace_map.get',
                                                    workspace=workspace,
                                                    mapname=mapname)
        assert resp_json[
            'title'] == "Administrativn\u00ed \u010dlen\u011bn\u00ed Libereck\u00e9ho kraje"
        assert resp_json[
            'description'] == "Na tematick\u00e9 map\u011b p\u0159i p\u0159ibl\u00ed\u017een\u00ed jsou postupn\u011b zobrazovan\u00e9 administrativn\u00ed celky Libereck\u00e9ho kraje : okresy, OP\u00da, ORP a obce."
        map_file = resp_json['file']
        assert 'status' not in map_file
        assert 'path' in map_file
        assert map_file['url'] == url_for_external(
            'rest_workspace_map_file.get',
            workspace=workspace,
            mapname=mapname)
        thumbnail = resp_json['thumbnail']
        assert 'status' in thumbnail
        assert thumbnail['status'] in ['PENDING', 'STARTED']
        assert 'id' not in resp_json.keys()
        assert 'type' not in resp_json.keys()

    with app.app_context():
        map_info = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname)).get_json()
    while 'status' in map_info['thumbnail'] and map_info['thumbnail'][
            'status'] in ['PENDING', 'STARTED']:
        time.sleep(0.1)
        with app.app_context():
            map_info = client.get(
                url_for('rest_workspace_map.get',
                        workspace=workspace,
                        mapname=mapname)).get_json()

    with app.app_context():
        response = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname))
        assert response.status_code == 200
        resp_json = response.get_json()
        thumbnail = resp_json['thumbnail']
        assert 'status' not in thumbnail
        assert 'path' in thumbnail
        assert thumbnail['url'] == url_for_external(
            'rest_workspace_map_thumbnail.get',
            workspace=workspace,
            mapname=mapname)

    with app.app_context():
        response = client.get(
            url_for('rest_workspace_map_file.get',
                    workspace=workspace,
                    mapname=mapname))
        assert response.status_code == 200
        resp_json = response.get_json()
        assert resp_json['name'] == mapname

    with app.app_context():
        map_info = client.get(
            url_for('rest_workspace_map.get',
                    workspace=workspace,
                    mapname=mapname)).get_json()
    while 'status' in map_info['metadata'] and map_info['metadata'][
            'status'] in ['PENDING', 'STARTED']:
        time.sleep(0.1)
        with app.app_context():
            map_info = client.get(
                url_for('rest_workspace_map.get',
                        workspace=workspace,
                        mapname=mapname)).get_json()

    assert set(map_info['metadata'].keys()) == {
        'identifier', 'csw_url', 'record_url', 'comparison_url'
    }
    assert map_info['metadata']['identifier'] == f"m-{uuid_str}"
    assert map_info['metadata']['csw_url'] == settings.CSW_PROXY_URL
    md_record_url = f"http://micka:80/record/basic/m-{uuid_str}"
    assert map_info['metadata']['record_url'].replace(
        "http://localhost:3080", "http://micka:80") == md_record_url
    response = requests.get(md_record_url, auth=settings.CSW_BASIC_AUTHN)
    response.raise_for_status()
    assert mapname in response.text

    with app.app_context():
        expected_md_values = {
            'abstract':
            "Na tematick\u00e9 map\u011b p\u0159i p\u0159ibl\u00ed\u017een\u00ed jsou postupn\u011b zobrazovan\u00e9 administrativn\u00ed celky Libereck\u00e9ho kraje : okresy, OP\u00da, ORP a obce.",
            'extent': [14.62, 50.58, 15.42, 50.82],
            'graphic_url':
            url_for_external('rest_workspace_map_thumbnail.get',
                             workspace=workspace,
                             mapname=mapname),
            'identifier': {
                "identifier":
                url_for_external('rest_workspace_map.get',
                                 workspace=workspace,
                                 mapname=mapname),
                "label":
                "administrativni_cleneni_libereckeho_kraje"
            },
            'map_endpoint':
            url_for_external('rest_workspace_map.get',
                             workspace=workspace,
                             mapname=mapname),
            'map_file_endpoint':
            url_for_external('rest_workspace_map_file.get',
                             workspace=workspace,
                             mapname=mapname),
            'operates_on': [],
            'organisation_name':
            None,
            'publication_date':
            TODAY_DATE,
            'reference_system': ['EPSG:3857'],
            'revision_date':
            None,
            'title':
            "Administrativn\u00ed \u010dlen\u011bn\u00ed Libereck\u00e9ho kraje",
        }
    check_metadata(client, workspace, mapname, METADATA_PROPERTIES_EQUAL,
                   expected_md_values)