diff --git a/configure.ac b/configure.ac index 5bdc626a87..5a5155f9e0 100644 --- a/configure.ac +++ b/configure.ac @@ -690,6 +690,7 @@ tests/Makefile tests/lib/Makefile tests/lib/mcconfig/Makefile tests/lib/search/Makefile +tests/lib/skin/Makefile tests/lib/strutil/Makefile tests/lib/vfs/Makefile tests/lib/vfs/mc.charsets diff --git a/lib/skin/common.c b/lib/skin/common.c index 48656b0870..69b8be3bd2 100644 --- a/lib/skin/common.c +++ b/lib/skin/common.c @@ -45,8 +45,6 @@ mc_skin_t mc_skin__default; /*** file scope variables ************************************************************************/ -static gboolean mc_skin_is_init = FALSE; - /* --------------------------------------------------------------------------------------------- */ /*** file scope functions ************************************************************************/ /* --------------------------------------------------------------------------------------------- */ @@ -149,10 +147,11 @@ mc_skin_init (const gchar *skin_override, GError **mcerror) } if (is_good_init && mc_skin__default.have_true_colors && !tty_use_truecolors (&error)) { - mc_propagate_error (mcerror, 0, - _ ("Unable to use '%s' skin with true colors support:\n%s\nDefault " - "skin has been loaded"), - mc_skin__default.name, error->message); + if (!mc_global.tty.disable_colors || skin_override != NULL) + mc_propagate_error (mcerror, 0, + _ ("Unable to use '%s' skin with true colors support:\n%s\n" + "Default skin has been loaded"), + mc_skin__default.name, error->message); g_error_free (error); mc_skin_try_to_load_default (); (void) mc_skin_ini_file_parse (&mc_skin__default); @@ -160,16 +159,16 @@ mc_skin_init (const gchar *skin_override, GError **mcerror) } if (is_good_init && mc_skin__default.have_256_colors && !tty_use_256colors (&error)) { - mc_propagate_error (mcerror, 0, - _ ("Unable to use '%s' skin with 256 colors support:\n%s\nDefault " - "skin has been loaded"), - mc_skin__default.name, error->message); + if (!mc_global.tty.disable_colors || skin_override != NULL) + mc_propagate_error (mcerror, 0, + _ ("Unable to use '%s' skin with 256 colors support:\n%s\n" + "Default skin has been loaded"), + mc_skin__default.name, error->message); g_error_free (error); mc_skin_try_to_load_default (); (void) mc_skin_ini_file_parse (&mc_skin__default); is_good_init = FALSE; } - mc_skin_is_init = TRUE; return is_good_init; } @@ -188,8 +187,6 @@ mc_skin_deinit (void) mc_config_deinit (mc_skin__default.config); mc_skin__default.config = NULL; - - mc_skin_is_init = FALSE; } /* --------------------------------------------------------------------------------------------- */ diff --git a/lib/tty/color.c b/lib/tty/color.c index 861f890486..34e2cd9e3f 100644 --- a/lib/tty/color.c +++ b/lib/tty/color.c @@ -62,7 +62,11 @@ gboolean need_convert_256color = FALSE; /*** file scope variables ************************************************************************/ -static GHashTable *mc_tty_color__hashtable = NULL; +#ifdef HAVE_TESTS +extern GHashTable *mc_tty_color__hashtable; +#endif + +MC_TESTABLE GHashTable *mc_tty_color__hashtable = NULL; /* --------------------------------------------------------------------------------------------- */ /*** file scope functions ************************************************************************/ diff --git a/lib/tty/color.h b/lib/tty/color.h index 0c4114d2db..b9e682fd5a 100644 --- a/lib/tty/color.h +++ b/lib/tty/color.h @@ -69,8 +69,8 @@ void tty_color_free_all (void); void tty_setcolor (int color); void tty_set_normal_attrs (void); -extern gboolean tty_use_256colors (GError **error); -extern gboolean tty_use_truecolors (GError **error); +MC_MOCKABLE gboolean tty_use_256colors (GError **error); +MC_MOCKABLE gboolean tty_use_truecolors (GError **error); /*** inline functions ****************************************************************************/ diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index 0793f3862a..0211c39398 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -1,6 +1,6 @@ PACKAGE_STRING = "/lib" -SUBDIRS = . mcconfig search strutil vfs widget +SUBDIRS = . mcconfig search strutil vfs widget skin AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) @CHECK_CFLAGS@ diff --git a/tests/lib/skin/Makefile.am b/tests/lib/skin/Makefile.am new file mode 100644 index 0000000000..af86831d0f --- /dev/null +++ b/tests/lib/skin/Makefile.am @@ -0,0 +1,29 @@ +PACKAGE_STRING = "/lib/skin" + +AM_CPPFLAGS = \ + -DTEST_SHARE_DIR=\"$(abs_srcdir)/fixtures\" \ + $(GLIB_CFLAGS) \ + -I$(top_srcdir) \ + @CHECK_CFLAGS@ + +LIBS = @CHECK_LIBS@ \ + $(top_builddir)/src/libinternal.la \ + $(top_builddir)/lib/libmc.la + +if ENABLE_MCLIB +LIBS += $(GLIB_LIBS) \ + @E2P_LIBS@ +endif + +EXTRA_DIST = \ + fixtures/skins/dark.ini \ + fixtures/skins/julia256.ini \ + fixtures/skins/seasons-summer16M.ini + +TESTS = \ + common__mc_skin_init + +check_PROGRAMS = $(TESTS) + +common__mc_skin_init_SOURCES = \ + common__mc_skin_init.c diff --git a/tests/lib/skin/common__mc_skin_init.c b/tests/lib/skin/common__mc_skin_init.c new file mode 100644 index 0000000000..366f54695b --- /dev/null +++ b/tests/lib/skin/common__mc_skin_init.c @@ -0,0 +1,177 @@ +/* + lib/skin - mc_skin_init() function testing + + Copyright (C) 2026 + Free Software Foundation, Inc. + + Written by: + Manuel Einfalt , 2026 + + This file is part of the Midnight Commander. + + The Midnight Commander 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. + + The Midnight Commander 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 . + */ + +#define TEST_SUITE_NAME "/lib/skin" + +#include "tests/mctest.h" + +#include "lib/util.h" +#include "lib/skin.h" + +#include "lib/strutil.h" // str_init_strings +#include "src/vfs/local/local.h" // vfs_init_localfs + +/* --------------------------------------------------------------------------------------------- */ + +static const struct skin_tests // xterm, xterm-256color, xterm-direct +{ + const char *term; + const gboolean nocolor; + const gchar *skin_name; + const gboolean has_error; + const gboolean ret; +} skin_tests[] = { + { "xterm", FALSE, "dark", FALSE, TRUE }, + { "xterm", FALSE, "julia256", TRUE, FALSE }, + { "xterm", FALSE, "seasons-summer16M", TRUE, FALSE }, + { "xterm", TRUE, "dark", FALSE, TRUE }, + { "xterm", TRUE, "julia256", TRUE, FALSE }, + { "xterm", TRUE, "seasons-summer16M", TRUE, FALSE }, + + { "xterm-256color", FALSE, "dark", FALSE, TRUE }, + { "xterm-256color", FALSE, "julia256", FALSE, TRUE }, + { "xterm-256color", FALSE, "seasons-summer16M", TRUE, FALSE }, + { "xterm-256color", TRUE, "dark", FALSE, TRUE }, + { "xterm-256color", TRUE, "julia256", FALSE, TRUE }, + { "xterm-256color", TRUE, "seasons-summer16M", TRUE, FALSE }, + + { "xterm-256direct", FALSE, "dark", FALSE, TRUE }, + { "xterm-256direct", FALSE, "julia256", FALSE, TRUE }, + { "xterm-256direct", FALSE, "seasons-summer16M", FALSE, TRUE }, + { "xterm-256direct", TRUE, "dark", FALSE, TRUE }, + { "xterm-256direct", TRUE, "julia256", FALSE, TRUE }, + { "xterm-256direct", TRUE, "seasons-summer16M", FALSE, TRUE }, +}; + +extern GHashTable *mc_tty_color__hashtable; + +/* --------------------------------------------------------------------------------------------- */ + +static void +setup (void) +{ + mc_global.share_data_dir = (char *) TEST_SHARE_DIR; + mc_global.sysconfig_dir = (char *) TEST_SHARE_DIR; + + str_init_strings (NULL); + vfs_init (); + vfs_init_localfs (); + tty_color_role_to_pair = g_new (int, COLOR_MAP_SIZE); + mc_tty_color__hashtable = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); +} + +static void +teardown (void) +{ + vfs_shut (); + str_uninit_strings (); +} + +/* --------------------------------------------------------------------------------------------- */ + +// Mock +gboolean +tty_use_truecolors (GError **error) +{ + const char *termname = getenv ("TERM"); + + if (termname == NULL) + { + mc_propagate_error (error, 0, _ ("foobar")); + return FALSE; + } + + if (strcmp (termname, "xterm-256direct") == 0) + return TRUE; + + mc_propagate_error (error, 0, _ ("foobar")); + return FALSE; +} + +// Mock +gboolean +tty_use_256colors (GError **error) +{ + const char *termname = getenv ("TERM"); + + if (termname == NULL) + { + mc_propagate_error (error, 0, _ ("foobar")); + return FALSE; + } + + if (strcmp (termname, "xterm-256color") == 0 || tty_use_truecolors (NULL)) + return TRUE; + + mc_propagate_error (error, 0, _ ("foobar")); + return FALSE; +} + +/* --------------------------------------------------------------------------------------------- */ + +START_PARAMETRIZED_TEST (skin_test, skin_tests) +{ + GError *mcerror = NULL; + + mc_global.tty.disable_colors = data->nocolor; + setenv ("TERM", data->term, 1); + + if (data->ret) + { + mctest_assert_true (mc_skin_init (data->skin_name, &mcerror)); + } + else + { + mctest_assert_false (mc_skin_init (data->skin_name, &mcerror)); + } + + if (data->has_error) + { + mctest_assert_not_null (mcerror); + g_error_free (mcerror); + } + else + mctest_assert_null (mcerror); +} +END_PARAMETRIZED_TEST + +/* --------------------------------------------------------------------------------------------- */ + +int +main (void) +{ + TCase *tc_core; + + tc_core = tcase_create ("Core"); + tcase_add_checked_fixture (tc_core, setup, teardown); + + // Add new tests here: *************** + mctest_add_parameterized_test (tc_core, skin_test, skin_tests); + // *********************************** + + return mctest_run_all (tc_core); +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/tests/lib/skin/fixtures/skins/dark.ini b/tests/lib/skin/fixtures/skins/dark.ini new file mode 100644 index 0000000000..563efa81e4 --- /dev/null +++ b/tests/lib/skin/fixtures/skins/dark.ini @@ -0,0 +1,2 @@ +[skin] + description = Dark skin diff --git a/tests/lib/skin/fixtures/skins/julia256.ini b/tests/lib/skin/fixtures/skins/julia256.ini new file mode 100644 index 0000000000..b8b08b00f7 --- /dev/null +++ b/tests/lib/skin/fixtures/skins/julia256.ini @@ -0,0 +1,3 @@ +[skin] + description = Dark skin with calm colors and good contrast + 256colors = true diff --git a/tests/lib/skin/fixtures/skins/seasons-summer16M.ini b/tests/lib/skin/fixtures/skins/seasons-summer16M.ini new file mode 100644 index 0000000000..d3ad52a160 --- /dev/null +++ b/tests/lib/skin/fixtures/skins/seasons-summer16M.ini @@ -0,0 +1,3 @@ +[skin] + description = Four Seasons – Summer + truecolors = true