Initial checkin of Pika from heckimp

This commit is contained in:
2023-09-25 15:35:21 -07:00
commit 891e999216
6761 changed files with 5240685 additions and 0 deletions

View File

@ -0,0 +1,29 @@
#!/usr/bin/env sh
# Copy tests resources
for dir in files pikadir pikadir-empty; do
rm -rf "${MESON_BUILD_ROOT}/${MESON_SUBDIR}/${dir}"
cp -r "${MESON_SOURCE_ROOT}/${MESON_SUBDIR}/${dir}" \
"${MESON_BUILD_ROOT}/${MESON_SUBDIR}"
done
# Link to Color icon theme for tests
IconsRoot="${MESON_SOURCE_ROOT}/icons/Color"
IconsDirs=$(find "${IconsRoot}" -name [0-9]* -type d -printf '%f\n' | sort -n)
for dir in ${IconsDirs} ; do
mkdir "${MESON_BUILD_ROOT}/${MESON_SUBDIR}/pika-test-icon-theme/hicolor/${dir}x${dir}" -p
LnName="${MESON_BUILD_ROOT}/${MESON_SUBDIR}/pika-test-icon-theme/hicolor/${dir}x${dir}/apps"
rm -rf "${LnName}"
ln -s "${IconsRoot}/${dir}" "${LnName}"
done
LnName="${MESON_BUILD_ROOT}/${MESON_SUBDIR}/pika-test-icon-theme/hicolor/index.theme"
rm -rf "${LnName}"
ln -s "${IconsRoot}/index.theme" "${LnName}"
# Create output dirs
rm -rf "${MESON_BUILD_ROOT}/${MESON_SUBDIR}/pikadir-output"
for dir in brushes gradients patterns; do
mkdir -p "${MESON_BUILD_ROOT}/${MESON_SUBDIR}/pikadir-output/${dir}"
done

Binary file not shown.

View File

@ -0,0 +1,15 @@
This file contains manual test cases
------------------------------------
/pika-manual-tests/opened_image_stays_on_top
Step-by-step:
1. Create a new image, make the image window almost as big as the screen
2. From the image window menu, do File -> Open
3. Select an image and open it
Expected result:
The image is opened and is kept above the image it was opened from
Last known PASS:
2010-06-23

81
app/tests/meson.build Normal file
View File

@ -0,0 +1,81 @@
apptests_links = [
libappconfig,
libappactions,
libappdialogs,
libappdisplay,
libappgui,
libappmenus,
libapppropgui,
libapptools,
libappwidgets,
libpikabase,
libpikacolor,
libpikaconfig,
libpikamath,
libpikamodule,
libpikathumb,
libpikawidgets,
]
libapptestutils_sources = [
'pika-app-test-utils.c',
'pika-test-session-utils.c',
]
libapptestutils = static_library('apptestutils',
libapptestutils_sources,
dependencies: libapp_dep,
link_with: apptests_links,
)
apptests_links += libapptestutils
app_tests = [
'core',
'pikaidtable',
'save-and-export',
#'session-2-8-compatibility-multi-window',
#'session-2-8-compatibility-single-window',
'single-window-mode',
#'tools',
'ui',
'xcf',
]
cmd = run_command('create_test_env.sh', check: false)
if cmd.returncode() != 0
error(cmd.stderr().strip())
endif
# Prevent parallel builds for the tests
# The tests must not be run in parallel or in a different order as specified
prio = 1000
foreach test_name : app_tests
test_exe = executable(test_name,
'test-@0@.c'.format(test_name),
'tests.c',
dependencies: [ libapp_dep, appstream_glib ],
link_with: apptests_links,
)
test(test_name,
test_exe,
env: [
'PIKA_TESTING_ABS_TOP_SRCDIR=' + meson.project_source_root(),
'PIKA_TESTING_ABS_TOP_BUILDDIR='+ meson.project_build_root(),
'PIKA_TESTING_PLUGINDIRS=' + meson.project_build_root()/'plug-ins'/'common',
'PIKA_TESTING_PLUGINDIRS_BASENAME_IGNORES=mkgen.pl',
'UI_TEST=yes',
],
suite: 'app',
timeout: 60,
is_parallel : false,
priority: prio,
)
prio = prio - 10
endforeach

View File

@ -0,0 +1,383 @@
/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* Copyright (C) 2009 Martin Nordholts <martinn@src.gnome.org>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#include "display/display-types.h"
#include "display/pikadisplay.h"
#include "display/pikadisplayshell.h"
#include "display/pikaimagewindow.h"
#include "menus/menus.h"
#include "widgets/pikauimanager.h"
#include "widgets/pikadialogfactory.h"
#include "core/pika.h"
#include "core/pikaimage.h"
#include "core/pikalayer.h"
#include "core/pikalayer-new.h"
#include "tests.h"
#include "pika-app-test-utils.h"
#ifdef G_OS_WIN32
/* SendInput() requirement is Windows 2000 pro or over.
* We may need to set WINVER to make sure the compiler does not try to
* compile for on older version of win32, thus breaking the build.
* See
* http://msdn.microsoft.com/en-us/library/aa383745%28v=vs.85%29.aspx#setting_winver_or__win32_winnt
*/
#define WINVER 0x0500
#include <windows.h>
#endif /* G_OS_WIN32 */
#ifdef GDK_WINDOWING_QUARTZ
// only to get keycode definitions from HIToolbox/Events.h
#include <Carbon/Carbon.h>
#include <Cocoa/Cocoa.h>
#endif /* GDK_WINDOWING_QUARTZ */
void
pika_test_utils_set_env_to_subdir (const gchar *root_env_var,
const gchar *subdir,
const gchar *target_env_var)
{
const gchar *root_dir = NULL;
gchar *target_dir = NULL;
/* Get root dir */
root_dir = g_getenv (root_env_var);
if (! root_dir)
g_printerr ("*\n"
"* The env var %s is not set, you are probably running\n"
"* in a debugger. Set it manually, e.g.:\n"
"*\n"
"* set env %s=%s/source/pika\n"
"*\n",
root_env_var,
root_env_var, g_get_home_dir ());
/* Construct path and setup target env var */
target_dir = g_build_filename (root_dir, subdir, NULL);
g_setenv (target_env_var, target_dir, TRUE);
g_free (target_dir);
}
void
pika_test_utils_set_env_to_subpath (const gchar *root_env_var1,
const gchar *root_env_var2,
const gchar *subdir,
const gchar *target_env_var)
{
const gchar *root_dir1 = NULL;
const gchar *root_dir2 = NULL;
gchar *target_dir1 = NULL;
gchar *target_dir2 = NULL;
gchar *target_path = NULL;
/* Get root dir */
root_dir1 = g_getenv (root_env_var1);
if (! root_dir1)
g_printerr ("*\n"
"* The env var %s is not set, you are probably running\n"
"* in a debugger. Set it manually, e.g.:\n"
"*\n"
"* set env %s=%s/source/pika\n"
"*\n",
root_env_var1,
root_env_var1, g_get_home_dir ());
root_dir2 = g_getenv (root_env_var2);
if (! root_dir2)
g_printerr ("*\n"
"* The env var %s is not set, you are probably running\n"
"* in a debugger. Set it manually, e.g.:\n"
"*\n"
"* set env %s=%s/source/pika\n"
"*\n",
root_env_var2,
root_env_var2, g_get_home_dir ());
/* Construct path and setup target env var */
target_dir1 = g_build_filename (root_dir1, subdir, NULL);
target_dir2 = g_build_filename (root_dir2, subdir, NULL);
target_path = g_strconcat (target_dir1, G_SEARCHPATH_SEPARATOR_S,
target_dir2, NULL);
g_free (target_dir1);
g_free (target_dir2);
g_setenv (target_env_var, target_path, TRUE);
g_free (target_path);
}
/**
* pika_test_utils_set_pika3_directory:
* @root_env_var: Either "PIKA_TESTING_ABS_TOP_SRCDIR" or
* "PIKA_TESTING_ABS_TOP_BUILDDIR"
* @subdir: Subdir, may be %NULL
*
* Sets PIKA3_DIRECTORY to the source dir @root_env_var/@subdir. The
* environment variables is set up by the test runner, see Makefile.am
**/
void
pika_test_utils_set_pika3_directory (const gchar *root_env_var,
const gchar *subdir)
{
pika_test_utils_set_env_to_subdir (root_env_var,
subdir,
"PIKA3_DIRECTORY" /*target_env_var*/);
}
/**
* pika_test_utils_setup_menus_path:
*
* Sets PIKA_TESTING_MENUS_PATH to "$top_srcdir/menus:$top_builddir/menus".
**/
void
pika_test_utils_setup_menus_path (void)
{
/* PIKA_TESTING_ABS_TOP_SRCDIR is set by the automake test runner,
* see Makefile.am
*/
pika_test_utils_set_env_to_subpath ("PIKA_TESTING_ABS_TOP_SRCDIR",
"PIKA_TESTING_ABS_TOP_BUILDDIR",
"menus",
"PIKA_TESTING_MENUS_PATH");
}
/**
* pika_test_utils_create_image:
* @pika: A #Pika instance.
* @width: Width of image (and layer)
* @height: Height of image (and layer)
*
* Creates a new image of a given size with one layer of same size and
* a display.
*
* Returns: The new #PikaImage.
**/
void
pika_test_utils_create_image (Pika *pika,
gint width,
gint height)
{
PikaImage *image;
PikaLayer *layer;
image = pika_image_new (pika, width, height,
PIKA_RGB, PIKA_PRECISION_U8_NON_LINEAR);
layer = pika_layer_new (image,
width,
height,
pika_image_get_layer_format (image, TRUE),
"layer1",
1.0,
PIKA_LAYER_MODE_NORMAL);
pika_image_add_layer (image,
layer,
NULL /*parent*/,
0 /*position*/,
FALSE /*push_undo*/);
pika_create_display (pika,
image,
PIKA_UNIT_PIXEL,
1.0 /*scale*/,
NULL);
}
/**
* pika_test_utils_synthesize_key_event:
* @widget: Widget to target.
* @keyval: Keyval, e.g. GDK_Return
*
* Simulates a keypress and release with gdk_test_simulate_key().
**/
void
pika_test_utils_synthesize_key_event (GtkWidget *widget,
guint keyval)
{
#if defined(GDK_WINDOWING_QUARTZ)
GdkKeymapKey *keys = NULL;
gint n_keys = 0;
gint i;
CGEventRef keyUp, keyDown;
if (gdk_keymap_get_entries_for_keyval (gdk_keymap_get_for_display (gdk_display_get_default ()), keyval, &keys, &n_keys))
{
/* XXX not in use yet */
CGEventRef commandDown = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)kVK_Command, true);
CGEventRef commandUp = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)kVK_Command, false);
CGEventRef shiftDown = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)kVK_Shift, true);
CGEventRef shiftUp = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)kVK_Shift, false);
CGEventRef optionDown = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)kVK_Option, true);
CGEventRef optionUp = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)kVK_Option, false);
for (i = 0; i < n_keys; i++)
{
/* Option press. */
if (keys[i].group)
{
CGEventPost (kCGHIDEventTap, optionDown);
}
/* Shift press. */
if (keys[i].level)
{
CGEventPost(kCGHIDEventTap, shiftDown);
}
keyDown = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)keys[i].keycode, true);
keyUp = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)keys[i].keycode, false);
/* Key pressed. */
CGEventPost (kCGHIDEventTap, keyDown);
CFRelease (keyDown);
usleep (100);
/* key released */
CGEventPost (kCGHIDEventTap, keyUp);
CFRelease (keyUp);
/* Shift release. */
if (keys[i].level)
{
CGEventPost (kCGHIDEventTap, shiftDown);
}
/* Option release. */
if (keys[i].group)
{
CGEventPost (kCGHIDEventTap, optionUp);
}
/* No need to loop for alternative keycodes. We want only one
* key generated. */
break;
}
CFRelease (commandDown);
CFRelease (commandUp);
CFRelease (shiftDown);
CFRelease (shiftUp);
CFRelease (optionDown);
CFRelease (optionUp);
g_free (keys);
}
else
{
g_warning ("%s: no macOS key mapping found for keyval %d.", G_STRFUNC, keyval);
}
#else /* ! GDK_WINDOWING_QUARTZ */
gdk_test_simulate_key (gtk_widget_get_window (widget),
-1, -1, /*x, y*/
keyval,
0 /*modifiers*/,
GDK_KEY_PRESS);
gdk_test_simulate_key (gtk_widget_get_window (widget),
-1, -1, /*x, y*/
keyval,
0 /*modifiers*/,
GDK_KEY_RELEASE);
#endif /* ! GDK_WINDOWING_QUARTZ */
}
/**
* pika_test_utils_get_ui_manager:
* @pika: The #Pika instance.
*
* Returns the "best" #PikaUIManager to use when performing
* actions. It gives the ui manager of the empty display if it exists,
* otherwise it gives it the ui manager of the first display.
*
* Returns: The #PikaUIManager.
**/
PikaUIManager *
pika_test_utils_get_ui_manager (Pika *pika)
{
return menus_get_image_manager_singleton (pika);
}
/**
* pika_test_utils_create_image_from_dalog:
* @pika:
*
* Creates a new image using the "New image" dialog, and then returns
* the #PikaImage created.
*
* Returns: The created #PikaImage.
**/
PikaImage *
pika_test_utils_create_image_from_dialog (Pika *pika)
{
PikaImage *image = NULL;
GtkWidget *new_image_dialog = NULL;
guint n_initial_images = g_list_length (pika_get_image_iter (pika));
guint n_images = -1;
gint tries_left = 100;
PikaUIManager *ui_manager = pika_test_utils_get_ui_manager (pika);
/* Bring up the new image dialog */
pika_ui_manager_activate_action (ui_manager,
"image",
"image-new");
pika_test_run_mainloop_until_idle ();
/* Get the GtkWindow of the dialog */
new_image_dialog =
pika_dialog_factory_dialog_raise (pika_dialog_factory_get_singleton (),
gdk_display_get_monitor (gdk_display_get_default (), 0),
NULL,
"pika-image-new-dialog",
-1 /*view_size*/);
/* Press the OK button. It will take a while for the image to be
* created so loop for a while
*/
gtk_dialog_response (GTK_DIALOG (new_image_dialog), GTK_RESPONSE_OK);
do
{
g_usleep (20 * 1000);
pika_test_run_mainloop_until_idle ();
n_images = g_list_length (pika_get_image_iter (pika));
}
while (tries_left-- &&
n_images != n_initial_images + 1);
/* Make sure there now is one image more than initially */
g_assert_cmpint (n_images,
==,
n_initial_images + 1);
image = PIKA_IMAGE (pika_get_image_iter (pika)->data);
return image;
}

View File

@ -0,0 +1,46 @@
/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* Copyright (C) 2009 Martin Nordholts <martinn@src.gnome.org>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#ifndef __PIKA_APP_TEST_UTILS_H__
#define __PIKA_APP_TEST_UTILS_H__
void pika_test_utils_set_env_to_subdir (const gchar *root_env_var,
const gchar *subdir,
const gchar *target_env_var);
void pika_test_utils_set_env_to_subpath (const gchar *root_env_var1,
const gchar *root_env_var2,
const gchar *subdir,
const gchar *target_env_var);
void pika_test_utils_set_pika3_directory (const gchar *root_env_var,
const gchar *subdir);
void pika_test_utils_setup_menus_path (void);
void pika_test_utils_create_image (Pika *pika,
gint width,
gint height);
void pika_test_utils_synthesize_key_event (GtkWidget *widget,
guint keyval);
PikaUIManager * pika_test_utils_get_ui_manager (Pika *pika);
PikaImage * pika_test_utils_create_image_from_dialog
(Pika *pika);
#endif /* __PIKA_APP_TEST_UTILS_H__ */

View File

@ -0,0 +1,256 @@
/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* Copyright (C) 2011 Martin Nordholts <martinn@src.gnome.org>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include <glib/gstdio.h>
#include <gtk/gtk.h>
#include <stdlib.h>
#include <string.h>
#include <utime.h>
#include "libpikabase/pikabase.h"
#include "dialogs/dialogs-types.h"
#include "widgets/pikadialogfactory.h"
#include "widgets/pikasessioninfo.h"
#include "core/pika.h"
#include "core/pikacontext.h"
#include "tests.h"
#include "pika-app-test-utils.h"
#include "pika-test-session-utils.h"
typedef struct
{
GFile *file;
gchar *md5;
guint64 modtime;
} PikaTestFileState;
static gboolean
pika_test_get_file_state_verbose (GFile *file,
PikaTestFileState *filestate)
{
gboolean success = TRUE;
filestate->file = g_object_ref (file);
/* Get checksum */
if (success)
{
gchar *filename;
gchar *contents = NULL;
gsize length = 0;
filename = g_file_get_path (file);
success = g_file_get_contents (filename,
&contents,
&length,
NULL);
g_free (filename);
if (success)
{
filestate->md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5,
contents,
length);
}
g_free (contents);
}
/* Get modification time */
if (success)
{
GFileInfo *info = g_file_query_info (file,
G_FILE_ATTRIBUTE_TIME_MODIFIED, 0,
NULL, NULL);
if (info)
{
filestate->modtime = g_file_info_get_attribute_uint64 (
info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
success = TRUE;
g_object_unref (info);
}
else
{
success = FALSE;
}
}
if (! success)
g_printerr ("Failed to get initial file info for '%s'\n",
pika_file_get_utf8_name (file));
return success;
}
static gboolean
pika_test_file_state_changes (GFile *file,
PikaTestFileState *state1,
PikaTestFileState *state2)
{
if (state1->modtime == state2->modtime)
{
g_printerr ("A new '%s' was not created\n",
pika_file_get_utf8_name (file));
return FALSE;
}
if (strcmp (state1->md5, state2->md5) != 0)
{
char *diff_argv[5] = {
"diff",
"-u",
g_file_get_path (state1->file),
g_file_get_path (state2->file),
NULL
};
g_printerr ("'%s' was changed but should not have been. Reason, using "
"`diff -u $expected $actual`\n",
pika_file_get_utf8_name (file));
g_spawn_sync (NULL /*working_directory*/,
diff_argv,
NULL /*envp*/,
G_SPAWN_SEARCH_PATH,
NULL /*child_setup*/,
NULL /*user_data*/,
NULL /*standard_output*/,
NULL /*standard_error*/,
NULL /*exist_status*/,
NULL /*error*/);
g_free (diff_argv[2]);
g_free (diff_argv[3]);
return FALSE;
}
return TRUE;
}
/**
* pika_test_session_load_and_write_session_files:
* @loaded_sessionrc: The name of the file of the sessionrc file to
* load
* @loaded_dockrc: The name of the file of the dockrc file to load
* @expected_sessionrc: The name of the file with the expected
* sessionrc file content
* @expected_dockrc: The name of the file with the expected dockrc
* file content
*
* Utility function for the various session management tests. We can't
* easily have all those tests in a single program several Gimp
* instance can't easily be initialized in the same process.
**/
void
pika_test_session_load_and_write_session_files (const gchar *loaded_sessionrc,
const gchar *loaded_dockrc,
const gchar *expected_sessionrc,
const gchar *expected_dockrc,
gboolean single_window_mode)
{
Pika *pika;
PikaTestFileState initial_sessionrc_state = { NULL, NULL, 0 };
PikaTestFileState initial_dockrc_state = { NULL, NULL, 0 };
PikaTestFileState final_sessionrc_state = { NULL, NULL, 0 };
PikaTestFileState final_dockrc_state = { NULL, NULL, 0 };
GFile *sessionrc_file = NULL;
GFile *dockrc_file = NULL;
/* Make sure to run this before we use any PIKA functions */
pika_test_utils_set_pika3_directory ("PIKA_TESTING_ABS_TOP_SRCDIR",
"app/tests/pikadir");
pika_test_utils_setup_menus_path ();
/* Note that we expect the resulting sessionrc to be different from
* the read file, which is why we check the MD5 of the -expected
* variant
*/
sessionrc_file = pika_directory_file (expected_sessionrc, NULL);
dockrc_file = pika_directory_file (expected_dockrc, NULL);
/* Remember the modtimes and MD5s */
g_assert (pika_test_get_file_state_verbose (sessionrc_file,
&initial_sessionrc_state));
g_assert (pika_test_get_file_state_verbose (dockrc_file,
&initial_dockrc_state));
/* Use specific input files when restoring the session */
g_setenv ("PIKA_TESTING_SESSIONRC_NAME", loaded_sessionrc, TRUE /*overwrite*/);
g_setenv ("PIKA_TESTING_DOCKRC_NAME", loaded_dockrc, TRUE /*overwrite*/);
/* Start up PIKA */
pika = pika_init_for_gui_testing (TRUE /*show_gui*/);
/* Let the main loop run until idle to let things stabilize. This
* includes parsing sessionrc and dockrc
*/
pika_test_run_mainloop_until_idle ();
/* Change the pika dir to the output dir so files are written there,
* we don't want to (can't always) write to files in the source
* dir. There is a hook in Makefile.am that makes sure the output
* dir exists
*/
pika_test_utils_set_pika3_directory ("PIKA_TESTING_ABS_TOP_BUILDDIR",
"app/tests/pikadir-output");
/* Use normal output names */
g_unsetenv ("PIKA_TESTING_SESSIONRC_NAME");
g_unsetenv ("PIKA_TESTING_DOCKRC_NAME");
g_object_unref (sessionrc_file);
g_object_unref (dockrc_file);
sessionrc_file = pika_directory_file ("sessionrc", NULL);
dockrc_file = pika_directory_file ("dockrc", NULL);
/* Exit. This includes writing sessionrc and dockrc*/
pika_exit (pika, TRUE);
/* Now get the new modtimes and MD5s */
g_assert (pika_test_get_file_state_verbose (sessionrc_file,
&final_sessionrc_state));
g_assert (pika_test_get_file_state_verbose (dockrc_file,
&final_dockrc_state));
/* If things have gone our way, PIKA will have deserialized
* sessionrc and dockrc, shown the GUI, and then serialized the new
* files. To make sure we have new files we check the modtime, and
* to make sure that their content remains the same we compare their
* MD5
*/
g_assert (pika_test_file_state_changes (g_file_new_for_path ("sessionrc"),
&initial_sessionrc_state,
&final_sessionrc_state));
g_assert (pika_test_file_state_changes (g_file_new_for_path ("dockrc"),
&initial_dockrc_state,
&final_dockrc_state));
}

View File

@ -0,0 +1,33 @@
/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* Copyright (C) 2009 Martin Nordholts <martinn@src.gnome.org>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#ifndef __PIKA_TEST_SESSION_UTILS_H__
#define __PIKA_TEST_SESSION_UTILS_H__
void pika_test_session_load_and_write_session_files (const gchar *loaded_sessionrc,
const gchar *loaded_dockrc,
const gchar *expected_sessionrc,
const gchar *expected_dockrc,
gboolean single_window_mode);
#endif /* __PIKA_TEST_SESSION_UTILS_H__ */

View File

@ -0,0 +1,24 @@
<?xml version='1.0' encoding='UTF-8'?>
<tags>
<resource identifier="pika-brush-clipboard" checksum="157dcef48665ab465439cfaf10d6feeb">
</resource>
<resource identifier="pika-pattern-clipboard" checksum="eff9598f9f61c1dc78d842f1798c2ab8">
</resource>
<resource identifier="pika-gradient-fg-bg-rgb" checksum="12ad9439c57e897e50fb0399439e5b2b">
</resource>
<resource identifier="pika-gradient-fg-bg-hsv-cw" checksum="86589f70c8a7777c6e2d1d14b99e3759">
</resource>
<resource identifier="pika-gradient-fg-bg-hsv-ccw" checksum="65aacbbd72d99ff20ca1bd310f0a21a5">
</resource>
<resource identifier="pika-gradient-fg-bg-rgb" checksum="4a878c6cfae0b0e03c0834723daadf92">
</resource>
<resource identifier="pika-gradient-fg-transparent" checksum="1491f74caf057a39c8193470da2d2a29">
</resource>
</tags>

44
app/tests/pikadir/dockrc Normal file
View File

@ -0,0 +1,44 @@
# recently closed docks
(PikaSessionInfo "Palettes - FG/BG - Images"
(factory-entry "pika-dock-window")
(position 585 115)
(size 200 575)
(open-on-exit)
(aux-info
(show-image-menu "false")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-palette-list"
(tab-style preview)))
(book
(position 140)
(current-page 0)
(dockable "pika-color-editor"
(tab-style preview)
(aux-info
(current-page "PikaColorSelect"))))
(book
(position 415)
(current-page 0)
(dockable "pika-image-list"
(tab-style preview)))))
(PikaSessionInfo "Selection, Fonts"
(factory-entry "pika-dock-window")
(position 200 180)
(size 200 300)
(open-on-exit)
(aux-info
(show-image-menu "false")
(follow-active-image "true"))
(pika-dock
(book
(current-page 1)
(dockable "pika-selection-editor"
(tab-style icon))
(dockable "pika-font-list"
(tab-style preview)))))
# end of recently closed docks

View File

@ -0,0 +1,44 @@
# recently closed docks
(PikaSessionInfo "Palettes - FG/BG - Images"
(factory-entry "pika-dock-window")
(position 585 115)
(size 200 575)
(open-on-exit)
(aux-info
(show-image-menu "false")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-palette-list"
(tab-style preview)))
(book
(position 140)
(current-page 0)
(dockable "pika-color-editor"
(tab-style preview)
(aux-info
(current-page "PikaColorSelect"))))
(book
(position 415)
(current-page 0)
(dockable "pika-image-list"
(tab-style preview)))))
(PikaSessionInfo "Selection, Fonts"
(factory-entry "pika-dock-window")
(position 200 180)
(size 200 300)
(open-on-exit)
(aux-info
(show-image-menu "false")
(follow-active-image "true"))
(pika-dock
(book
(current-page 1)
(dockable "pika-selection-editor"
(tab-style icon))
(dockable "pika-font-list"
(tab-style preview)))))
# end of recently closed docks

View File

@ -0,0 +1,44 @@
# recently closed docks
(PikaSessionInfo "Palettes - FG/BG - Images"
(factory-entry "pika-dock-window")
(position 585 115)
(size 200 575)
(open-on-exit)
(aux-info
(show-image-menu "false")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-palette-list"
(tab-style preview)))
(book
(position 140)
(current-page 0)
(dockable "pika-color-editor"
(tab-style preview)
(aux-info
(current-page "PikaColorSelect"))))
(book
(position 415)
(current-page 0)
(dockable "pika-image-list"
(tab-style preview)))))
(PikaSessionInfo "Selection, Fonts"
(factory-entry "pika-dock-window")
(position 200 180)
(size 200 300)
(open-on-exit)
(aux-info
(show-image-menu "false")
(follow-active-image "true"))
(pika-dock
(book
(current-page 1)
(dockable "pika-selection-editor"
(tab-style icon))
(dockable "pika-font-list"
(tab-style preview)))))
# end of recently closed docks

117
app/tests/pikadir/sessionrc Normal file
View File

@ -0,0 +1,117 @@
# PIKA sessionrc
#
# This file takes session-specific info (that is info, you want to keep
# between two PIKA sessions). You are not supposed to edit it manually, but
# of course you can do. The sessionrc will be entirely rewritten every time
# you quit PIKA. If this file isn't found, defaults are used.
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 565 170)
(size 210 535)
(open-on-exit)
(aux-info
(show-image-menu "false")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-layer-list"
(tab-style icon)
(preview-size 32)
(aux-info
(show-button-bar "true"))))
(book
(position 290)
(current-page 0)
(dockable "pika-brush-grid"
(tab-style preview)
(aux-info
(show-button-bar "true"))))))
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 140 290)
(size 445 300)
(open-on-exit)
(aux-info
(show-image-menu "false")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-tool-options"
(tab-style icon)
(aux-info
(show-button-bar "true")))))
(pika-dock
(position 230)
(book
(current-page 0)
(dockable "pika-device-status"
(tab-style icon)
(aux-info
(show-button-bar "true"))))))
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 795 45)
(size 200 265)
(open-on-exit)
(aux-info
(show-image-menu "true")
(follow-active-image "true"))
(pika-dock
(book
(current-page 1)
(dockable "pika-pattern-grid"
(tab-style preview)
(aux-info
(show-button-bar "true")))
(dockable "pika-gradient-list"
(tab-style preview)
(aux-info
(show-button-bar "true"))))))
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 805 345)
(size 200 450)
(open-on-exit)
(aux-info
(show-image-menu "true")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-channel-list"
(tab-style icon)
(preview-size 32)
(aux-info
(show-button-bar "true"))))
(book
(position 200)
(current-page 0)
(dockable "pika-palette-editor"
(tab-style icon)
(aux-info
(show-button-bar "true")
(edit-active "true")
(current-data "Color History")
(zoom-factor "2.80"))))))
(session-info "toplevel"
(factory-entry "pika-file-open-dialog")
(position 390 140)
(size 900 815))
(session-info "toplevel"
(factory-entry "pika-image-new-dialog")
(position 100 100))
(session-info "toplevel"
(factory-entry "pika-empty-image-window")
(position 140 30)
(size 610 190))
(session-info "toplevel"
(factory-entry "pika-single-image-window")
(position 10 40)
(size 900 600))
(last-tip-shown 0)
# end of sessionrc

View File

@ -0,0 +1,105 @@
# PIKA sessionrc
#
# This file takes session-specific info (that is info, you want to keep
# between two PIKA sessions). You are not supposed to edit it manually, but
# of course you can do. The sessionrc will be entirely rewritten every time
# you quit PIKA. If this file isn't found, defaults are used.
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 565 170)
(size 210 535)
(open-on-exit)
(aux-info
(show-image-menu "false")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-layer-list"
(tab-style icon)
(preview-size 32)))
(book
(position 290)
(current-page 0)
(dockable "pika-brush-grid"
(tab-style preview)))))
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 140 290)
(size 445 300)
(open-on-exit)
(aux-info
(show-image-menu "false")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-tool-options"
(tab-style icon))))
(pika-dock
(position 230)
(book
(current-page 0)
(dockable "pika-device-status"
(tab-style icon)))))
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 795 45)
(size 200 265)
(open-on-exit)
(aux-info
(show-image-menu "true")
(follow-active-image "true"))
(pika-dock
(book
(current-page 1)
(dockable "pika-pattern-grid"
(tab-style preview))
(dockable "pika-gradient-list"
(tab-style preview)))))
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 805 345)
(size 200 450)
(open-on-exit)
(aux-info
(show-image-menu "true")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-channel-list"
(tab-style icon)
(preview-size 32)))
(book
(position 200)
(current-page 0)
(dockable "pika-palette-editor"
(tab-style icon)
(aux-info
(edit-active "true")
(current-data "Color History")
(zoom-factor "2.80"))))))
(session-info "toplevel"
(factory-entry "pika-file-open-dialog")
(position 390 140)
(size 900 815))
(session-info "toplevel"
(factory-entry "pika-image-new-dialog")
(position 100 100))
(session-info "toplevel"
(factory-entry "pika-empty-image-window")
(position 140 30)
(size 610 190)
(open-on-exit))
(session-info "toplevel"
(factory-entry "pika-single-image-window")
(position 10 40)
(size 900 600))
(hide-docks no)
(single-window-mode no)
(last-tip-shown 0)
# end of sessionrc

View File

@ -0,0 +1,63 @@
# PIKA sessionrc
#
# This file takes session-specific info (that is info, you want to keep
# between two PIKA sessions). You are not supposed to edit it manually, but
# of course you can do. The sessionrc will be entirely rewritten every time
# you quit PIKA. If this file isn't found, defaults are used.
(session-info "toplevel"
(factory-entry "pika-file-open-dialog")
(position 390 140)
(size 900 815))
(session-info "toplevel"
(factory-entry "pika-image-new-dialog")
(position 100 100))
(session-info "toplevel"
(factory-entry "pika-empty-image-window")
(position 140 30)
(size 1285 750))
(session-info "toplevel"
(factory-entry "pika-single-image-window")
(position 140 30)
(size 1050 770)
(open-on-exit)
(aux-info
(left-docks-width "80")
(right-docks-width "400")
(maximized "no"))
(pika-toolbox
(side left))
(pika-dock
(side right)
(book
(current-page 0)
(dockable "pika-layer-list"
(tab-style icon)
(preview-size 32)))
(book
(position 380)
(current-page 0)
(dockable "pika-brush-grid"
(tab-style preview))))
(pika-dock
(side right)
(position 200)
(book
(current-page 0)
(dockable "pika-tool-options"
(tab-style icon))))
(pika-dock
(side right)
(position 550)
(book
(current-page 1)
(dockable "pika-pattern-grid"
(tab-style preview))
(dockable "pika-gradient-list"
(tab-style preview)))))
(hide-docks no)
(single-window-mode yes)
(last-tip-shown 0)
# end of sessionrc

View File

@ -0,0 +1,105 @@
# PIKA sessionrc
#
# This file takes session-specific info (that is info, you want to keep
# between two PIKA sessions). You are not supposed to edit it manually, but
# of course you can do. The sessionrc will be entirely rewritten every time
# you quit PIKA. If this file isn't found, defaults are used.
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 565 170)
(size 210 535)
(open-on-exit)
(aux-info
(show-image-menu "false")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-layer-list"
(tab-style icon)
(preview-size 32)))
(book
(position 290)
(current-page 0)
(dockable "pika-brush-grid"
(tab-style preview)))))
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 140 290)
(size 445 300)
(open-on-exit)
(aux-info
(show-image-menu "false")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-tool-options"
(tab-style icon))))
(pika-dock
(position 230)
(book
(current-page 0)
(dockable "pika-device-status"
(tab-style icon)))))
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 795 45)
(size 200 265)
(open-on-exit)
(aux-info
(show-image-menu "true")
(follow-active-image "true"))
(pika-dock
(book
(current-page 1)
(dockable "pika-pattern-grid"
(tab-style preview))
(dockable "pika-gradient-list"
(tab-style preview)))))
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 805 345)
(size 200 450)
(open-on-exit)
(aux-info
(show-image-menu "true")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-channel-list"
(tab-style icon)
(preview-size 32)))
(book
(position 200)
(current-page 0)
(dockable "pika-palette-editor"
(tab-style icon)
(aux-info
(edit-active "true")
(current-data "Color History")
(zoom-factor "2.80"))))))
(session-info "toplevel"
(factory-entry "pika-file-open-dialog")
(position 390 140)
(size 900 815))
(session-info "toplevel"
(factory-entry "pika-image-new-dialog")
(position 100 100))
(session-info "toplevel"
(factory-entry "pika-empty-image-window")
(position 140 30)
(size 610 190)
(open-on-exit))
(session-info "toplevel"
(factory-entry "pika-single-image-window")
(position 10 40)
(size 900 600))
(hide-docks no)
(single-window-mode no)
(last-tip-shown 0)
# end of sessionrc

View File

@ -0,0 +1,122 @@
# PIKA sessionrc
#
# This file takes session-specific info (that is info, you want to keep
# between two PIKA sessions). You are not supposed to edit it manually, but
# of course you can do. The sessionrc will be entirely rewritten every time
# you quit PIKA. If this file isn't found, defaults are used.
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 565 170)
(size 210 535)
(open-on-exit)
(aux-info
(show-image-menu "false")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-layer-list"
(tab-style icon)
(preview-size 32)
(aux-info
(show-button-bar "true"))))
(book
(position 290)
(current-page 0)
(dockable "pika-brush-grid"
(tab-style preview)
(aux-info
(show-button-bar "true"))))))
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 140 290)
(size 445 300)
(open-on-exit)
(aux-info
(show-image-menu "false")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-tool-options"
(tab-style icon)
(aux-info
(show-button-bar "true")))))
(pika-dock
(position 230)
(book
(current-page 0)
(dockable "pika-device-status"
(tab-style icon)
(aux-info
(show-button-bar "true"))))))
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 795 45)
(size 200 265)
(open-on-exit)
(aux-info
(show-image-menu "true")
(follow-active-image "true"))
(pika-dock
(book
(current-page 1)
(dockable "pika-pattern-grid"
(tab-style preview)
(aux-info
(show-button-bar "true")))
(dockable "pika-gradient-list"
(tab-style preview)
(aux-info
(show-button-bar "true"))))))
(session-info "toplevel"
(factory-entry "pika-dock-window")
(position 805 345)
(size 200 450)
(open-on-exit)
(aux-info
(show-image-menu "true")
(follow-active-image "true"))
(pika-dock
(book
(current-page 0)
(dockable "pika-channel-list"
(tab-style icon)
(preview-size 32)
(aux-info
(show-button-bar "true"))))
(book
(position 200)
(current-page 0)
(dockable "pika-palette-editor"
(tab-style icon)
(aux-info
(show-button-bar "true")
(edit-active "true")
(current-data "Color History")
(zoom-factor "2.80"))))))
(session-info "toplevel"
(factory-entry "pika-file-open-dialog")
(position 390 140)
(size 900 815))
(session-info "toplevel"
(factory-entry "pika-image-new-dialog")
(position 100 100))
(session-info "toplevel"
(factory-entry "pika-empty-image-window")
(position 140 30)
(size 610 190)
(open-on-exit))
(session-info "toplevel"
(factory-entry "pika-single-image-window")
(position 10 40)
(size 900 600))
(hide-docks no)
(single-window-mode no)
(show-tabs yes)
(tabs-position 0)
(last-tip-shown 0)
# end of sessionrc

View File

@ -0,0 +1,75 @@
# PIKA sessionrc
#
# This file takes session-specific info (that is info, you want to keep
# between two PIKA sessions). You are not supposed to edit it manually, but
# of course you can do. The sessionrc will be entirely rewritten every time
# you quit PIKA. If this file isn't found, defaults are used.
(session-info "toplevel"
(factory-entry "pika-file-open-dialog")
(position 390 140)
(size 900 815))
(session-info "toplevel"
(factory-entry "pika-image-new-dialog")
(position 100 100))
(session-info "toplevel"
(factory-entry "pika-empty-image-window")
(position 140 30)
(size 1285 750))
(session-info "toplevel"
(factory-entry "pika-single-image-window")
(position 140 30)
(size 1050 770)
(open-on-exit)
(aux-info
(left-docks-width "80")
(right-docks-width "400")
(maximized "no"))
(pika-toolbox
(side left))
(pika-dock
(side right)
(book
(current-page 0)
(dockable "pika-layer-list"
(tab-style icon)
(preview-size 32)
(aux-info
(show-button-bar "true"))))
(book
(position 380)
(current-page 0)
(dockable "pika-brush-grid"
(tab-style preview)
(aux-info
(show-button-bar "true")))))
(pika-dock
(side right)
(position 200)
(book
(current-page 0)
(dockable "pika-tool-options"
(tab-style icon)
(aux-info
(show-button-bar "true")))))
(pika-dock
(side right)
(position 550)
(book
(current-page 1)
(dockable "pika-pattern-grid"
(tab-style preview)
(aux-info
(show-button-bar "true")))
(dockable "pika-gradient-list"
(tab-style preview)
(aux-info
(show-button-bar "true"))))))
(hide-docks no)
(single-window-mode yes)
(show-tabs yes)
(tabs-position 0)
(last-tip-shown 0)
# end of sessionrc

View File

@ -0,0 +1,24 @@
<?xml version='1.0' encoding='UTF-8'?>
<tags>
<resource identifier="pika-brush-clipboard" checksum="157dcef48665ab465439cfaf10d6feeb">
</resource>
<resource identifier="pika-pattern-clipboard" checksum="eff9598f9f61c1dc78d842f1798c2ab8">
</resource>
<resource identifier="pika-gradient-fg-bg-hsv-cw" checksum="86589f70c8a7777c6e2d1d14b99e3759">
</resource>
<resource identifier="pika-gradient-fg-bg-hsv-ccw" checksum="65aacbbd72d99ff20ca1bd310f0a21a5">
</resource>
<resource identifier="pika-gradient-fg-bg-rgb" checksum="12ad9439c57e897e50fb0399439e5b2b">
</resource>
<resource identifier="pika-gradient-fg-bg-rgb" checksum="4a878c6cfae0b0e03c0834723daadf92">
</resource>
<resource identifier="pika-gradient-fg-transparent" checksum="1491f74caf057a39c8193470da2d2a29">
</resource>
</tags>

297
app/tests/test-core.c Normal file
View File

@ -0,0 +1,297 @@
/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* 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 <https://www.gnu.org/licenses/>.
*/
#include <gegl.h>
#include <gtk/gtk.h>
#include "widgets/widgets-types.h"
#include "widgets/pikauimanager.h"
#include "core/pika.h"
#include "core/pikacontext.h"
#include "core/pikaimage.h"
#include "core/pikalayer.h"
#include "core/pikalayer-new.h"
#include "operations/pikalevelsconfig.h"
#include "tests.h"
#include "pika-app-test-utils.h"
#define PIKA_TEST_IMAGE_SIZE 100
#define ADD_IMAGE_TEST(function) \
g_test_add ("/pika-core/" #function, \
PikaTestFixture, \
pika, \
pika_test_image_setup, \
function, \
pika_test_image_teardown);
#define ADD_TEST(function) \
g_test_add ("/pika-core/" #function, \
PikaTestFixture, \
pika, \
NULL, \
function, \
NULL);
typedef struct
{
PikaImage *image;
} PikaTestFixture;
static void pika_test_image_setup (PikaTestFixture *fixture,
gconstpointer data);
static void pika_test_image_teardown (PikaTestFixture *fixture,
gconstpointer data);
/**
* pika_test_image_setup:
* @fixture:
* @data:
*
* Test fixture setup for a single image.
**/
static void
pika_test_image_setup (PikaTestFixture *fixture,
gconstpointer data)
{
Pika *pika = PIKA (data);
fixture->image = pika_image_new (pika,
PIKA_TEST_IMAGE_SIZE,
PIKA_TEST_IMAGE_SIZE,
PIKA_RGB,
PIKA_PRECISION_FLOAT_LINEAR);
}
/**
* pika_test_image_teardown:
* @fixture:
* @data:
*
* Test fixture teardown for a single image.
**/
static void
pika_test_image_teardown (PikaTestFixture *fixture,
gconstpointer data)
{
g_object_unref (fixture->image);
}
/**
* rotate_non_overlapping:
* @fixture:
* @data:
*
* Super basic test that makes sure we can add a layer
* and call pika_item_rotate with center at (0, -10)
* without triggering a failed assertion .
**/
static void
rotate_non_overlapping (PikaTestFixture *fixture,
gconstpointer data)
{
Pika *pika = PIKA (data);
PikaImage *image = fixture->image;
PikaLayer *layer;
PikaContext *context = pika_context_new (pika, "Test", NULL /*template*/);
gboolean result;
g_assert_cmpint (pika_image_get_n_layers (image), ==, 0);
layer = pika_layer_new (image,
PIKA_TEST_IMAGE_SIZE,
PIKA_TEST_IMAGE_SIZE,
babl_format ("R'G'B'A u8"),
"Test Layer",
PIKA_OPACITY_OPAQUE,
PIKA_LAYER_MODE_NORMAL);
g_assert_cmpint (PIKA_IS_LAYER (layer), ==, TRUE);
result = pika_image_add_layer (image,
layer,
PIKA_IMAGE_ACTIVE_PARENT,
0,
FALSE);
pika_item_rotate (PIKA_ITEM (layer), context, PIKA_ROTATE_90, 0., -10., TRUE);
g_assert_cmpint (result, ==, TRUE);
g_assert_cmpint (pika_image_get_n_layers (image), ==, 1);
g_object_unref (context);
}
/**
* add_layer:
* @fixture:
* @data:
*
* Super basic test that makes sure we can add a layer.
**/
static void
add_layer (PikaTestFixture *fixture,
gconstpointer data)
{
PikaImage *image = fixture->image;
PikaLayer *layer;
gboolean result;
g_assert_cmpint (pika_image_get_n_layers (image), ==, 0);
layer = pika_layer_new (image,
PIKA_TEST_IMAGE_SIZE,
PIKA_TEST_IMAGE_SIZE,
babl_format ("R'G'B'A u8"),
"Test Layer",
PIKA_OPACITY_OPAQUE,
PIKA_LAYER_MODE_NORMAL);
g_assert_cmpint (PIKA_IS_LAYER (layer), ==, TRUE);
result = pika_image_add_layer (image,
layer,
PIKA_IMAGE_ACTIVE_PARENT,
0,
FALSE);
g_assert_cmpint (result, ==, TRUE);
g_assert_cmpint (pika_image_get_n_layers (image), ==, 1);
}
/**
* remove_layer:
* @fixture:
* @data:
*
* Super basic test that makes sure we can remove a layer.
**/
static void
remove_layer (PikaTestFixture *fixture,
gconstpointer data)
{
PikaImage *image = fixture->image;
PikaLayer *layer;
gboolean result;
g_assert_cmpint (pika_image_get_n_layers (image), ==, 0);
layer = pika_layer_new (image,
PIKA_TEST_IMAGE_SIZE,
PIKA_TEST_IMAGE_SIZE,
babl_format ("R'G'B'A u8"),
"Test Layer",
PIKA_OPACITY_OPAQUE,
PIKA_LAYER_MODE_NORMAL);
g_assert_cmpint (PIKA_IS_LAYER (layer), ==, TRUE);
result = pika_image_add_layer (image,
layer,
PIKA_IMAGE_ACTIVE_PARENT,
0,
FALSE);
g_assert_cmpint (result, ==, TRUE);
g_assert_cmpint (pika_image_get_n_layers (image), ==, 1);
pika_image_remove_layer (image,
layer,
FALSE,
NULL);
g_assert_cmpint (pika_image_get_n_layers (image), ==, 0);
}
/**
* white_graypoint_in_red_levels:
* @fixture:
* @data:
*
* Makes sure the levels algorithm can handle when the graypoint is
* white. It's easy to get a divide by zero problem when trying to
* calculate what gamma will give a white graypoint.
**/
static void
white_graypoint_in_red_levels (PikaTestFixture *fixture,
gconstpointer data)
{
PikaRGB black = { 0, 0, 0, 0 };
PikaRGB gray = { 1, 1, 1, 1 };
PikaRGB white = { 1, 1, 1, 1 };
PikaHistogramChannel channel = PIKA_HISTOGRAM_RED;
PikaLevelsConfig *config;
config = g_object_new (PIKA_TYPE_LEVELS_CONFIG, NULL);
pika_levels_config_adjust_by_colors (config,
channel,
&black,
&gray,
&white);
/* Make sure we didn't end up with an invalid gamma value */
g_object_set (config,
"gamma", config->gamma[channel],
NULL);
}
int
main (int argc,
char **argv)
{
Pika *pika;
int result;
g_test_init (&argc, &argv, NULL);
pika_test_utils_set_pika3_directory ("PIKA_TESTING_ABS_TOP_SRCDIR",
"app/tests/pikadir");
/* We share the same application instance across all tests */
pika = pika_init_for_testing ();
/* Add tests */
ADD_IMAGE_TEST (add_layer);
ADD_IMAGE_TEST (remove_layer);
ADD_IMAGE_TEST (rotate_non_overlapping);
ADD_TEST (white_graypoint_in_red_levels);
/* Run the tests */
result = g_test_run ();
/* Don't write files to the source dir */
pika_test_utils_set_pika3_directory ("PIKA_TESTING_ABS_TOP_BUILDDIR",
"app/tests/pikadir-output");
/* Exit so we don't break script-fu plug-in wire */
pika_exit (pika, TRUE);
return result;
}

View File

@ -0,0 +1,231 @@
/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* Copyright (C) 2011 Martin Nordholts <martinn@src.gnome.org>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib-object.h>
#include "core/core-types.h"
#include "core/pikaidtable.h"
#define ADD_TEST(function) \
g_test_add ("/pikaidtable/" #function, \
PikaTestFixture, \
NULL, \
pika_test_id_table_setup, \
pika_test_id_table_ ## function, \
pika_test_id_table_teardown);
typedef struct
{
PikaIdTable *id_table;
} PikaTestFixture;
static gpointer data1 = (gpointer) 0x00000001;
static gpointer data2 = (gpointer) 0x00000002;
static void
pika_test_id_table_setup (PikaTestFixture *fixture,
gconstpointer data)
{
fixture->id_table = pika_id_table_new ();
}
static void
pika_test_id_table_teardown (PikaTestFixture *fixture,
gconstpointer data)
{
g_object_unref (fixture->id_table);
fixture->id_table = NULL;
}
/**
* pika_test_id_table_insert_and_lookup:
*
* Test that insert and lookup works.
**/
static void
pika_test_id_table_insert_and_lookup (PikaTestFixture *f,
gconstpointer data)
{
gint ret_id = pika_id_table_insert (f->id_table, data1);
gpointer ret_data = pika_id_table_lookup (f->id_table, ret_id);
g_assert (ret_data == data1);
}
/**
* pika_test_id_table_insert_twice:
*
* Test that two consecutive inserts generates different IDs.
**/
static void
pika_test_id_table_insert_twice (PikaTestFixture *f,
gconstpointer data)
{
gint ret_id = pika_id_table_insert (f->id_table, data1);
gpointer ret_data = pika_id_table_lookup (f->id_table, ret_id);
gint ret_id2 = pika_id_table_insert (f->id_table, data2);
gpointer ret_data2 = pika_id_table_lookup (f->id_table, ret_id2);
g_assert (ret_id != ret_id2);
g_assert (ret_data == data1);
g_assert (ret_data2 == data2);
}
/**
* pika_test_id_table_insert_with_id:
*
* Test that it is possible to insert data with a specific ID.
**/
static void
pika_test_id_table_insert_with_id (PikaTestFixture *f,
gconstpointer data)
{
const int id = 10;
int ret_id = pika_id_table_insert_with_id (f->id_table, id, data1);
gpointer ret_data = pika_id_table_lookup (f->id_table, id);
g_assert (ret_id == id);
g_assert (ret_data == data1);
}
/**
* pika_test_id_table_insert_with_id_existing:
*
* Test that it is not possible to insert data with a specific ID if
* that ID already is inserted.
**/
static void
pika_test_id_table_insert_with_id_existing (PikaTestFixture *f,
gconstpointer data)
{
const int id = 10;
int ret_id = pika_id_table_insert_with_id (f->id_table, id, data1);
gpointer ret_data = pika_id_table_lookup (f->id_table, ret_id);
int ret_id2 = pika_id_table_insert_with_id (f->id_table, id, data2);
gpointer ret_data2 = pika_id_table_lookup (f->id_table, ret_id2);
g_assert (id == ret_id);
g_assert (ret_id2 == -1);
g_assert (ret_data == data1);
g_assert (ret_data2 == NULL);
}
/**
* pika_test_id_table_replace:
*
* Test that it is possible to replace data with a given ID with
* different data.
**/
static void
pika_test_id_table_replace (PikaTestFixture *f,
gconstpointer data)
{
int ret_id = pika_id_table_insert (f->id_table, data1);
gpointer ret_data;
pika_id_table_replace (f->id_table, ret_id, data2);
ret_data = pika_id_table_lookup (f->id_table, ret_id);
g_assert (ret_data == data2);
}
/**
* pika_test_id_table_replace_as_insert:
*
* Test that replace works like insert when there is no data to
* replace.
**/
static void
pika_test_id_table_replace_as_insert (PikaTestFixture *f,
gconstpointer data)
{
const int id = 10;
gpointer ret_data;
pika_id_table_replace (f->id_table, id, data1);
ret_data = pika_id_table_lookup (f->id_table, id);
g_assert (ret_data == data1);
}
/**
* pika_test_id_table_remove:
*
* Test that it is possible to remove data identified by the ID:
**/
static void
pika_test_id_table_remove (PikaTestFixture *f,
gconstpointer data)
{
gint ret_id = pika_id_table_insert (f->id_table, data1);
void *ret_data = pika_id_table_lookup (f->id_table, ret_id);
gboolean remove_successful = pika_id_table_remove (f->id_table, ret_id);
void *ret_data2 = pika_id_table_lookup (f->id_table, ret_id);
g_assert (remove_successful);
g_assert (ret_data == data1);
g_assert (ret_data2 == NULL);
}
/**
* pika_test_id_table_remove_non_existing:
*
* Tests that things work properly when trying to remove data with an
* ID that doesn't exist.
**/
static void
pika_test_id_table_remove_non_existing (PikaTestFixture *f,
gconstpointer data)
{
const int id = 10;
gboolean remove_successful = pika_id_table_remove (f->id_table, id);
void *ret_data = pika_id_table_lookup (f->id_table, id);
g_assert (! remove_successful);
g_assert (ret_data == NULL);
}
int main(int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
ADD_TEST (insert_and_lookup);
ADD_TEST (insert_twice);
ADD_TEST (insert_with_id);
ADD_TEST (insert_with_id_existing);
ADD_TEST (replace);
ADD_TEST (replace_as_insert);
ADD_TEST (remove);
ADD_TEST (remove_non_existing);
return g_test_run ();
}

View File

@ -0,0 +1,391 @@
/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* Copyright (C) 2009 Martin Nordholts <martinn@src.gnome.org>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <gegl.h>
#include <glib/gstdio.h>
#include <gtk/gtk.h>
#include "libpikabase/pikabase.h"
#include "libpikamath/pikamath.h"
#include "libpikawidgets/pikawidgets.h"
#include "dialogs/dialogs-types.h"
#include "core/pika.h"
#include "core/pikachannel.h"
#include "core/pikacontext.h"
#include "core/pikaimage.h"
#include "core/pikalayer.h"
#include "core/pikatoolinfo.h"
#include "core/pikatooloptions.h"
#include "plug-in/pikapluginmanager-file.h"
#include "file/file-open.h"
#include "file/file-save.h"
#include "widgets/pikadialogfactory.h"
#include "widgets/pikadock.h"
#include "widgets/pikadockable.h"
#include "widgets/pikadockbook.h"
#include "widgets/pikadocked.h"
#include "widgets/pikadockwindow.h"
#include "widgets/pikahelp-ids.h"
#include "widgets/pikasessioninfo.h"
#include "widgets/pikatoolbox.h"
#include "widgets/pikatooloptionseditor.h"
#include "widgets/pikauimanager.h"
#include "widgets/pikawidgets-utils.h"
#include "display/pikadisplay.h"
#include "display/pikadisplayshell.h"
#include "display/pikadisplayshell-scale.h"
#include "display/pikadisplayshell-transform.h"
#include "display/pikaimagewindow.h"
#include "pikacoreapp.h"
#include "pika-app-test-utils.h"
#include "tests.h"
#define ADD_TEST(function) \
g_test_add_data_func ("/pika-save-and-export/" #function, pika, function);
typedef gboolean (*PikaUiTestFunc) (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)
{
Pika *pika = PIKA (data);
PikaImage *image = pika_test_utils_create_image_from_dialog (pika);
g_assert (pika_image_get_file (image) == NULL);
g_assert (pika_image_get_imported_file (image) == NULL);
g_assert (pika_image_get_exported_file (image) == NULL);
}
/**
* opened_xcf_file_files:
* @data:
*
* Tests that PikaImage URIs are correct for an XCF file that has just
* been opened.
**/
static void
opened_xcf_file_files (gconstpointer data)
{
Pika *pika = PIKA (data);
PikaImage *image;
GFile *file;
gchar *filename;
PikaPDBStatusType status;
filename = g_build_filename (g_getenv ("PIKA_TESTING_ABS_TOP_SRCDIR"),
"app/tests/files/pika-2-6-file.xcf",
NULL);
file = g_file_new_for_path (filename);
g_free (filename);
image = file_open_image (pika,
pika_get_user_context (pika),
NULL /*progress*/,
file,
FALSE /*as_new*/,
NULL /*file_proc*/,
PIKA_RUN_NONINTERACTIVE,
&status,
NULL /*mime_type*/,
NULL /*error*/);
g_assert (g_file_equal (pika_image_get_file (image), file));
g_assert (pika_image_get_imported_file (image) == NULL);
g_assert (pika_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)
{
Pika *pika = PIKA (data);
PikaImage *image;
GFile *file;
gchar *filename;
PikaPDBStatusType status;
filename = g_build_filename (g_getenv ("PIKA_TESTING_ABS_TOP_SRCDIR"),
"desktop/64x64/pika.png",
NULL);
g_assert (g_file_test (filename, G_FILE_TEST_EXISTS));
file = g_file_new_for_path (filename);
g_free (filename);
image = file_open_image (pika,
pika_get_user_context (pika),
NULL /*progress*/,
file,
FALSE /*as_new*/,
NULL /*file_proc*/,
PIKA_RUN_NONINTERACTIVE,
&status,
NULL /*mime_type*/,
NULL /*error*/);
g_assert (pika_image_get_file (image) == NULL);
g_assert (g_file_equal (pika_image_get_imported_file (image), file));
g_assert (pika_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)
{
Pika *pika = PIKA (data);
PikaImage *image;
GFile *import_file;
gchar *import_filename;
GFile *save_file;
gchar *save_filename;
PikaPDBStatusType status;
PikaPlugInProcedure *proc;
import_filename = g_build_filename (g_getenv ("PIKA_TESTING_ABS_TOP_SRCDIR"),
"desktop/64x64/pika.png",
NULL);
import_file = g_file_new_for_path (import_filename);
g_free (import_filename);
save_filename = g_build_filename (g_get_tmp_dir (), "pika-test.xcf", NULL);
save_file = g_file_new_for_path (save_filename);
g_free (save_filename);
/* Import */
image = file_open_image (pika,
pika_get_user_context (pika),
NULL /*progress*/,
import_file,
FALSE /*as_new*/,
NULL /*file_proc*/,
PIKA_RUN_NONINTERACTIVE,
&status,
NULL /*mime_type*/,
NULL /*error*/);
g_object_unref (import_file);
/* Save */
proc = pika_plug_in_manager_file_procedure_find (image->pika->plug_in_manager,
PIKA_FILE_PROCEDURE_GROUP_SAVE,
save_file,
NULL /*error*/);
file_save (pika,
image,
NULL /*progress*/,
save_file,
proc,
PIKA_RUN_NONINTERACTIVE,
TRUE /*change_saved_state*/,
FALSE /*export_backward*/,
FALSE /*export_forward*/,
NULL /*error*/);
/* Assert */
g_assert (g_file_equal (pika_image_get_file (image), save_file));
g_assert (pika_image_get_imported_file (image) == NULL);
g_assert (pika_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;
PikaPlugInProcedure *proc;
Pika *pika = PIKA (data);
PikaImage *image = pika_test_utils_create_image_from_dialog (pika);
save_filename = g_build_filename (g_get_tmp_dir (), "pika-test.png", NULL);
save_file = g_file_new_for_path (save_filename);
g_free (save_filename);
proc = pika_plug_in_manager_file_procedure_find (image->pika->plug_in_manager,
PIKA_FILE_PROCEDURE_GROUP_EXPORT,
save_file,
NULL /*error*/);
file_save (pika,
image,
NULL /*progress*/,
save_file,
proc,
PIKA_RUN_NONINTERACTIVE,
FALSE /*change_saved_state*/,
FALSE /*export_backward*/,
TRUE /*export_forward*/,
NULL /*error*/);
g_assert (pika_image_get_file (image) == NULL);
g_assert (pika_image_get_imported_file (image) == NULL);
g_assert (g_file_equal (pika_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)
{
Pika *pika = PIKA (data);
PikaImage *image;
GFile *file;
gchar *filename;
GFile *save_file;
gchar *save_filename;
PikaPlugInProcedure *proc;
PikaPDBStatusType status;
filename = g_build_filename (g_getenv ("PIKA_TESTING_ABS_TOP_SRCDIR"),
"desktop/64x64/pika.png",
NULL);
file = g_file_new_for_path (filename);
g_free (filename);
image = file_open_image (pika,
pika_get_user_context (pika),
NULL /*progress*/,
file,
FALSE /*as_new*/,
NULL /*file_proc*/,
PIKA_RUN_NONINTERACTIVE,
&status,
NULL /*mime_type*/,
NULL /*error*/);
g_assert (pika_image_get_file (image) == NULL);
g_assert (g_file_equal (pika_image_get_imported_file (image), file));
g_assert (pika_image_get_exported_file (image) == NULL);
g_object_unref (file);
save_filename = g_build_filename (g_get_tmp_dir (), "pika-test.png", NULL);
save_file = g_file_new_for_path (save_filename);
g_free (save_filename);
proc = pika_plug_in_manager_file_procedure_find (image->pika->plug_in_manager,
PIKA_FILE_PROCEDURE_GROUP_EXPORT,
save_file,
NULL /*error*/);
file_save (pika,
image,
NULL /*progress*/,
save_file,
proc,
PIKA_RUN_NONINTERACTIVE,
FALSE /*change_saved_state*/,
FALSE /*export_backward*/,
TRUE /*export_forward*/,
NULL /*error*/);
g_assert (pika_image_get_file (image) == NULL);
g_assert (pika_image_get_imported_file (image) == NULL);
g_assert (g_file_equal (pika_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)
{
Pika *pika = NULL;
gint result = -1;
pika_test_bail_if_no_display ();
gtk_test_init (&argc, &argv, NULL);
pika_test_utils_setup_menus_path ();
/* Start up PIKA */
pika = pika_init_for_gui_testing (TRUE /*show_gui*/);
pika_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 (pika->app, 0, NULL);
result = pika_core_app_get_exit_status (PIKA_CORE_APP (pika->app));
g_application_quit (G_APPLICATION (pika->app));
g_clear_object (&pika->app);
return result;
}

View File

@ -0,0 +1,75 @@
/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* Copyright (C) 2011 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 <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#include "dialogs/dialogs-types.h"
#include "tests.h"
#include "pika-test-session-utils.h"
#include "pika-app-test-utils.h"
#define ADD_TEST(function) \
g_test_add_func ("/pika-session-2-8-compatibility-multi-window/" #function, \
function);
#define SKIP_TEST(function) \
g_test_add_func ("/pika-session-2-8-compatibility-multi-window/subprocess/" #function, \
function);
/**
* Tests that a single-window sessionrc in PIKA 2.8 format is loaded
* and written (thus also interpreted) like we expect.
**/
static void
read_and_write_session_files (void)
{
pika_test_session_load_and_write_session_files ("sessionrc-2-8-multi-window",
"dockrc-2-8",
"sessionrc-expected-multi-window",
"dockrc-expected",
FALSE /*single_window_mode*/);
}
int main(int argc, char **argv)
{
pika_test_bail_if_no_display ();
gtk_test_init (&argc, &argv, NULL);
#ifdef HAVE_XVFB_RUN
ADD_TEST (read_and_write_session_files);
#else
SKIP_TEST (read_and_write_session_files);
#endif
/* Don't bother freeing stuff, the process is short-lived */
#ifdef HAVE_XVFB_RUN
return g_test_run ();
#else
return PIKA_EXIT_TEST_SKIPPED;
#endif
}

View File

@ -0,0 +1,74 @@
/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* Copyright (C) 2011 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 <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#include "dialogs/dialogs-types.h"
#include "tests.h"
#include "pika-test-session-utils.h"
#include "pika-app-test-utils.h"
#define ADD_TEST(function) \
g_test_add_func ("/pika-session-2-8-compatibility-single-window/" #function, \
function);
#define SKIP_TEST(function) \
g_test_add_func ("/pika-session-2-8-compatibility-single-window/subprocess/" #function, \
function);
/**
* Tests that a multi-window sessionrc in PIKA 2.8 format is loaded
* and written (thus also interpreted) like we expect.
**/
static void
read_and_write_session_files (void)
{
pika_test_session_load_and_write_session_files ("sessionrc-2-8-single-window",
"dockrc-2-8",
"sessionrc-expected-single-window",
"dockrc-expected",
TRUE /*single_window_mode*/);
}
int main(int argc, char **argv)
{
pika_test_bail_if_no_display ();
gtk_test_init (&argc, &argv, NULL);
#ifdef HAVE_XVFB_RUN
ADD_TEST (read_and_write_session_files);
#else
SKIP_TEST (read_and_write_session_files);
#endif
/* Don't bother freeing stuff, the process is short-lived */
#ifdef HAVE_XVFB_RUN
return g_test_run ();
#else
return PIKA_EXIT_TEST_SKIPPED;
#endif
}

View File

@ -0,0 +1,159 @@
/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* test-single-window-mode.c
* Copyright (C) 2011 Martin Nordholts <martinn@src.gnome.org>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include <gegl.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "libpikabase/pikabase.h"
#include "libpikamath/pikamath.h"
#include "libpikawidgets/pikawidgets.h"
#include "dialogs/dialogs-types.h"
#include "display/pikadisplay.h"
#include "display/pikadisplayshell.h"
#include "display/pikadisplayshell-scale.h"
#include "display/pikadisplayshell-transform.h"
#include "display/pikaimagewindow.h"
#include "widgets/pikadialogfactory.h"
#include "widgets/pikadock.h"
#include "widgets/pikadockable.h"
#include "widgets/pikadockbook.h"
#include "widgets/pikadockcontainer.h"
#include "widgets/pikadocked.h"
#include "widgets/pikadockwindow.h"
#include "widgets/pikahelp-ids.h"
#include "widgets/pikasessioninfo.h"
#include "widgets/pikatoolbox.h"
#include "widgets/pikatooloptionseditor.h"
#include "widgets/pikauimanager.h"
#include "widgets/pikawidgets-utils.h"
#include "core/pika.h"
#include "core/pikachannel.h"
#include "core/pikacontext.h"
#include "core/pikaimage.h"
#include "core/pikalayer.h"
#include "core/pikatoolinfo.h"
#include "core/pikatooloptions.h"
#include "pikacoreapp.h"
#include "pika-app-test-utils.h"
#include "tests.h"
#define ADD_TEST(function) \
g_test_add_data_func ("/pika-single-window-mode/" #function, pika, function);
/* Put this in the code below when you want the test to pause so you
* can do measurements of widgets on the screen for example
*/
#define PIKA_PAUSE (g_usleep (20 * 1000 * 1000))
/**
* new_dockable_not_in_new_window:
* @data:
*
* Test that in single-window mode, new dockables are not put in new
* windows (they should end up in the single image window).
**/
static void
new_dockable_not_in_new_window (gconstpointer data)
{
Pika *pika = PIKA (data);
PikaDialogFactory *factory = pika_dialog_factory_get_singleton ();
gint dialogs_before = 0;
gint toplevels_before = 0;
gint dialogs_after = 0;
gint toplevels_after = 0;
GList *dialogs;
GList *iter;
pika_test_run_mainloop_until_idle ();
/* Count dialogs before we create the dockable */
dialogs = pika_dialog_factory_get_open_dialogs (factory);
dialogs_before = g_list_length (dialogs);
for (iter = dialogs; iter; iter = g_list_next (iter))
{
if (gtk_widget_is_toplevel (iter->data))
toplevels_before++;
}
/* Create a dockable */
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
"dialogs",
"dialogs-undo-history");
pika_test_run_mainloop_until_idle ();
/* Count dialogs after we created the dockable */
dialogs = pika_dialog_factory_get_open_dialogs (factory);
dialogs_after = g_list_length (dialogs);
for (iter = dialogs; iter; iter = g_list_next (iter))
{
if (gtk_widget_is_toplevel (iter->data))
toplevels_after++;
}
/* We got one more session managed dialog ... */
g_assert_cmpint (dialogs_before + 1, ==, dialogs_after);
/* ... but no new toplevels */
g_assert_cmpint (toplevels_before, ==, toplevels_after);
}
int main(int argc, char **argv)
{
Pika *pika = NULL;
gint result = -1;
pika_test_bail_if_no_display ();
gtk_test_init (&argc, &argv, NULL);
pika_test_utils_setup_menus_path ();
/* Launch PIKA in single-window mode */
g_setenv ("PIKA_TESTING_SESSIONRC_NAME", "sessionrc-2-8-single-window", TRUE /*overwrite*/);
pika = pika_init_for_gui_testing (TRUE /*show_gui*/);
pika_test_run_mainloop_until_idle ();
ADD_TEST (new_dockable_not_in_new_window);
/* Run the tests and return status */
g_application_run (pika->app, 0, NULL);
result = pika_core_app_get_exit_status (PIKA_CORE_APP (pika->app));
/* Exit properly so we don't break script-fu plug-in wire */
g_application_quit (G_APPLICATION (pika->app));
g_clear_object (&pika->app);
return result;
}

498
app/tests/test-tools.c Normal file
View File

@ -0,0 +1,498 @@
/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* Copyright (C) 2009 Martin Nordholts <martinn@src.gnome.org>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include <gegl.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "libpikabase/pikabase.h"
#include "libpikamath/pikamath.h"
#include "libpikawidgets/pikawidgets.h"
#include "tools/tools-types.h"
#include "tools/pikarectangleoptions.h"
#include "tools/tool_manager.h"
#include "display/pikadisplay.h"
#include "display/pikadisplayshell.h"
#include "display/pikadisplayshell-callbacks.h"
#include "display/pikadisplayshell-scale.h"
#include "display/pikadisplayshell-tool-events.h"
#include "display/pikadisplayshell-transform.h"
#include "display/pikaimagewindow.h"
#include "widgets/pikadialogfactory.h"
#include "widgets/pikadock.h"
#include "widgets/pikadockable.h"
#include "widgets/pikadockbook.h"
#include "widgets/pikadocked.h"
#include "widgets/pikadockwindow.h"
#include "widgets/pikahelp-ids.h"
#include "widgets/pikasessioninfo.h"
#include "widgets/pikatoolbox.h"
#include "widgets/pikatooloptionseditor.h"
#include "widgets/pikauimanager.h"
#include "widgets/pikawidgets-utils.h"
#include "core/pika.h"
#include "core/pikachannel.h"
#include "core/pikacontext.h"
#include "core/pikaimage.h"
#include "core/pikalayer.h"
#include "core/pikatoolinfo.h"
#include "core/pikatooloptions.h"
#include "pikacoreapp.h"
#include "pika-app-test-utils.h"
#include "tests.h"
#define PIKA_TEST_IMAGE_WIDTH 150
#define PIKA_TEST_IMAGE_HEIGHT 267
/* Put this in the code below when you want the test to pause so you
* can do measurements of widgets on the screen for example
*/
#define PIKA_PAUSE (g_usleep (2 * 1000 * 1000))
#define ADD_TEST(function) \
g_test_add ("/pika-tools/" #function, \
PikaTestFixture, \
pika, \
pika_tools_setup_image, \
function, \
pika_tools_teardown_image);
typedef struct
{
int avoid_sizeof_zero;
} PikaTestFixture;
static void pika_tools_setup_image (PikaTestFixture *fixture,
gconstpointer data);
static void pika_tools_teardown_image (PikaTestFixture *fixture,
gconstpointer data);
static void pika_tools_synthesize_image_click_drag_release (PikaDisplayShell *shell,
gdouble start_image_x,
gdouble start_image_y,
gdouble end_image_x,
gdouble end_image_y,
gint button,
GdkModifierType modifiers);
static PikaDisplay * pika_test_get_only_display (Pika *pika);
static PikaImage * pika_test_get_only_image (Pika *pika);
static PikaDisplayShell * pika_test_get_only_display_shell (Pika *pika);
static void
pika_tools_setup_image (PikaTestFixture *fixture,
gconstpointer data)
{
Pika *pika = PIKA (data);
pika_test_utils_create_image (pika,
PIKA_TEST_IMAGE_WIDTH,
PIKA_TEST_IMAGE_HEIGHT);
pika_test_run_mainloop_until_idle ();
}
static void
pika_tools_teardown_image (PikaTestFixture *fixture,
gconstpointer data)
{
Pika *pika = PIKA (data);
g_object_unref (pika_test_get_only_image (pika));
pika_display_close (pika_test_get_only_display (pika));
pika_test_run_mainloop_until_idle ();
}
/**
* pika_tools_set_tool:
* @pika:
* @tool_id:
* @display:
*
* Makes sure the given tool is the active tool and that the passed
* display is the focused tool display.
**/
static void
pika_tools_set_tool (Pika *pika,
const gchar *tool_id,
PikaDisplay *display)
{
/* Activate tool and setup active display for the new tool */
pika_context_set_tool (pika_get_user_context (pika),
pika_get_tool_info (pika, tool_id));
tool_manager_focus_display_active (pika, display);
}
/**
* pika_test_get_only_display:
* @pika:
*
* Asserts that there only is one image and display and then
* returns the display.
*
* Returns: The #PikaDisplay.
**/
static PikaDisplay *
pika_test_get_only_display (Pika *pika)
{
g_assert (g_list_length (pika_get_image_iter (pika)) == 1);
g_assert (g_list_length (pika_get_display_iter (pika)) == 1);
return PIKA_DISPLAY (pika_get_display_iter (pika)->data);
}
/**
* pika_test_get_only_display_shell:
* @pika:
*
* Asserts that there only is one image and display shell and then
* returns the display shell.
*
* Returns: The #PikaDisplayShell.
**/
static PikaDisplayShell *
pika_test_get_only_display_shell (Pika *pika)
{
return pika_display_get_shell (pika_test_get_only_display (pika));
}
/**
* pika_test_get_only_image:
* @pika:
*
* Asserts that there is only one image and returns that.
*
* Returns: The #PikaImage.
**/
static PikaImage *
pika_test_get_only_image (Pika *pika)
{
g_assert (g_list_length (pika_get_image_iter (pika)) == 1);
g_assert (g_list_length (pika_get_display_iter (pika)) == 1);
return PIKA_IMAGE (pika_get_image_iter (pika)->data);
}
static void
pika_test_synthesize_tool_button_event (PikaDisplayShell *shell,
gint x,
gint y,
gint button,
gint modifiers,
GdkEventType button_event_type)
{
GdkEvent *event = gdk_event_new (button_event_type);
GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (shell->canvas));
GdkDisplay *display = gdk_window_get_display (window);
GdkSeat *seat = gdk_display_get_default_seat (display);
g_assert (button_event_type == GDK_BUTTON_PRESS ||
button_event_type == GDK_BUTTON_RELEASE);
gdk_event_set_device (event, gdk_seat_get_pointer (seat));
event->button.window = g_object_ref (window);
event->button.send_event = TRUE;
event->button.time = gtk_get_current_event_time ();
event->button.x = x;
event->button.y = y;
event->button.axes = NULL;
event->button.state = 0;
event->button.button = button;
event->button.x_root = -1;
event->button.y_root = -1;
pika_display_shell_canvas_tool_events (shell->canvas,
event,
shell);
gdk_event_free (event);
}
static void
pika_test_synthesize_tool_motion_event (PikaDisplayShell *shell,
gint x,
gint y,
gint modifiers)
{
GdkEvent *event = gdk_event_new (GDK_MOTION_NOTIFY);
GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (shell->canvas));
GdkDisplay *display = gdk_window_get_display (window);
GdkSeat *seat = gdk_display_get_default_seat (display);
gdk_event_set_device (event, gdk_seat_get_pointer (seat));
event->motion.window = g_object_ref (window);
event->motion.send_event = TRUE;
event->motion.time = gtk_get_current_event_time ();
event->motion.x = x;
event->motion.y = y;
event->motion.axes = NULL;
event->motion.state = GDK_BUTTON1_MASK | modifiers;
event->motion.is_hint = FALSE;
event->motion.x_root = -1;
event->motion.y_root = -1;
pika_display_shell_canvas_tool_events (shell->canvas,
event,
shell);
gdk_event_free (event);
}
static void
pika_test_synthesize_tool_crossing_event (PikaDisplayShell *shell,
gint x,
gint y,
gint modifiers,
GdkEventType crossing_event_type)
{
GdkEvent *event = gdk_event_new (crossing_event_type);
GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (shell->canvas));
GdkDisplay *display = gdk_window_get_display (window);
GdkSeat *seat = gdk_display_get_default_seat (display);
g_assert (crossing_event_type == GDK_ENTER_NOTIFY ||
crossing_event_type == GDK_LEAVE_NOTIFY);
gdk_event_set_device (event, gdk_seat_get_pointer (seat));
event->crossing.window = g_object_ref (window);
event->crossing.send_event = TRUE;
event->crossing.subwindow = NULL;
event->crossing.time = gtk_get_current_event_time ();
event->crossing.x = x;
event->crossing.y = y;
event->crossing.x_root = -1;
event->crossing.y_root = -1;
event->crossing.mode = GDK_CROSSING_NORMAL;
event->crossing.detail = GDK_NOTIFY_UNKNOWN;
event->crossing.focus = TRUE;
event->crossing.state = modifiers;
pika_display_shell_canvas_tool_events (shell->canvas,
event,
shell);
gdk_event_free (event);
}
static void
pika_tools_synthesize_image_click_drag_release (PikaDisplayShell *shell,
gdouble start_image_x,
gdouble start_image_y,
gdouble end_image_x,
gdouble end_image_y,
gint button /*1..3*/,
GdkModifierType modifiers)
{
gdouble start_canvas_x = -1.0;
gdouble start_canvas_y = -1.0;
gdouble middle_canvas_x = -1.0;
gdouble middle_canvas_y = -1.0;
gdouble end_canvas_x = -1.0;
gdouble end_canvas_y = -1.0;
/* Transform coordinates */
pika_display_shell_transform_xy_f (shell,
start_image_x,
start_image_y,
&start_canvas_x,
&start_canvas_y);
pika_display_shell_transform_xy_f (shell,
end_image_x,
end_image_y,
&end_canvas_x,
&end_canvas_y);
middle_canvas_x = (start_canvas_x + end_canvas_x) / 2;
middle_canvas_y = (start_canvas_y + end_canvas_y) / 2;
/* Enter notify */
pika_test_synthesize_tool_crossing_event (shell,
(int)start_canvas_x,
(int)start_canvas_y,
modifiers,
GDK_ENTER_NOTIFY);
/* Button press */
pika_test_synthesize_tool_button_event (shell,
(int)start_canvas_x,
(int)start_canvas_y,
button,
modifiers,
GDK_BUTTON_PRESS);
/* Move events */
pika_test_synthesize_tool_motion_event (shell,
(int)start_canvas_x,
(int)start_canvas_y,
modifiers);
pika_test_synthesize_tool_motion_event (shell,
(int)middle_canvas_x,
(int)middle_canvas_y,
modifiers);
pika_test_synthesize_tool_motion_event (shell,
(int)end_canvas_x,
(int)end_canvas_y,
modifiers);
/* Button release */
pika_test_synthesize_tool_button_event (shell,
(int)end_canvas_x,
(int)end_canvas_y,
button,
modifiers,
GDK_BUTTON_RELEASE);
/* Leave notify */
pika_test_synthesize_tool_crossing_event (shell,
(int)start_canvas_x,
(int)start_canvas_y,
modifiers,
GDK_LEAVE_NOTIFY);
/* Process them */
pika_test_run_mainloop_until_idle ();
}
/**
* crop_tool_can_crop:
* @fixture:
* @data:
*
* Make sure it's possible to crop at all. Regression test for
* "Bug 315255 - SIGSEGV, while doing a crop".
**/
static void
crop_tool_can_crop (PikaTestFixture *fixture,
gconstpointer data)
{
Pika *pika = PIKA (data);
PikaImage *image = pika_test_get_only_image (pika);
PikaDisplayShell *shell = pika_test_get_only_display_shell (pika);
gint cropped_x = 10;
gint cropped_y = 10;
gint cropped_w = 20;
gint cropped_h = 30;
/* Fit display and pause and let it stabalize (two idlings seems to
* always be enough)
*/
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
"view",
"view-shrink-wrap");
pika_test_run_mainloop_until_idle ();
pika_test_run_mainloop_until_idle ();
/* Activate crop tool */
pika_tools_set_tool (pika, "pika-crop-tool", shell->display);
/* Do the crop rect */
pika_tools_synthesize_image_click_drag_release (shell,
cropped_x,
cropped_y,
cropped_x + cropped_w,
cropped_y + cropped_h,
1 /*button*/,
0 /*modifiers*/);
/* Crop */
pika_test_utils_synthesize_key_event (GTK_WIDGET (shell), GDK_KEY_Return);
pika_test_run_mainloop_until_idle ();
/* Make sure the new image has the expected size */
g_assert_cmpint (cropped_w, ==, pika_image_get_width (image));
g_assert_cmpint (cropped_h, ==, pika_image_get_height (image));
}
/**
* crop_tool_can_crop:
* @fixture:
* @data:
*
* Make sure it's possible to change width of crop rect in tool
* options without there being a pending rectangle. Regression test
* for "Bug 322396 - Crop dimension entering causes crash".
**/
static void
crop_set_width_without_pending_rect (PikaTestFixture *fixture,
gconstpointer data)
{
Pika *pika = PIKA (data);
PikaDisplay *display = pika_test_get_only_display (pika);
PikaToolInfo *tool_info;
PikaRectangleOptions *rectangle_options;
GtkWidget *size_entry;
/* Activate crop tool */
pika_tools_set_tool (pika, "pika-crop-tool", display);
/* Get tool options */
tool_info = pika_get_tool_info (pika, "pika-crop-tool");
rectangle_options = PIKA_RECTANGLE_OPTIONS (tool_info->tool_options);
/* Find 'Width' or 'Height' GtkTextEntry in tool options */
size_entry = pika_rectangle_options_get_size_entry (rectangle_options);
/* Set arbitrary non-0 value */
pika_size_entry_set_value (PIKA_SIZE_ENTRY (size_entry),
0 /*field*/,
42.0 /*lower*/);
/* If we don't crash, everything s fine */
}
int main(int argc, char **argv)
{
Pika *pika = NULL;
gint result = -1;
pika_test_bail_if_no_display ();
gtk_test_init (&argc, &argv, NULL);
pika_test_utils_setup_menus_path ();
/* Start up PIKA */
pika = pika_init_for_gui_testing (TRUE /*show_gui*/);
pika_test_run_mainloop_until_idle ();
/* Add tests */
ADD_TEST (crop_tool_can_crop);
ADD_TEST (crop_set_width_without_pending_rect);
/* Run the tests and return status */
g_application_run (pika->app, 0, NULL);
result = pika_core_app_get_exit_status (PIKA_CORE_APP (pika->app));
g_application_quit (G_APPLICATION (pika->app));
g_clear_object (&pika->app);
return result;
}

908
app/tests/test-ui.c Normal file
View File

@ -0,0 +1,908 @@
/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* Copyright (C) 2009 Martin Nordholts <martinn@src.gnome.org>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include <gegl.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "libpikabase/pikabase.h"
#include "libpikamath/pikamath.h"
#include "libpikawidgets/pikawidgets.h"
#include "dialogs/dialogs-types.h"
#include "display/pikadisplay.h"
#include "display/pikadisplayshell.h"
#include "display/pikadisplayshell-scale.h"
#include "display/pikadisplayshell-transform.h"
#include "display/pikaimagewindow.h"
#include "menus/menus.h"
#include "widgets/pikadialogfactory.h"
#include "widgets/pikadock.h"
#include "widgets/pikadockable.h"
#include "widgets/pikadockbook.h"
#include "widgets/pikadockcontainer.h"
#include "widgets/pikadocked.h"
#include "widgets/pikadockwindow.h"
#include "widgets/pikahelp-ids.h"
#include "widgets/pikasessioninfo.h"
#include "widgets/pikasessioninfo-aux.h"
#include "widgets/pikasessionmanaged.h"
#include "widgets/pikatoolbox.h"
#include "widgets/pikatooloptionseditor.h"
#include "widgets/pikauimanager.h"
#include "widgets/pikawidgets-utils.h"
#include "core/pika.h"
#include "core/pikachannel.h"
#include "core/pikacontext.h"
#include "core/pikaimage.h"
#include "core/pikalayer.h"
#include "core/pikalayer-new.h"
#include "core/pikatoolinfo.h"
#include "core/pikatooloptions.h"
#include "pikacoreapp.h"
#include "pika-app-test-utils.h"
#include "tests.h"
#define PIKA_UI_WINDOW_POSITION_EPSILON 30
#define PIKA_UI_POSITION_EPSILON 1
#define PIKA_UI_ZOOM_EPSILON 0.01
#define ADD_TEST(function) \
g_test_add_data_func ("/pika-ui/" #function, pika, function);
/* Put this in the code below when you want the test to pause so you
* can do measurements of widgets on the screen for example
*/
#define PIKA_PAUSE (g_usleep (20 * 1000 * 1000))
typedef gboolean (*PikaUiTestFunc) (GObject *object);
static void pika_ui_synthesize_delete_event (GtkWidget *widget);
static gboolean pika_ui_synthesize_click (GtkWidget *widget,
gint x,
gint y,
gint button,
GdkModifierType modifiers);
static GtkWidget * pika_ui_find_window (PikaDialogFactory *dialog_factory,
PikaUiTestFunc predicate);
static gboolean pika_ui_not_toolbox_window (GObject *object);
static gboolean pika_ui_multicolumn_not_toolbox_window (GObject *object);
static gboolean pika_ui_is_pika_layer_list (GObject *object);
static int pika_ui_aux_data_eqiuvalent (gconstpointer _a,
gconstpointer _b);
static void pika_ui_switch_window_mode (Pika *pika);
/**
* tool_options_editor_updates:
* @data:
*
* Makes sure that the tool options editor is updated when the tool
* changes.
**/
static void
tool_options_editor_updates (gconstpointer data)
{
Pika *pika = PIKA (data);
PikaDisplay *display = PIKA_DISPLAY (pika_get_empty_display (pika));
PikaDisplayShell *shell = pika_display_get_shell (display);
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (shell));
PikaUIManager *ui_manager = menus_get_image_manager_singleton (pika);
GtkWidget *dockable = pika_dialog_factory_dialog_new (pika_dialog_factory_get_singleton (),
pika_widget_get_monitor (toplevel),
NULL /*ui_manager*/,
toplevel,
"pika-tool-options",
-1 /*view_size*/,
FALSE /*present*/);
PikaToolOptionsEditor *editor = PIKA_TOOL_OPTIONS_EDITOR (gtk_bin_get_child (GTK_BIN (dockable)));
/* First select the rect select tool */
pika_ui_manager_activate_action (ui_manager,
"tools",
"tools-rect-select");
g_assert_cmpstr (PIKA_HELP_TOOL_RECT_SELECT,
==,
pika_tool_options_editor_get_tool_options (editor)->
tool_info->help_id);
/* Change tool and make sure the change is taken into account by the
* tool options editor
*/
pika_ui_manager_activate_action (ui_manager,
"tools",
"tools-ellipse-select");
g_assert_cmpstr (PIKA_HELP_TOOL_ELLIPSE_SELECT,
==,
pika_tool_options_editor_get_tool_options (editor)->
tool_info->help_id);
}
static void
create_new_image_via_dialog (gconstpointer data)
{
Pika *pika = PIKA (data);
PikaImage *image;
PikaLayer *layer;
image = pika_test_utils_create_image_from_dialog (pika);
/* Add a layer to the image to make it more useful in later tests */
layer = pika_layer_new (image,
pika_image_get_width (image),
pika_image_get_height (image),
pika_image_get_layer_format (image, TRUE),
"Layer for testing",
PIKA_OPACITY_OPAQUE,
PIKA_LAYER_MODE_NORMAL);
pika_image_add_layer (image, layer,
PIKA_IMAGE_ACTIVE_PARENT, -1, TRUE);
pika_test_run_mainloop_until_idle ();
}
static void
keyboard_zoom_focus (gconstpointer data)
{
Pika *pika = PIKA (data);
PikaDisplay *display = PIKA_DISPLAY (pika_get_display_iter (pika)->data);
PikaDisplayShell *shell = pika_display_get_shell (display);
PikaImageWindow *window = pika_display_shell_get_window (shell);
gint image_x;
gint image_y;
gint shell_x_before_zoom;
gint shell_y_before_zoom;
gdouble factor_before_zoom;
gint shell_x_after_zoom;
gint shell_y_after_zoom;
gdouble factor_after_zoom;
/* We need to use a point that is within the visible (exposed) part
* of the canvas
*/
image_x = 400;
image_y = 50;
/* Setup zoom focus on the bottom right part of the image. We avoid
* 0,0 because that's essentially a particularly easy special case.
*/
pika_display_shell_transform_xy (shell,
image_x,
image_y,
&shell_x_before_zoom,
&shell_y_before_zoom);
pika_display_shell_push_zoom_focus_pointer_pos (shell,
shell_x_before_zoom,
shell_y_before_zoom);
factor_before_zoom = pika_zoom_model_get_factor (shell->zoom);
/* Do the zoom */
pika_test_utils_synthesize_key_event (GTK_WIDGET (window), GDK_KEY_plus);
pika_test_run_mainloop_until_idle ();
/* Make sure the zoom focus point remained fixed */
pika_display_shell_transform_xy (shell,
image_x,
image_y,
&shell_x_after_zoom,
&shell_y_after_zoom);
factor_after_zoom = pika_zoom_model_get_factor (shell->zoom);
/* First of all make sure a zoom happened at all. If this assert
* fails, it means that the zoom didn't happen. Possible causes:
*
* * gdk_test_simulate_key() failed to map 'GDK_KEY_plus' to the proper
* 'plus' X keysym, probably because it is mapped to a keycode
* with modifiers like 'shift'. Run "xmodmap -pk | grep plus" to
* find out. Make sure 'plus' is the first keysym for the given
* keycode. If not, use "xmodmap <keycode> = plus" to correct it.
*/
g_assert_cmpfloat (fabs (factor_before_zoom - factor_after_zoom),
>=,
PIKA_UI_ZOOM_EPSILON);
#ifdef __GNUC__
#warning disabled zoom test, it fails randomly, no clue how to fix it
#endif
#if 0
g_assert_cmpint (ABS (shell_x_after_zoom - shell_x_before_zoom),
<=,
PIKA_UI_POSITION_EPSILON);
g_assert_cmpint (ABS (shell_y_after_zoom - shell_y_before_zoom),
<=,
PIKA_UI_POSITION_EPSILON);
#endif
}
/**
* alt_click_is_layer_to_selection:
* @data:
*
* Makes sure that we can alt-click on a layer to do
* layer-to-selection. Also makes sure that the layer clicked on is
* not set as the active layer.
**/
static void
alt_click_is_layer_to_selection (gconstpointer data)
{
#if __GNUC__
#warning FIXME: please fix alt_click_is_layer_to_selection test
#endif
#if 0
Pika *pika = PIKA (data);
PikaImage *image = PIKA_IMAGE (pika_get_image_iter (pika)->data);
PikaChannel *selection = pika_image_get_mask (image);
GList *selected_layers;
GList *iter;
GtkWidget *dockable;
GtkWidget *gtk_tree_view;
gint assumed_layer_x;
gint assumed_empty_layer_y;
gint assumed_background_layer_y;
/* Hardcode assumptions of where the layers are in the
* GtkTreeView. Doesn't feel worth adding proper API for this. One
* can just use PIKA_PAUSE and re-measure new coordinates if we
* start to layout layers in the GtkTreeView differently
*/
assumed_layer_x = 96;
assumed_empty_layer_y = 16;
assumed_background_layer_y = 42;
/* Store the active layer, it shall not change during the execution
* of this test
*/
selected_layers = pika_image_get_selected_layers (image);
selected_layers = g_list_copy (selected_layers);
/* Find the layer tree view to click in. Note that there is a
* potential problem with gtk_test_find_widget and GtkNotebook: it
* will return e.g. a GtkTreeView from another page if that page is
* "on top" of the reference label.
*/
dockable = pika_ui_find_window (pika_dialog_factory_get_singleton (),
pika_ui_is_pika_layer_list);
gtk_tree_view = gtk_test_find_widget (dockable,
"Lock:",
GTK_TYPE_TREE_VIEW);
/* First make sure there is no selection */
g_assert (pika_channel_is_empty (selection));
/* Now simulate alt-click on the background layer */
g_assert (pika_ui_synthesize_click (gtk_tree_view,
assumed_layer_x,
assumed_background_layer_y,
1 /*button*/,
GDK_MOD1_MASK));
pika_test_run_mainloop_until_idle ();
/* Make sure we got a selection and that the active layer didn't
* change
*/
g_assert (! pika_channel_is_empty (selection));
g_assert (g_list_length (pika_image_get_selected_layers (image)) ==
g_list_length (selected_layers));
for (iter = selected_layers; iter; iter = iter->next)
g_assert (g_list_find (pika_image_get_selected_layers (image), iter->data));
/* Now simulate alt-click on the empty layer */
g_assert (pika_ui_synthesize_click (gtk_tree_view,
assumed_layer_x,
assumed_empty_layer_y,
1 /*button*/,
GDK_MOD1_MASK));
pika_test_run_mainloop_until_idle ();
/* Make sure that emptied the selection and that the active layer
* still didn't change
*/
g_assert (pika_channel_is_empty (selection));
g_assert (g_list_length (pika_image_get_selected_layers (image)) ==
g_list_length (selected_layers));
for (iter = selected_layers; iter; iter = iter->next)
g_assert (g_list_find (pika_image_get_selected_layers (image), iter->data));
g_list_free (selected_layers);
#endif
}
static void
restore_recently_closed_multi_column_dock (gconstpointer data)
{
Pika *pika = PIKA (data);
GtkWidget *dock_window = NULL;
gint n_session_infos_before_close = -1;
gint n_session_infos_after_close = -1;
gint n_session_infos_after_restore = -1;
GList *session_infos = NULL;
/* Find a non-toolbox dock window */
dock_window = pika_ui_find_window (pika_dialog_factory_get_singleton (),
pika_ui_multicolumn_not_toolbox_window);
g_assert (dock_window != NULL);
/* Count number of docks */
session_infos = pika_dialog_factory_get_session_infos (pika_dialog_factory_get_singleton ());
n_session_infos_before_close = g_list_length (session_infos);
/* Close one of the dock windows */
pika_ui_synthesize_delete_event (GTK_WIDGET (dock_window));
pika_test_run_mainloop_until_idle ();
/* Make sure the number of session infos went down */
session_infos = pika_dialog_factory_get_session_infos (pika_dialog_factory_get_singleton ());
n_session_infos_after_close = g_list_length (session_infos);
g_assert_cmpint (n_session_infos_before_close,
>,
n_session_infos_after_close);
/* Restore the (only available) closed dock and make sure the session
* infos in the global dock factory are increased again
*/
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
"windows",
/* FIXME: This is severely hardcoded */
"windows-recent-0003");
pika_test_run_mainloop_until_idle ();
session_infos = pika_dialog_factory_get_session_infos (pika_dialog_factory_get_singleton ());
n_session_infos_after_restore = g_list_length (session_infos);
g_assert_cmpint (n_session_infos_after_close,
<,
n_session_infos_after_restore);
}
/**
* tab_toggle_dont_change_dock_window_position:
* @data:
*
* Makes sure that when dock windows are hidden with Tab and shown
* again, their positions and sizes are not changed. We don't really
* use Tab though, we only simulate its effect.
**/
static void
tab_toggle_dont_change_dock_window_position (gconstpointer data)
{
Pika *pika = PIKA (data);
GtkWidget *dock_window = NULL;
gint x_before_hide = -1;
gint y_before_hide = -1;
gint w_before_hide = -1;
gint h_before_hide = -1;
gint x_after_show = -1;
gint y_after_show = -1;
gint w_after_show = -1;
gint h_after_show = -1;
/* Find a non-toolbox dock window */
dock_window = pika_ui_find_window (pika_dialog_factory_get_singleton (),
pika_ui_not_toolbox_window);
g_assert (dock_window != NULL);
g_assert (gtk_widget_get_visible (dock_window));
/* Get the position and size */
pika_test_run_mainloop_until_idle ();
gtk_window_get_position (GTK_WINDOW (dock_window),
&x_before_hide,
&y_before_hide);
gtk_window_get_size (GTK_WINDOW (dock_window),
&w_before_hide,
&h_before_hide);
/* Hide all dock windows */
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
"windows",
"windows-hide-docks");
pika_test_run_mainloop_until_idle ();
g_assert (! gtk_widget_get_visible (dock_window));
/* Show them again */
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
"windows",
"windows-hide-docks");
pika_test_run_mainloop_until_idle ();
g_assert (gtk_widget_get_visible (dock_window));
/* Get the position and size again and make sure it's the same as
* before
*/
gtk_window_get_position (GTK_WINDOW (dock_window),
&x_after_show,
&y_after_show);
gtk_window_get_size (GTK_WINDOW (dock_window),
&w_after_show,
&h_after_show);
g_assert_cmpint ((int)abs (x_before_hide - x_after_show), <=, PIKA_UI_WINDOW_POSITION_EPSILON);
g_assert_cmpint ((int)abs (y_before_hide - y_after_show), <=, PIKA_UI_WINDOW_POSITION_EPSILON);
g_assert_cmpint ((int)abs (w_before_hide - w_after_show), <=, PIKA_UI_WINDOW_POSITION_EPSILON);
g_assert_cmpint ((int)abs (h_before_hide - h_after_show), <=, PIKA_UI_WINDOW_POSITION_EPSILON);
}
static void
switch_to_single_window_mode (gconstpointer data)
{
Pika *pika = PIKA (data);
/* Switch to single-window mode. We consider this test as passed if
* we don't get any GLib warnings/errors
*/
pika_ui_switch_window_mode (pika);
}
static void
pika_ui_toggle_docks_in_single_window_mode (Pika *pika)
{
PikaDisplay *display = PIKA_DISPLAY (pika_get_display_iter (pika)->data);
PikaDisplayShell *shell = pika_display_get_shell (display);
GtkWidget *toplevel = GTK_WIDGET (pika_display_shell_get_window (shell));
gint x_temp = -1;
gint y_temp = -1;
gint x_before_hide = -1;
gint y_before_hide = -1;
gint x_after_hide = -1;
gint y_after_hide = -1;
g_assert (shell);
g_assert (toplevel);
/* Get toplevel coordinate of image origin */
pika_test_run_mainloop_until_idle ();
pika_display_shell_transform_xy (shell,
0.0, 0.0,
&x_temp, &y_temp);
gtk_widget_translate_coordinates (GTK_WIDGET (shell),
toplevel,
x_temp, y_temp,
&x_before_hide, &y_before_hide);
/* Hide all dock windows */
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
"windows",
"windows-hide-docks");
pika_test_run_mainloop_until_idle ();
/* Get toplevel coordinate of image origin */
pika_test_run_mainloop_until_idle ();
pika_display_shell_transform_xy (shell,
0.0, 0.0,
&x_temp, &y_temp);
gtk_widget_translate_coordinates (GTK_WIDGET (shell),
toplevel,
x_temp, y_temp,
&x_after_hide, &y_after_hide);
g_assert_cmpint ((int)abs (x_after_hide - x_before_hide), <=, PIKA_UI_POSITION_EPSILON);
g_assert_cmpint ((int)abs (y_after_hide - y_before_hide), <=, PIKA_UI_POSITION_EPSILON);
}
static void
hide_docks_in_single_window_mode (gconstpointer data)
{
Pika *pika = PIKA (data);
pika_ui_toggle_docks_in_single_window_mode (pika);
}
static void
show_docks_in_single_window_mode (gconstpointer data)
{
Pika *pika = PIKA (data);
pika_ui_toggle_docks_in_single_window_mode (pika);
}
static void
maximize_state_in_aux_data (gconstpointer data)
{
Pika *pika = PIKA (data);
PikaDisplay *display = PIKA_DISPLAY (pika_get_display_iter (pika)->data);
PikaDisplayShell *shell = pika_display_get_shell (display);
PikaImageWindow *window = pika_display_shell_get_window (shell);
gint i;
for (i = 0; i < 2; i++)
{
GList *aux_info = NULL;
PikaSessionInfoAux *target_info;
gboolean target_max_state;
if (i == 0)
{
target_info = pika_session_info_aux_new ("maximized" , "yes");
target_max_state = TRUE;
}
else
{
target_info = pika_session_info_aux_new ("maximized", "no");
target_max_state = FALSE;
}
/* Set the aux info to out target data */
aux_info = g_list_append (aux_info, target_info);
pika_session_managed_set_aux_info (PIKA_SESSION_MANAGED (window), aux_info);
g_list_free (aux_info);
/* Give the WM a chance to maximize/unmaximize us */
pika_test_run_mainloop_until_idle ();
g_usleep (500 * 1000);
pika_test_run_mainloop_until_idle ();
/* Make sure the maximize/unmaximize happened */
g_assert (pika_image_window_is_maximized (window) == target_max_state);
/* Make sure we can read out the window state again */
aux_info = pika_session_managed_get_aux_info (PIKA_SESSION_MANAGED (window));
g_assert (g_list_find_custom (aux_info, target_info, pika_ui_aux_data_eqiuvalent));
g_list_free_full (aux_info,
(GDestroyNotify) pika_session_info_aux_free);
pika_session_info_aux_free (target_info);
}
}
static void
switch_back_to_multi_window_mode (gconstpointer data)
{
Pika *pika = PIKA (data);
/* Switch back to multi-window mode. We consider this test as passed
* if we don't get any GLib warnings/errors
*/
pika_ui_switch_window_mode (pika);
}
static void
close_image (gconstpointer data)
{
Pika *pika = PIKA (data);
int undo_count = 4;
/* Undo all changes so we don't need to find the 'Do you want to
* save?'-dialog and its 'No' button
*/
while (undo_count--)
{
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
"edit",
"edit-undo");
pika_test_run_mainloop_until_idle ();
}
/* Close the image */
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
"view",
"view-close");
pika_test_run_mainloop_until_idle ();
/* Did it really disappear? */
g_assert_cmpint (g_list_length (pika_get_image_iter (pika)), ==, 0);
}
/**
* repeatedly_switch_window_mode:
* @data:
*
* Makes sure that the size of the image window is properly handled
* when repeatedly switching between window modes.
**/
static void
repeatedly_switch_window_mode (gconstpointer data)
{
#ifdef __GNUC__
#warning FIXME: plesase fix repeatedly_switch_window_mode test
#endif
#if 0
Pika *pika = PIKA (data);
PikaDisplay *display = PIKA_DISPLAY (pika_get_empty_display (pika));
PikaDisplayShell *shell = pika_display_get_shell (display);
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (shell));
gint expected_initial_height;
gint expected_initial_width;
gint expected_second_height;
gint expected_second_width;
gint initial_width;
gint initial_height;
gint second_width;
gint second_height;
/* We need this for some reason */
pika_test_run_mainloop_until_idle ();
/* Remember the multi-window mode size */
gtk_window_get_size (GTK_WINDOW (toplevel),
&expected_initial_width,
&expected_initial_height);
/* Switch to single-window mode */
pika_ui_switch_window_mode (pika);
/* Remember the single-window mode size */
gtk_window_get_size (GTK_WINDOW (toplevel),
&expected_second_width,
&expected_second_height);
/* Make sure they differ, otherwise the test is pointless */
g_assert_cmpint (expected_initial_width, !=, expected_second_width);
g_assert_cmpint (expected_initial_height, !=, expected_second_height);
/* Switch back to multi-window mode */
pika_ui_switch_window_mode (pika);
/* Make sure the size is the same as before */
gtk_window_get_size (GTK_WINDOW (toplevel), &initial_width, &initial_height);
g_assert_cmpint (expected_initial_width, ==, initial_width);
g_assert_cmpint (expected_initial_height, ==, initial_height);
/* Switch to single-window mode again... */
pika_ui_switch_window_mode (pika);
/* Make sure the size is the same as before */
gtk_window_get_size (GTK_WINDOW (toplevel), &second_width, &second_height);
g_assert_cmpint (expected_second_width, ==, second_width);
g_assert_cmpint (expected_second_height, ==, second_height);
/* Finally switch back to multi-window mode since that was the mode
* when we started
*/
pika_ui_switch_window_mode (pika);
#endif
}
/**
* window_roles:
* @data:
*
* Makes sure that different windows have the right roles specified.
**/
static void
window_roles (gconstpointer data)
{
GdkMonitor *monitor = NULL;
GtkWidget *dock = NULL;
GtkWidget *toolbox = NULL;
PikaDockWindow *dock_window = NULL;
PikaDockWindow *toolbox_window = NULL;
monitor = gdk_display_get_primary_monitor (gdk_display_get_default ());
dock = pika_dock_with_window_new (pika_dialog_factory_get_singleton (),
monitor,
FALSE /*toolbox*/);
toolbox = pika_dock_with_window_new (pika_dialog_factory_get_singleton (),
monitor,
TRUE /*toolbox*/);
dock_window = pika_dock_window_from_dock (PIKA_DOCK (dock));
toolbox_window = pika_dock_window_from_dock (PIKA_DOCK (toolbox));
g_assert_cmpint (g_str_has_prefix (gtk_window_get_role (GTK_WINDOW (dock_window)), "pika-dock-"), ==,
TRUE);
g_assert_cmpint (g_str_has_prefix (gtk_window_get_role (GTK_WINDOW (toolbox_window)), "pika-toolbox-"), ==,
TRUE);
/* When we get here we have a ref count of one, but the signals we
* emit cause the reference count to become less than zero for some
* reason. So we're lazy and simply ignore to unref these
g_object_unref (toolbox);
g_object_unref (dock);
*/
}
static void
paintbrush_is_standard_tool (gconstpointer data)
{
Pika *pika = PIKA (data);
PikaContext *user_context = pika_get_user_context (pika);
PikaToolInfo *tool_info = pika_context_get_tool (user_context);
g_assert_cmpstr (tool_info->help_id,
==,
"pika-tool-paintbrush");
}
/**
* pika_ui_synthesize_delete_event:
* @widget:
*
* Synthesize a delete event to @widget.
**/
static void
pika_ui_synthesize_delete_event (GtkWidget *widget)
{
GdkWindow *window = NULL;
GdkEvent *event = NULL;
window = gtk_widget_get_window (widget);
g_assert (window);
event = gdk_event_new (GDK_DELETE);
event->any.window = g_object_ref (window);
event->any.send_event = TRUE;
gtk_main_do_event (event);
gdk_event_free (event);
}
static gboolean
pika_ui_synthesize_click (GtkWidget *widget,
gint x,
gint y,
gint button, /*1..3*/
GdkModifierType modifiers)
{
return (gdk_test_simulate_button (gtk_widget_get_window (widget),
x, y,
button,
modifiers,
GDK_BUTTON_PRESS) &&
gdk_test_simulate_button (gtk_widget_get_window (widget),
x, y,
button,
modifiers,
GDK_BUTTON_RELEASE));
}
static GtkWidget *
pika_ui_find_window (PikaDialogFactory *dialog_factory,
PikaUiTestFunc predicate)
{
GList *iter = NULL;
GtkWidget *dock_window = NULL;
g_return_val_if_fail (predicate != NULL, NULL);
for (iter = pika_dialog_factory_get_session_infos (dialog_factory);
iter;
iter = g_list_next (iter))
{
GtkWidget *widget = pika_session_info_get_widget (iter->data);
if (predicate (G_OBJECT (widget)))
{
dock_window = widget;
break;
}
}
return dock_window;
}
static gboolean
pika_ui_not_toolbox_window (GObject *object)
{
return (PIKA_IS_DOCK_WINDOW (object) &&
! pika_dock_window_has_toolbox (PIKA_DOCK_WINDOW (object)));
}
static gboolean
pika_ui_multicolumn_not_toolbox_window (GObject *object)
{
gboolean not_toolbox_window;
PikaDockWindow *dock_window;
PikaDockContainer *dock_container;
GList *docks;
if (! PIKA_IS_DOCK_WINDOW (object))
return FALSE;
dock_window = PIKA_DOCK_WINDOW (object);
dock_container = PIKA_DOCK_CONTAINER (object);
docks = pika_dock_container_get_docks (dock_container);
not_toolbox_window = (! pika_dock_window_has_toolbox (dock_window) &&
g_list_length (docks) > 1);
g_list_free (docks);
return not_toolbox_window;
}
static gboolean
pika_ui_is_pika_layer_list (GObject *object)
{
PikaDialogFactoryEntry *entry = NULL;
if (! GTK_IS_WIDGET (object))
return FALSE;
pika_dialog_factory_from_widget (GTK_WIDGET (object), &entry);
return strcmp (entry->identifier, "pika-layer-list") == 0;
}
static int
pika_ui_aux_data_eqiuvalent (gconstpointer _a, gconstpointer _b)
{
PikaSessionInfoAux *a = (PikaSessionInfoAux*) _a;
PikaSessionInfoAux *b = (PikaSessionInfoAux*) _b;
return (strcmp (a->name, b->name) || strcmp (a->value, b->value));
}
static void
pika_ui_switch_window_mode (Pika *pika)
{
pika_ui_manager_activate_action (pika_test_utils_get_ui_manager (pika),
"windows",
"windows-use-single-window-mode");
pika_test_run_mainloop_until_idle ();
/* Add a small sleep to let things stabilize */
g_usleep (500 * 1000);
pika_test_run_mainloop_until_idle ();
}
int main(int argc, char **argv)
{
Pika *pika = NULL;
gint result = -1;
pika_test_bail_if_no_display ();
gtk_test_init (&argc, &argv, NULL);
pika_test_utils_setup_menus_path ();
/* Start up PIKA */
pika = pika_init_for_gui_testing (TRUE /*show_gui*/);
pika_test_run_mainloop_until_idle ();
/* Add tests. Note that the order matters. For example,
* 'paintbrush_is_standard_tool' can't be after
* 'tool_options_editor_updates'
*/
ADD_TEST (paintbrush_is_standard_tool);
ADD_TEST (tool_options_editor_updates);
ADD_TEST (create_new_image_via_dialog);
ADD_TEST (keyboard_zoom_focus);
ADD_TEST (alt_click_is_layer_to_selection);
ADD_TEST (restore_recently_closed_multi_column_dock);
ADD_TEST (tab_toggle_dont_change_dock_window_position);
ADD_TEST (switch_to_single_window_mode);
#warning "FIXME: hide/show docks doesn't work when running make check"
#if 0
ADD_TEST (hide_docks_in_single_window_mode);
ADD_TEST (show_docks_in_single_window_mode);
#endif
#warning "FIXME: maximize_state_in_aux_data doesn't work without WM"
#if 0
ADD_TEST (maximize_state_in_aux_data);
#endif
ADD_TEST (switch_back_to_multi_window_mode);
ADD_TEST (close_image);
ADD_TEST (repeatedly_switch_window_mode);
ADD_TEST (window_roles);
/* Run the tests and return status */
g_application_run (pika->app, 0, NULL);
result = pika_core_app_get_exit_status (PIKA_CORE_APP (pika->app));
g_application_quit (G_APPLICATION (pika->app));
g_clear_object (&pika->app);
return result;
}

1047
app/tests/test-xcf.c Normal file

File diff suppressed because it is too large Load Diff

287
app/tests/tests.c Normal file
View File

@ -0,0 +1,287 @@
/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* 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 <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <stdlib.h>
#include <gegl.h>
#include <gtk/gtk.h>
#include "gui/gui-types.h"
#include "gui/gui.h"
#include "actions/actions.h"
#include "menus/menus.h"
#include "widgets/pikasessioninfo.h"
#include "config/pikageglconfig.h"
#include "core/pika.h"
#include "core/pika-contexts.h"
#include "gegl/pika-gegl.h"
#include "pika-log.h"
#include "pikacoreapp.h"
#include "pika-app-test-utils.h"
#include "tests.h"
#ifdef GDK_WINDOWING_QUARTZ
#include <Cocoa/Cocoa.h>
#endif
static void
pika_status_func_dummy (const gchar *text1,
const gchar *text2,
gdouble percentage)
{
}
/**
* pika_init_for_testing:
*
* Initialize the PIKA object system for unit testing. This is a
* selected subset of the initialization happening in app_run().
**/
Pika *
pika_init_for_testing (void)
{
Pika *pika;
pika_log_init ();
gegl_init (NULL, NULL);
pika = pika_new ("Unit Tested PIKA", NULL, NULL, FALSE, TRUE, TRUE, TRUE,
FALSE, FALSE, TRUE, FALSE, FALSE,
PIKA_STACK_TRACE_QUERY, PIKA_PDB_COMPAT_OFF);
pika_load_config (pika, NULL, NULL);
pika_gegl_init (pika);
pika_initialize (pika, pika_status_func_dummy);
pika_restore (pika, pika_status_func_dummy, NULL);
return pika;
}
#ifndef PIKA_CONSOLE_COMPILATION
static void
pika_init_icon_theme_for_testing (void)
{
gchar *icon_root;
icon_root = g_test_build_filename (G_TEST_BUILT, "pika-test-icon-theme", NULL);
gtk_icon_theme_prepend_search_path (gtk_icon_theme_get_default (),
icon_root);
g_free (icon_root);
return;
}
#ifdef GDK_WINDOWING_QUARTZ
static gboolean
pika_osx_focus_window (gpointer user_data)
{
[NSApp activateIgnoringOtherApps:YES];
return FALSE;
}
#endif
static void
pika_test_app_activate_callback (PikaCoreApp *app,
gpointer user_data)
{
Pika *pika = NULL;
g_return_if_fail (PIKA_IS_CORE_APP (app));
pika = pika_core_app_get_pika (app);
pika_core_app_set_exit_status (app, EXIT_SUCCESS);
gui_init (pika, TRUE, NULL, g_getenv ("PIKA_TESTING_ABS_TOP_SRCDIR"));
pika_init_icon_theme_for_testing ();
pika_initialize (pika, pika_status_func_dummy);
pika_restore (pika, pika_status_func_dummy, NULL);
#ifdef GDK_WINDOWING_QUARTZ
g_idle_add (pika_osx_focus_window, NULL);
#endif
pika->initialized = TRUE;
pika_core_app_set_exit_status (app, g_test_run ());
/* Don't write files to the source dir */
pika_test_utils_set_pika3_directory ("PIKA_TESTING_ABS_TOP_BUILDDIR",
"app/tests/pikadir-output");
pika_exit (pika, TRUE);
}
static Pika *
pika_init_for_gui_testing_internal (gboolean show_gui,
GFile *pikarc)
{
Pika *pika;
/* Load configuration from the source dir */
pika_test_utils_set_pika3_directory ("PIKA_TESTING_ABS_TOP_SRCDIR",
"app/tests/pikadir");
#if defined (G_OS_WIN32)
/* g_test_init() sets warnings always fatal, which is a usually a good
testing default. Nevertheless the Windows platform may have a few
quirks generating warnings, yet we want to finish tests. So we
allow some relaxed rules on this platform. */
GLogLevelFlags fatal_mask;
fatal_mask = (GLogLevelFlags) (G_LOG_FATAL_MASK | G_LOG_LEVEL_CRITICAL);
g_log_set_always_fatal (fatal_mask);
#endif
/* from main() */
pika_log_init ();
gegl_init (NULL, NULL);
/* Introduce an error margin for positions written to sessionrc */
pika_session_info_set_position_accuracy (5);
/* from app_run() */
pika = pika_new ("Unit Tested PIKA", NULL, NULL, FALSE, TRUE, TRUE, !show_gui,
FALSE, FALSE, TRUE, FALSE, FALSE,
PIKA_STACK_TRACE_QUERY, PIKA_PDB_COMPAT_OFF);
pika->app = pika_app_new (pika, TRUE, FALSE, FALSE, NULL, NULL, NULL);
pika_set_show_gui (pika, show_gui);
pika_load_config (pika, pikarc, NULL);
pika_gegl_init (pika);
g_signal_connect (pika->app, "activate",
G_CALLBACK (pika_test_app_activate_callback),
NULL);
return pika;
}
/**
* pika_init_for_gui_testing:
* @show_gui:
*
* Initializes a #Pika instance for use in test cases that rely on GUI
* code to be initialized.
*
* Returns: The #Pika instance.
**/
Pika *
pika_init_for_gui_testing (gboolean show_gui)
{
return pika_init_for_gui_testing_internal (show_gui, NULL);
}
/**
* pika_init_for_gui_testing:
* @show_gui:
* @pikarc:
*
* Like pika_init_for_gui_testing(), but also allows a custom pikarc
* filename to be specified.
*
* Returns: The #Pika instance.
**/
Pika *
pika_init_for_gui_testing_with_rc (gboolean show_gui,
GFile *pikarc)
{
return pika_init_for_gui_testing_internal (show_gui, pikarc);
}
#endif /* PIKA_CONSOLE_COMPILATION */
static gboolean
pika_tests_quit_mainloop (GMainLoop *loop)
{
g_main_loop_quit (loop);
return FALSE;
}
/**
* pika_test_run_temp_mainloop:
* @running_time: The time to run the main loop.
*
* Helper function for tests that wants to run a main loop for a
* while. Useful when you want PIKA's state to settle before doing
* tests.
**/
void
pika_test_run_temp_mainloop (guint32 running_time)
{
GMainLoop *loop;
loop = g_main_loop_new (NULL, FALSE);
g_timeout_add (running_time,
(GSourceFunc) pika_tests_quit_mainloop,
loop);
g_main_loop_run (loop);
g_main_loop_unref (loop);
}
/**
* pika_test_run_mainloop_until_idle:
*
* Creates and runs a main loop until it is idle, i.e. has no more
* work to do.
**/
void
pika_test_run_mainloop_until_idle (void)
{
GMainLoop *loop = g_main_loop_new (NULL, FALSE);
g_idle_add ((GSourceFunc) pika_tests_quit_mainloop, loop);
g_main_loop_run (loop);
g_main_loop_unref (loop);
}
/**
* pika_test_bail_if_no_display:
* @void:
*
* If no DISPLAY is set, call exit(EXIT_SUCCESS). There is no use in
* having UI tests failing in DISPLAY-less environments.
**/
void
pika_test_bail_if_no_display (void)
{
if (! g_getenv ("DISPLAY"))
{
g_message ("No DISPLAY set, not running UI tests\n");
exit (EXIT_SUCCESS);
}
}

45
app/tests/tests.h Normal file
View File

@ -0,0 +1,45 @@
/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* 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 <https://www.gnu.org/licenses/>.
*/
#ifndef __TESTS_H__
#define __TESTS_H__
/* Automake doc says:
"When no test protocol is in use, an exit status of 0 from a test
script will denote a success, an exit status of 77 a skipped test,
an exit status of 99 an hard error, and any other exit status will
denote a failure."
Unfortunately glib returns a SUCCESS when you skip tests, which is
not a reliable test feedback. So we hard-code the SKIPPED return
value. */
#define PIKA_EXIT_TEST_SKIPPED 77
Pika * pika_init_for_testing (void);
Pika * pika_init_for_gui_testing (gboolean show_gui);
Pika * pika_init_for_gui_testing_with_rc (gboolean show_gui,
GFile *pikarc);
void pika_test_run_temp_mainloop (guint32 running_time);
void pika_test_run_mainloop_until_idle (void);
void pika_test_bail_if_no_display (void);
#endif /* __TESTS_H__ */