diff --git a/app/meson.build b/app/meson.build index fb6efb55e7..94a5d44a2e 100644 --- a/app/meson.build +++ b/app/meson.build @@ -128,7 +128,6 @@ libapp_dep = declare_dependency( # Those subdirs need to link against the first ones subdir('config') -subdir('tests') console_libapps += [ libappconfig ] diff --git a/app/tests/meson.build b/app/tests/meson.build index 18e6c434ad..bca4405a96 100644 --- a/app/tests/meson.build +++ b/app/tests/meson.build @@ -35,7 +35,6 @@ apptests_links += libapptestutils app_tests = [ 'core', 'gimpidtable', - 'save-and-export', #'session-2-8-compatibility-multi-window', #'session-2-8-compatibility-single-window', 'single-window-mode', @@ -73,3 +72,41 @@ foreach test_name : app_tests prio = prio - 10 endforeach + +## Newer Tests using GIMP directly ## + +if not meson.can_run_host_binaries() + warning('XCF loading unit testing disabled in cross-building or similar environments.') + subdir_done() +endif + +tests = [ + { + 'name': 'save-and-export', + } +] + +test_env=gimp_run_env +test_env.set('GIMP_TESTING_ABS_TOP_SRCDIR', meson.project_source_root()) +test_env.set('GIMP_TESTING_ABS_TOP_BUILDDIR', meson.project_build_root()) + +run_python_test = find_program(meson.project_source_root() / 'libgimp/tests/libgimp-run-python-test.py') +foreach testinfo : tests + test_name = testinfo['name'] + basename = 'test-' + testinfo['name'] + + py_test = meson.current_source_dir() / basename + '.py' + if testinfo.has_key('input') + test(test_name, run_python_test, + args: [ gimp_exe.full_path(), py_test, testinfo['input']], + env: test_env, + suite: ['app'], + timeout: 90) + else + test(test_name, run_python_test, + args: [ gimp_exe.full_path(), py_test ], + env: test_env, + suite: ['app'], + timeout: 90) + endif +endforeach diff --git a/app/tests/test-save-and-export.c b/app/tests/test-save-and-export.c deleted file mode 100644 index ddb25080af..0000000000 --- a/app/tests/test-save-and-export.c +++ /dev/null @@ -1,399 +0,0 @@ -/* GIMP - The GNU Image Manipulation Program - * Copyright (C) 2009 Martin Nordholts - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "config.h" - -#include -#include - -#include -#include -#include - -#include "libgimpbase/gimpbase.h" -#include "libgimpmath/gimpmath.h" -#include "libgimpwidgets/gimpwidgets.h" - -#include "dialogs/dialogs-types.h" - -#include "core/gimp.h" -#include "core/gimpchannel.h" -#include "core/gimpcontext.h" -#include "core/gimpimage.h" -#include "core/gimplayer.h" -#include "core/gimptoolinfo.h" -#include "core/gimptooloptions.h" - -#include "plug-in/gimppluginmanager-file.h" - -#include "file/file-open.h" -#include "file/file-save.h" - -#include "widgets/gimpdialogfactory.h" -#include "widgets/gimpdock.h" -#include "widgets/gimpdockable.h" -#include "widgets/gimpdockbook.h" -#include "widgets/gimpdocked.h" -#include "widgets/gimpdockwindow.h" -#include "widgets/gimphelp-ids.h" -#include "widgets/gimpsessioninfo.h" -#include "widgets/gimptoolbox.h" -#include "widgets/gimptooloptionseditor.h" -#include "widgets/gimpuimanager.h" -#include "widgets/gimpwidgets-utils.h" - -#include "display/gimpdisplay.h" -#include "display/gimpdisplayshell.h" -#include "display/gimpdisplayshell-scale.h" -#include "display/gimpdisplayshell-transform.h" -#include "display/gimpimagewindow.h" - -#include "gimpcoreapp.h" - -#include "gimp-app-test-utils.h" -#include "tests.h" - - -#define ADD_TEST(function) \ - g_test_add_data_func ("/gimp-save-and-export/" #function, gimp, function); - - -typedef gboolean (*GimpUiTestFunc) (GObject *object); - - -/** - * new_file_has_no_files: - * @data: - * - * Tests that the URIs are correct for a newly created image. - **/ -static void -new_file_has_no_files (gconstpointer data) -{ - Gimp *gimp = GIMP (data); - GimpImage *image = gimp_test_utils_create_image_from_dialog (gimp); - - g_assert_true (gimp_image_get_file (image) == NULL); - g_assert_true (gimp_image_get_imported_file (image) == NULL); - g_assert_true (gimp_image_get_exported_file (image) == NULL); -} - -/** - * opened_xcf_file_files: - * @data: - * - * Tests that GimpImage URIs are correct for an XCF file that has just - * been opened. - **/ -static void -opened_xcf_file_files (gconstpointer data) -{ - Gimp *gimp = GIMP (data); - GimpImage *image; - GFile *file; - gchar *filename; - GimpPDBStatusType status; - - filename = g_build_filename (g_getenv ("GIMP_TESTING_ABS_TOP_SRCDIR"), - "app/tests/files/gimp-2-6-file.xcf", - NULL); - file = g_file_new_for_path (filename); - g_free (filename); - - image = file_open_image (gimp, - gimp_get_user_context (gimp), - NULL /*progress*/, - file, - 0, 0, /* vector width, height */ - TRUE, /* vector keep ratio */ - FALSE /*as_new*/, - NULL /*file_proc*/, - GIMP_RUN_NONINTERACTIVE, - NULL, /* file_proc_handles_vector */ - &status, - NULL /*mime_type*/, - NULL /*error*/); - - g_assert_true (g_file_equal (gimp_image_get_file (image), file)); - g_assert_true (gimp_image_get_imported_file (image) == NULL); - g_assert_true (gimp_image_get_exported_file (image) == NULL); - - g_object_unref (file); -} - -/** - * imported_file_files: - * @data: - * - * Tests that URIs are correct for an imported image. - **/ -static void -imported_file_files (gconstpointer data) -{ - Gimp *gimp = GIMP (data); - GimpImage *image; - GFile *file; - gchar *filename; - GimpPDBStatusType status; - - filename = g_build_filename (g_getenv ("GIMP_TESTING_ABS_TOP_BUILDDIR"), - "gimp-data/images/logo/gimp64x64.png", - NULL); - g_assert_true (g_file_test (filename, G_FILE_TEST_EXISTS)); - file = g_file_new_for_path (filename); - g_free (filename); - - image = file_open_image (gimp, - gimp_get_user_context (gimp), - NULL /*progress*/, - file, - 0, 0, /* vector width, height */ - TRUE, /* vector keep ratio */ - FALSE /*as_new*/, - NULL /*file_proc*/, - GIMP_RUN_NONINTERACTIVE, - NULL, /* file_proc_handles_vector */ - &status, - NULL /*mime_type*/, - NULL /*error*/); - - g_assert_true (gimp_image_get_file (image) == NULL); - g_assert_true (g_file_equal (gimp_image_get_imported_file (image), file)); - g_assert_true (gimp_image_get_exported_file (image) == NULL); - - g_object_unref (file); -} - -/** - * saved_imported_file_files: - * @data: - * - * Tests that the URIs are correct for an image that has been imported - * and then saved. - **/ -static void -saved_imported_file_files (gconstpointer data) -{ - Gimp *gimp = GIMP (data); - GimpImage *image; - GFile *import_file; - gchar *import_filename; - GFile *save_file; - gchar *save_filename; - GimpPDBStatusType status; - GimpPlugInProcedure *proc; - - import_filename = g_build_filename (g_getenv ("GIMP_TESTING_ABS_TOP_BUILDDIR"), - "gimp-data/images/logo/gimp64x64.png", - NULL); - import_file = g_file_new_for_path (import_filename); - g_free (import_filename); - - save_filename = g_build_filename (g_get_tmp_dir (), "gimp-test.xcf", NULL); - save_file = g_file_new_for_path (save_filename); - g_free (save_filename); - - /* Import */ - image = file_open_image (gimp, - gimp_get_user_context (gimp), - NULL /*progress*/, - import_file, - 0, 0, /* vector width, height */ - TRUE, /* vector keep ratio */ - FALSE /*as_new*/, - NULL /*file_proc*/, - GIMP_RUN_NONINTERACTIVE, - NULL, /* file_proc_handles_vector */ - &status, - NULL /*mime_type*/, - NULL /*error*/); - - g_object_unref (import_file); - - /* Save */ - proc = gimp_plug_in_manager_file_procedure_find (image->gimp->plug_in_manager, - GIMP_FILE_PROCEDURE_GROUP_SAVE, - save_file, - NULL /*error*/); - file_save (gimp, - image, - NULL /*progress*/, - save_file, - proc, - GIMP_RUN_NONINTERACTIVE, - TRUE /*change_saved_state*/, - FALSE /*export_backward*/, - FALSE /*export_forward*/, - NULL /*error*/); - - /* Assert */ - g_assert_true (g_file_equal (gimp_image_get_file (image), save_file)); - g_assert_true (gimp_image_get_imported_file (image) == NULL); - g_assert_true (gimp_image_get_exported_file (image) == NULL); - - g_file_delete (save_file, NULL, NULL); - g_object_unref (save_file); -} - -/** - * exported_file_files: - * @data: - * - * Tests that the URIs for an exported, newly created file are - * correct. - **/ -static void -exported_file_files (gconstpointer data) -{ - GFile *save_file; - gchar *save_filename; - GimpPlugInProcedure *proc; - Gimp *gimp = GIMP (data); - GimpImage *image = gimp_test_utils_create_image_from_dialog (gimp); - - save_filename = g_build_filename (g_get_tmp_dir (), "gimp-test.png", NULL); - save_file = g_file_new_for_path (save_filename); - g_free (save_filename); - - proc = gimp_plug_in_manager_file_procedure_find (image->gimp->plug_in_manager, - GIMP_FILE_PROCEDURE_GROUP_EXPORT, - save_file, - NULL /*error*/); - file_save (gimp, - image, - NULL /*progress*/, - save_file, - proc, - GIMP_RUN_NONINTERACTIVE, - FALSE /*change_saved_state*/, - FALSE /*export_backward*/, - TRUE /*export_forward*/, - NULL /*error*/); - - g_assert_true (gimp_image_get_file (image) == NULL); - g_assert_true (gimp_image_get_imported_file (image) == NULL); - g_assert_true (g_file_equal (gimp_image_get_exported_file (image), save_file)); - - g_file_delete (save_file, NULL, NULL); - g_object_unref (save_file); -} - -/** - * clear_import_file_after_export: - * @data: - * - * Tests that after a XCF file that was imported has been exported, - * the import URI is cleared. An image can not be considered both - * imported and exported at the same time. - **/ -static void -clear_import_file_after_export (gconstpointer data) -{ - Gimp *gimp = GIMP (data); - GimpImage *image; - GFile *file; - gchar *filename; - GFile *save_file; - gchar *save_filename; - GimpPlugInProcedure *proc; - GimpPDBStatusType status; - - filename = g_build_filename (g_getenv ("GIMP_TESTING_ABS_TOP_BUILDDIR"), - "gimp-data/images/logo/gimp64x64.png", - NULL); - file = g_file_new_for_path (filename); - g_free (filename); - - image = file_open_image (gimp, - gimp_get_user_context (gimp), - NULL /*progress*/, - file, - 0, 0, /* vector width, height */ - TRUE, /* vector keep ratio */ - FALSE /*as_new*/, - NULL /*file_proc*/, - GIMP_RUN_NONINTERACTIVE, - NULL, /* file_proc_handles_vector */ - &status, - NULL /*mime_type*/, - NULL /*error*/); - - g_assert_true (gimp_image_get_file (image) == NULL); - g_assert_true (g_file_equal (gimp_image_get_imported_file (image), file)); - g_assert_true (gimp_image_get_exported_file (image) == NULL); - - g_object_unref (file); - - save_filename = g_build_filename (g_get_tmp_dir (), "gimp-test.png", NULL); - save_file = g_file_new_for_path (save_filename); - g_free (save_filename); - - proc = gimp_plug_in_manager_file_procedure_find (image->gimp->plug_in_manager, - GIMP_FILE_PROCEDURE_GROUP_EXPORT, - save_file, - NULL /*error*/); - file_save (gimp, - image, - NULL /*progress*/, - save_file, - proc, - GIMP_RUN_NONINTERACTIVE, - FALSE /*change_saved_state*/, - FALSE /*export_backward*/, - TRUE /*export_forward*/, - NULL /*error*/); - - g_assert_true (gimp_image_get_file (image) == NULL); - g_assert_true (gimp_image_get_imported_file (image) == NULL); - g_assert_true (g_file_equal (gimp_image_get_exported_file (image), save_file)); - - g_file_delete (save_file, NULL, NULL); - g_object_unref (save_file); -} - -int -main(int argc, - char **argv) -{ - Gimp *gimp = NULL; - gint result = -1; - - gimp_test_bail_if_no_display (); - gtk_test_init (&argc, &argv, NULL); - - gimp_test_utils_setup_menus_path (); - - /* Start up GIMP */ - gimp = gimp_init_for_gui_testing (TRUE /*show_gui*/); - gimp_test_run_mainloop_until_idle (); - - ADD_TEST (new_file_has_no_files); - ADD_TEST (opened_xcf_file_files); - ADD_TEST (imported_file_files); - ADD_TEST (saved_imported_file_files); - ADD_TEST (exported_file_files); - ADD_TEST (clear_import_file_after_export); - - /* Run the tests and return status */ - g_application_run (gimp->app, 0, NULL); - result = gimp_core_app_get_exit_status (GIMP_CORE_APP (gimp->app)); - - g_application_quit (G_APPLICATION (gimp->app)); - g_clear_object (&gimp->app); - - return result; -} diff --git a/app/tests/test-save-and-export.py b/app/tests/test-save-and-export.py new file mode 100644 index 0000000000..c3c2bf1fdb --- /dev/null +++ b/app/tests/test-save-and-export.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 + +# NOTE: these tests were originally mostly supposed to be GUI tests, but +# the early tests were much too flimsy. And to be fair, they were not +# proper GUI tests either, as they would hack-call some core functions, +# but without actually loading the full process and clicking on buttons +# or actually interacting with the interface. +# These replacement tests are further away since they use the public API +# (but this one does use core code too!). +# +# Now the ideal implementation would use dedicated GUI testing +# frameworks, which actually simulate human interactions with GUI +# applications through automated scripts. When we'll have these, we may +# replace the below tests. + +tmpdir = Gimp.temp_directory() + +# Tests that the URIs are correct for a newly created image. +image = Gimp.Image.new(800, 600, Gimp.ImageBaseType.RGB) +#Gimp.Display.new(image) +gimp_assert("New image has no file associated", image.get_xcf_file() is None) +gimp_assert("New image has no imported file", image.get_imported_file() is None); +gimp_assert("New image has no exported file", image.get_exported_file() is None); +image.delete() + + +# Tests that GimpImage URIs are correct for an XCF file that has just been opened. +path = os.path.join(os.environ['GIMP_TESTING_ABS_TOP_SRCDIR'], + 'app/tests/files/gimp-2-6-file.xcf') +gimp_assert("XCF file to load exists", GLib.file_test(path, GLib.FileTest.EXISTS)) +file = Gio.File.new_for_path(path) +image = Gimp.file_load(Gimp.RunMode.NONINTERACTIVE, file) +gimp_assert("Loaded XCF's file equals the loaded file", image.get_xcf_file().equal(file)); +gimp_assert("Loaded XCF has no imported file", image.get_imported_file() is None); +gimp_assert("Loaded XCF has no exported file", image.get_exported_file() is None); + + +# Tests that the URIs are correct for an image that has been imported and then saved. +path = os.path.join(tmpdir, 'gimp-test.xcf') +saved_file = Gio.File.new_for_path(path) +gimp_assert(f"Making sure {path} does not exists", not GLib.file_test(path, GLib.FileTest.EXISTS)) +Gimp.file_save(Gimp.RunMode.NONINTERACTIVE, image, saved_file, None) +gimp_assert("XCF file was properly saved", GLib.file_test(path, GLib.FileTest.EXISTS)) +gimp_assert("Saved XCF's file is correct", image.get_xcf_file().equal(saved_file)); +gimp_assert("Saved XCF has no imported file", image.get_imported_file() is None); +gimp_assert("Saved XCF has no exported file", image.get_exported_file() is None); + + +# Tests that the URIs for an exported, newly created file are correct. +path = os.path.join(tmpdir, 'gimp-test.png') +exported_file = Gio.File.new_for_path(path) +gimp_assert(f"Making sure {path} does not exists", not GLib.file_test(path, GLib.FileTest.EXISTS)) +Gimp.file_save(Gimp.RunMode.NONINTERACTIVE, image, exported_file, None) +gimp_assert("PNG file was properly saved", GLib.file_test(path, GLib.FileTest.EXISTS)) +gimp_assert("Exported image's file still equals the saved file", image.get_xcf_file().equal(saved_file)); +gimp_assert("Exported image has no imported file", image.get_imported_file() is None); +gimp_assert("Exported image's exported file is correct", image.get_exported_file().equal(exported_file)); + +saved_file.delete() +exported_file.delete() +image.delete() + + +# Tests that URIs are correct for an imported image. +path = os.path.join(os.environ['GIMP_TESTING_ABS_TOP_BUILDDIR'], + 'gimp-data/images/logo/gimp64x64.png') +gimp_assert("Image file to import exists", GLib.file_test(path, GLib.FileTest.EXISTS)) +file = Gio.File.new_for_path(path) +image = Gimp.file_load(Gimp.RunMode.NONINTERACTIVE, file) +gimp_assert("Imported image has no file associated", image.get_xcf_file() is None) +gimp_assert("Imported image's imported file equals the loaded file", image.get_imported_file().equal(file)); +gimp_assert("Imported image has no exported file", image.get_exported_file() is None); + + +# Tests that after a XCF file was imported then exported, the import URI is cleared. +# An image can not be considered both imported and exported at the same time. +gimp_assert(f"Making sure {exported_file.peek_path()} does not exists", + not GLib.file_test(exported_file.peek_path(), GLib.FileTest.EXISTS)) +Gimp.file_save(Gimp.RunMode.NONINTERACTIVE, image, exported_file, None) +gimp_assert("Imported then exported image has no file associated", image.get_xcf_file() is None) +gimp_assert("Imported then exported image has no imported file", image.get_imported_file() is None) +gimp_assert("Imported then exported image has a correct exported file", image.get_exported_file().equal(exported_file)) + +exported_file.delete() +image.delete() diff --git a/meson.build b/meson.build index 3540950a85..0697adbdc6 100644 --- a/meson.build +++ b/meson.build @@ -2090,6 +2090,7 @@ gimp_exe = find_program('tools'/'in-build-gimp.py') subdir('gimp-data/images/') # Unit testing +subdir('app/tests') subdir('libgimp/tests') # Docs