def test_get_layer_title(): workspace = 'test_get_layer_title_workspace' layers = [("c_test_get_layer_title_layer", "C Test get layer title - map layer íářžý"), ("a_test_get_layer_title_layer", "A Test get layer title - map layer íářžý"), ("b_test_get_layer_title_layer", "B Test get layer title - map layer íářžý")] sorted_layers = sorted(layers) for (name, title) in layers: process_client.publish_workspace_layer(workspace, name, title=title) # layers.GET with app.app_context(): url = url_for('rest_workspace_layers.get', workspace=workspace) response = requests.get(url) assert response.status_code == 200, response.text for i in range(0, len(sorted_layers) - 1): assert response.json()[i]["name"] == sorted_layers[i][0] assert response.json()[i]["title"] == sorted_layers[i][1] for (name, title) in layers: process_client.delete_workspace_layer(workspace, name)
def delete_layer_after_test(): def register_layer_to_delete(workspace, layername): LAYERS_TO_DELETE_AFTER_TEST.append((workspace, layername)) yield register_layer_to_delete for workspace, layername in LAYERS_TO_DELETE_AFTER_TEST: process_client.delete_workspace_layer(workspace, layername)
def test_wrong_sld_causes_no_thumbnail(): workspace = 'test_wrong_sld_causes_no_thumbnail_workspace' layer = 'test_wrong_sld_causes_no_thumbnail_layer' geojson_file = ['/code/sample/layman.layer/sample_point_cz.geojson'] style_file = '/code/sample/layman.layer/sample_point_cz_wrong_literal.sld' def wait_for_thumbnail_error(response): ok_keys = ['db_table', 'wms', 'wfs', 'file'] if response.status_code == 200: r_json = response.json() result = response.status_code == 200 and all( 'status' not in r_json[k] for k in ok_keys ) and 'status' in r_json['thumbnail'] and r_json['thumbnail']['status'] in ['FAILURE'] else: result = False return result process_client.publish_workspace_layer(workspace, layer, file_paths=geojson_file, style_file=style_file, check_response_fn=wait_for_thumbnail_error, ) layer_info = process_client.get_workspace_layer(workspace, layer) assert 'error' in layer_info['thumbnail'] assert layer_info['thumbnail']['error']['message'] == 'Thumbnail rendering failed' assert layer_info['thumbnail']['error']['code'] == -1 process_client.delete_workspace_layer(workspace, layer)
def test_wfs_bbox(style_file, thumbnail_style_postfix): workspace = 'test_wfs_bbox_workspace' layer = 'test_wfs_bbox_layer' process_client.publish_workspace_layer( workspace, layer, style_file=style_file, ) native_crs = SMALL_LAYER_NATIVE_CRS assert_util.assert_all_sources_bbox( workspace, layer, SMALL_LAYER_BBOX, expected_native_bbox=SMALL_LAYER_NATIVE_BBOX, expected_native_crs=native_crs) expected_bbox = (1571000.0, 6268800.0, 1572590.854206196, 6269876.33561699) exp_native_bbox = (14.112533113517683, 48.964264493114904, 14.126824, 48.970612) method_bbox_thumbnail_tuples = [ (data_wfs.get_wfs20_insert_points, expected_bbox, exp_native_bbox, '_bigger'), (data_wfs.get_wfs20_delete_point, SMALL_LAYER_BBOX, SMALL_LAYER_NATIVE_BBOX, ''), ] for wfs_method, exp_bbox, exp_native_bbox, thumbnail_bbox_postfix in method_bbox_thumbnail_tuples: data_xml = wfs_method( workspace, layer, ) process_client.post_wfst(data_xml, workspace=workspace) process_client.wait_for_publication_status(workspace, process_client.LAYER_TYPE, layer) assert_util.assert_all_sources_bbox( workspace, layer, exp_bbox, expected_native_bbox=exp_native_bbox, expected_native_crs=native_crs) expected_thumbnail_path = f'/code/sample/style/{layer}{thumbnail_style_postfix}{thumbnail_bbox_postfix}.png' with app.app_context(): thumbnail_path = thumbnail.get_layer_thumbnail_path( workspace, layer) diffs = test_util.compare_images(expected_thumbnail_path, thumbnail_path) assert diffs < 100, expected_thumbnail_path process_client.delete_workspace_layer( workspace, layer, )
def provide_publications(self): username = self.username authz_headers = self.authz_headers layername = self.layername mapname = self.mapname process_client.ensure_reserved_username(username, headers=authz_headers) process_client.publish_workspace_layer(username, layername, headers=authz_headers) process_client.publish_workspace_map(username, mapname, headers=authz_headers) yield process_client.delete_workspace_layer(username, layername, headers=authz_headers) process_client.delete_workspace_map(username, mapname, headers=authz_headers)
def test_map_refresh_after_layer_change(): workspace = 'test_map_refresh_after_layer_change_workspace' layer = 'test_map_refresh_after_layer_change_layer' map = 'test_map_refresh_after_layer_change_map' bbox = (1571000.0, 6268800.0, 1572590.8542062, 6269876.33561699) process_client.publish_workspace_layer(workspace, layer) file_path = f'tmp/map_with_internal_layers.json' map_data.create_map_with_internal_layers_file([(workspace, layer)], file_path=file_path, native_extent=bbox, native_crs='EPSG:3857') process_client.publish_workspace_map(workspace, map, file_paths=[file_path]) assert_map_thumbnail( workspace, map, f'/code/test_tools/data/thumbnail/map_with_internal_layer_basic.png') # Test refresh map thumbnail after layer WFS-T query data_xml = data_wfs.get_wfs20_insert_points( workspace, layer, ) process_client.post_wfst(data_xml) process_client.wait_for_publication_status(workspace, process_client.LAYER_TYPE, layer) assert_map_thumbnail( workspace, map, f'/code/test_tools/data/thumbnail/map_with_internal_layer_basic_after_wfst.png' ) # Test refresh map thumbnail after patch layer process_client.patch_workspace_layer( workspace, layer, file_paths=['sample/layman.layer/small_layer.geojson']) process_client.wait_for_publication_status(workspace, process_client.LAYER_TYPE, layer) assert_map_thumbnail( workspace, map, f'/code/test_tools/data/thumbnail/map_with_internal_layer_basic.png') process_client.delete_workspace_map(workspace, map) process_client.delete_workspace_layer(workspace, layer)
def test_layer_with_different_geometry(): workspace = 'testgeometryuser1' layername = 'layer_with_different_geometry' file_paths = [ 'tmp/naturalearth/110m/cultural/ne_110m_populated_places.geojson', ] process_client.publish_workspace_layer(workspace, layername, file_paths=file_paths) url_path_ows = urljoin(urljoin(settings.LAYMAN_GS_URL, workspace), 'ows?service=WFS&request=Transaction') url_path_wfs = urljoin(urljoin(settings.LAYMAN_GS_URL, workspace), 'wfs?request=Transaction') headers_wfs = { 'Accept': 'text/xml', 'Content-type': 'text/xml', } data_xml = data_wfs.get_wfs20_insert_points(workspace, layername) response = requests.post(url_path_ows, data=data_xml, headers=headers_wfs, auth=settings.LAYMAN_GS_AUTH ) response.raise_for_status() response = requests.post(url_path_wfs, data=data_xml, headers=headers_wfs, auth=settings.LAYMAN_GS_AUTH ) assert response.status_code == 200, f"HTTP Error {response.status_code}\n{response.text}" data_xml2 = data_wfs.get_wfs20_insert_lines(workspace, layername) response = requests.post(url_path_ows, data=data_xml2, headers=headers_wfs, auth=settings.LAYMAN_GS_AUTH ) assert response.status_code == 200, f"HTTP Error {response.status_code}\n{response.text}" response = requests.post(url_path_wfs, data=data_xml2, headers=headers_wfs, auth=settings.LAYMAN_GS_AUTH ) assert response.status_code == 200, f"HTTP Error {response.status_code}\n{response.text}" process_client.delete_workspace_layer(workspace, layername)
def test_style_correctly_saved(source_style_file_path, layer_suffix, expected_style_file_template, expected_style_type): workspace = 'test_style_correctly_saved_workspace' layer = 'test_style_correctly_saved_layer' + layer_suffix expected_style_file = expected_style_file_template.format( workspace=workspace, layer=layer) if expected_style_file_template else None process_client.publish_workspace_layer(workspace, layer, style_file=source_style_file_path) assert_style_file(workspace, layer, expected_style_file) with app.app_context(): info = layman_util.get_publication_info(workspace, process_client.LAYER_TYPE, layer, context={ 'keys': ['style_type', 'style'], }) assert info['style_type'] == expected_style_type process_client.delete_workspace_layer(workspace, layer) process_client.publish_workspace_layer(workspace, layer) with app.app_context(): info = layer_util.get_layer_info(workspace, layer) assert info['style_type'] == 'sld' assert info['style']['type'] == 'sld', info.get('style') assert info['style']['url'], info.get('style') assert_style_file(workspace, layer, None) process_client.patch_workspace_layer(workspace, layer, style_file=source_style_file_path) assert_style_file(workspace, layer, expected_style_file) with app.app_context(): info = layer_util.get_layer_info(workspace, layer) assert info['style_type'] == expected_style_type process_client.delete_workspace_layer(workspace, layer)
def test_post_layers_zero_length_attribute(): workspace = 'testuser1' layername = 'zero_length_attribute' file_paths = [ 'sample/data/zero_length_attribute.geojson', ] def wait_for_db_finish(response): info = response.json() return info.get('db_table', dict()).get('status', '') == 'FAILURE' process_client.publish_workspace_layer(workspace, layername, file_paths=file_paths, check_response_fn=wait_for_db_finish) layer_info = util.get_layer_info(workspace, layername) assert layer_info['db_table']['status'] == 'FAILURE', f'layer_info={layer_info}' assert layer_info['db_table']['error']['code'] == 28, f'layer_info={layer_info}' process_client.delete_workspace_layer(workspace, layername) uuid.check_redis_consistency(expected_publ_num_by_type={ f'{LAYER_TYPE}': publication_counter.get() })
def test_geometry_types(layer, exp_db_types, qml_geometry_dict): def get_qml_style_path(style_name): return f'/code/sample/data/geometry-types/{style_name}.qml' if style_name else None workspace = 'test_geometry_types_workspace' process_client.publish_workspace_layer(workspace, layer, file_paths=[f'/code/sample/data/geometry-types/{layer}.geojson'], ) with app.app_context(): db_types = db.get_geometry_types(workspace, layer) assert set(db_types) == exp_db_types qgis_geometries = ['Point', 'Line', 'Polygon', 'Unknown geometry'] old_qml_style_name = None for qml_geometry in qgis_geometries: exp_source_type, new_qml_style_name = qml_geometry_dict.get(qml_geometry, (None, None)) if exp_source_type is None: with pytest.raises(LaymanError) as excinfo: util.get_source_type(db_types, qml_geometry) assert excinfo.value.code == 47, f"qml_geometry={qml_geometry}, exp_source_type={exp_source_type}" else: source_type = util.get_source_type(db_types, qml_geometry) assert source_type == exp_source_type, f"qml_geometry={qml_geometry}, exp_source_type={exp_source_type}, " \ f"source_type={source_type}, db_types={db_types}" if new_qml_style_name: if new_qml_style_name != old_qml_style_name: process_client.patch_workspace_layer(workspace, layer, style_file=get_qml_style_path(new_qml_style_name)) old_qml_style_name = new_qml_style_name with app.app_context(): qml = util.get_original_style_xml(workspace, layer) found_qml_geometry = util.get_qml_geometry_from_qml(qml) assert found_qml_geometry == qml_geometry exp_file_path = f'/code/sample/data/geometry-types/{new_qml_style_name}.png' with app.app_context(): thumbnail_path = thumbnail.get_layer_thumbnail_path(workspace, layer) diff_pixels = test_util.compare_images(thumbnail_path, exp_file_path) assert diff_pixels == 0, f"thumbnail_path={thumbnail_path}, exp_file_path={exp_file_path}" process_client.delete_workspace_layer(workspace, layer)
def test_empty_shapefile(layername, file_paths): workspace = 'test_empty_bbox_workspace' title = layername process_client.publish_workspace_layer(workspace, layername, file_paths=file_paths) wms_layer = assert_wms_layer(workspace, layername, title) native_bbox = wms_layer.boundingBox wgs_bbox = wms_layer.boundingBoxWGS84 title = 'new title' process_client.patch_workspace_layer(workspace, layername, title=title) wms_layer = assert_wms_layer(workspace, layername, title) assert wms_layer.boundingBox == native_bbox assert wms_layer.boundingBoxWGS84 == wgs_bbox wfs_t_insert_point(workspace, layername) wms_layer = assert_wms_layer(workspace, layername, title) assert wms_layer.boundingBox == native_bbox assert wms_layer.boundingBoxWGS84 == wgs_bbox process_client.delete_workspace_layer(workspace, layername)
def test_missing_attribute(style_file, ): username = '******' layername = 'inexisting_attribute_layer' layername2 = 'inexisting_attribute_layer2' authn_headers = get_authz_headers(username) process_client.ensure_reserved_username(username, headers=authn_headers) process_client.publish_workspace_layer( username, layername, file_paths=[ 'tmp/naturalearth/110m/cultural/ne_110m_admin_0_countries.geojson', ], style_file=style_file, headers=authn_headers, ) process_client.publish_workspace_layer( username, layername2, file_paths=[ 'tmp/naturalearth/110m/cultural/ne_110m_admin_0_countries.geojson', ], style_file=style_file, headers=authn_headers, ) with app.app_context(): style_type = layman_util.get_publication_info( username, process_client.LAYER_TYPE, layername, context={ 'keys': ['style_type'], })['style_type'] def wfs_post(workspace, attr_names_list, data_xml): with app.app_context(): wfs_url = f"http://{settings.LAYMAN_SERVER_NAME}/geoserver/{workspace}/wfs" old_db_attributes = {} old_wfs_properties = {} for layer, attr_names in attr_names_list: # test that all attr_names are not yet presented in DB table old_db_attributes[layer] = db.get_all_column_names( workspace, layer) for attr_name in attr_names: assert attr_name not in old_db_attributes[ layer], f"old_db_attributes={old_db_attributes[layer]}, attr_name={attr_name}" layer_schema = get_wfs_schema(wfs_url, typename=f"{workspace}:{layer}", version=geoserver_wfs.VERSION, headers=authn_headers) old_wfs_properties[layer] = sorted( layer_schema['properties'].keys()) if style_type == 'qml': assert qgis_wms.get_layer_info(workspace, layer) old_qgis_attributes = qgis_util.get_layer_attribute_names( workspace, layer) assert all( attr_name not in old_qgis_attributes for attr_name in attr_names), (attr_names, old_qgis_attributes) process_client.post_wfst(data_xml, headers=authn_headers, workspace=username) new_db_attributes = {} new_wfs_properties = {} for layer, attr_names in attr_names_list: # test that exactly all attr_names were created in DB table new_db_attributes[layer] = db.get_all_column_names( workspace, layer) for attr_name in attr_names: assert attr_name in new_db_attributes[ layer], f"new_db_attributes={new_db_attributes[layer]}, attr_name={attr_name}" assert set(attr_names).union(set( old_db_attributes[layer])) == set(new_db_attributes[layer]) # test that exactly all attr_names were distinguished also in WFS feature type layer_schema = get_wfs_schema(wfs_url, typename=f"{workspace}:{layer}", version=geoserver_wfs.VERSION, headers=authn_headers) new_wfs_properties[layer] = sorted( layer_schema['properties'].keys()) for attr_name in attr_names: assert attr_name in new_wfs_properties[ layer], f"new_wfs_properties={new_wfs_properties[layer]}, attr_name={attr_name}" assert set(attr_names).union(set(old_wfs_properties[layer])) == set(new_wfs_properties[layer]),\ set(new_wfs_properties[layer]).difference(set(attr_names).union(set(old_wfs_properties[layer]))) if style_type == 'qml': assert qgis_wms.get_layer_info(workspace, layer) new_qgis_attributes = qgis_util.get_layer_attribute_names( workspace, layer) assert all( attr_name in new_qgis_attributes for attr_name in attr_names), (attr_names, new_qgis_attributes) else: assert not qgis_wms.get_layer_info(workspace, layer) attr_names = ['inexisting_attribute_attr', 'inexisting_attribute_attr1a'] data_xml = data_wfs.get_wfs20_insert_points_new_attr( username, layername, attr_names) wfs_post(username, [(layername, attr_names)], data_xml) attr_names2 = ['inexisting_attribute_attr2'] data_xml = data_wfs.get_wfs20_update_points_new_attr( username, layername, attr_names2) wfs_post(username, [(layername, attr_names2)], data_xml) attr_names3 = ['inexisting_attribute_attr3'] data_xml = data_wfs.get_wfs20_update_points_new_attr( username, layername, attr_names3, with_attr_namespace=True) wfs_post(username, [(layername, attr_names3)], data_xml) attr_names4 = ['inexisting_attribute_attr4'] data_xml = data_wfs.get_wfs20_update_points_new_attr(username, layername, attr_names4, with_filter=True) wfs_post(username, [(layername, attr_names4)], data_xml) attr_names5 = ['inexisting_attribute_attr5'] data_xml = data_wfs.get_wfs20_replace_points_new_attr( username, layername, attr_names5) wfs_post(username, [(layername, attr_names5)], data_xml) attr_names_i1 = ['inexisting_attribute_attr_complex_i1'] attr_names_i2 = ['inexisting_attribute_attr_complex_i2'] attr_names_u = ['inexisting_attribute_attr_complex_u'] attr_names_r = ['inexisting_attribute_attr_complex_r'] attr_names_complex = [(layername, attr_names_i1 + attr_names_r), (layername2, attr_names_i2 + attr_names_u)] data_xml = data_wfs.get_wfs20_complex_new_attr( workspace=username, layername1=layername, layername2=layername2, attr_names_insert1=attr_names_i1, attr_names_insert2=attr_names_i2, attr_names_update=attr_names_u, attr_names_replace=attr_names_r) wfs_post(username, attr_names_complex, data_xml) attr_names6 = ['inexisting_attribute_attr6'] data_xml = data_wfs.get_wfs10_insert_points_new_attr( username, layername, attr_names6) wfs_post(username, [(layername, attr_names6)], data_xml) attr_names7 = ['inexisting_attribute_attr7'] data_xml = data_wfs.get_wfs11_insert_points_new_attr( username, layername, attr_names7) wfs_post(username, [(layername, attr_names7)], data_xml) attr_names8 = ['inexisting_attribute_attr8'] data_xml = data_wfs.get_wfs10_update_points_new(username, layername, attr_names8, with_attr_namespace=True) wfs_post(username, [(layername, attr_names8)], data_xml) attr_names9 = ['inexisting_attribute_attr9'] data_xml = data_wfs.get_wfs10_update_points_new(username, layername, attr_names9, with_filter=True) wfs_post(username, [(layername, attr_names9)], data_xml) attr_names10 = ['inexisting_attribute_attr10'] data_xml = data_wfs.get_wfs11_insert_polygon_new_attr( username, layername, attr_names10) wfs_post(username, [(layername, attr_names10)], data_xml) process_client.delete_workspace_layer(username, layername, headers=authn_headers) process_client.delete_workspace_layer(username, layername2, headers=authn_headers)
def test_missing_attribute_authz(): username = '******' layername1 = 'testmissingattr_authz_layer' username2 = 'testmissingattr_authz2' authn_headers1 = get_authz_headers(username) authn_headers2 = get_authz_headers(username2) def do_test(wfs_query, attribute_names): # Test, that unauthorized user will not cause new attribute with app.app_context(): old_db_attributes = db.get_all_column_names(username, layername1) for attr_name in attribute_names: assert attr_name not in old_db_attributes, f"old_db_attributes={old_db_attributes}, attr_name={attr_name}" with pytest.raises(GS_Error) as exc: process_client.post_wfst(wfs_query, headers=authn_headers2, workspace=username) assert exc.value.data['status_code'] == 400 with app.app_context(): new_db_attributes = db.get_all_column_names(username, layername1) for attr_name in attribute_names: assert attr_name not in new_db_attributes, f"new_db_attributes={new_db_attributes}, attr_name={attr_name}" # Test, that authorized user will cause new attribute process_client.post_wfst(wfs_query, headers=authn_headers1, workspace=username) with app.app_context(): new_db_attributes = db.get_all_column_names(username, layername1) for attr_name in attribute_names: assert attr_name in new_db_attributes, f"new_db_attributes={new_db_attributes}, attr_name={attr_name}" process_client.reserve_username(username, headers=authn_headers1) process_client.publish_workspace_layer( username, layername1, file_paths=[ 'tmp/naturalearth/110m/cultural/ne_110m_admin_0_countries.geojson', ], headers=authn_headers1) # Testing, that user2 is not able to write to layer of user1 process_client.reserve_username(username2, headers=authn_headers2) # INSERT attr_names = ['inexisting_attribute_auth1', 'inexisting_attribute_auth2'] data_xml = data_wfs.get_wfs20_insert_points_new_attr( username, layername1, attr_names) do_test(data_xml, attr_names) # UPDATE attr_names = ['inexisting_attribute_auth3', 'inexisting_attribute_auth4'] data_xml = data_wfs.get_wfs20_update_points_new_attr( username, layername1, attr_names) do_test(data_xml, attr_names) process_client.delete_workspace_layer(username, layername1, headers=authn_headers1)
def clear_country_chunks(): yield process_client.delete_workspace_layer(WORKSPACE, LAYERNAME, skip_404=True)
def test_geoserver_bbox(): workspace = 'test_geoserver_bbox_workspace' layer = 'test_geoserver_bbox_layer' expected_bbox_1 = test_data.SMALL_LAYER_BBOX crs = crs_def.EPSG_3857 no_area_bbox_padding = crs_def.CRSDefinitions[crs].no_area_bbox_padding expected_bboxes = [ ((1571203, 6268895, 1572589, 6269864), (1571203, 6268895, 1572589, 6269864)), ((1571203, 6268895, 1571203, 6269864), (1571203 - no_area_bbox_padding, 6268895, 1571203 + no_area_bbox_padding, 6269864)), # line ((1571203, 6268895, 1571203, 6268895), (1571203 - no_area_bbox_padding, 6268895 - no_area_bbox_padding, 1571203 + no_area_bbox_padding, 6268895 + no_area_bbox_padding)), # point ((None, None, None, None), crs_def.CRSDefinitions[crs].max_bbox), ] process_client.publish_workspace_layer( workspace, layer, style_file='sample/style/small_layer.qml') assert_util.assert_wfs_bbox(workspace, layer, expected_bbox_1) assert_util.assert_wms_bbox(workspace, layer, expected_bbox_1) kwargs = { 'description': '', 'title': layer, 'access_rights': None, } # test WFS for bbox, expected_bbox in expected_bboxes: wfs.delete_layer(workspace, layer) with app.app_context(): publications.set_bbox( workspace, process_client.LAYER_TYPE, layer, bbox, crs, ) wfs.delete_layer(workspace, layer) tasks.refresh_wfs.apply( args=[workspace, layer], kwargs=kwargs, ) assert_util.assert_wfs_bbox(workspace, layer, expected_bbox) # test WMS for bbox, expected_bbox in expected_bboxes: wms.delete_layer(workspace, layer) with app.app_context(): publications.set_bbox( workspace, process_client.LAYER_TYPE, layer, bbox, crs, ) tasks.refresh_wms.apply( args=[workspace, layer, True], kwargs=kwargs, ) assert_util.assert_wms_bbox(workspace, layer, expected_bbox) # test cascade WMS from QGIS for bbox, expected_bbox in expected_bboxes: wms.delete_layer(workspace, layer) with app.app_context(): publications.set_bbox( workspace, process_client.LAYER_TYPE, layer, bbox, crs, ) wms.delete_layer(workspace, layer) tasks.refresh_wms.apply( args=[workspace, layer, False], kwargs=kwargs, ) assert_util.assert_wms_bbox(workspace, layer, expected_bbox) process_client.delete_workspace_layer(workspace, layer)