# SPDX-License-Identifier: GPL-2.0-or-later # Helper function to add a CLI test # # Run an Inkscape command line and check for pass/fail condition (by default only exit status is checked) # # Command line options: # INPUT_FILENAME - name of input file (optional) # OUTPUT_FILENAME - name of output file (optional) # PARAMETERS - additional command line parameters to pass to Inkscape # # Pass/fail criteria: # PASS_FOR_OUTPUT - pass if output matches the given value, otherwise fail # see https://cmake.org/cmake/help/latest/prop_test/PASS_REGULAR_EXPRESSION.html for details # FAIL_FOR_OUTPUT - fail if output matches the given value # see https://cmake.org/cmake/help/latest/prop_test/FAIL_REGULAR_EXPRESSION.html for details # REFERENCE_FILENAME - compare OUTPUT_FILENAME with this pre-rendered reference file # both files are converted to PNG and compared with ImageMagick's 'compare' # EXPECTED_FILES - verify the command produced the expected files (i.e. they exist on disk) # TEST_SCRIPT - additional script to run after performing all checks and before cleaning up # # Other options: # ENVIRONMENT - Additional environment variables to set while running the test function(add_cli_test name) # parse arguments set(oneValueArgs INPUT_FILENAME OUTPUT_FILENAME PASS_FOR_OUTPUT FAIL_FOR_OUTPUT REFERENCE_FILENAME) set(multiValueArgs PARAMETERS EXPECTED_FILES TEST_SCRIPT ENVIRONMENT) cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) set(testname cli_${name}) #disable dithering set(ARG_PARAMETERS ${ARG_PARAMETERS} "--export-png-use-dithering=false") if(DEFINED ARG_OUTPUT_FILENAME) # for actions: if an export-do is present do not append export-filename option to prevent if(NOT ARG_PARAMETERS MATCHES "export-do") set(ARG_PARAMETERS ${ARG_PARAMETERS} "--export-filename=${ARG_OUTPUT_FILENAME}") endif() endif() if(DEFINED ARG_INPUT_FILENAME) set(ARG_INPUT_FILENAME "${CMAKE_CURRENT_SOURCE_DIR}/testcases/${ARG_INPUT_FILENAME}") set(ARG_PARAMETERS ${ARG_PARAMETERS} ${ARG_INPUT_FILENAME}) endif() set(CMAKE_CTEST_ENV "${INKSCAPE_TEST_PROFILE_DIR_ENV}/${testname};${CMAKE_CTEST_ENV}") if(DEFINED ARG_ENVIRONMENT) if(ARG_ENVIRONMENT STREQUAL "unset") unset(CMAKE_CTEST_ENV) else() # variables might already be set, however the last value wins list(APPEND CMAKE_CTEST_ENV ${ARG_ENVIRONMENT}) endif() endif() # add test for main command line add_test(NAME ${testname} COMMAND inkscape ${ARG_PARAMETERS}) set_tests_properties(${testname} PROPERTIES ENVIRONMENT "${CMAKE_CTEST_ENV}") if(DEFINED ARG_PASS_FOR_OUTPUT) set_tests_properties(${testname} PROPERTIES PASS_REGULAR_EXPRESSION ${ARG_PASS_FOR_OUTPUT}) endif() if(DEFINED ARG_FAIL_FOR_OUTPUT) set_tests_properties(${testname} PROPERTIES FAIL_REGULAR_EXPRESSION ${ARG_FAIL_FOR_OUTPUT}) endif() # add test to check output files if(DEFINED ARG_REFERENCE_FILENAME OR DEFINED ARG_EXPECTED_FILES OR DEFINED ARG_TEST_SCRIPT) if(DEFINED ARG_REFERENCE_FILENAME) file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/testcases/${ARG_REFERENCE_FILENAME}" ARG_REFERENCE_FILENAME) endif() if(DEFINED ARG_EXPECTED_FILES) string(REPLACE ";" " " ARG_EXPECTED_FILES "${ARG_EXPECTED_FILES}") endif() if(DEFINED ARG_TEST_SCRIPT) set(ARG_TEST_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/${ARG_TEST_SCRIPT}") endif() add_test(NAME ${testname}_check_output COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/check_output.sh "${ARG_OUTPUT_FILENAME}" "${ARG_REFERENCE_FILENAME}" "${ARG_EXPECTED_FILES}" "${ARG_TEST_SCRIPT}") set_tests_properties(${testname}_check_output PROPERTIES ENVIRONMENT "${CMAKE_CTEST_ENV}" DEPENDS ${testname} SKIP_RETURN_CODE 42) endif() endfunction(add_cli_test) ##### Tests follow below ##### ############################################################################################# ### Command line options (basic tests for all program options as listed in --help output) ### ############################################################################################# # --help # --version (check if we can run inkscape and the revision is known) add_cli_test(version PARAMETERS --version) add_cli_test(version_known PARAMETERS --version FAIL_FOR_OUTPUT unknown) # --system-data-directory / --user-data-directory (unset environment variables to override our override) # TODO: Can we make these tests more specific without making too many assumptions? add_cli_test(system-data-directory PARAMETERS --system-data-directory ENVIRONMENT unset PASS_FOR_OUTPUT "inkscape\n$") add_cli_test(user-data-directory PARAMETERS --user-data-directory ENVIRONMENT unset PASS_FOR_OUTPUT "inkscape\n$") # --pipe # --pdf-page=PAGE # --pdf-poppler add_cli_test(pdf-poppler-mesh-import PARAMETERS --pdf-poppler INPUT_FILENAME pdf-mesh.pdf OUTPUT_FILENAME pdf-mesh_poppler.svg TEST_SCRIPT match_regex.sh pdf-mesh_poppler.svg "file-close$file-open:${CMAKE_CURRENT_SOURCE_DIR}/testcases/theta.svg$export-filename:actions-file-close.svg$export-do TEST_SCRIPT match_regex.sh actions-file-close.svg "id=\"purple-cover\"") # file-new add_cli_test(actions-file-new1 PARAMETERS --actions=file-new$export-filename:actions-file-new1.svg$export-do TEST_SCRIPT match_regex.sh actions-file-new1.svg "viewBox=\"0 0 210 297\"") add_cli_test(actions-file-new2 PARAMETERS --actions=file-new:${CMAKE_CURRENT_SOURCE_DIR}/testcases/theta.svg$export-filename:actions-file-new2.svg$export-do TEST_SCRIPT match_regex.sh actions-file-new2.svg "id=\"purple-cover\"") # file-open add_cli_test(actions-file-open PARAMETERS --actions=file-open:${CMAKE_CURRENT_SOURCE_DIR}/testcases/theta.svg$export-filename:actions-file-open.png$export-do OUTPUT_FILENAME actions-file-open.png REFERENCE_FILENAME actions-file-open_expected.png) # inkscape-version add_cli_test(actions-inkscape-version PARAMETERS --actions=inkscape-version PASS_FOR_OUTPUT "Inkscape [0-9]+\\.[0-9]+") # no-convert-baseline # object-align add_cli_test(actions-object-align INPUT_FILENAME lambda.svg PARAMETERS --actions=select-by-id:green$object-align:left\ page OUTPUT_FILENAME actions-object-align.png REFERENCE_FILENAME actions-object-align_expected.png) # object-distribute add_cli_test(actions-object-distribute INPUT_FILENAME rects.svg PARAMETERS --actions=select-by-element:rect$object-distribute:vgap OUTPUT_FILENAME actions-object-distribute.png REFERENCE_FILENAME actions-object-distribute_expected.png) # object-set-attribute add_cli_test(actions-object-set-attribute INPUT_FILENAME rects.svg PARAMETERS --actions=select-by-id:rect1$object-set-attribute:rx,15 OUTPUT_FILENAME actions-object-set-attribute.png REFERENCE_FILENAME actions-object-set-attribute_expected.png) # object-set-property add_cli_test(actions-object-set-property INPUT_FILENAME areas.svg PARAMETERS --actions=select-by-id:MyRect$object-set-property:fill,gold OUTPUT_FILENAME actions-object-set-property.svg TEST_SCRIPT match_regex.sh actions-object-set-property.svg "style=\"fill:gold\"") # path-simplify add_cli_test(actions-path-simplify INPUT_FILENAME path.svg PARAMETERS --actions=select-by-id:gates$path-simplify$export-id:gates$export-id-only OUTPUT_FILENAME actions-object-simplify-path.png REFERENCE_FILENAME actions-object-simplify-path_expected.png) # object-stroke-to-path add_cli_test(actions-object-stroke-to-path INPUT_FILENAME path.svg PARAMETERS --actions=select-by-id:cross$object-stroke-to-path$select-by-selector:path\:nth-of-type\(2\)$object-set-attribute:stroke,red$export-id:cross$export-id-only OUTPUT_FILENAME actions-object-stroke-to-path.png REFERENCE_FILENAME actions-object-stroke-to-path_expected.png) add_cli_test(action_stroke-to-path_varied INPUT_FILENAME stroke-to-path-variations.svg PARAMETERS --actions=select-all:all$object-stroke-to-path$export-filename:stroke-to-path-variations_out.svg$export-do EXPECTED_FILES stroke-to-path-variations_out.svg TEST_SCRIPT match_regex_fail.sh stroke-to-path-variations_out.svg "(#mixed)|(#fillet)|(object-to-path$export-id:MyRect$export-id-only OUTPUT_FILENAME actions-object-to-path.svg TEST_SCRIPT match_regex.sh actions-object-to-path.svg "object-unlink-clones$object-set-attribute:fill,red$export-id:clone$export-id-only OUTPUT_FILENAME actions-object-unlink-clones.png REFERENCE_FILENAME actions-object-unlink-clones_expected.png) # open-page add_cli_test(actions-open-page PARAMETERS --actions=open-page:3$file-open:${CMAKE_CURRENT_SOURCE_DIR}/testcases/pdf-pages.pdf$export-filename:actions-open-page.png$export-do OUTPUT_FILENAME actions-open-page.png REFERENCE_FILENAME actions-open-page_expected.png) # query-all: test = query-all add_cli_test(actions-query-all INPUT_FILENAME rects.svg PARAMETERS --actions=select-by-id:rect2$query-all PASS_FOR_OUTPUT ${query_all_expected}) # query-height: test = query-height add_cli_test(actions-query-height INPUT_FILENAME rects.svg PARAMETERS --actions=select-by-id:rect2$query-height PASS_FOR_OUTPUT 70) # query-width: test = query-width add_cli_test(actions-query-width INPUT_FILENAME rects.svg PARAMETERS --actions=select-by-id:rect2$query-width PASS_FOR_OUTPUT 80) # query-x: test = query-x add_cli_test(actions-query-x INPUT_FILENAME rects.svg PARAMETERS --actions=select-by-id:rect2$query-x PASS_FOR_OUTPUT 110) # query-y: test = query-y add_cli_test(actions-query-y INPUT_FILENAME rects.svg PARAMETERS --actions=select-by-id:rect2$query-y PASS_FOR_OUTPUT 20) # quit-inkscape # Failed because of https://gitlab.com/inkscape/inkscape/-/issues/1565 # add_cli_test(actions-quit-inkscape PARAMETERS --actions=quit-inkscape FAIL_FOR_OUTPUT ".+") # select: it is deprecated # select-all # Failed because of https://gitlab.com/inkscape/inkscape/-/issues/1565 # add_cli_test(actions-select-all INPUT_FILENAME path.svg PARAMETERS --actions=select-all$select-list # PASS_FOR_OUTPUT "^heart .+\nbottom-left-corner .+\nsquare .+\ntop-right-corner .+\narc-big .+\narc-small .+\ngates .+\ncross .+\nclone .+$") # select-by-class # Failed because of https://gitlab.com/inkscape/inkscape/-/issues/1565 # add_cli_test(actions-select-by-class INPUT_FILENAME path.svg PARAMETERS --actions=select-by-class:corner$select-list # PASS_FOR_OUTPUT "^bottom-left-corner .+\ntop-right-corner .+$") # select-by-element # Failed because of https://gitlab.com/inkscape/inkscape/-/issues/1565 # add_cli_test(actions-select-by-element INPUT_FILENAME path.svg PARAMETERS --actions=select-by-element:use$select-list # PASS_FOR_OUTPUT "^clone .+$") # select-by-id # Failed because of https://gitlab.com/inkscape/inkscape/-/issues/1565 # add_cli_test(actions-select-by-id INPUT_FILENAME path.svg PARAMETERS --actions=select-by-id:top-right-corner$select-list # PASS_FOR_OUTPUT "^top-right-corner .+$") # select-by-selector = svg > path:nth-child(2n) ~ *[fill=red]:nth-of-type(even) # Failed because of https://gitlab.com/inkscape/inkscape/-/issues/1565 # add_cli_test(actions-select-by-selector INPUT_FILENAME path.svg PARAMETERS --actions=select-by-selector:svg\ >\ path:nth-child\(2n\)\ ~\ *\[fill\=red\]:nth-of-type\(even\)$select-list # PASS_FOR_OUTPUT "^arc-big .+\nclone .+$") # select-clear # Failed because of https://gitlab.com/inkscape/inkscape/-/issues/1565 # add_cli_test(actions-select-clear INPUT_FILENAME path.svg PARAMETERS --actions=select-by-element:path$select-clear$select-by-id:cross$select-list # PASS_FOR_OUTPUT "^cross .+$") # select-invert # Failed because of https://gitlab.com/inkscape/inkscape/-/issues/1565 # add_cli_test(actions-select-invert INPUT_FILENAME path.svg PARAMETERS --actions=select-by-selector:path:nth-of-type\(2n\)$select-invert:all$select-list # PASS_FOR_OUTPUT "^heart .+\nsquare .+\narc-big .+\ngates .+\nclone .+$") # select-list # Failed because of https://gitlab.com/inkscape/inkscape/-/issues/1565 # add_cli_test(actions-select-list INPUT_FILENAME path.svg PARAMETERS --actions=select-by-selector:*[stroke-width]:nth-child\(3n+3\)$select-list # PASS_FOR_OUTPUT "^gates cloned: false ref: 1 href: 0 total href: 0\n$") # system-data-directory: test = system-data-directory add_cli_test(actions-system-data-directory PARAMETERS --actions=system-data-directory ENVIRONMENT unset PASS_FOR_OUTPUT "inkscape\n$") # transform-remove add_cli_test(actions-transform-remove INPUT_FILENAME pyramids.svg PARAMETERS --actions=select-by-id:quad_snapped_4$transform-rotate:2$transform-remove OUTPUT_FILENAME actions-transform-remove.png REFERENCE_FILENAME actions-transform-remove_expected.png) # transform-rotate add_cli_test(actions-transform-rotate INPUT_FILENAME pyramids.svg PARAMETERS --actions=select-by-id:rect_snapped_4$transform-rotate:45 OUTPUT_FILENAME actions-transform-rotate.png REFERENCE_FILENAME actions-transform-rotate_expected.png) # transform-scale add_cli_test(actions-transform-grow INPUT_FILENAME pyramids.svg PARAMETERS --actions=select-by-id:quad_snapped_1$transform-grow:10 OUTPUT_FILENAME actions-transform-grow.png REFERENCE_FILENAME actions-transform-grow_expected.png) # transform-translate add_cli_test(actions-transform-translate INPUT_FILENAME pyramids.svg PARAMETERS --actions=select-by-id:quad_snapped_1$transform-translate:-5,-5 OUTPUT_FILENAME actions-transform-translate.png REFERENCE_FILENAME actions-transform-translate_expected.png) # unselect: it is deprecated # unselect-by-id # Failed because of https://gitlab.com/inkscape/inkscape/-/issues/1565 # add_cli_test(actions-unselect-by-id INPUT_FILENAME path.svg PARAMETERS --actions=select-by-element:path$unselect-by-id:heart,bottom-left-corner,square,top-right-corner,arc-big,arc-small,gates$select-list # PASS_FOR_OUTPUT "^cross .+$") # user-data-directory: test = user-data-directory add_cli_test(actions-user-data-directory PARAMETERS --actions=user-data-directory ENVIRONMENT unset PASS_FOR_OUTPUT "inkscape\n$") # vacuum-defs # window-close # window-open # tests x/y values are not swapped in tspans. add_cli_test(action_test_multiline_anchoring INPUT_FILENAME multiline-anchoring.svg PARAMETERS --actions=select-by-id:grouped_text$transform-translate:10,0$transform-translate:-10,0$export-filename:multiline-anchoring_out.svg$export-plain-svg$export-do EXPECTED_FILES multiline-anchoring_out.svg TEST_SCRIPT match_regex_fail.sh multiline-anchoring_out.svg "(x=\"[3-9][0-9]{2}\")|(x=\"[12][0-9]{3}\")|(y=\"[0-9]{2}\")|(y=\"1[0-9]{2}\")") ########################### ### file format support ### ########################### # librevenge formats if(WITH_LIBCDR) # add_cli_test(import_cdr PARAMETERS --export-type=png # fails to open (regression in libcdr 1.6.0) # INPUT_FILENAME librevenge_formats/corel_draw.cdr OUTPUT_FILENAME format_corel_draw.png # REFERENCE_FILENAME librevenge_formats/corel_draw_expected.png) # check png size is correct add_cli_test(import_cdr2 PARAMETERS --export-type=png INPUT_FILENAME librevenge_formats/corel_draw2.cdr OUTPUT_FILENAME format_corel_draw2.png REFERENCE_FILENAME librevenge_formats/corel_draw2_expected.png) endif() if(WITH_LIBVISIO) add_cli_test(import_vsd PARAMETERS --export-type=png INPUT_FILENAME librevenge_formats/visio.vsd OUTPUT_FILENAME format_visio.vsd.png REFERENCE_FILENAME librevenge_formats/visio.vsd_expected.png) add_cli_test(import_vsdx PARAMETERS --export-type=png INPUT_FILENAME librevenge_formats/visio.vsdx OUTPUT_FILENAME format_visio.vsdx.png REFERENCE_FILENAME librevenge_formats/visio.vsdx_expected.png) endif() if(WITH_LIBWPG) add_cli_test(import_wpg PARAMETERS --export-type=png INPUT_FILENAME librevenge_formats/word_perfect.wpg OUTPUT_FILENAME format_word_perfect.png REFERENCE_FILENAME librevenge_formats/word_perfect_expected.png) endif() ############################## ### advanced functionality ### ############################## # check whether INKSCAPE_DATADIR / INKSCAPE_PROFILE_DIR environment variables work # TODO: INKSCAPE_PROFILE_DIR does not seem to be sanitized at all (i.e. is used verbatim by Inkscape) set(fancy_dir "i_certainly_do_not_exist") file(TO_NATIVE_PATH "${fancy_dir}/inkscape" expected_dir) string(REPLACE "\\" "\\\\" expected_dir "${expected_dir}") add_cli_test(inkscape_datadir PARAMETERS --system-data-directory ENVIRONMENT INKSCAPE_DATADIR=${fancy_dir} PASS_FOR_OUTPUT "${expected_dir}\n$") add_cli_test(inkscape_profile_dir PARAMETERS --user-data-directory ENVIRONMENT INKSCAPE_PROFILE_DIR=${fancy_dir}/inkscape PASS_FOR_OUTPUT "${fancy_dir}/inkscape\n$") add_cli_test(inkscape_profile_dir_handle_illegal ENVIRONMENT INKSCAPE_PROFILE_DIR=invalid:dir INPUT_FILENAME empty.svg OUTPUT_FILENAME empty.svg) # check if "systemLanguage" attribute is properly handled add_cli_test(systemLanguage_en ENVIRONMENT LANGUAGE=en INPUT_FILENAME systemLanguage.svg OUTPUT_FILENAME systemLanguage_en.png REFERENCE_FILENAME systemLanguage_en.png) add_cli_test(systemLanguage_fr ENVIRONMENT LANGUAGE=fr_FR INPUT_FILENAME systemLanguage.svg OUTPUT_FILENAME systemLanguage_fr.png REFERENCE_FILENAME systemLanguage_fr.png) add_cli_test(systemLanguage_fr2 ENVIRONMENT LANGUAGE=fr_FR.UTF-8 INPUT_FILENAME systemLanguage.svg OUTPUT_FILENAME systemLanguage_fr2.png REFERENCE_FILENAME systemLanguage_fr.png) add_cli_test(systemLanguage_de ENVIRONMENT LANGUAGE=de INPUT_FILENAME systemLanguage.svg OUTPUT_FILENAME systemLanguage_de.png REFERENCE_FILENAME systemLanguage_de.png) add_cli_test(systemLanguage_de-CH ENVIRONMENT LANGUAGE=de_CH INPUT_FILENAME systemLanguage.svg OUTPUT_FILENAME systemLanguage_de-CH.png REFERENCE_FILENAME systemLanguage_de.png) add_cli_test(systemLanguage_pt ENVIRONMENT LANGUAGE=pt INPUT_FILENAME systemLanguage.svg OUTPUT_FILENAME systemLanguage_pt.png REFERENCE_FILENAME systemLanguage_pt.png) add_cli_test(systemLanguage_xy ENVIRONMENT LANGUAGE=xy INPUT_FILENAME systemLanguage.svg OUTPUT_FILENAME systemLanguage_xy.png REFERENCE_FILENAME systemLanguage_default.png) add_cli_test(systemLanguage_fr_RDF ENVIRONMENT LANGUAGE=xy INPUT_FILENAME systemLanguage_RDF.svg OUTPUT_FILENAME systemLanguage_fr_RDF.png REFERENCE_FILENAME systemLanguage_fr.png)