11c235774Smrg/* 21c235774Smrg * Copyright (c) 2023, Oracle and/or its affiliates. 31c235774Smrg * 41c235774Smrg * Permission is hereby granted, free of charge, to any person obtaining a 51c235774Smrg * copy of this software and associated documentation files (the "Software"), 61c235774Smrg * to deal in the Software without restriction, including without limitation 71c235774Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 81c235774Smrg * and/or sell copies of the Software, and to permit persons to whom the 91c235774Smrg * Software is furnished to do so, subject to the following conditions: 101c235774Smrg * 111c235774Smrg * The above copyright notice and this permission notice (including the next 121c235774Smrg * paragraph) shall be included in all copies or substantial portions of the 131c235774Smrg * Software. 141c235774Smrg * 151c235774Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 161c235774Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 171c235774Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 181c235774Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 191c235774Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 201c235774Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 211c235774Smrg * DEALINGS IN THE SOFTWARE. 221c235774Smrg */ 231c235774Smrg 241c235774Smrg#include <glib.h> 251c235774Smrg 261c235774Smrg#include <errno.h> 271c235774Smrg#include <limits.h> 281c235774Smrg#include <setjmp.h> 291c235774Smrg#include <signal.h> 301c235774Smrg#include <stdlib.h> 311c235774Smrg#include <unistd.h> 321c235774Smrg 331c235774Smrg#include "config.h" 341c235774Smrg 3552dc082bSmrg/* g_pattern_spec_match_string is available in glib 2.70 and later, 3652dc082bSmrg to replace the deprecated g_pattern_match_string */ 3752dc082bSmrg#ifdef HAVE_G_PATTERN_SPEC_MATCH_STRING 3852dc082bSmrg#define g_pattern_match_string g_pattern_spec_match_string 3952dc082bSmrg#endif 4052dc082bSmrg 411c235774Smrg#define DEFAULT_TIMEOUT 10 /* maximum seconds for each file */ 421c235774Smrg 431c235774Smrgstatic sigjmp_buf jump_env; 441c235774Smrg 451c235774Smrgstatic void sigalrm (int sig) 461c235774Smrg{ 471c235774Smrg siglongjmp(jump_env, 1); 481c235774Smrg} 491c235774Smrg 501c235774Smrgtypedef int (*testfilefunc)(const gchar *filepath); 511c235774Smrg 521c235774Smrg/* 531c235774Smrg * Test all files in a given subdir of either the build or source directory 541c235774Smrg */ 551c235774Smrgstatic void 561c235774SmrgTestAllFilesByType(GTestFileType file_type, gboolean compressed, 571c235774Smrg const char *subdir, int expected, testfilefunc testfunc) 581c235774Smrg{ 591c235774Smrg const gchar *datadir_path, *filename; 601c235774Smrg GDir *datadir; 611c235774Smrg GError *err = NULL; 621c235774Smrg int timeout = DEFAULT_TIMEOUT; 631c235774Smrg char *timeout_env; 641c235774Smrg 651c235774Smrg GPatternSpec *xpm_pattern = g_pattern_spec_new("*.xpm"); 661c235774Smrg#ifndef NO_ZPIPE 671c235774Smrg GPatternSpec *z_pattern = compressed ? g_pattern_spec_new("*.xpm.Z") : NULL; 681c235774Smrg GPatternSpec *gz_pattern = compressed ? g_pattern_spec_new("*.xpm.gz") : NULL; 691c235774Smrg#endif 701c235774Smrg 711c235774Smrg /* Allow override when debugging tests */ 721c235774Smrg timeout_env = getenv("XPM_TEST_TIMEOUT"); 731c235774Smrg if (timeout_env != NULL) { 741c235774Smrg int from_env = atoi(timeout_env); 751c235774Smrg 761c235774Smrg if (from_env >= 0) 771c235774Smrg timeout = from_env; 781c235774Smrg } 791c235774Smrg 801c235774Smrg datadir_path = g_test_get_filename(file_type, "pixmaps", subdir, 811c235774Smrg (file_type == G_TEST_BUILT) ? "generated" : NULL, NULL); 821c235774Smrg g_assert_nonnull(datadir_path); 831c235774Smrg g_test_message("Reading files from %s", datadir_path); 841c235774Smrg 851c235774Smrg datadir = g_dir_open(datadir_path, 0, &err); 861c235774Smrg g_assert_no_error(err); 871c235774Smrg 881c235774Smrg errno = 0; 891c235774Smrg while ((filename = g_dir_read_name(datadir)) != NULL) { 901c235774Smrg 911c235774Smrg if (!g_pattern_match_string(xpm_pattern, filename)) { 921c235774Smrg#ifndef NO_ZPIPE 931c235774Smrg if (!compressed || 941c235774Smrg (!g_pattern_match_string(z_pattern, filename) && 951c235774Smrg !g_pattern_match_string(gz_pattern, filename))) 961c235774Smrg#endif 971c235774Smrg { 981c235774Smrg g_test_message("skipping \"%s\"", filename); 991c235774Smrg continue; 1001c235774Smrg } 1011c235774Smrg } 1021c235774Smrg 1031c235774Smrg /* 1041c235774Smrg * Assumes the test function should complete in less than "timeout" 1051c235774Smrg * seconds and fails if they don't, in order to catch runaway loops. 1061c235774Smrg */ 1071c235774Smrg if (timeout > 0) { 1081c235774Smrg struct sigaction sa = { 1091c235774Smrg .sa_handler = sigalrm, 1101c235774Smrg .sa_flags = SA_RESTART 1111c235774Smrg }; 1121c235774Smrg sigemptyset (&sa.sa_mask); 1131c235774Smrg sigaction(SIGALRM, &sa, NULL); 1141c235774Smrg } 1151c235774Smrg 1161c235774Smrg if (sigsetjmp(jump_env, 1) == 0) { 1171c235774Smrg int status; 1181c235774Smrg gchar *filepath; 1191c235774Smrg 1201c235774Smrg filepath = g_build_filename(datadir_path, filename, NULL); 1211c235774Smrg 1221c235774Smrg g_test_message("testing \"%s\", should return %d", 1231c235774Smrg filename, expected); 1241c235774Smrg if (timeout > 0) 1251c235774Smrg alarm(timeout); 1261c235774Smrg status = testfunc(filepath); 1271c235774Smrg g_assert_cmpint(status, ==, expected); 1281c235774Smrg 1291c235774Smrg if (timeout > 0) { 1301c235774Smrg status = alarm(0); /* cancel alarm */ 1311c235774Smrg g_test_message("%d seconds left on %d second timer", 1321c235774Smrg status, timeout); 1331c235774Smrg } 1341c235774Smrg 1351c235774Smrg g_free(filepath); 1361c235774Smrg } 1371c235774Smrg else { 1381c235774Smrg g_test_message("timed out reading %s", filename); 1391c235774Smrg g_assertion_message(G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, 1401c235774Smrg "test timed out"); 1411c235774Smrg } 1421c235774Smrg 1431c235774Smrg errno = 0; 1441c235774Smrg } 1451c235774Smrg // g_assert_cmpint(errno, ==, 0); - not sure why this sometimes fails 1461c235774Smrg 1471c235774Smrg g_dir_close(datadir); 1481c235774Smrg} 1491c235774Smrg 1501c235774Smrg/* 1511c235774Smrg * Test all non-compressed files in a given subdir 1521c235774Smrg */ 1531c235774Smrgstatic void 1541c235774SmrgTestAllNormalFiles(const char *subdir, int expected, testfilefunc testfunc) 1551c235774Smrg{ 1561c235774Smrg TestAllFilesByType(G_TEST_DIST, FALSE, subdir, expected, testfunc); 1571c235774Smrg} 1581c235774Smrg 1591c235774Smrg/* 1601c235774Smrg * Test all compressed files in a given subdir 1611c235774Smrg */ 1621c235774Smrgstatic void 1631c235774SmrgTestAllCompressedFiles(const char *subdir, int expected, testfilefunc testfunc) 1641c235774Smrg{ 16574835918Smrg#ifdef NO_ZPIPE 16674835918Smrg g_test_message("compression disabled, skipping compressed file tests"); 16774835918Smrg#else 1681c235774Smrg TestAllFilesByType(G_TEST_BUILT, TRUE, subdir, expected, testfunc); 16974835918Smrg#endif 1701c235774Smrg} 171