plug-ins: add file-plug-in testing framework

Copied over from the original separate work in:
https://gitlab.gnome.org/Wormnest/gimp-file-plugin-tests
After that further improved and changed and added more file format
tests.

Added meson.build files to integrate it in our build, but we do not
install it for releases.
This commit is contained in:
Jacob Boerema 2023-11-22 11:56:38 -05:00
parent 44225ef1c0
commit 3478e1c00f
39 changed files with 1806 additions and 0 deletions

View File

@ -607,6 +607,47 @@ gimp-win-x86:
## Analysis ##
file-plug-in-tests:
# FIXME: Do we need another job testing this under Windows? MSYS2 usually has
# the latest deps. It might be a good idea to test that too, maybe weekly?
extends: .default
rules:
# Don't run on release since the plug-in doesn't get installed in releases
- <<: *CI_MERGE
- <<: *CI_COMMIT
needs: ["deps-debian-x64", "gimp-debian-x64"]
stage: analysis
variables:
GIMP_TESTS_DATA_FOLDER: "$CI_PROJECT_DIR/_data/gimp-test-images/"
GIMP_TESTS_LOG_FILE: "$CI_PROJECT_DIR/_log/import-tests.log"
REGRESSION_STRING: "Total number of regressions: 0"
cache:
- key: "$CI_JOB_NAME"
paths:
- _data
image: $CI_REGISTRY_IMAGE:build-debian-latest
artifacts:
paths:
- _log/
expire_in: 2 days
script:
- API_VER=$(grep GIMP_PKGCONFIG_VERSION _build${ARTIFACTS_SUFFIX}/config.h | head -1 | sed 's/^.*"\([^"]*\)"$/\1/')
- APP_VER=$(grep GIMP_USER_VERSION _build${ARTIFACTS_SUFFIX}/config.h | head -1 | sed 's/^.*"\([^"]*\)"$/\1/')
- pkg-config --variable=gimplibdir gimp-${API_VER} 2>/dev/null | grep . && PLUG_IN_DIR=$(echo $(pkg-config --variable=gimplibdir gimp-${API_VER})'/plug-ins/')
- export PYTHONPATH="${PLUG_IN_DIR}test-file-plug-ins"
- export GIMP_TESTS_CONFIG_FILE="${PLUG_IN_DIR}test-file-plug-ins/tests/batch-config.ini"
- mkdir _log
- mkdir _data && cd _data
- git clone --depth=${GIT_DEPTH} https://gitlab.gnome.org/Infrastructure/gimp-test-images.git gimp-test-images
- cd ..
- cat ${PLUG_IN_DIR}test-file-plug-ins/batch-import-tests.py | gimp-console-${APP_VER} -idf --batch-interpreter python-fu-eval -b - --quit
- if [ $(grep -c "${REGRESSION_STRING}" "${GIMP_TESTS_LOG_FILE}") -ne 1 ]; then
echo "There are file import regressions. Check the log at ${GIMP_TESTS_LOG_FILE}!";
exit 1;
fi
# FIXME No export testing for now until it's more developed. A limited test
# can be done from the plug-in for bmp export.
clang-format:
extends: .default
rules:

View File

@ -18,6 +18,7 @@ if not stable or not release
endif
subdir('python-console')
subdir('tests')
foreach plugin : plugins
name = plugin.get('name')

View File

@ -0,0 +1,5 @@
if not have_python
subdir_done()
endif
subdir('test-file-plug-ins')

View File

@ -0,0 +1,126 @@
# test-file-plugins
Version 0.5
Jacob Boerema, 2021-2024
## Introduction
This is a Python 3 framework for testing GIMP file import and export plug-ins.
It can be run both as a plug-in from within GIMP (in case it is installed),
and from the command line in batch mode.
## Installation and set-up
1. For running as a plug-in in GIMP this plug-in needs to be in a location
that GIMP knows of for plug-ins. By default it is only installed for
unstable builds. For using the batch version, it is not necessary to
have it installed.
2. There is a `tests` folder inside the plug-in folder for
configuration files. The main configuration file is
`config.ini` for the plug-in; I use a separate `batch-config.ini` for
command line testing, but that's not required.
This configuration file is where you define the file import and export
plug-ins to test. Each plug-in has its own separate configuration
file that defines the tests and test files which should be in the same
folder.
The location and name of the main configuration file can be changed by
setting an environment variable: `GIMP_TESTS_CONFIG_FILE`.
3. The plug-in specific configuration file, e.g.
`png-tests.ini` defines the specific test sets. This configuration file is
expected to be in the same location as the main configuration file.
Each test set can be enabled/disabled and needs to
have a folder set where the test images can be found.
This folder is expected to be relative to the base test data folder.
By default this is the `./data/` folder, but it can also be
changed, see below.
The specific test images are defined in a file set in `files=`. These are
expected to be in the same folder as the images they are testing.
The root folder for all test images is by default `./data/`. This folder can
be changed by setting the environment variable `GIMP_TESTS_DATA_FOLDER`.
4. The file that defines the images to be tested, should be a text file
where each line contains the filename of one test image, optionally
followed by a ',' and then a code for the expected result.
Currently there are four results defined:
- `EXPECTED_OK` (the default if omitted, if loading should succeed)
- `EXPECTED_FAIL` (if loading should fail)
- `EXPECTED_TODO` (if loading is currently expected to fail, but the
intention is to fix this in the future)
- `SKIP` (this temporarily skips testing a file, useful when a file causes
problems working on other test files) Note: this is **only** intended
for temporary debugging purposes. They should not be committed like that
to our repository.
We may add `EXPECTED_NO_CRASH` in the future, to define fuzzed images
where we don't care whether they load or not, as long as there is no crash.
## How to run
Start GIMP, then start the plug-in from:
- Menu Filters, Development, Python-Fu, Test file import plug-ins.
Note: this plug-in is not installed for stable builds.
Or, from the commandline or a shell script:
```
export GIMP_TESTS_CONFIG_FILE="/location/of/config.ini"
export GIMP_TESTS_LOG_FILE="/location/of/logfile.log"
export GIMP_TESTS_DATA_FOLDER="/location/of/test-images/rootfolder/"
export PYTHONPATH="/location/of/your/python/script/"
cd location/of/plug-in/gimp-file-plugin-tests
cat batch-import-tests.py | gimp-console-2.99 -idf --batch-interpreter python-fu-eval -b - --quit
```
In case you run the batch version, the log file is written to the folder
where the plug-in resides. This location can be adjusted by setting the
environment variable `GIMP_TESTS_LOG_FILE`. Note that the path to this file
needs to exist!
To test for success or regressions in batch mode you can test whether there
were regressions.
You should grep for `Total number of regressions: 0`.
### Status
- The only thing currently being tested is whether the image loads or not. No
testing is done to see if the image is correctly shown.
- When running all tiff tests from inside GIMP, it may crash, at least on
Windows, due to the error console running out of resources because of
the amount of messages.
- There is some preliminary export testing support, see `batch-export-tests.py`,
but it is incomplete. That is: there is no error tracking yet, nor support
for comparing exported images with reference images.
### File import plug-ins being tested
At this moment the following file import plug-ins have
tests available:
- file-bmp
- file-dcx
- file-dds
- file-fits
- file-gif
- file-jpeg
- file-pcx
- file-png
- file-pnm
- file-psb
- file-psd
- file-psd-load-merged
- file-psp
- file-sgi
- file-tga
- file-tiff
## Future enhancements
- Add tests for all our image loading plug-ins.
- Test if loaded images are loaded correctly, i.e.
do they look like they should.
- Fuzzing of images before loading to test our handling of corrupt images.
We may need to add another result type: `EXPECTED_NO_CRASH`, meaning we
don't care whether it loads or not, as long as there is no crash.
- GUI to select/deselect tests.
- Improve file export testing.
- It would be nice to be able to capture all stdout/stderr output and
possibly filter it for crashes, criticals and warnings, and add that to
the log file. Maybe with an option to filter out certain kinds of messages.

View File

@ -0,0 +1,54 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# GIMP - The GNU Image Manipulation Program
# Copyright (C) 1995 Spencer Kimball and Peter Mattis
#
# batch-export-tests.py
# Copyright (C) 2021-2024 Jacob Boerema
#
# 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/>.
"""Batch non-interactive GIMP file export plug-ins testing."""
from gimpconfig import GimpConfig
from gimplogger import GimpLogger
from gimptestframework import GimpExportTestRunner
from gimpexporttests import BmpExportTests
#DEBUGGING=True
DEBUGGING=False
#PRINT_VERBOSE = True
PRINT_VERBOSE = False
LOG_APPEND = False
test_cfg = GimpConfig()
log = GimpLogger(False, test_cfg.log_file, LOG_APPEND, PRINT_VERBOSE, DEBUGGING)
runner = GimpExportTestRunner(log, "export", test_cfg)
if not runner:
log.error("Failed to create export test runner!")
else:
runner.load_test_configs()
bmp_tests = BmpExportTests("bmp", log)
runner.add_test(bmp_tests)
# Add additional tests here
runner.run_tests()

View File

@ -0,0 +1,43 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# GIMP - The GNU Image Manipulation Program
# Copyright (C) 1995 Spencer Kimball and Peter Mattis
#
# batch-import-tests.py
# Copyright (C) 2021-2024 Jacob Boerema
#
# 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/>.
"""Batch non-interactive GIMP file import plug-ins testing."""
from gimpconfig import GimpConfig
from gimplogger import GimpLogger
from gimptestframework import GimpTestRunner
#DEBUGGING=True
DEBUGGING=False
#PRINT_VERBOSE = True
PRINT_VERBOSE = False
LOG_APPEND = False
test_cfg = GimpConfig()
log = GimpLogger(False, test_cfg.log_file, LOG_APPEND, PRINT_VERBOSE, DEBUGGING)
runner = GimpTestRunner(log, "import", test_cfg)
runner.run_tests()

View File

@ -0,0 +1,81 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# GIMP - The GNU Image Manipulation Program
# Copyright (C) 1995 Spencer Kimball and Peter Mattis
#
# gimpconfig.py
# Copyright (C) 2022-2024 Jacob Boerema
#
# 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/>.
"""Configuration handling for use with our testing framework."""
import os
class GimpConfig(object):
DEFAULT_CONFIG = "config.ini"
DEFAULT_CONFIG_FOLDER = "/tests/"
DEFAULT_LOGFILE = "/tests/gimp-tests.log"
DEFAULT_DATA_FOLDER = "/tests/"
def __init__(self, config_path=None, log_path=None, data_path=None):
base_path = os.path.dirname(os.path.realpath(__file__))
if config_path is None:
config_path = os.getenv("GIMP_TESTS_CONFIG_FILE")
if log_path is None:
log_path = os.getenv("GIMP_TESTS_LOG_FILE")
if data_path is None:
data_path = os.getenv("GIMP_TESTS_DATA_FOLDER")
if config_path is None:
config_path = base_path + self.DEFAULT_CONFIG_FOLDER + self.DEFAULT_CONFIG
#print(f"Config path for file plug-in tests: {config_path}")
self.config_folder = os.path.dirname(config_path)
if os.path.exists(self.config_folder):
self.config_folder += "/"
else:
if self.config_folder is not None:
print (f"Config folder '{self.config_folder}' does not exist!")
self.config_folder = self.DEFAULT_CONFIG_FOLDER
self.config_file = os.path.basename(config_path)
if self.config_file is None:
self.config_file = self.DEFAULT_CONFIG
filepath = self.config_folder + self.config_file
if not os.path.exists(filepath):
raise Exception(f"Config file '{filepath}' does not exist!")
if log_path is None:
log_path = base_path + self.DEFAULT_LOGFILE
filepath = os.path.dirname(log_path)
if not os.path.exists(filepath):
if filepath is not None:
print (f"Log file path '{filepath}' does not exist!")
self.log_file = self.DEFAULT_LOGFILE
else:
self.log_file = log_path
if data_path is None:
data_path = base_path + self.DEFAULT_DATA_FOLDER
self.data_folder = data_path
if not os.path.exists(self.data_folder):
if self.data_folder is not None:
print (f"Data path for test images '{self.data_folder}' does not exist!")
self.data_folder = self.DEFAULT_DATA_FOLDER

View File

@ -0,0 +1,140 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# GIMP - The GNU Image Manipulation Program
# Copyright (C) 1995 Spencer Kimball and Peter Mattis
#
# gimpexporttests.py
# Copyright (C) 2021-2024 Jacob Boerema
#
# 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/>.
"""Module where we add export tests for GIMP's file export plug-ins."""
import sys
import gi
gi.require_version('Gimp', '3.0')
from gi.repository import Gimp
from gi.repository import Gio
from gimptestframework import GimpExportTest
class BmpExportTests(GimpExportTest):
def __init__(self, group_name, log):
super().__init__(group_name, log)
def load_bmp(self, bmp_name):
pdb_proc = Gimp.get_pdb().lookup_procedure(self.file_import)
pdb_config = pdb_proc.create_config()
pdb_config.set_property('run-mode', Gimp.RunMode.NONINTERACTIVE)
pdb_config.set_property('file', Gio.File.new_for_path(bmp_name))
result = pdb_proc.run(pdb_config)
status = result.index(0)
img = result.index(1)
if (status == Gimp.PDBStatusType.SUCCESS and img is not None and img.is_valid()):
return img
else:
self.log.error(f"Loading image {bmp_name} failed!")
return None
def export_bmp(self, img, bmp_exp_name, rle, space, rgb):
drw = img.list_layers()
export_file_path = self.output_path + bmp_exp_name
pdb_proc = Gimp.get_pdb().lookup_procedure(self.file_export)
pdb_config = pdb_proc.create_config()
pdb_config.set_property('run-mode', Gimp.RunMode.NONINTERACTIVE)
pdb_config.set_property('image', img)
pdb_config.set_property('num-drawables', 1)
pdb_config.set_property('drawables', Gimp.ObjectArray.new(Gimp.Drawable, drw, False))
pdb_config.set_property('file', Gio.File.new_for_path(export_file_path))
pdb_config.set_property('use-rle', rle)
pdb_config.set_property('write-color-space', space)
pdb_config.set_property('rgb-format', rgb)
result = pdb_proc.run(pdb_config)
status = result.index(0)
if status == Gimp.PDBStatusType.SUCCESS:
self.log.info(f"Exporting image {export_file_path} succeeded.")
else:
self.log.error(f"Exporting image {export_file_path} failed!")
def bmp_setup(self, image_name, test_description):
self.log.consoleinfo(test_description)
tmp = self.input_path + image_name
img = self.load_bmp(tmp)
return img
def bmp_teardown(self, image):
if image is not None:
image.delete()
def bmp_1bpp_indexed(self, image_name, test_description):
img = self.bmp_setup(image_name, test_description)
if img is not None:
self.export_bmp(img, "1bpp-norle-nospace.bmp", 0, 0, 0)
self.export_bmp(img, "1bpp-norle-withspace.bmp", 0, 1, 0)
# rle with 1-bit is not valid, test to see if it
# is correctly ignored...
self.export_bmp(img, "1bpp-rle-nospace.bmp", 1, 0, 0)
self.export_bmp(img, "1bpp-rle-withspace.bmp", 1, 1, 0)
self.bmp_teardown(img)
def bmp_4bpp_indexed(self, image_name, test_description):
img = self.bmp_setup(image_name, test_description)
if img is not None:
self.export_bmp(img, "4bpp-norle-nospace.bmp", 0, 0, 0)
self.export_bmp(img, "4bpp-norle-withspace.bmp", 0, 1, 0)
self.export_bmp(img, "4bpp-rle-nospace.bmp", 1, 0, 0)
self.export_bmp(img, "4bpp-rle-withspace.bmp", 1, 1, 0)
self.bmp_teardown(img)
def bmp_8bpp_indexed(self, image_name, test_description):
img = self.bmp_setup(image_name, test_description)
if img is not None:
self.export_bmp(img, "8bpp-norle-nospace.bmp", 0, 0, 0)
self.export_bmp(img, "8bpp-norle-withspace.bmp", 0, 1, 0)
self.export_bmp(img, "8bpp-rle-nospace.bmp", 1, 0, 0)
self.export_bmp(img, "8bpp-rle-withspace.bmp", 1, 1, 0)
self.bmp_teardown(img)
def bmp_rgba(self, image_name, test_description):
img = self.bmp_setup(image_name, test_description)
if img is not None:
# first test correctly ignoring rle
self.export_bmp(img, "rgb-with-rle-nospace.bmp", 1, 0, 3)
# All rgb modes without color space
self.export_bmp(img, "rgb-nrle-nospace-type0.bmp", 0, 0, 0)
self.export_bmp(img, "rgb-nrle-nospace-type1.bmp", 0, 0, 1)
self.export_bmp(img, "rgb-nrle-nospace-type2.bmp", 0, 0, 2)
self.export_bmp(img, "rgb-nrle-nospace-type3.bmp", 0, 0, 3)
self.export_bmp(img, "rgb-nrle-nospace-type4.bmp", 0, 0, 4)
self.export_bmp(img, "rgb-nrle-nospace-type5.bmp", 0, 0, 5)
# All rgb modes with color space
self.export_bmp(img, "rgb-nrle-withspace-type0.bmp", 0, 1, 0)
self.export_bmp(img, "rgb-nrle-withspace-type1.bmp", 0, 1, 1)
self.export_bmp(img, "rgb-nrle-withspace-type2.bmp", 0, 1, 2)
self.export_bmp(img, "rgb-nrle-withspace-type3.bmp", 0, 1, 3)
self.export_bmp(img, "rgb-nrle-withspace-type4.bmp", 0, 1, 4)
self.export_bmp(img, "rgb-nrle-withspace-type5.bmp", 0, 1, 5)
self.bmp_teardown(img)
def run_test(self, group_config):
self.bmp_1bpp_indexed('test1-exp1.bmp', " 1. Using 1bpp indexed BMP...")
self.bmp_4bpp_indexed('pal4rle-exp1.bmp', " 2. Using 4bpp indexed BMP...")
self.bmp_8bpp_indexed('pal8v5-exp1.bmp', " 3. Using 8bpp indexed BMP...")
self.bmp_rgba('rgb32-with-alpha-1.bmp', " 4. Using rgb(a) BMP...")

View File

@ -0,0 +1,100 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# GIMP - The GNU Image Manipulation Program
# Copyright (C) 1995 Spencer Kimball and Peter Mattis
#
# gimplogger.py
# Copyright (C) 2021-2024 Jacob Boerema
#
# 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/>.
"""Logging framework for use with GIMP Python plug-ins."""
import os
import logging
import gi
gi.require_version('Gimp', '3.0')
from gi.repository import Gimp
class GimpLogger (object):
def __init__(self, interactive, logfile, append=False, verbose=False, debugging=False):
self.interactive = interactive
self.verbose = verbose
self.debugging = debugging
if debugging:
log_level = logging.DEBUG
else:
log_level = logging.INFO
if append:
log_filemode = 'a'
else:
log_filemode = 'w'
logging.basicConfig(
filename=logfile,
filemode=log_filemode,
encoding='utf-8',
level=log_level,
format='%(asctime)s | %(name)s | %(levelname)s | %(message)s')
logging.debug("Starting logger...")
logging.debug("Log file: %s", os.path.abspath(logfile))
def set_interactive(self, interactive):
if self.interactive != interactive:
self.interactive = interactive
logging.debug("Interactive set to %s", self.interactive)
def message(self, msg):
logging.info(msg)
print(msg)
if self.interactive:
Gimp.message(msg)
def gimp_verbose_message(self, msg):
if self.verbose and self.interactive:
Gimp.message(msg)
def info(self, msg):
if self.verbose:
logging.info(msg)
print(msg)
def consoleinfo(self, msg):
logging.info(msg)
print(msg)
def warning(self, msg):
warn_msg = 'WARNING: ' + msg
logging.warning(msg)
print(warn_msg)
if self.interactive:
Gimp.message(warn_msg)
def error(self, msg):
err_msg = 'ERROR: ' + msg
logging.error(msg)
print(err_msg)
if self.interactive:
Gimp.message(err_msg)
def debug(self, msg):
logging.debug(msg)
if self.debugging:
print(msg)

View File

@ -0,0 +1,573 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# GIMP - The GNU Image Manipulation Program
# Copyright (C) 1995 Spencer Kimball and Peter Mattis
#
# gimptestframework.py
# Copyright (C) 2021-2024 Jacob Boerema
#
# 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/>.
"""GIMP file plug-ins testing framework."""
import os
import configparser
import gi
gi.require_version('Gimp', '3.0')
from gi.repository import Gimp
from gi.repository import Gio
VERSION = "0.5"
AUTHORS = "Jacob Boerema"
YEARS = "2021-2024"
EXPECTED_FAIL = 0
EXPECTED_OK = 1
EXPECTED_TODO = 2
RESULT_FAIL = 0
RESULT_OK = 1
RESULT_CRASH = 2
class PluginTestConfig(object):
def __init__(self, log, path, testconfig):
self.valid_config = False
self.enabled = False
self.plugin = testconfig.get('plugin-import')
if self.plugin is None:
self.plugin = testconfig.get('plugin')
if self.plugin is not None:
log.warning("Test is using deprecated 'plugin' parameter. Use 'plugin-import' instead!")
else:
log.error("Missing required 'plugin-import' parameter!")
return
tests = testconfig.get('tests')
if tests is None:
log.error("Missing required 'tests' parameter!")
return
self.tests = path + tests
enabled = testconfig.get('enabled')
if enabled == 'True':
self.enabled = True
self.extension = testconfig.get('extension','<missing>')
self.valid_config = True
# preliminary export testing support
self.export_plugin = testconfig.get('plugin-export')
self.export_tests = testconfig.get('tests-export')
self.export_enabled = testconfig.get('enabled-export')
class ConfigLoader(object):
def __init__(self, log, config_path, config_file):
self.config_path = config_path
self.config_file = config_file
log.debug(f"Using config file: {self.config_path}{self.config_file}")
self.tests = []
self.export_tests = []
self.problems = 0
self.disabled = 0
self.config = configparser.ConfigParser()
self.config.read(self.config_path + self.config_file)
msg = "Available tests:"
for key in self.config.sections():
if key == 'main':
pass
else:
# Add test config
test = PluginTestConfig(log, self.config_path, self.config[key])
if test.valid_config:
self.tests.append(test)
msg += f"\nPlugin: {test.plugin}, test config: {test.tests}, enabled: {test.enabled}"
if not test.enabled:
self.disabled += 1
else:
log.warning(f"\nSkipping invalid config for {key}!")
self.problems += 1
if test.export_plugin is not None and test.export_tests is not None:
log.info(f"Export test found for {key}")
self.export_tests.append(test)
log.gimp_verbose_message(msg)
class FileLoadTest(object):
def __init__(self, file_load_plugin_name, image_type, data_path, log):
self.log = log
self.data_root = data_path
self.plugin_name = file_load_plugin_name
self.image_type = image_type
self.unexpected_success_images = []
self.unexpected_failure_images = []
self.total_tests = 0
self.total_failed = 0
self.total_todo = 0
self.total_ok = 0
self.total_crash = 0
def run_file_load(self, image_file, expected):
if not os.path.exists(image_file):
msg = "Regression loading " + image_file + ". File does not exist!"
self.log.error("--> " + msg)
return RESULT_FAIL
pdb_proc = Gimp.get_pdb().lookup_procedure(self.plugin_name)
if pdb_proc is None:
msg = "Plug-in procedure '" + self.plugin_name + "' not found!"
self.log.error("--> " + msg)
return RESULT_FAIL
pdb_config = pdb_proc.create_config()
pdb_config.set_property('run-mode', Gimp.RunMode.NONINTERACTIVE)
pdb_config.set_property('file', Gio.File.new_for_path(image_file))
result = pdb_proc.run(pdb_config)
status = result.index(0)
img = result.index(1)
if (status == Gimp.PDBStatusType.SUCCESS and img is not None and img.is_valid()):
self.log.info ("Loading succeeded for " + image_file)
img.delete()
if expected == EXPECTED_FAIL:
self.unexpected_success_images.append(image_file)
msg = "Regression loading " + image_file + ". Loading unexpectedly succeeded."
self.log.error("--> " + msg)
return RESULT_FAIL
elif expected == EXPECTED_TODO:
self.unexpected_success_images.append(image_file)
msg = "Loading unexpectedly succeeded for test marked TODO. Image: " + image_file
self.log.error("--> " + msg)
return RESULT_FAIL
return RESULT_OK
else:
self.log.info ("Loading failed for " + image_file)
if status == Gimp.PDBStatusType.CALLING_ERROR:
# A calling error indicates the plug-in crashed, which should
# always be considered failure!
if expected == EXPECTED_OK:
self.unexpected_failure_images.append(image_file)
elif expected == EXPECTED_TODO:
self.unexpected_success_images.append(image_file)
msg = "Plug-in crashed while loading " + image_file + "."
self.log.error("--> " + msg)
return RESULT_CRASH
elif expected == EXPECTED_OK:
self.unexpected_failure_images.append(image_file)
msg = "Regression loading " + image_file + ". Loading unexpectedly failed."
self.log.error("--> " + msg)
return RESULT_FAIL
return RESULT_OK
def load_test_images(self, test_images):
test_list = []
if not os.path.exists(test_images):
msg = "Path does not exist: " + test_images
self.log.error(msg)
return None
with open(test_images, encoding='UTF-8') as f:
try:
content = f.readlines()
except UnicodeDecodeError as err:
self.log.error(f"Invalid encoding for {test_images}: {err}")
return None
# strip whitespace
content = [x.strip() for x in content]
for line in content:
data = line.split(",")
data[0] = data[0].strip()
if len(data) > 1:
expected_str = data[1].strip()
else:
expected_str = 'EXPECTED_OK'
data.append(expected_str)
if expected_str == 'EXPECTED_FAIL':
data[1] = EXPECTED_FAIL
elif expected_str == 'EXPECTED_TODO':
data[1] = EXPECTED_TODO
elif expected_str == 'SKIP':
continue
else:
# Assume that anything else is supposed to load OK
data[1] = EXPECTED_OK
test_list.append(data)
return test_list
def run_tests(self, image_folder, test_images, test_description):
test_fail = 0
test_ok = 0
test_todo = 0
test_crash = 0
test_total = 0
test_images_list = self.load_test_images(test_images)
if not test_images_list:
# Maybe we should create another type of test failure (test_filesystem?)
test_fail += 1
test_crash += 1
self.total_failed += test_fail
self.total_crash += test_crash
msg = f"No images found for '{test_description}'.'"
self.log.error(msg)
return
test_total = len(test_images_list)
for imgfile, expected in test_images_list:
test_result = self.run_file_load(self.data_root + image_folder + imgfile, expected)
if test_result == RESULT_FAIL:
test_fail += 1
elif test_result == RESULT_OK:
test_ok += 1
elif test_result == RESULT_CRASH:
test_crash += 1
test_fail += 1
else:
test_crash += 1
test_fail += 1
msg = "Invalid test result value: " + str(test_result)
self.log.error(msg)
if expected == EXPECTED_TODO:
test_todo += 1
result_msg = "Test: " + test_description + "\n"
if test_crash > 0:
result_msg += "Number of plug-in crashes: " + str(test_crash) + "\n"
if test_fail > 0:
result_msg += "Failed " + str(test_fail) + " of " + str(test_total) + " tests"
if test_todo > 0:
result_msg += ", and " + str(test_todo) + " known test failures."
elif test_todo > 0:
result_msg += "All " + str(test_total) + " tests succeeded, but there are " + str(test_todo) + " known test failures."
else:
result_msg += "All " + str(test_total) + " tests succeeded."
self.log.info("\n--- results ---")
self.log.info(result_msg)
if ((test_fail > 0 or test_todo > 0) and self.log.interactive):
Gimp.message (result_msg)
self.total_tests += test_total
self.total_todo += test_todo
self.total_failed += test_fail
self.total_ok += test_ok
self.total_crash += test_crash
def show_results_total(self):
msg = "\n----- Test result totals -----"
msg += f"\nTotal {self.image_type} tests: {self.total_tests}"
if self.total_crash > 0:
msg += f"\nTests crashed: {self.total_crash}"
msg += f"\nTests failed: {self.total_failed}"
if self.total_crash > 0:
msg += f" (including crashes)"
msg += f"\nTests todo: {self.total_todo}"
self.log.message(msg)
msg = ""
for img in self.unexpected_success_images:
msg += f"{img}\n"
if len(msg) > 0:
msg = "\nImages that unexpectedly loaded:\n" + msg
self.log.message(msg)
msg = ""
for img in self.unexpected_failure_images:
msg += f"{img}\n"
if len(msg) > 0:
msg = "\nImages that unexpectedly failed to load:\n" + msg
self.log.message(msg)
class RunTests(object):
def __init__(self, test, config_path, data_path, log):
self.test_count = 0
self.regression_count = 0
if os.path.exists(test.tests):
self.plugin_test = FileLoadTest(test.plugin, test.extension, data_path, log)
cfg = configparser.ConfigParser()
cfg.read(test.tests)
for subtest in cfg.sections():
if not 'description' in cfg[subtest]:
description = "Missing description for " + test.extension
else:
description = cfg[subtest]['description']
enabled = True
if 'enabled' in cfg[subtest]:
if cfg[subtest]['enabled'] == 'False':
enabled = False
folder = cfg[subtest]['folder']
files = self.plugin_test.data_root + folder + cfg[subtest]['files']
if enabled:
self.plugin_test.run_tests(folder, files, description)
else:
log.info(f"Testing is disabled for: {description}.")
self.plugin_test.show_results_total()
self.test_count = self.plugin_test.total_tests
self.regression_count = self.plugin_test.total_failed
else:
self.plugin_test = None
log.error("Test path " + test.tests + " does not exist!")
self.regression_count = 1
def get_unexpected_success_regressions(self):
return self.plugin_test.unexpected_success_images
def get_unexpected_failure_regressions(self):
return self.plugin_test.unexpected_failure_images
def get_todo_count(self):
return self.plugin_test.total_todo
def get_crash_count(self):
return self.plugin_test.total_crash
class GimpTestRunner(object):
def __init__(self, log, test_type, test_cfg):
self.log = log
self.test_type = test_type
self.test_cfg = test_cfg
self.tests_total = 0
self.error_total = 0
self.todo_total = 0
self.crash_total = 0
self.unexpected_success_images = []
self.unexpected_failure_images = []
def print_header(self, test_type):
divider = "\n--------------------------------"
msg = f"\nGIMP file plug-in tests version {VERSION}\n"
#msg += f"\n{AUTHORS}, {YEARS}\n"
msg += f"\n--- Starting {test_type} test run ---"
msg += divider
if self.log.verbose:
msg += f"\nConfig: {self.test_cfg.config_folder + self.test_cfg.config_file}"
msg += f"\nLog: {self.test_cfg.log_file}"
msg += f"\nData path: {self.test_cfg.data_folder}"
self.log.message(msg)
def print_footer(self, msg):
msg += "\n--------------------------------"
self.log.message(msg)
def list_regressions(self):
regression_list = ""
msg = ""
extra = "\n"
for img in self.unexpected_success_images:
msg += f"\n{img}"
if len(msg) > 0:
regression_list = "\nImages that unexpectedly loaded:" + msg + extra
extra = ""
msg = ""
for img in self.unexpected_failure_images:
msg += f"\n{img}"
if len(msg) > 0:
regression_list += "\nImages that unexpectedly failed to load:" + msg + extra
return regression_list
def run_tests(self):
self.print_header(self.test_type)
# Load test config
cfg = ConfigLoader(self.log, self.test_cfg.config_folder, self.test_cfg.config_file)
# Actual tests
for test in cfg.tests:
if test.enabled:
self.log.consoleinfo(f"\nTesting {test.extension} import using {test.plugin}...\n")
plugin_tests = RunTests(test, cfg.config_path, self.test_cfg.data_folder, self.log)
self.tests_total += plugin_tests.test_count
self.error_total += plugin_tests.regression_count
if plugin_tests.plugin_test is not None:
self.todo_total += plugin_tests.get_todo_count()
self.crash_total += plugin_tests.get_crash_count()
if plugin_tests.regression_count > 0:
temp = plugin_tests.get_unexpected_success_regressions()
if len(temp) > 0:
self.unexpected_success_images.extend(temp)
temp = plugin_tests.get_unexpected_failure_regressions()
if len(temp) > 0:
self.unexpected_failure_images.extend(temp)
else:
self.crash_total += 1
self.log.consoleinfo(f"\nFinished testing {test.extension}\n")
else:
self.log.consoleinfo(f"Testing {test.extension} import using {test.plugin} is disabled.")
msg = "\n--------- Test results ---------"
if cfg.disabled > 0:
msg += f"\nNumber of test sections disabled: {cfg.disabled}"
if cfg.problems > 0:
msg += f"\nNumber of test sections skipped due to configuration errors: {cfg.problems}"
msg += f"\nTotal number of tests executed: {self.tests_total}"
msg += f"\nTotal number of regressions: {self.error_total}"
if self.crash_total > 0:
msg += f"\nTotal number of crashes: {self.crash_total}"
if self.todo_total > 0:
msg += f"\nTotal number of todo tests: {self.todo_total}"
if self.error_total > 0:
msg += "\n" + self.list_regressions()
self.print_footer(msg)
class GimpExportTestGroup(object):
def __init__(self, group_test_cfg, group_name, group_description,
input_folder, output_folder):
self.group_test_cfg = group_test_cfg
self.group_name = group_name
self.group_description = group_description
self.input_folder = input_folder
self.output_folder = output_folder
class GimpExportTestSections(object):
def __init__(self, test, config_path, data_path, log):
self.test_groups = []
self.test_count = 0
self.regression_count = 0
self.export_test_path = config_path + test.export_tests
if os.path.exists(self.export_test_path):
cfg = configparser.ConfigParser()
cfg.read(self.export_test_path)
for subtest in cfg.sections():
if not 'description' in cfg[subtest]:
description = "Missing description for " + test.extension
log.warning(f"Missing description for {test.extension}")
else:
description = cfg[subtest]['description']
log.info(f"Test: {description}")
enabled = True
if 'enabled' in cfg[subtest]:
if cfg[subtest]['enabled'] == 'False':
enabled = False
folder_input = cfg[subtest]['folder-input']
folder_output = cfg[subtest]['folder-output']
if enabled:
group = GimpExportTestGroup(test, test.extension, description,
folder_input, folder_output)
self.test_groups.append(group)
else:
log.info(f"Testing is disabled for: {description}.")
else:
log.error("Test path " + test.export_tests + " does not exist!")
self.regression_count = 1
class GimpExportTest(object):
def __init__(self, group_name, log):
self.group_name = group_name
self.log = log
self.base_path = None
self.input_path = None
self.output_path = None
self.file_import = None
self.file_export = None
def _setup(self, group_config, test_data_path):
self.base_path = test_data_path
self.input_path = self.base_path + group_config.input_folder
self.output_path = self.base_path + group_config.output_folder
if self.base_path is None or self.input_path is None or self.output_path is None:
return False
self.file_import = group_config.group_test_cfg.plugin
self.file_export = group_config.group_test_cfg.export_plugin
if self.file_import is None or self.file_export is None:
return False
return True
def setup(self, group_config):
pass
def teardown(self, group_config):
pass
def run_test(self, group_config):
pass
def execute(self, group_config, test_data_path):
if not self._setup(group_config, test_data_path):
self.log.error("Invalid config, can't execute test!")
return
self.setup(group_config)
self.run_test(group_config)
self.teardown(group_config)
class GimpExportTestRunner(GimpTestRunner):
def __init__(self, log, test_type, test_cfg):
self.cfg = None
self.log = log
self.test_type = test_type
self.test_cfg = test_cfg
self.sections = None
self.tests = []
super().__init__(log, test_type, test_cfg)
def load_test_configs(self):
self.cfg = ConfigLoader(self.log, self.test_cfg.config_folder,
self.test_cfg.config_file)
for test in self.cfg.export_tests:
if test.export_enabled:
self.sections = GimpExportTestSections(test, self.cfg.config_path,
self.test_cfg.data_folder,
self.log)
else:
pass
def get_test_group_config(self, test_name):
#FIXME maybe have this sorted and use a search...
for test in self.sections.test_groups:
if test.group_name == test_name:
return test
return None
def add_test(self, test_class):
self.log.info(f"Adding tests for {test_class.group_name}")
self.tests.append(test_class)
def run_tests(self):
self.print_header(self.test_type)
for test in self.tests:
self.log.message(f"Running tests for {test.group_name}")
test_config = self.get_test_group_config(test.group_name)
if test_config is None:
self.log.error(f"Could not find configuration for {test.group_name}!")
else:
test.execute(test_config, self.test_cfg.data_folder)
self.print_footer("Export tests finished")
def show_results(self):
#FIXME export results are not implemented yet
pass

View File

@ -0,0 +1,23 @@
if not stable or not release
# This does not get installed for releases
plugins += {
'name': 'test-file-plug-ins',
'srcs': [
# modules
'tests/test-file-plug-ins/gimplogger.py',
'tests/test-file-plug-ins/gimpconfig.py',
'tests/test-file-plug-ins/gimptestframework.py',
'tests/test-file-plug-ins/gimpexporttests.py',
# actual GIMP plug-in
'tests/test-file-plug-ins/test-file-plug-ins.py',
# scripts to start the tests in batch mode
'tests/test-file-plug-ins/batch-import-tests.py',
'tests/test-file-plug-ins/batch-export-tests.py',
],
}
# configuration data for the tests
subdir('tests')
endif

View File

@ -0,0 +1,124 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# GIMP - The GNU Image Manipulation Program
# Copyright (C) 1995 Spencer Kimball and Peter Mattis
#
# test-file-plug-ins.py
# Copyright (C) 2021-2024 Jacob Boerema
#
# 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/>.
"""Plug-in to test GIMP file import plug-ins from within GIMP."""
import sys
import gi
gi.require_version('Gimp', '3.0')
from gi.repository import Gimp
from gi.repository import GLib
from gimpconfig import GimpConfig
from gimplogger import GimpLogger
from gimptestframework import GimpTestRunner, GimpExportTestRunner, AUTHORS, YEARS, VERSION
from gimpexporttests import BmpExportTests
#DEBUGGING=True
DEBUGGING=False
#PRINT_VERBOSE = True
PRINT_VERBOSE = False
LOG_APPEND = False
test_cfg = GimpConfig()
log = GimpLogger(False, test_cfg.log_file, LOG_APPEND, PRINT_VERBOSE, DEBUGGING)
class PythonTest (Gimp.PlugIn):
## GimpPlugIn virtual methods ##
def do_set_i18n(self, _name):
# We don't support internationalization here...
return False
def do_query_procedures(self):
return [ 'test-import-plug-ins',
'test-export-plug-ins' ]
def do_create_procedure(self, name):
if name == 'test-import-plug-ins':
procedure = Gimp.ImageProcedure.new(self, name,
Gimp.PDBProcType.PLUGIN,
self.run_import_tests, None)
procedure.set_image_types("*")
procedure.set_sensitivity_mask(Gimp.ProcedureSensitivityMask.ALWAYS)
procedure.set_menu_label('Test file _import plug-ins')
procedure.add_menu_path('<Image>/Filters/Development/Python-Fu/')
procedure.set_documentation('Run file import plug-in tests',
'Run file import plug-in tests',
name)
elif name == 'test-export-plug-ins':
procedure = Gimp.ImageProcedure.new(self, name,
Gimp.PDBProcType.PLUGIN,
self.run_export_tests, None)
procedure.set_image_types("*")
procedure.set_sensitivity_mask(Gimp.ProcedureSensitivityMask.ALWAYS)
procedure.set_menu_label('Test file _export plug-ins')
procedure.add_menu_path('<Image>/Filters/Development/Python-Fu/')
procedure.set_documentation('Run file export plug-in tests',
'Run file export plug-in tests',
name)
else:
return None
procedure.set_attribution(AUTHORS, #author
AUTHORS, #copyright
YEARS) #year
return procedure
def run_import_tests(self, procedure, _run_mode, _image,
_n_drawables, _drawable, _config, _data):
log.set_interactive(True)
runner = GimpTestRunner(log, "import", test_cfg)
runner.run_tests()
return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())
def run_export_tests(self, procedure, _run_mode, _image,
_n_drawables, _drawable, _config, _data):
log.set_interactive(True)
runner = GimpExportTestRunner(log, "export", test_cfg)
if not runner:
log.error("Failed to create export test runner!")
else:
runner.load_test_configs()
bmp_tests = BmpExportTests("bmp", log)
runner.add_test(bmp_tests)
# Add additional tests here
runner.run_tests()
return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())
Gimp.main(PythonTest.__gtype__, sys.argv)

View File

@ -0,0 +1,145 @@
[main]
verbose=0
[bmp]
enabled=True
enabled-export=False
plugin-import=file-bmp-load
plugin-export=file-bmp-export
extension=bmp
tests=bmp-tests.ini
tests-export=bmp-export-tests.ini
[dcx]
enabled=True
plugin-import=file-dcx-load
extension=dcx
tests=dcx-tests.ini
[dds]
enabled=True
plugin-import=file-dds-load
extension=dds
tests=dds-tests.ini
[eps]
enabled=True
plugin-import=file-eps-load
extension=eps
tests=eps-tests.ini
[fits]
enabled=True
plugin-import=file-fits-load
extension=fits
tests=fits-tests.ini
[fli]
enabled=True
plugin-import=file-fli-load
extension=fli
tests=fli-tests.ini
[gif]
enabled=True
plugin-import=file-gif-load
extension=gif
tests=gif-tests.ini
[icns]
enabled=True
plugin-import=file-icns-load
extension=icns
tests=icns-tests.ini
[ico]
enabled=True
plugin-import=file-ico-load
extension=ico
tests=ico-tests.ini
[j2k]
enabled=True
plugin-import=file-j2k-load
extension=j2k
tests=j2k-tests.ini
[jp2]
enabled=True
plugin-import=file-jp2-load
extension=jp2
tests=jp2-tests.ini
[jpeg]
enabled=True
plugin-import=file-jpeg-load
extension=jpg
tests=jpeg-tests.ini
[pcx]
enabled=True
plugin-import=file-pcx-load
extension=pcx
tests=pcx-tests.ini
[png]
enabled=True
plugin-import=file-png-load
extension=png
tests=png-tests.ini
[pnm]
enabled=True
plugin-import=file-pnm-load
extension=pnm
tests=pnm-tests.ini
[psb]
enabled=True
plugin-import=file-psd-load
extension=psb
tests=psb-tests.ini
[psd]
enabled=True
plugin-import=file-psd-load
extension=psd
tests=psd-tests.ini
[psd-merged-image]
# This uses the same tests configuration and files as above, but uses a different loader
enabled=True
plugin-import=file-psd-load-merged
extension=psd
tests=psd-tests.ini
[psp]
enabled=True
plugin-import=file-psp-load
extension=psd
tests=psp-tests.ini
[sgi]
enabled=True
plugin-import=file-sgi-load
# Other extensions used: bw, rgb, rgba
extension=sgi
tests=sgi-tests.ini
[tga]
enabled=True
plugin-import=file-tga-load
extension=tga
tests=tga-tests.ini
[tif]
enabled=True
plugin-import=file-tiff-load
extension=tif
tests=tif-tests.ini
[webp]
enabled=True
plugin-import=file-webp-load
extension=webp
tests=webp-tests.ini

View File

@ -0,0 +1,5 @@
[test-1]
enabled=True
description=Test exporting bmp images
folder-input=bmp/export/input/
folder-output=bmp/export/

View File

@ -0,0 +1,27 @@
[test-1]
enabled=True
description=Test loading bmpsuite good images
folder=bmp/bmpsuite/g/
files=bmpsuite-g-tests.files
source=https://github.com/jsummers/bmpsuite
[test-2]
enabled=True
description=Test loading bmpsuite questionable images
folder=bmp/bmpsuite/q/
files=bmpsuite-q-tests.files
source=https://github.com/jsummers/bmpsuite
[test-3]
enabled=True
description=Test loading bmpsuite bad images
folder=bmp/bmpsuite/b/
files=bmpsuite-b-tests.files
source=https://github.com/jsummers/bmpsuite
[test-4]
enabled=True
description=Test loading bmpsuite x (bmp related) images
folder=bmp/bmpsuite/x/
files=bmpsuite-x-tests.files
source=https://github.com/jsummers/bmpsuite

View File

@ -0,0 +1,7 @@
[main]
verbose=0
# Add tests here that you want to be executed when starting the plug-in
# from within GIMP. See batch-config.ini for examples.
# You will also need to make the test images available somewhere, see
# the readme or .gitlab-ci.yml for more details.

View File

@ -0,0 +1,6 @@
[test-1]
enabled=True
description=Test loading dcx images from Sembiance (telparia)
folder=dcx/sembiance/
files=dcx-tests-1.files
source=https://sembiance.com/fileFormatSamples/image/dcx/

View File

@ -0,0 +1,13 @@
[test-1]
enabled=True
description=Test loading dds images
folder=zaail-testimages/DDS/
files=dds-zaail-tests.files
source=https://github.com/ZaaLabs/ZaaIL-TestImages
[test-2]
enabled=True
description=Test loading dds images from GIMP issues
folder=dds/gimp-issues/
files=dds-tests-2.files
source=several GIMP GitLab issues

View File

@ -0,0 +1,13 @@
[test-1]
enabled=True
description=Test loading eps images from Pillow TestSuite
folder=pillow/
files=eps-pillow-tests.files
source=https://github.com/python-pillow/Pillow/tree/master/Tests/images
[test-2]
enabled=True
description=Test loading fits images from graphicex
folder=graphicex/EPS/
files=eps-graphicex-tests.files
source=https://github.com/mike-lischke/GraphicEx/tree/master/TestSuite%20original

View File

@ -0,0 +1,13 @@
[test-1]
enabled=True
description=Test loading fits images from Pillow TestSuite
folder=pillow/
files=fits-pillow-tests.files
source=https://github.com/python-pillow/Pillow/tree/master/Tests/images
[test-2]
enabled=True
description=Test loading fits images from GIMP issues
folder=fits/gimp-issues/
files=fits-tests-2.files
source=several GIMP GitLab issues

View File

@ -0,0 +1,6 @@
[test-1]
enabled=True
description=Test loading fli images from Pillow TestSuite
folder=pillow/
files=fli-pillow-tests.files
source=https://github.com/python-pillow/Pillow/tree/master/Tests/images

View File

@ -0,0 +1,16 @@
[test-1]
enabled=True
description=Test loading gif imagetestsuite images
folder=gif/imagetestsuite/
files=gif-imagetestsuite-tests.files
# Warning some images in this repo may trigger AntiVirus programs
source=https://github.com/Wormnest/imagetestsuite/
# Original:
source2=http://code.google.com/p/imagetestsuite/
[test-2]
enabled=True
description=Test loading gif test images from pillow
folder=pillow/
files=gif-pillow-tests.files
source=https://github.com/python-pillow/Pillow/tree/master/Tests/images

View File

@ -0,0 +1,6 @@
[test-1]
enabled=True
description=Test loading icns images from Pillow TestSuite
folder=pillow/
files=icns-pillow-tests.files
source=https://github.com/python-pillow/Pillow/tree/master/Tests/images

View File

@ -0,0 +1,6 @@
[test-1]
enabled=True
description=Test loading ico images from Pillow TestSuite
folder=pillow/
files=ico-pillow-tests.files
source=https://github.com/python-pillow/Pillow/tree/master/Tests/images

View File

@ -0,0 +1,6 @@
[test-1]
enabled=True
description=Test loading j2k images from Pillow TestSuite
folder=pillow/
files=j2k-pillow-tests.files
source=https://github.com/python-pillow/Pillow/tree/master/Tests/images

View File

@ -0,0 +1,6 @@
[test-1]
enabled=True
description=Test loading jp2 images from Pillow TestSuite
folder=pillow/
files=jp2-pillow-tests.files
source=https://github.com/python-pillow/Pillow/tree/master/Tests/images

View File

@ -0,0 +1,9 @@
[test-1]
enabled=True
description=Test loading jpeg imagetestsuite images
folder=jpg/imagetestsuite/
files=jpeg-imagetestsuite-tests.files
# Warning some images in this repo may trigger AntiVirus programs
source=https://github.com/Wormnest/imagetestsuite/
# Original:
source2=http://code.google.com/p/imagetestsuite/

View File

@ -0,0 +1,34 @@
# Add test configuration data...
install_data([
# main config files
'config.ini', # not yet updated!
'batch-config.ini',
# file format specific config files for import testing
'bmp-tests.ini',
'dcx-tests.ini',
'dds-tests.ini',
'eps-tests.ini',
'fits-tests.ini',
'fli-tests.ini',
'gif-tests.ini',
'icns-tests.ini',
'ico-tests.ini',
'j2k-tests.ini',
'jp2-tests.ini',
'jpeg-tests.ini',
'pcx-tests.ini',
'png-tests.ini',
'pnm-tests.ini',
'psb-tests.ini',
'psd-tests.ini',
'psp-tests.ini',
'sgi-tests.ini',
'tga-tests.ini',
'tif-tests.ini',
'webp-tests.ini',
# file format specific config files for export testing
'bmp-export-tests.ini',
],
install_dir: gimpplugindir / 'plug-ins' / 'test-file-plug-ins' / 'tests',
)

View File

@ -0,0 +1,13 @@
[test-1]
enabled=True
description=Test loading pcx images from Pillow TestSuite
folder=pillow/
files=pcx-pillow-tests.files
source=https://github.com/python-pillow/Pillow/tree/master/Tests/images
[test-2]
enabled=True
description=Test loading pcx images from ZaaIL
folder=zaail-testimages/PCX/
files=pcx-zaail-tests.files
source=https://github.com/ZaaLabs/ZaaIL-TestImages/PCX/

View File

@ -0,0 +1,32 @@
[test-1]
enabled=True
description=Test loading png suite images
folder=png/pngsuite/
files=png-suite-tests.files
source=http://www.schaik.com/pngsuite/pngsuite.html
#Also listing the below since there are some differences
source2=http://www.schaik.com/pngsuite2011/pngsuite.html
[test-2]
enabled=True
description=Test loading corrupt png suite images
folder=png/pngsuite/
files=png-suite-tests-corrupt.files
source=http://www.schaik.com/pngsuite/pngsuite_xxx_png.html
[test-3]
enabled=True
description=Test loading png brokensuite images
folder=png/brokensuite/
files=png-brokensuite-tests.files
source=https://code.google.com/archive/p/javapng/downloads
[test-4]
enabled=True
description=Test loading png imagetestsuite images
folder=png/imagetestsuite/
files=png-imagetestsuite-tests.files
# Warning some images in this repo may trigger AntiVirus programs
source=https://github.com/Wormnest/imagetestsuite/
# Original:
source2=http://code.google.com/p/imagetestsuite/

View File

@ -0,0 +1,20 @@
[test-1]
enabled=True
description=Test loading pnm (pbm, pgm, ppm, pnm) images
folder=zaail-testimages/PNM/
files=pnm-zaail-tests.files
source=https://github.com/ZaaLabs/ZaaIL-TestImages
[test-2]
enabled=True
description=Test loading pfm images
folder=pnm/oiio-pfm/
files=pnm-oiio-tests.files
source=https://github.com/AcademySoftwareFoundation/OpenImageIO-images/tree/master/pnm
[test-3]
enabled=True
description=Test loading pam images
folder=pnm/sembiance-pam/
files=pnm-sembiance-tests.files
source=https://sembiance.com/fileFormatSamples/image/pam/

View File

@ -0,0 +1,7 @@
[test-1]
enabled=True
description=Test loading psb images
folder=psd/psd-tools/
files=psb-tests.files
source=https://github.com/psd-tools/psd-tools

View File

@ -0,0 +1,20 @@
[test-1]
enabled=True
description=Test loading psd images
folder=psd/psd-tools/
files=psd-tests.files
source=https://github.com/psd-tools/psd-tools
[test-2]
enabled=True
description=Test loading psd colormode images
folder=psd/psd-tools/colormodes/
files=psd-colormodes-tests.files
source=https://github.com/psd-tools/psd-tools/tree/master/tests/psd_files/colormodes
[test-3]
enabled=True
description=Test loading psdparse sample images
folder=psd/psdparse/
files=psdparse-tests.files
source=http://www.telegraphics.com.au/svn/psdparse/trunk/psd/

View File

@ -0,0 +1,13 @@
[test-1]
enabled=True
description=Test loading psp images from GraphicEx TestSuite
folder=graphicex/PSP/
files=psp-graphicex-tests.files
source=https://github.com/mike-lischke/GraphicEx/tree/master/TestSuite%20original
[test-2]
enabled=True
description=Test loading psp images from GIMP issues
folder=psp/gimp-issues/
files=psp-tests-2.files
source=several GIMP GitLab issues

View File

@ -0,0 +1,20 @@
[test-1]
enabled=True
description=Test loading sgi images from GraphicEx TestSuite
folder=graphicex/SGI/
files=sgi-graphicex-tests.files
source=https://github.com/mike-lischke/GraphicEx/tree/master/TestSuite%20original
[test-2]
enabled=True
description=Test loading sgi images from ZaaIL
folder=zaail-testimages/SGI/
files=sgi-zaail-tests.files
source=https://github.com/ZaaLabs/ZaaIL-TestImages/SGI/
[test-3]
enabled=True
description=Test loading sgi images from Pillow TestSuite
folder=pillow/
files=sgi-pillow-tests.files
source=https://github.com/python-pillow/Pillow/tree/master/Tests/images

View File

@ -0,0 +1,13 @@
[test-1]
enabled=True
description=Test loading tga images
folder=zaail-testimages/TGA/
files=tga-zaail-tests.files
source=https://github.com/ZaaLabs/ZaaIL-TestImages
[test-2]
enabled=True
description=Test loading tga test images from pillow
folder=pillow/
files=tga-pillow-tests.files
source=https://github.com/python-pillow/Pillow/tree/master/Tests/images

View File

@ -0,0 +1,31 @@
[test-1]
enabled=True
description=Test loading tif test images from cpan: Imager-File-TIFF
folder=tiff/cpan-imager-file-tiff/
files=tif-cpan-tests.files
source=https://metacpan.org/source/TONYC/Imager-File-TIFF-0.92/testimg
[test-2]
enabled=True
description=Test loading tif imagetestsuite images, part 1
folder=tiff/imagetestsuite/
files=tif-imagetestsuite-tests.files
# Warning some images in this repo may trigger AntiVirus programs
source=https://github.com/Wormnest/imagetestsuite/tif/
# Original:
source2=http://code.google.com/p/imagetestsuite/
[test-3]
enabled=True
description=Test loading tif imagetestsuite images, part 2
folder=tiff/imagetestsuite/
files=tif-imagetestsuite-tests-2.files
source=https://github.com/Wormnest/imagetestsuite/tif/
[test-4]
enabled=True
description=Test loading tif imagetestsuite images, part 3
folder=tiff/imagetestsuite/
files=tif-imagetestsuite-tests-3.files
# Some are processed real slow, needs to be investigated
source=https://github.com/Wormnest/imagetestsuite/tif/

View File

@ -0,0 +1,7 @@
[test-1]
enabled=True
description=Test loading webp images from Pillow TestSuite
folder=pillow/
files=webp-pillow-tests.files
source=https://github.com/python-pillow/Pillow/tree/master/Tests/images

View File

@ -49,6 +49,7 @@ plug-ins/maze
plug-ins/metadata
plug-ins/pagecurl
plug-ins/print
plug-ins/python/tests
plug-ins/screenshot
plug-ins/script-fu
plug-ins/selection-to-path