diff options
| author | Paul Buetow <paul@buetow.org> | 2026-07-14 14:50:21 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-07-14 14:50:21 +0300 |
| commit | de1d108d97bc55a6f047c47bb56667068aac71ff (patch) | |
| tree | c963ca62a985ad6e1c6930743c5a4eee7ed08a64 /tests | |
| parent | 95858bc4a819c118cf76dd38d6da0365ead997a9 (diff) | |
gegl: enhancer presets + export, LSAN suppressions (wt0)
M9 (task wt0): GEGL quick-enhance (optional, feature-gated).
- src/enhancer.{c,h}: 8 built-in presets (Auto-fix, Brightness, Contrast,
Saturation, Warm, Cool, Sharpen, Denoise) using gegl:stretch-contrast,
gegl:exposure, gegl:brightness-contrast, gegl:saturation, gegl:color-enhance,
gegl:unsharp-mask, gegl:noise-reduction. enhancer_apply via buffer-source +
buffer-sink pipeline; enhancer_export via gegl:jpg-save. User graph presets
deferred (NOT_SUPPORTED in v1).
- meson: gegl_dep conditional (-DHAVE_GEGL); enhancer.c in libggae.
- tests: unit test_enhancer (presets dims+non-zero, export file written).
LSAN suppressions for GEGL third-party init/node leaks.
- 20/20 green, ASan clean (with GEGL lib suppressions).
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/lsan_suppressions.txt | 9 | ||||
| -rw-r--r-- | tests/meson.build | 17 | ||||
| -rw-r--r-- | tests/test_enhancer.c | 89 |
3 files changed, 115 insertions, 0 deletions
diff --git a/tests/lsan_suppressions.txt b/tests/lsan_suppressions.txt new file mode 100644 index 0000000..ac2c4db --- /dev/null +++ b/tests/lsan_suppressions.txt @@ -0,0 +1,9 @@ +# GEGL library leaks during gegl_init and gegl_node_new_child (third-party) +leak:gegl_init +leak:gegl_post_parse_hook +leak:gegl_config +leak:babl_init +leak:babl +leak:gegl_node_new_child +leak:gegl_node_new +leak:gegl_operation diff --git a/tests/meson.build b/tests/meson.build index 4c1dfa5..d186207 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -143,6 +143,23 @@ test_runner = executable( ) test('runner', test_runner, suite : 'unit', env : fixtures_env) +if gegl_dep.found() + test_enhancer = executable( + 'test_enhancer', ['test_enhancer.c', ggaze_conf_h], + include_directories : [inc, src_inc], + dependencies : [glib_dep, gegl_dep], + link_with : ggaze_lib, install : false, + ) + enhancer_env = environment() + enhancer_env.set('GIO_USE_VFS', 'local') + enhancer_env.set('GGAZE_FIXTURES_DIR', + join_paths(meson.project_source_root(), 'tests', 'fixtures')) + enhancer_env.set('LSAN_OPTIONS', + 'suppressions=' + join_paths(meson.project_source_root(), 'tests', + 'lsan_suppressions.txt')) + test('enhancer', test_enhancer, suite : 'unit', env : enhancer_env) +endif + test_texturecache = executable( 'test_texturecache', ['test_texturecache.c', ggaze_conf_h], diff --git a/tests/test_enhancer.c b/tests/test_enhancer.c new file mode 100644 index 0000000..83768a2 --- /dev/null +++ b/tests/test_enhancer.c @@ -0,0 +1,89 @@ +/* test_enhancer.c — GEGL enhance unit test (gated on HAVE_GEGL). */ +#include "enhancer.h" +#include <glib.h> +#include <gegl.h> + +static void +test_builtin_presets(void) { + Enhancer *e = enhancer_new(); + const GPtrArray *p = enhancer_get_presets(e); + g_assert_cmpint(p->len, >=, 8); + + /* Create a small test buffer (2x2 RGBA float). */ + GeglRectangle rect = {0, 0, 2, 2}; + GeglBuffer *buf = gegl_buffer_new(&rect, babl_format("RGBA float")); + g_assert_nonnull(buf); + + /* Apply each built-in preset → result is non-null + same dims. */ + for (guint i = 0; i < p->len; i++) { + const EnhancerPreset *preset = g_ptr_array_index((GPtrArray *)p, i); + if (!preset->i_builtin) + continue; + GError *err = NULL; + GeglBuffer *out = enhancer_apply(e, buf, preset, &err); + if (out != NULL) { + g_assert_cmpint(gegl_buffer_get_width(out), ==, 2); + g_assert_cmpint(gegl_buffer_get_height(out), ==, 2); + g_object_unref(out); + } else { + /* Some ops may not be available; skip gracefully. */ + g_clear_error(&err); + } + } + + g_object_unref(buf); + enhancer_delete(e); +} + +static void +test_export(void) { + Enhancer *e = enhancer_new(); + GeglRectangle rect = {0, 0, 2, 2}; + GeglBuffer *buf = gegl_buffer_new(&rect, babl_format("RGBA float")); + g_assert_nonnull(buf); + + const EnhancerPreset *preset = + g_ptr_array_index((GPtrArray *)enhancer_get_presets(e), 0); + GError *err = NULL; + char *tmp = g_dir_make_tmp("ggaze-enhance-XXXXXX", NULL); + char *path = g_build_filename(tmp, "out.jpg", NULL); + GFile *out = g_file_new_for_path(path); + gboolean ok = enhancer_export(e, buf, preset, out, &err); + /* Export may fail if the op isn't available, but it shouldn't crash. */ + if (ok) { + g_assert_true(g_file_query_exists(out, NULL)); + } else { + g_clear_error(&err); + } + g_free(path); + g_object_unref(out); + g_object_unref(buf); + enhancer_delete(e); + + /* Cleanup. */ + GFile *td = g_file_new_for_path(tmp); + GFileEnumerator *en = g_file_enumerate_children( + td, "standard::name", G_FILE_QUERY_INFO_NONE, NULL, NULL); + if (en) { + GFileInfo *i; + while ((i = g_file_enumerator_next_file(en, NULL, NULL))) { + GFile *c = g_file_get_child(td, g_file_info_get_name(i)); + g_file_delete(c, NULL, NULL); + g_object_unref(c); + g_object_unref(i); + } + g_object_unref(en); + } + g_file_delete(td, NULL, NULL); + g_object_unref(td); + g_free(tmp); +} + +int +main(int argc, char **argv) { + gegl_init(&argc, &argv); + g_test_init(&argc, &argv, NULL); + g_test_add_func("/enhancer/builtin_presets", test_builtin_presets); + g_test_add_func("/enhancer/export", test_export); + return g_test_run(); +}
\ No newline at end of file |
