/*
 *  $Id: error-list.c 29697 2026-03-31 16:21:05Z yeti-dn $
 *  Copyright (C) 2009-2026 David Nečas (Yeti).
 *  E-mail: yeti@gwyddion.net.
 *
 *  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 2 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, write to the
 *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "tests/testlibgwy.h"

static gint
compare_errors(gconstpointer pa, gconstpointer pb)
{
    GError *a = (GError*)pa, *b = (GError*)pb;
    if (a->domain < b->domain)
        return -1;
    if (a->domain > b->domain)
        return 1;
    if (a->code < b->code)
        return -1;
    if (a->code > b->code)
        return 1;
    return strcmp(a->message, b->message);
}

void
assert_error_list(GwyErrorList *error_list,
                  GwyErrorList *expected_errors,
                  gboolean unsorted)
{
    if (g_slist_length(error_list) != g_slist_length(expected_errors)) {
        fprintf(stderr, "Actual errors\n");
        dump_error_list(error_list);
        fprintf(stderr, "Expected errors\n");
        dump_error_list(expected_errors);
        g_assert_cmpuint(g_slist_length(error_list), ==, g_slist_length(expected_errors));
    }
    guint n = g_slist_length(expected_errors);
    if (!n)
        return;

    if (unsorted) {
        error_list = g_slist_sort(error_list, compare_errors);
        expected_errors = g_slist_sort(expected_errors, compare_errors);
    }
    for (guint i = 0; i < n; i++) {
        GError *expected_error = g_slist_nth_data(expected_errors, i);
        GError *error = g_slist_nth_data(error_list, i);
        g_assert_error(error, expected_error->domain, expected_error->code);
        g_assert_cmpstr(error->message, ==, expected_error->message);
    }
}

void
test_error_list_basic(void)
{
    GwyErrorList *errlist = NULL;
    GError *err;

    /* A simple error. */
    gwy_error_list_add(&errlist, GWY_EXPR_ERROR, GWY_EXPR_ERROR_GARBAGE, "Just testing...");
    g_assert_cmpuint(g_slist_length(errlist), ==, 1);

    /* Several errors. */
    gwy_error_list_add(&errlist, GWY_EXPR_ERROR, GWY_EXPR_ERROR_GARBAGE, "Just testing %d...", 2);
    g_assert_cmpuint(g_slist_length(errlist), ==, 2);
    /* The latter must be on top. */
    err = errlist->data;
    g_assert_cmpuint(err->domain, ==, GWY_EXPR_ERROR);
    g_assert_cmpuint(err->code, ==, GWY_EXPR_ERROR_GARBAGE);
    g_assert_cmpstr(err->message, ==, "Just testing 2...");

    /* Destruction. */
    gwy_error_list_clear(&errlist);
    g_assert_cmpuint(g_slist_length(errlist), ==, 0);
}

void
test_error_list_propagation(void)
{
    GwyErrorList *errlist = NULL;
    GError *err;

    /* Propagation */
    gwy_error_list_propagate(&errlist, NULL);
    g_assert_cmpuint(g_slist_length(errlist), ==, 0);
    err = g_error_new(GWY_EXPR_ERROR, GWY_EXPR_ERROR_GARBAGE, "Just testing 3...");
    gwy_error_list_propagate(&errlist, err);
    g_assert_cmpuint(g_slist_length(errlist), ==, 1);
    gwy_error_list_clear(&errlist);

    /* Ignoring errors. */
    gwy_error_list_add(NULL, GWY_EXPR_ERROR, GWY_EXPR_ERROR_GARBAGE, "Ignored error");
    err = g_error_new(GWY_EXPR_ERROR, GWY_EXPR_ERROR_GARBAGE, "Ignored error");
    gwy_error_list_propagate(NULL, err);
    gwy_error_list_clear(NULL);
}

void
dump_error_list(GwyErrorList *error_list)
{
    guint i = 0;
    for (GSList *l = error_list; l; l = g_slist_next(l), i++) {
        fprintf(stderr, "error%u: %s\n", i, ((GError*)l->data)->message);
    }
}

/* vim: set cin columns=120 tw=118 et ts=4 sw=4 cino=>1s,e0,n0,f0,{0,}0,^0,\:1s,=0,g1s,h0,t0,+1s,c3,(0,u0 : */
